1/* 2 * Copyright (C) 2011, 2012 Igalia S.L. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free 16 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301 USA 18 */ 19 20#include "config.h" 21 22#if USE(3D_GRAPHICS) 23#include "GraphicsContext3DPrivate.h" 24 25#include "HostWindow.h" 26#include "NotImplemented.h" 27#include <wtf/StdLibExtras.h> 28 29#if USE(CAIRO) 30#include "PlatformContextCairo.h" 31#endif 32 33#if USE(OPENGL_ES_2) 34#include <GLES2/gl2.h> 35#include <GLES2/gl2ext.h> 36#else 37#include "OpenGLShims.h" 38#endif 39 40#if USE(TEXTURE_MAPPER) && USE(TEXTURE_MAPPER_GL) 41#include <texmap/TextureMapperGL.h> 42#endif 43 44using namespace std; 45 46namespace WebCore { 47 48GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, GraphicsContext3D::RenderStyle renderStyle) 49 : m_context(context) 50 , m_renderStyle(renderStyle) 51{ 52 switch (renderStyle) { 53 case GraphicsContext3D::RenderOffscreen: 54 m_glContext = GLContext::createOffscreenContext(GLContext::sharingContext()); 55 break; 56 case GraphicsContext3D::RenderToCurrentGLContext: 57 break; 58 case GraphicsContext3D::RenderDirectlyToHostWindow: 59 ASSERT_NOT_REACHED(); 60 break; 61 } 62} 63 64GraphicsContext3DPrivate::~GraphicsContext3DPrivate() 65{ 66#if USE(TEXTURE_MAPPER) 67 if (client()) 68 client()->platformLayerWillBeDestroyed(); 69#endif 70} 71 72bool GraphicsContext3DPrivate::makeContextCurrent() 73{ 74 return m_glContext ? m_glContext->makeContextCurrent() : false; 75} 76 77PlatformGraphicsContext3D GraphicsContext3DPrivate::platformContext() 78{ 79 return m_glContext ? m_glContext->platformContext() : GLContext::getCurrent()->platformContext(); 80} 81 82#if USE(TEXTURE_MAPPER) 83void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity) 84{ 85 if (!m_glContext) 86 return; 87 88 ASSERT(m_renderStyle == GraphicsContext3D::RenderOffscreen); 89 90 m_context->markLayerComposited(); 91 92 // FIXME: We do not support mask for the moment with TextureMapperImageBuffer. 93 if (textureMapper->accelerationMode() != TextureMapper::OpenGLMode) { 94 GraphicsContext* context = textureMapper->graphicsContext(); 95 context->save(); 96 context->platformContext()->setGlobalAlpha(opacity); 97 98 const int height = m_context->m_currentHeight; 99 const int width = m_context->m_currentWidth; 100 int totalBytes = width * height * 4; 101 102 auto pixels = std::make_unique<unsigned char[]>(totalBytes); 103 if (!pixels) 104 return; 105 106 // OpenGL keeps the pixels stored bottom up, so we need to flip the image here. 107 context->translate(0, height); 108 context->scale(FloatSize(1, -1)); 109 110 context->concatCTM(matrix.toAffineTransform()); 111 112 m_context->readRenderingResults(pixels.get(), totalBytes); 113 114 // Premultiply alpha. 115 for (int i = 0; i < totalBytes; i += 4) 116 if (pixels[i + 3] != 255) { 117 pixels[i + 0] = min(255, pixels[i + 0] * pixels[i + 3] / 255); 118 pixels[i + 1] = min(255, pixels[i + 1] * pixels[i + 3] / 255); 119 pixels[i + 2] = min(255, pixels[i + 2] * pixels[i + 3] / 255); 120 } 121 122 RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data( 123 const_cast<unsigned char*>(pixels.get()), CAIRO_FORMAT_ARGB32, width, height, width * 4)); 124 125 context->platformContext()->drawSurfaceToContext(imageSurface.get(), targetRect, IntRect(0, 0, width, height), context); 126 127 context->restore(); 128 return; 129 } 130 131#if USE(TEXTURE_MAPPER_GL) 132 if (m_context->m_attrs.antialias && m_context->m_state.boundFBO == m_context->m_multisampleFBO) { 133 GLContext* previousActiveContext = GLContext::getCurrent(); 134 if (previousActiveContext != m_glContext) 135 m_context->makeContextCurrent(); 136 137 m_context->resolveMultisamplingIfNecessary(); 138 ::glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_context->m_state.boundFBO); 139 140 if (previousActiveContext && previousActiveContext != m_glContext) 141 previousActiveContext->makeContextCurrent(); 142 } 143 144 TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper); 145 TextureMapperGL::Flags flags = TextureMapperGL::ShouldFlipTexture | (m_context->m_attrs.alpha ? TextureMapperGL::ShouldBlend : 0); 146 IntSize textureSize(m_context->m_currentWidth, m_context->m_currentHeight); 147 texmapGL->drawTexture(m_context->m_texture, flags, textureSize, targetRect, matrix, opacity); 148#endif // USE(TEXTURE_MAPPER_GL) 149} 150#endif // USE(TEXTURE_MAPPER) 151 152} // namespace WebCore 153 154#endif // USE(3D_GRAPHICS) 155