2 Copyright (C) 2012 Samsung Electronics
3 Copyright (C) 2012 Intel Corporation.
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 "GraphicsContext3D.h"
25 #include "GraphicsContext3DPrivate.h"
27 #include "ImageSource.h"
28 #include "NotImplemented.h"
29 #include "PlatformContextCairo.h"
33 PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle)
35 RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, renderStyle));
36 return context->m_private ? context.release() : 0;
39 GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
42 , m_compiler(isGLES2Compliant() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT)
44 , m_renderStyle(renderStyle)
46 , m_compositorTexture(0)
52 , m_depthStencilBuffer(0)
53 , m_layerComposited(false)
54 , m_internalColorFormat(0)
56 , m_multisampleDepthStencilBuffer(0)
57 , m_multisampleColorBuffer(0)
58 , m_private(GraphicsContext3DPrivate::create(this, hostWindow))
65 if (renderStyle == RenderOffscreen) {
66 // Create buffers for the canvas FBO.
67 glGenFramebuffers(1, &m_fbo);
69 // Create a texture to render into.
70 glGenTextures(1, &m_texture);
71 glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture);
72 glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
73 glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
74 glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
75 glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
76 glBindTexture(GraphicsContext3D::TEXTURE_2D, 0);
78 // Create a multisample FBO.
79 if (m_attrs.antialias) {
80 glGenFramebuffers(1, &m_multisampleFBO);
81 glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
82 m_state.boundFBO = m_multisampleFBO;
83 glGenRenderbuffers(1, &m_multisampleColorBuffer);
84 if (m_attrs.stencil || m_attrs.depth)
85 glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer);
88 glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
89 m_state.boundFBO = m_fbo;
92 glGenRenderbuffers(1, &m_depthBuffer);
94 glGenRenderbuffers(1, &m_stencilBuffer);
96 if (m_attrs.stencil || m_attrs.depth)
97 glGenRenderbuffers(1, &m_depthStencilBuffer);
101 // ANGLE initialization.
102 ShBuiltInResources ANGLEResources;
103 ShInitBuiltInResources(&ANGLEResources);
105 getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs);
106 getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors);
107 getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors);
108 getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits);
109 getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits);
110 getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits);
111 getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors);
113 // Always set to 1 for OpenGL ES.
114 ANGLEResources.MaxDrawBuffers = 1;
116 GC3Dint range[2], precision;
117 getShaderPrecisionFormat(GraphicsContext3D::FRAGMENT_SHADER, GraphicsContext3D::HIGH_FLOAT, range, &precision);
118 ANGLEResources.FragmentPrecisionHigh = (range[0] || range[1] || precision);
120 m_compiler.setResources(ANGLEResources);
122 #if !USE(OPENGL_ES_2)
123 glEnable(GL_POINT_SPRITE);
124 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
126 if (renderStyle != RenderToCurrentGLContext)
127 glClearColor(0.0, 0.0, 0.0, 0.0);
130 GraphicsContext3D::~GraphicsContext3D()
132 if (!m_private || (m_renderStyle == RenderToCurrentGLContext) || !makeContextCurrent())
135 glBindFramebuffer(GL_FRAMEBUFFER, 0);
136 glBindTexture(GL_TEXTURE_2D, 0);
139 glDeleteTextures(1, &m_texture);
142 glDeleteFramebuffers(1, &m_fbo);
144 if (m_attrs.antialias) {
145 if (m_multisampleColorBuffer)
146 glDeleteRenderbuffers(1, &m_multisampleColorBuffer);
148 if (m_multisampleDepthStencilBuffer)
149 glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer);
151 if (m_multisampleFBO)
152 glDeleteFramebuffers(1, &m_multisampleFBO);
153 } else if (m_attrs.stencil || m_attrs.depth) {
156 glDeleteRenderbuffers(1, &m_depthBuffer);
159 glDeleteRenderbuffers(1, &m_stencilBuffer);
161 if (m_depthStencilBuffer)
162 glDeleteRenderbuffers(1, &m_depthStencilBuffer);
166 PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
168 return m_private->platformGraphicsContext3D();
171 Platform3DObject GraphicsContext3D::platformTexture() const
176 PlatformLayer* GraphicsContext3D::platformLayer() const
178 return m_private.get();
181 bool GraphicsContext3D::makeContextCurrent()
183 return m_private->makeContextCurrent();
186 bool GraphicsContext3D::isGLES2Compliant() const
195 void GraphicsContext3D::setContextLostCallback(std::unique_ptr<ContextLostCallback> callBack)
197 m_private->setContextLostCallback(WTF::move(callBack));
200 void GraphicsContext3D::setErrorMessageCallback(std::unique_ptr<ErrorMessageCallback>)
205 void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context)
207 if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
210 cairo_t* cr = context->cr();
213 RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data(
214 const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4));
216 cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight);
218 // OpenGL keeps the pixels stored bottom up, so we need to flip the image here.
219 cairo_matrix_t matrix;
220 cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, imageHeight);
221 cairo_set_matrix(cr, &matrix);
222 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
223 cairo_set_source_surface(cr, imageSurface.get(), 0, 0);
228 void GraphicsContext3D::createGraphicsSurfaces(const IntSize& size)
230 m_private->didResizeCanvas(size);
233 GraphicsContext3D::ImageExtractor::~ImageExtractor()
238 bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
240 // This implementation is taken from GraphicsContext3DCairo.
245 // We need this to stay in scope because the native image is just a shallow copy of the data.
246 m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
251 ImageSource& decoder = *m_decoder;
252 m_alphaOp = AlphaDoNothing;
254 if (m_image->data()) {
255 decoder.setData(m_image->data(), true);
257 if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
260 m_imageSurface = decoder.createFrameAtIndex(0);
262 m_imageSurface = m_image->nativeImageForCurrentFrame();
263 // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel,
264 // which is true at present and may be changed in the future and needs adjustment accordingly.
265 // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port,
266 // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
267 if (!premultiplyAlpha && m_imageHtmlDomSource != HtmlDomVideo)
268 m_alphaOp = AlphaDoUnmultiply;
274 m_imageWidth = cairo_image_surface_get_width(m_imageSurface.get());
275 m_imageHeight = cairo_image_surface_get_height(m_imageSurface.get());
277 if (!m_imageWidth || !m_imageHeight)
280 if (cairo_image_surface_get_format(m_imageSurface.get()) != CAIRO_FORMAT_ARGB32)
283 uint srcUnpackAlignment = 1;
284 size_t bytesPerRow = cairo_image_surface_get_stride(m_imageSurface.get());
285 size_t bitsPerPixel = 32;
286 unsigned padding = bytesPerRow - bitsPerPixel / 8 * m_imageWidth;
289 srcUnpackAlignment = padding + 1;
290 while (bytesPerRow % srcUnpackAlignment)
291 ++srcUnpackAlignment;
294 m_imagePixelData = cairo_image_surface_get_data(m_imageSurface.get());
295 m_imageSourceFormat = DataFormatBGRA8;
296 m_imageSourceUnpackAlignment = srcUnpackAlignment;
301 } // namespace WebCore