[EFL] Remove non Coordinated Graphics code path from cmake build system after r142169
[WebKit-https.git] / Source / WebCore / platform / graphics / efl / GraphicsContext3DEfl.cpp
1 /*
2     Copyright (C) 2012 Samsung Electronics
3     Copyright (C) 2012 Intel Corporation.
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 "GraphicsContext3D.h"
23
24 #include "GLDefs.h"
25 #include "GraphicsContext3DPrivate.h"
26 #include "Image.h"
27 #include "ImageSource.h"
28 #include "NotImplemented.h"
29 #include "PlatformContextCairo.h"
30
31 namespace WebCore {
32
33 PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle)
34 {
35     RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, renderStyle));
36     return context->m_private ? context.release() : 0;
37 }
38
39 GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
40     : m_currentWidth(0)
41     , m_currentHeight(0)
42     , m_compiler(isGLES2Compliant() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT)
43     , m_attrs(attrs)
44     , m_renderStyle(renderStyle)
45     , m_texture(0)
46     , m_compositorTexture(0)
47     , m_fbo(0)
48 #if USE(OPENGL_ES_2)
49     , m_depthBuffer(0)
50     , m_stencilBuffer(0)
51 #endif
52     , m_depthStencilBuffer(0)
53     , m_layerComposited(false)
54     , m_internalColorFormat(0)
55     , m_multisampleFBO(0)
56     , m_multisampleDepthStencilBuffer(0)
57     , m_multisampleColorBuffer(0)
58     , m_private(GraphicsContext3DPrivate::create(this, hostWindow))
59 {
60     if (!m_private)
61         return;
62
63     validateAttributes();
64
65     if (renderStyle == RenderOffscreen) {
66         // Create buffers for the canvas FBO.
67         glGenFramebuffers(1, &m_fbo);
68
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);
77
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);
86         } else {
87             // Bind canvas FBO.
88             glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
89             m_state.boundFBO = m_fbo;
90 #if USE(OPENGL_ES_2)
91             if (m_attrs.depth)
92                 glGenRenderbuffers(1, &m_depthBuffer);
93             if (m_attrs.stencil)
94                 glGenRenderbuffers(1, &m_stencilBuffer);
95 #endif
96             if (m_attrs.stencil || m_attrs.depth)
97                 glGenRenderbuffers(1, &m_depthStencilBuffer);
98         }
99     }
100
101     // ANGLE initialization.
102     ShBuiltInResources ANGLEResources;
103     ShInitBuiltInResources(&ANGLEResources);
104
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);
112
113     // Always set to 1 for OpenGL ES.
114     ANGLEResources.MaxDrawBuffers = 1;
115
116     GC3Dint range[2], precision;
117     getShaderPrecisionFormat(GraphicsContext3D::FRAGMENT_SHADER, GraphicsContext3D::HIGH_FLOAT, range, &precision);
118     ANGLEResources.FragmentPrecisionHigh = (range[0] || range[1] || precision);
119
120     m_compiler.setResources(ANGLEResources);
121
122 #if !USE(OPENGL_ES_2)
123     glEnable(GL_POINT_SPRITE);
124     glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
125 #endif
126     if (renderStyle != RenderToCurrentGLContext)
127         glClearColor(0.0, 0.0, 0.0, 0.0);
128 }
129
130 GraphicsContext3D::~GraphicsContext3D()
131 {
132     if (!m_private || (m_renderStyle == RenderToCurrentGLContext) || !makeContextCurrent())
133         return;
134
135     glBindFramebuffer(GL_FRAMEBUFFER, 0);
136     glBindTexture(GL_TEXTURE_2D, 0);
137
138     if (m_texture)
139         glDeleteTextures(1, &m_texture);
140
141     if (m_fbo)
142         glDeleteFramebuffers(1, &m_fbo);
143
144     if (m_attrs.antialias) {
145         if (m_multisampleColorBuffer)
146             glDeleteRenderbuffers(1, &m_multisampleColorBuffer);
147
148         if (m_multisampleDepthStencilBuffer)
149             glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer);
150
151         if (m_multisampleFBO)
152             glDeleteFramebuffers(1, &m_multisampleFBO);
153     } else if (m_attrs.stencil || m_attrs.depth) {
154 #if USE(OPENGL_ES_2)
155         if (m_depthBuffer)
156             glDeleteRenderbuffers(1, &m_depthBuffer);
157
158         if (m_stencilBuffer)
159             glDeleteRenderbuffers(1, &m_stencilBuffer);
160 #endif
161         if (m_depthStencilBuffer)
162             glDeleteRenderbuffers(1, &m_depthStencilBuffer);
163     }
164 }
165
166 PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
167 {
168     return m_private->platformGraphicsContext3D();
169 }
170
171 Platform3DObject GraphicsContext3D::platformTexture() const
172 {
173     return m_texture;
174 }
175
176 PlatformLayer* GraphicsContext3D::platformLayer() const
177 {
178     return m_private.get();
179 }
180
181 bool GraphicsContext3D::makeContextCurrent()
182 {
183     return m_private->makeContextCurrent();
184 }
185
186 bool GraphicsContext3D::isGLES2Compliant() const
187 {
188 #if USE(OPENGL_ES_2)
189     return true;
190 #else
191     return false;
192 #endif
193 }
194
195 void GraphicsContext3D::setContextLostCallback(std::unique_ptr<ContextLostCallback> callBack)
196 {
197     m_private->setContextLostCallback(WTF::move(callBack));
198 }
199
200 void GraphicsContext3D::setErrorMessageCallback(std::unique_ptr<ErrorMessageCallback>)
201 {
202     notImplemented();
203 }
204
205 void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context)
206 {
207     if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
208         return;
209
210     cairo_t* cr = context->cr();
211     context->save(); 
212
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));
215
216     cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight);
217
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);
224     cairo_fill(cr);
225     context->restore();
226 }
227
228 void GraphicsContext3D::createGraphicsSurfaces(const IntSize& size)
229 {
230     m_private->didResizeCanvas(size);
231 }
232
233 GraphicsContext3D::ImageExtractor::~ImageExtractor()
234 {
235     delete m_decoder;
236 }
237
238 bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
239 {
240     // This implementation is taken from GraphicsContext3DCairo.
241
242     if (!m_image)
243         return false;
244
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);
247
248     if (!m_decoder)
249         return false;
250
251     ImageSource& decoder = *m_decoder;
252     m_alphaOp = AlphaDoNothing;
253
254     if (m_image->data()) {
255         decoder.setData(m_image->data(), true);
256
257         if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
258             return false;
259
260         m_imageSurface = decoder.createFrameAtIndex(0);
261     } else {
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;
269     }
270
271     if (!m_imageSurface)
272         return false;
273
274     m_imageWidth = cairo_image_surface_get_width(m_imageSurface.get());
275     m_imageHeight = cairo_image_surface_get_height(m_imageSurface.get());
276
277     if (!m_imageWidth || !m_imageHeight)
278         return false;
279
280     if (cairo_image_surface_get_format(m_imageSurface.get()) != CAIRO_FORMAT_ARGB32)
281         return false;
282
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;
287
288     if (padding) {
289         srcUnpackAlignment = padding + 1;
290         while (bytesPerRow % srcUnpackAlignment)
291             ++srcUnpackAlignment;
292     }
293
294     m_imagePixelData = cairo_image_surface_get_data(m_imageSurface.get());
295     m_imageSourceFormat = DataFormatBGRA8;
296     m_imageSourceUnpackAlignment = srcUnpackAlignment;
297
298     return true;
299 }
300
301 } // namespace WebCore