6fa83cd2454775e508a25a5be5136cd869990243
[WebKit-https.git] / Source / WebCore / platform / graphics / opengl / Extensions3DOpenGLES.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
4  * Copyright (C) 2014 Collabora Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29
30 #if USE(OPENGL_ES_2)
31 #include "Extensions3DOpenGLES.h"
32
33 #if ENABLE(GRAPHICS_CONTEXT_3D)
34 #include "GraphicsContext3D.h"
35 #include "NotImplemented.h"
36
37 #if USE(LIBEPOXY)
38 #include <epoxy/egl.h>
39 #else
40 #include <EGL/egl.h>
41 #endif
42
43 namespace WebCore {
44
45 Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context, bool useIndexedGetString)
46     : Extensions3DOpenGLCommon(context, useIndexedGetString)
47     , m_contextResetStatus(GL_NO_ERROR)
48     , m_supportsOESvertexArrayObject(false)
49     , m_supportsIMGMultisampledRenderToTexture(false)
50     , m_supportsANGLEinstancedArrays(false)
51     , m_glFramebufferTexture2DMultisampleIMG(0)
52     , m_glRenderbufferStorageMultisampleIMG(0)
53     , m_glBindVertexArrayOES(0)
54     , m_glDeleteVertexArraysOES(0)
55     , m_glGenVertexArraysOES(0)
56     , m_glIsVertexArrayOES(0)
57     , m_glGetGraphicsResetStatusEXT(0)
58     , m_glReadnPixelsEXT(0)
59     , m_glGetnUniformfvEXT(0)
60     , m_glGetnUniformivEXT(0)
61     , m_glVertexAttribDivisorANGLE(nullptr)
62     , m_glDrawArraysInstancedANGLE(nullptr)
63     , m_glDrawElementsInstancedANGLE(nullptr)
64 {
65 }
66
67 Extensions3DOpenGLES::~Extensions3DOpenGLES()
68 {
69 }
70
71 void Extensions3DOpenGLES::framebufferTexture2DMultisampleIMG(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned int texture, int level, unsigned long samples)
72 {
73     if (m_glFramebufferTexture2DMultisampleIMG)
74         m_glFramebufferTexture2DMultisampleIMG(target, attachment, textarget, texture, level, samples);
75     else
76         m_context->synthesizeGLError(GL_INVALID_OPERATION);
77 }
78
79 void Extensions3DOpenGLES::renderbufferStorageMultisampleIMG(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height)
80 {
81     if (m_glRenderbufferStorageMultisampleIMG)
82         m_glRenderbufferStorageMultisampleIMG(target, samples, internalformat, width, height);
83     else
84         m_context->synthesizeGLError(GL_INVALID_OPERATION);
85 }
86
87 void Extensions3DOpenGLES::blitFramebuffer(long /* srcX0 */, long /* srcY0 */, long /* srcX1 */, long /* srcY1 */, long /* dstX0 */, long /* dstY0 */, long /* dstX1 */, long /* dstY1 */, unsigned long /* mask */, unsigned long /* filter */)
88 {
89     notImplemented();
90 }
91
92 void Extensions3DOpenGLES::renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height)
93 {
94     if (m_glRenderbufferStorageMultisampleIMG)
95         renderbufferStorageMultisampleIMG(target, samples, internalformat, width, height);
96     else
97         notImplemented();
98 }
99
100 void Extensions3DOpenGLES::insertEventMarkerEXT(const String&)
101 {
102     notImplemented();
103 }
104
105 void Extensions3DOpenGLES::pushGroupMarkerEXT(const String&)
106 {
107     notImplemented();
108 }
109
110 void Extensions3DOpenGLES::popGroupMarkerEXT(void)
111 {
112     notImplemented();
113 }
114
115 Platform3DObject Extensions3DOpenGLES::createVertexArrayOES()
116 {
117     m_context->makeContextCurrent();
118     if (m_glGenVertexArraysOES) {
119         GLuint array = 0;
120         m_glGenVertexArraysOES(1, &array);
121         return array;
122     }
123
124     m_context->synthesizeGLError(GL_INVALID_OPERATION);
125     return 0;
126 }
127
128 void Extensions3DOpenGLES::deleteVertexArrayOES(Platform3DObject array)
129 {
130     if (!array)
131         return;
132
133     m_context->makeContextCurrent();
134     if (m_glDeleteVertexArraysOES)
135         m_glDeleteVertexArraysOES(1, &array);
136     else
137         m_context->synthesizeGLError(GL_INVALID_OPERATION);
138 }
139
140 GC3Dboolean Extensions3DOpenGLES::isVertexArrayOES(Platform3DObject array)
141 {
142     if (!array)
143         return GL_FALSE;
144
145     m_context->makeContextCurrent();
146     if (m_glIsVertexArrayOES)
147         return m_glIsVertexArrayOES(array);
148
149     m_context->synthesizeGLError(GL_INVALID_OPERATION);
150     return false;
151 }
152
153 void Extensions3DOpenGLES::bindVertexArrayOES(Platform3DObject array)
154 {
155     if (!array)
156         return;
157
158     m_context->makeContextCurrent();
159     if (m_glBindVertexArrayOES)
160         m_glBindVertexArrayOES(array);
161     else
162         m_context->synthesizeGLError(GL_INVALID_OPERATION);
163 }
164
165 void Extensions3DOpenGLES::drawBuffersEXT(GC3Dsizei /* n */, const GC3Denum* /* bufs */)
166 {
167     // FIXME: implement the support.
168     notImplemented();
169 }
170
171 int Extensions3DOpenGLES::getGraphicsResetStatusARB()
172 {
173     // FIXME: This does not call getGraphicsResetStatusARB, but instead getGraphicsResetStatusEXT.
174     // The return codes from the two extensions are identical and their purpose is the same, so it
175     // may be best to rename getGraphicsResetStatusARB() to getGraphicsResetStatus().
176     if (m_contextResetStatus != GL_NO_ERROR)
177         return m_contextResetStatus;
178     if (m_glGetGraphicsResetStatusEXT) {
179         m_context->makeContextCurrent();
180         int reasonForReset = m_glGetGraphicsResetStatusEXT();
181         if (reasonForReset != GL_NO_ERROR) {
182             ASSERT(m_contextLostCallback);
183             if (m_contextLostCallback)
184                 m_contextLostCallback->onContextLost();
185             m_contextResetStatus = reasonForReset;
186         }
187         return reasonForReset;
188     }
189
190     m_context->synthesizeGLError(GL_INVALID_OPERATION);
191     return false;
192 }
193
194 void Extensions3DOpenGLES::setEXTContextLostCallback(std::unique_ptr<GraphicsContext3D::ContextLostCallback> callback)
195 {
196     m_contextLostCallback = WTFMove(callback);
197 }
198
199 void Extensions3DOpenGLES::readnPixelsEXT(int x, int y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, GC3Dsizei bufSize, void *data)
200 {
201     if (m_glReadnPixelsEXT) {
202         m_context->makeContextCurrent();
203         // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e.,
204         // all previous rendering calls should be done before reading pixels.
205         ::glFlush();
206
207         // FIXME: If non-BlackBerry platforms use this, they will need to implement
208         // their anti-aliasing code here.
209         m_glReadnPixelsEXT(x, y, width, height, format, type, bufSize, data);
210         return;
211     }
212
213     m_context->synthesizeGLError(GL_INVALID_OPERATION);
214 }
215
216 void Extensions3DOpenGLES::getnUniformfvEXT(GC3Duint program, int location, GC3Dsizei bufSize, float *params)
217 {
218     if (m_glGetnUniformfvEXT) {
219         m_context->makeContextCurrent();
220         m_glGetnUniformfvEXT(program, location, bufSize, params);
221         return;
222     }
223
224     m_context->synthesizeGLError(GL_INVALID_OPERATION);
225 }
226
227 void Extensions3DOpenGLES::getnUniformivEXT(GC3Duint program, int location, GC3Dsizei bufSize, int *params)
228 {
229     if (m_glGetnUniformivEXT) {
230         m_context->makeContextCurrent();
231         m_glGetnUniformivEXT(program, location, bufSize, params);
232         return;
233     }
234
235     m_context->synthesizeGLError(GL_INVALID_OPERATION);
236 }
237
238 void Extensions3DOpenGLES::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
239 {
240     if (!m_glDrawArraysInstancedANGLE) {
241         m_context->synthesizeGLError(GL_INVALID_OPERATION);
242         return;
243     }
244
245     m_context->makeContextCurrent();
246     m_glDrawArraysInstancedANGLE(mode, first, count, primcount);
247 }
248
249 void Extensions3DOpenGLES::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount)
250 {
251     if (!m_glDrawElementsInstancedANGLE) {
252         m_context->synthesizeGLError(GL_INVALID_OPERATION);
253         return;
254     }
255
256     m_context->makeContextCurrent();
257     m_glDrawElementsInstancedANGLE(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)), primcount);
258 }
259
260 void Extensions3DOpenGLES::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
261 {
262     if (!m_glVertexAttribDivisorANGLE) {
263         m_context->synthesizeGLError(GL_INVALID_OPERATION);
264         return;
265     }
266
267     m_context->makeContextCurrent();
268     m_glVertexAttribDivisorANGLE(index, divisor);
269 }
270
271 bool Extensions3DOpenGLES::supportsExtension(const String& name)
272 {
273     if (m_availableExtensions.contains(name)) {
274         if (!m_supportsOESvertexArrayObject && name == "GL_OES_vertex_array_object") {
275             m_glBindVertexArrayOES = reinterpret_cast<PFNGLBINDVERTEXARRAYOESPROC>(eglGetProcAddress("glBindVertexArrayOES"));
276             m_glGenVertexArraysOES = reinterpret_cast<PFNGLGENVERTEXARRAYSOESPROC>(eglGetProcAddress("glGenVertexArraysOES"));
277             m_glDeleteVertexArraysOES = reinterpret_cast<PFNGLDELETEVERTEXARRAYSOESPROC>(eglGetProcAddress("glDeleteVertexArraysOES"));
278             m_glIsVertexArrayOES = reinterpret_cast<PFNGLISVERTEXARRAYOESPROC>(eglGetProcAddress("glIsVertexArrayOES"));
279             m_supportsOESvertexArrayObject = true;
280         } else if (!m_supportsIMGMultisampledRenderToTexture && name == "GL_IMG_multisampled_render_to_texture") {
281             m_glFramebufferTexture2DMultisampleIMG = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC>(eglGetProcAddress("glFramebufferTexture2DMultisampleIMG"));
282             m_glRenderbufferStorageMultisampleIMG = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC>(eglGetProcAddress("glRenderbufferStorageMultisampleIMG"));
283             m_supportsIMGMultisampledRenderToTexture = true;
284         } else if (!m_glGetGraphicsResetStatusEXT && name == "GL_EXT_robustness") {
285             m_glGetGraphicsResetStatusEXT = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSEXTPROC>(eglGetProcAddress("glGetGraphicsResetStatusEXT"));
286             m_glReadnPixelsEXT = reinterpret_cast<PFNGLREADNPIXELSEXTPROC>(eglGetProcAddress("glReadnPixelsEXT"));
287             m_glGetnUniformfvEXT = reinterpret_cast<PFNGLGETNUNIFORMFVEXTPROC>(eglGetProcAddress("glGetnUniformfvEXT"));
288             m_glGetnUniformivEXT = reinterpret_cast<PFNGLGETNUNIFORMIVEXTPROC>(eglGetProcAddress("glGetnUniformivEXT"));
289         } else if (!m_supportsANGLEinstancedArrays && name == "GL_ANGLE_instanced_arrays") {
290             m_glVertexAttribDivisorANGLE = reinterpret_cast<PFNGLVERTEXATTRIBDIVISORANGLEPROC>(eglGetProcAddress("glVertexAttribDivisorANGLE"));
291             m_glDrawArraysInstancedANGLE = reinterpret_cast<PFNGLDRAWARRAYSINSTANCEDANGLEPROC >(eglGetProcAddress("glDrawArraysInstancedANGLE"));
292             m_glDrawElementsInstancedANGLE = reinterpret_cast<PFNGLDRAWELEMENTSINSTANCEDANGLEPROC >(eglGetProcAddress("glDrawElementsInstancedANGLE"));
293             m_supportsANGLEinstancedArrays = true;
294         } else if (name == "GL_EXT_draw_buffers") {
295             // FIXME: implement the support.
296             return false;
297         }
298         return true;
299     }
300
301     return false;
302 }
303
304 String Extensions3DOpenGLES::getExtensions()
305 {
306     return String(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)));
307 }
308
309 } // namespace WebCore
310
311 #endif // ENABLE(GRAPHICS_CONTEXT_3D)
312
313 #endif // USE(OPENGL_ES_2)