2 Copyright (C) 2012 Samsung Electronics
3 Copyright (C) 2012 Intel Corporation. All rights reserved.
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 #include "GraphicsContext3DPrivate.h"
24 #include "HostWindow.h"
25 #include "NotImplemented.h"
29 std::unique_ptr<GraphicsContext3DPrivate> GraphicsContext3DPrivate::create(GraphicsContext3D* context, HostWindow* hostWindow)
31 std::unique_ptr<GraphicsContext3DPrivate> platformLayer = std::make_unique<GraphicsContext3DPrivate>(context, hostWindow);
33 if (platformLayer && platformLayer->initialize())
39 GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* hostWindow)
41 , m_hostWindow(hostWindow)
45 bool GraphicsContext3DPrivate::initialize()
47 if (m_context->m_renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow)
50 if (m_hostWindow && m_hostWindow->platformPageClient()) {
51 // FIXME: Implement this code path for WebKit1.
52 // Get Evas object from platformPageClient and set EvasGL related members.
56 m_offScreenContext = GLPlatformContext::createContext(m_context->m_renderStyle);
57 if (!m_offScreenContext)
60 if (m_context->m_renderStyle == GraphicsContext3D::RenderOffscreen) {
61 m_offScreenSurface = GLPlatformSurface::createOffScreenSurface();
63 if (!m_offScreenSurface)
66 if (!m_offScreenContext->initialize(m_offScreenSurface.get()))
69 if (!makeContextCurrent())
71 m_surfaceOperation = CreateSurface;
77 GraphicsContext3DPrivate::~GraphicsContext3DPrivate()
82 void GraphicsContext3DPrivate::releaseResources()
84 if (m_context->m_renderStyle == GraphicsContext3D::RenderToCurrentGLContext)
87 // Release the current context and drawable only after destroying any associated gl resources.
88 if (m_previousGraphicsSurface)
89 m_previousGraphicsSurface = nullptr;
91 if (m_graphicsSurface)
92 m_graphicsSurface = nullptr;
94 m_surfaceHandle = GraphicsSurfaceToken();
95 if (m_offScreenSurface)
96 m_offScreenSurface->destroy();
98 if (m_offScreenContext) {
99 m_offScreenContext->destroy();
100 m_offScreenContext->releaseCurrent();
104 void GraphicsContext3DPrivate::setContextLostCallback(std::unique_ptr<GraphicsContext3D::ContextLostCallback> callBack)
106 m_contextLostCallback = WTF::move(callBack);
109 PlatformGraphicsContext3D GraphicsContext3DPrivate::platformGraphicsContext3D() const
111 return m_offScreenContext->handle();
114 bool GraphicsContext3DPrivate::makeContextCurrent() const
116 bool success = m_offScreenContext->makeCurrent(m_offScreenSurface.get());
118 if (!m_offScreenContext->isValid()) {
119 // FIXME: Restore context
120 if (m_contextLostCallback)
121 m_contextLostCallback->onContextLost();
129 bool GraphicsContext3DPrivate::prepareBuffer() const
131 if (!makeContextCurrent())
134 m_context->markLayerComposited();
136 if (m_context->m_attrs.antialias) {
137 bool enableScissorTest = false;
138 int width = m_context->m_currentWidth;
139 int height = m_context->m_currentHeight;
140 // We should copy the full buffer, and not respect the current scissor bounds.
141 // FIXME: It would be more efficient to track the state of the scissor test.
142 if (m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST)) {
143 enableScissorTest = true;
144 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
147 glBindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_context->m_multisampleFBO);
148 glBindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_context->m_fbo);
150 // Use NEAREST as no scale is performed during the blit.
151 m_context->getExtensions()->blitFramebuffer(0, 0, width, height, 0, 0, width, height, GraphicsContext3D::COLOR_BUFFER_BIT, GraphicsContext3D::NEAREST);
153 if (enableScissorTest)
154 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
156 glBindFramebuffer(GL_FRAMEBUFFER, m_context->m_state.boundFBO);
162 void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper*, const FloatRect& /* target */, const TransformationMatrix&, float /* opacity */)
167 void GraphicsContext3DPrivate::createGraphicsSurface()
169 static PendingSurfaceOperation pendingOperation = DeletePreviousSurface | Resize | CreateSurface;
170 if (!(m_surfaceOperation & pendingOperation))
173 if (m_surfaceOperation & DeletePreviousSurface) {
174 m_previousGraphicsSurface = nullptr;
175 m_surfaceOperation &= ~DeletePreviousSurface;
178 if (!(m_surfaceOperation & pendingOperation))
181 // Don't release current graphics surface until we have prepared surface
182 // with requested size. This is to avoid flashing during resize.
183 if (m_surfaceOperation & Resize) {
184 m_previousGraphicsSurface = m_graphicsSurface;
185 m_surfaceOperation &= ~Resize;
186 m_surfaceOperation |= DeletePreviousSurface;
187 m_size = IntSize(m_context->m_currentWidth, m_context->m_currentHeight);
189 m_surfaceOperation &= ~CreateSurface;
191 m_targetRect = IntRect(IntPoint(), m_size);
193 if (m_size.isEmpty()) {
194 if (m_graphicsSurface) {
195 m_graphicsSurface = nullptr;
196 m_surfaceHandle = GraphicsSurfaceToken();
197 makeContextCurrent();
203 m_offScreenContext->releaseCurrent();
204 GraphicsSurface::Flags flags = GraphicsSurface::SupportsTextureTarget | GraphicsSurface::SupportsSharing;
206 if (m_context->m_attrs.alpha)
207 flags |= GraphicsSurface::SupportsAlpha;
209 m_graphicsSurface = GraphicsSurface::create(m_size, flags, m_offScreenContext->handle());
211 if (!m_graphicsSurface)
212 m_surfaceHandle = GraphicsSurfaceToken();
214 m_surfaceHandle = GraphicsSurfaceToken(m_graphicsSurface->exportToken());
216 makeContextCurrent();
219 void GraphicsContext3DPrivate::didResizeCanvas(const IntSize& size)
221 if (m_surfaceOperation & CreateSurface) {
223 createGraphicsSurface();
227 m_surfaceOperation |= Resize;
230 uint32_t GraphicsContext3DPrivate::copyToGraphicsSurface()
232 createGraphicsSurface();
234 if (!m_graphicsSurface || m_context->m_layerComposited || !prepareBuffer())
237 m_graphicsSurface->copyFromTexture(m_context->m_texture, m_targetRect);
238 makeContextCurrent();
240 return m_graphicsSurface->frontBuffer();
243 GraphicsSurfaceToken GraphicsContext3DPrivate::graphicsSurfaceToken() const
245 return m_surfaceHandle;
248 IntSize GraphicsContext3DPrivate::platformLayerSize() const
253 GraphicsSurface::Flags GraphicsContext3DPrivate::graphicsSurfaceFlags() const
255 if (m_graphicsSurface)
256 return m_graphicsSurface->flags();
258 return TextureMapperPlatformLayer::graphicsSurfaceFlags();
261 } // namespace WebCore