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