1/* 2 Copyright (C) 2012 Samsung Electronics 3 Copyright (C) 2012 Intel Corporation. All rights reserved. 4 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. 9 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. 14 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. 19*/ 20 21#include "config.h" 22#include "GraphicsContext3DPrivate.h" 23 24#include "HostWindow.h" 25#include "NotImplemented.h" 26 27namespace WebCore { 28 29std::unique_ptr<GraphicsContext3DPrivate> GraphicsContext3DPrivate::create(GraphicsContext3D* context, HostWindow* hostWindow) 30{ 31 std::unique_ptr<GraphicsContext3DPrivate> platformLayer = std::make_unique<GraphicsContext3DPrivate>(context, hostWindow); 32 33 if (platformLayer && platformLayer->initialize()) 34 return platformLayer; 35 36 return nullptr; 37} 38 39GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* hostWindow) 40 : m_context(context) 41 , m_hostWindow(hostWindow) 42{ 43} 44 45bool GraphicsContext3DPrivate::initialize() 46{ 47 if (m_context->m_renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow) 48 return false; 49 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. 53 return false; 54 } 55 56 m_offScreenContext = GLPlatformContext::createContext(m_context->m_renderStyle); 57 if (!m_offScreenContext) 58 return false; 59 60 if (m_context->m_renderStyle == GraphicsContext3D::RenderOffscreen) { 61 m_offScreenSurface = GLPlatformSurface::createOffScreenSurface(); 62 63 if (!m_offScreenSurface) 64 return false; 65 66 if (!m_offScreenContext->initialize(m_offScreenSurface.get())) 67 return false; 68 69 if (!makeContextCurrent()) 70 return false; 71#if USE(GRAPHICS_SURFACE) 72 m_surfaceOperation = CreateSurface; 73#endif 74 } 75 76 return true; 77} 78 79GraphicsContext3DPrivate::~GraphicsContext3DPrivate() 80{ 81 releaseResources(); 82} 83 84void GraphicsContext3DPrivate::releaseResources() 85{ 86 if (m_context->m_renderStyle == GraphicsContext3D::RenderToCurrentGLContext) 87 return; 88 89 // Release the current context and drawable only after destroying any associated gl resources. 90#if USE(GRAPHICS_SURFACE) 91 if (m_previousGraphicsSurface) 92 m_previousGraphicsSurface = nullptr; 93 94 if (m_graphicsSurface) 95 m_graphicsSurface = nullptr; 96 97 m_surfaceHandle = GraphicsSurfaceToken(); 98#endif 99 if (m_offScreenSurface) 100 m_offScreenSurface->destroy(); 101 102 if (m_offScreenContext) { 103 m_offScreenContext->destroy(); 104 m_offScreenContext->releaseCurrent(); 105 } 106} 107 108void GraphicsContext3DPrivate::setContextLostCallback(std::unique_ptr<GraphicsContext3D::ContextLostCallback> callBack) 109{ 110 m_contextLostCallback = WTF::move(callBack); 111} 112 113PlatformGraphicsContext3D GraphicsContext3DPrivate::platformGraphicsContext3D() const 114{ 115 return m_offScreenContext->handle(); 116} 117 118bool GraphicsContext3DPrivate::makeContextCurrent() const 119{ 120 bool success = m_offScreenContext->makeCurrent(m_offScreenSurface.get()); 121 122 if (!m_offScreenContext->isValid()) { 123 // FIXME: Restore context 124 if (m_contextLostCallback) 125 m_contextLostCallback->onContextLost(); 126 127 return false; 128 } 129 130 return success; 131} 132 133bool GraphicsContext3DPrivate::prepareBuffer() const 134{ 135 if (!makeContextCurrent()) 136 return false; 137 138 m_context->markLayerComposited(); 139 140 if (m_context->m_attrs.antialias) { 141 bool enableScissorTest = false; 142 int width = m_context->m_currentWidth; 143 int height = m_context->m_currentHeight; 144 // We should copy the full buffer, and not respect the current scissor bounds. 145 // FIXME: It would be more efficient to track the state of the scissor test. 146 if (m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST)) { 147 enableScissorTest = true; 148 m_context->disable(GraphicsContext3D::SCISSOR_TEST); 149 } 150 151 glBindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_context->m_multisampleFBO); 152 glBindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_context->m_fbo); 153 154 // Use NEAREST as no scale is performed during the blit. 155 m_context->getExtensions()->blitFramebuffer(0, 0, width, height, 0, 0, width, height, GraphicsContext3D::COLOR_BUFFER_BIT, GraphicsContext3D::NEAREST); 156 157 if (enableScissorTest) 158 m_context->enable(GraphicsContext3D::SCISSOR_TEST); 159 160 glBindFramebuffer(GL_FRAMEBUFFER, m_context->m_state.boundFBO); 161 } 162 163 return true; 164} 165 166#if USE(TEXTURE_MAPPER_GL) 167void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper*, const FloatRect& /* target */, const TransformationMatrix&, float /* opacity */) 168{ 169 notImplemented(); 170} 171#endif 172 173#if USE(GRAPHICS_SURFACE) 174void GraphicsContext3DPrivate::createGraphicsSurface() 175{ 176 static PendingSurfaceOperation pendingOperation = DeletePreviousSurface | Resize | CreateSurface; 177 if (!(m_surfaceOperation & pendingOperation)) 178 return; 179 180 if (m_surfaceOperation & DeletePreviousSurface) { 181 m_previousGraphicsSurface = nullptr; 182 m_surfaceOperation &= ~DeletePreviousSurface; 183 } 184 185 if (!(m_surfaceOperation & pendingOperation)) 186 return; 187 188 // Don't release current graphics surface until we have prepared surface 189 // with requested size. This is to avoid flashing during resize. 190 if (m_surfaceOperation & Resize) { 191 m_previousGraphicsSurface = m_graphicsSurface; 192 m_surfaceOperation &= ~Resize; 193 m_surfaceOperation |= DeletePreviousSurface; 194 m_size = IntSize(m_context->m_currentWidth, m_context->m_currentHeight); 195 } else 196 m_surfaceOperation &= ~CreateSurface; 197 198 m_targetRect = IntRect(IntPoint(), m_size); 199 200 if (m_size.isEmpty()) { 201 if (m_graphicsSurface) { 202 m_graphicsSurface = nullptr; 203 m_surfaceHandle = GraphicsSurfaceToken(); 204 makeContextCurrent(); 205 } 206 207 return; 208 } 209 210 m_offScreenContext->releaseCurrent(); 211 GraphicsSurface::Flags flags = GraphicsSurface::SupportsTextureTarget | GraphicsSurface::SupportsSharing; 212 213 if (m_context->m_attrs.alpha) 214 flags |= GraphicsSurface::SupportsAlpha; 215 216 m_graphicsSurface = GraphicsSurface::create(m_size, flags, m_offScreenContext->handle()); 217 218 if (!m_graphicsSurface) 219 m_surfaceHandle = GraphicsSurfaceToken(); 220 else 221 m_surfaceHandle = GraphicsSurfaceToken(m_graphicsSurface->exportToken()); 222 223 makeContextCurrent(); 224} 225 226void GraphicsContext3DPrivate::didResizeCanvas(const IntSize& size) 227{ 228 if (m_surfaceOperation & CreateSurface) { 229 m_size = size; 230 createGraphicsSurface(); 231 return; 232 } 233 234 m_surfaceOperation |= Resize; 235} 236 237uint32_t GraphicsContext3DPrivate::copyToGraphicsSurface() 238{ 239 createGraphicsSurface(); 240 241 if (!m_graphicsSurface || m_context->m_layerComposited || !prepareBuffer()) 242 return 0; 243 244 m_graphicsSurface->copyFromTexture(m_context->m_texture, m_targetRect); 245 makeContextCurrent(); 246 247 return m_graphicsSurface->frontBuffer(); 248} 249 250GraphicsSurfaceToken GraphicsContext3DPrivate::graphicsSurfaceToken() const 251{ 252 return m_surfaceHandle; 253} 254 255IntSize GraphicsContext3DPrivate::platformLayerSize() const 256{ 257 return m_size; 258} 259 260GraphicsSurface::Flags GraphicsContext3DPrivate::graphicsSurfaceFlags() const 261{ 262 if (m_graphicsSurface) 263 return m_graphicsSurface->flags(); 264 265 return TextureMapperPlatformLayer::graphicsSurfaceFlags(); 266} 267#endif 268 269} // namespace WebCore 270