Replace WTF::move with WTFMove
[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 #include <EGL/egl.h>
37 #include <wtf/Vector.h>
38
39 namespace WebCore {
40
41 Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context)
42     : Extensions3DOpenGLCommon(context)
43     , m_contextResetStatus(GL_NO_ERROR)
44     , m_supportsOESvertexArrayObject(false)
45     , m_supportsIMGMultisampledRenderToTexture(false)
46     , m_supportsANGLEinstancedArrays(false)
47     , m_glFramebufferTexture2DMultisampleIMG(0)
48     , m_glRenderbufferStorageMultisampleIMG(0)
49     , m_glBindVertexArrayOES(0)
50     , m_glDeleteVertexArraysOES(0)
51     , m_glGenVertexArraysOES(0)
52     , m_glIsVertexArrayOES(0)
53     , m_glGetGraphicsResetStatusEXT(0)
54     , m_glReadnPixelsEXT(0)
55     , m_glGetnUniformfvEXT(0)
56     , m_glGetnUniformivEXT(0)
57     , m_glVertexAttribDivisorANGLE(nullptr)
58     , m_glDrawArraysInstancedANGLE(nullptr)
59     , m_glDrawElementsInstancedANGLE(nullptr)
60 {
61 }
62
63 Extensions3DOpenGLES::~Extensions3DOpenGLES()
64 {
65 }
66
67 void Extensions3DOpenGLES::framebufferTexture2DMultisampleIMG(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned int texture, int level, unsigned long samples)
68 {
69     if (m_glFramebufferTexture2DMultisampleIMG)
70         m_glFramebufferTexture2DMultisampleIMG(target, attachment, textarget, texture, level, samples);
71     else
72         m_context->synthesizeGLError(GL_INVALID_OPERATION);
73 }
74
75 void Extensions3DOpenGLES::renderbufferStorageMultisampleIMG(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height)
76 {
77     if (m_glRenderbufferStorageMultisampleIMG)
78         m_glRenderbufferStorageMultisampleIMG(target, samples, internalformat, width, height);
79     else
80         m_context->synthesizeGLError(GL_INVALID_OPERATION);
81 }
82
83 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 */)
84 {
85     notImplemented();
86 }
87
88 void Extensions3DOpenGLES::renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height)
89 {
90     if (m_glRenderbufferStorageMultisampleIMG)
91         renderbufferStorageMultisampleIMG(target, samples, internalformat, width, height);
92     else
93         notImplemented();
94 }
95
96 void Extensions3DOpenGLES::insertEventMarkerEXT(const String&)
97 {
98     notImplemented();
99 }
100
101 void Extensions3DOpenGLES::pushGroupMarkerEXT(const String&)
102 {
103     notImplemented();
104 }
105
106 void Extensions3DOpenGLES::popGroupMarkerEXT(void)
107 {
108     notImplemented();
109 }
110
111 Platform3DObject Extensions3DOpenGLES::createVertexArrayOES()
112 {
113     m_context->makeContextCurrent();
114     if (m_glGenVertexArraysOES) {
115         GLuint array = 0;
116         m_glGenVertexArraysOES(1, &array);
117         return array;
118     }
119
120     m_context->synthesizeGLError(GL_INVALID_OPERATION);
121     return 0;
122 }
123
124 void Extensions3DOpenGLES::deleteVertexArrayOES(Platform3DObject array)
125 {
126     if (!array)
127         return;
128
129     m_context->makeContextCurrent();
130     if (m_glDeleteVertexArraysOES)
131         m_glDeleteVertexArraysOES(1, &array);
132     else
133         m_context->synthesizeGLError(GL_INVALID_OPERATION);
134 }
135
136 GC3Dboolean Extensions3DOpenGLES::isVertexArrayOES(Platform3DObject array)
137 {
138     if (!array)
139         return GL_FALSE;
140
141     m_context->makeContextCurrent();
142     if (m_glIsVertexArrayOES)
143         return m_glIsVertexArrayOES(array);
144
145     m_context->synthesizeGLError(GL_INVALID_OPERATION);
146     return false;
147 }
148
149 void Extensions3DOpenGLES::bindVertexArrayOES(Platform3DObject array)
150 {
151     if (!array)
152         return;
153
154     m_context->makeContextCurrent();
155     if (m_glBindVertexArrayOES)
156         m_glBindVertexArrayOES(array);
157     else
158         m_context->synthesizeGLError(GL_INVALID_OPERATION);
159 }
160
161 void Extensions3DOpenGLES::drawBuffersEXT(GC3Dsizei /* n */, const GC3Denum* /* bufs */)
162 {
163     // FIXME: implement the support.
164     notImplemented();
165 }
166
167 int Extensions3DOpenGLES::getGraphicsResetStatusARB()
168 {
169     // FIXME: This does not call getGraphicsResetStatusARB, but instead getGraphicsResetStatusEXT.
170     // The return codes from the two extensions are identical and their purpose is the same, so it
171     // may be best to rename getGraphicsResetStatusARB() to getGraphicsResetStatus().
172     if (m_contextResetStatus != GL_NO_ERROR)
173         return m_contextResetStatus;
174     if (m_glGetGraphicsResetStatusEXT) {
175         m_context->makeContextCurrent();
176         int reasonForReset = m_glGetGraphicsResetStatusEXT();
177         if (reasonForReset != GL_NO_ERROR) {
178             ASSERT(m_contextLostCallback);
179             if (m_contextLostCallback)
180                 m_contextLostCallback->onContextLost();
181             m_contextResetStatus = reasonForReset;
182         }
183         return reasonForReset;
184     }
185
186     m_context->synthesizeGLError(GL_INVALID_OPERATION);
187     return false;
188 }
189
190 void Extensions3DOpenGLES::setEXTContextLostCallback(std::unique_ptr<GraphicsContext3D::ContextLostCallback> callback)
191 {
192     m_contextLostCallback = WTFMove(callback);
193 }
194
195 void Extensions3DOpenGLES::readnPixelsEXT(int x, int y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, GC3Dsizei bufSize, void *data)
196 {
197     if (m_glReadnPixelsEXT) {
198         m_context->makeContextCurrent();
199         // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e.,
200         // all previous rendering calls should be done before reading pixels.
201         ::glFlush();
202
203         // FIXME: If non-BlackBerry platforms use this, they will need to implement
204         // their anti-aliasing code here.
205         m_glReadnPixelsEXT(x, y, width, height, format, type, bufSize, data);
206         return;
207     }
208
209     m_context->synthesizeGLError(GL_INVALID_OPERATION);
210 }
211
212 void Extensions3DOpenGLES::getnUniformfvEXT(GC3Duint program, int location, GC3Dsizei bufSize, float *params)
213 {
214     if (m_glGetnUniformfvEXT) {
215         m_context->makeContextCurrent();
216         m_glGetnUniformfvEXT(program, location, bufSize, params);
217         return;
218     }
219
220     m_context->synthesizeGLError(GL_INVALID_OPERATION);
221 }
222
223 void Extensions3DOpenGLES::getnUniformivEXT(GC3Duint program, int location, GC3Dsizei bufSize, int *params)
224 {
225     if (m_glGetnUniformivEXT) {
226         m_context->makeContextCurrent();
227         m_glGetnUniformivEXT(program, location, bufSize, params);
228         return;
229     }
230
231     m_context->synthesizeGLError(GL_INVALID_OPERATION);
232 }
233
234 void Extensions3DOpenGLES::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
235 {
236     if (!m_glDrawArraysInstancedANGLE) {
237         m_context->synthesizeGLError(GL_INVALID_OPERATION);
238         return;
239     }
240
241     m_context->makeContextCurrent();
242     m_glDrawArraysInstancedANGLE(mode, first, count, primcount);
243 }
244
245 void Extensions3DOpenGLES::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount)
246 {
247     if (!m_glDrawElementsInstancedANGLE) {
248         m_context->synthesizeGLError(GL_INVALID_OPERATION);
249         return;
250     }
251
252     m_context->makeContextCurrent();
253     m_glDrawElementsInstancedANGLE(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)), primcount);
254 }
255
256 void Extensions3DOpenGLES::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
257 {
258     if (!m_glVertexAttribDivisorANGLE) {
259         m_context->synthesizeGLError(GL_INVALID_OPERATION);
260         return;
261     }
262
263     m_context->makeContextCurrent();
264     m_glVertexAttribDivisorANGLE(index, divisor);
265 }
266
267 bool Extensions3DOpenGLES::supportsExtension(const String& name)
268 {
269     if (m_availableExtensions.contains(name)) {
270         if (!m_supportsOESvertexArrayObject && name == "GL_OES_vertex_array_object") {
271             m_glBindVertexArrayOES = reinterpret_cast<PFNGLBINDVERTEXARRAYOESPROC>(eglGetProcAddress("glBindVertexArrayOES"));
272             m_glGenVertexArraysOES = reinterpret_cast<PFNGLGENVERTEXARRAYSOESPROC>(eglGetProcAddress("glGenVertexArraysOES"));
273             m_glDeleteVertexArraysOES = reinterpret_cast<PFNGLDELETEVERTEXARRAYSOESPROC>(eglGetProcAddress("glDeleteVertexArraysOES"));
274             m_glIsVertexArrayOES = reinterpret_cast<PFNGLISVERTEXARRAYOESPROC>(eglGetProcAddress("glIsVertexArrayOES"));
275             m_supportsOESvertexArrayObject = true;
276         } else if (!m_supportsIMGMultisampledRenderToTexture && name == "GL_IMG_multisampled_render_to_texture") {
277             m_glFramebufferTexture2DMultisampleIMG = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC>(eglGetProcAddress("glFramebufferTexture2DMultisampleIMG"));
278             m_glRenderbufferStorageMultisampleIMG = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC>(eglGetProcAddress("glRenderbufferStorageMultisampleIMG"));
279             m_supportsIMGMultisampledRenderToTexture = true;
280         } else if (!m_glGetGraphicsResetStatusEXT && name == "GL_EXT_robustness") {
281             m_glGetGraphicsResetStatusEXT = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSEXTPROC>(eglGetProcAddress("glGetGraphicsResetStatusEXT"));
282             m_glReadnPixelsEXT = reinterpret_cast<PFNGLREADNPIXELSEXTPROC>(eglGetProcAddress("glReadnPixelsEXT"));
283             m_glGetnUniformfvEXT = reinterpret_cast<PFNGLGETNUNIFORMFVEXTPROC>(eglGetProcAddress("glGetnUniformfvEXT"));
284             m_glGetnUniformivEXT = reinterpret_cast<PFNGLGETNUNIFORMIVEXTPROC>(eglGetProcAddress("glGetnUniformivEXT"));
285         } else if (!m_supportsANGLEinstancedArrays && name == "GL_ANGLE_instanced_arrays") {
286             m_glVertexAttribDivisorANGLE = reinterpret_cast<PFNGLVERTEXATTRIBDIVISORANGLEPROC>(eglGetProcAddress("glVertexAttribDivisorANGLE"));
287             m_glDrawArraysInstancedANGLE = reinterpret_cast<PFNGLDRAWARRAYSINSTANCEDANGLEPROC >(eglGetProcAddress("glDrawArraysInstancedANGLE"));
288             m_glDrawElementsInstancedANGLE = reinterpret_cast<PFNGLDRAWELEMENTSINSTANCEDANGLEPROC >(eglGetProcAddress("glDrawElementsInstancedANGLE"));
289             m_supportsANGLEinstancedArrays = true;
290         } else if (name == "GL_EXT_draw_buffers") {
291             // FIXME: implement the support.
292             return false;
293         }
294         return true;
295     }
296
297     return false;
298 }
299
300 String Extensions3DOpenGLES::getExtensions()
301 {
302     return String(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)));
303 }
304
305 } // namespace WebCore
306
307 #endif // ENABLE(GRAPHICS_CONTEXT_3D)
308
309 #endif // USE(OPENGL_ES_2)