1/* 2 * Copyright (C) 2012 Intel Corporation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27 28#if USE(3D_GRAPHICS) 29#include "GLPlatformContext.h" 30 31#if USE(GLX) 32#include "GLXContext.h" 33#elif USE(EGL) 34#include "EGLContext.h" 35#endif 36 37#include "NotImplemented.h" 38 39namespace WebCore { 40 41#if USE(OPENGL_ES_2) 42static PFNGLGETGRAPHICSRESETSTATUSEXTPROC glGetGraphicsResetStatus = 0; 43#else 44static PFNGLGETGRAPHICSRESETSTATUSARBPROC glGetGraphicsResetStatus = 0; 45#endif 46static GLPlatformContext* m_currentContext = 0; 47 48class GLCurrentContextWrapper : public GLPlatformContext { 49 50public: 51 GLCurrentContextWrapper() 52 : GLPlatformContext() 53 { 54#if USE(GLX) 55 m_contextHandle = glXGetCurrentContext(); 56#elif USE(EGL) 57 m_contextHandle = eglGetCurrentContext(); 58#endif 59 if (m_contextHandle) 60 m_currentContext = this; 61 } 62 63 virtual ~GLCurrentContextWrapper() { } 64}; 65 66static std::unique_ptr<GLPlatformContext> createOffScreenContext() 67{ 68#if USE(GLX) 69 return std::make_unique<GLXOffScreenContext>(); 70#elif USE(EGL) 71 return std::make_unique<EGLOffScreenContext>(); 72#else 73 return nullptr; 74#endif 75} 76 77static HashSet<String> parseExtensions(const String& extensionsString) 78{ 79 Vector<String> extNames; 80 extensionsString.split(" ", extNames); 81 HashSet<String> splitExtNames; 82 unsigned size = extNames.size(); 83 for (unsigned i = 0; i < size; ++i) 84 splitExtNames.add(extNames[i]); 85 extNames.clear(); 86 87 return splitExtNames; 88} 89 90static void resolveResetStatusExtension() 91{ 92 static bool resolvedRobustnessExtension = false; 93 if (!resolvedRobustnessExtension) { 94 resolvedRobustnessExtension = true; 95#if USE(OPENGL_ES_2) 96 glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSEXTPROC>(eglGetProcAddress("glGetGraphicsResetStatusEXT")); 97#elif USE(EGL) 98 glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSARBPROC>(eglGetProcAddress("glGetGraphicsResetStatusARB")); 99#elif USE(GLX) 100 glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSARBPROC>(glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("glGetGraphicsResetStatusARB"))); 101#endif 102 } 103} 104 105std::unique_ptr<GLPlatformContext> GLPlatformContext::createContext(GraphicsContext3D::RenderStyle renderStyle) 106{ 107#if !USE(OPENGL_ES_2) 108 if (!initializeOpenGLShims()) 109 return nullptr; 110#endif 111 112 switch (renderStyle) { 113 case GraphicsContext3D::RenderOffscreen: 114 return createOffScreenContext(); 115 case GraphicsContext3D::RenderToCurrentGLContext: 116 return std::make_unique<GLCurrentContextWrapper>(); 117 case GraphicsContext3D::RenderDirectlyToHostWindow: 118 ASSERT_NOT_REACHED(); 119 break; 120 } 121 122 return nullptr; 123} 124 125bool GLPlatformContext::supportsGLExtension(const String& name) 126{ 127 static HashSet<String> supportedExtensions; 128 129 if (!supportedExtensions.size()) { 130 String rawExtensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)); 131 supportedExtensions = parseExtensions(rawExtensions); 132 } 133 134 if (supportedExtensions.contains(name)) 135 return true; 136 137 return false; 138} 139 140#if USE(EGL) 141bool GLPlatformContext::supportsEGLExtension(EGLDisplay display, const String& name) 142{ 143 static HashSet<String> supportedExtensions; 144 145 if (!supportedExtensions.size()) { 146 if (display == EGL_NO_DISPLAY) 147 return false; 148 149 String rawExtensions = reinterpret_cast<const char*>(eglQueryString(display, EGL_EXTENSIONS)); 150 supportedExtensions = parseExtensions(rawExtensions); 151 } 152 153 if (supportedExtensions.contains(name)) 154 return true; 155 156 return false; 157} 158#endif 159 160#if USE(GLX) 161bool GLPlatformContext::supportsGLXExtension(Display* display, const String& name) 162{ 163 static HashSet<String> supportedExtensions; 164 165 if (!supportedExtensions.size()) { 166 if (!display) 167 return false; 168 169 String rawExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); 170 supportedExtensions = parseExtensions(rawExtensions); 171 } 172 173 if (supportedExtensions.contains(name)) 174 return true; 175 176 return false; 177} 178#endif 179 180GLPlatformContext::GLPlatformContext() 181 : m_contextHandle(0) 182 , m_resetLostContext(false) 183{ 184} 185 186GLPlatformContext::~GLPlatformContext() 187{ 188 if (this == m_currentContext) 189 m_currentContext = 0; 190} 191 192bool GLPlatformContext::makeCurrent(GLPlatformSurface* surface) 193{ 194 m_contextLost = false; 195 196 if (m_currentContext == this && (!surface || surface->isCurrentDrawable())) 197 return true; 198 199 m_currentContext = 0; 200 201 if (!surface || (surface && !surface->drawable())) 202 platformReleaseCurrent(); 203 else if (platformMakeCurrent(surface)) { 204 m_currentContext = this; 205 surface->onMakeCurrent(); 206 } 207 208 if (m_resetLostContext) { 209 resolveResetStatusExtension(); 210 211 if (glGetGraphicsResetStatus) { 212 GLenum status = glGetGraphicsResetStatus(); 213 214 switch (status) { 215 case PLATFORMCONTEXT_NO_ERROR: 216 break; 217 case PLATFORMCONTEXT_GUILTY_CONTEXT_RESET: 218 m_contextLost = true; 219 break; 220 case PLATFORMCONTEXT_INNOCENT_CONTEXT_RESET: 221 break; 222 case PLATFORMCONTEXT_UNKNOWN_CONTEXT_RESET: 223 m_contextLost = true; 224 break; 225 default: 226 break; 227 } 228 } 229 } 230 231 return m_currentContext; 232} 233 234bool GLPlatformContext::isValid() const 235{ 236 return !m_contextLost; 237} 238 239void GLPlatformContext::releaseCurrent() 240{ 241 if (this == m_currentContext) { 242 m_currentContext = 0; 243 platformReleaseCurrent(); 244 } 245} 246 247PlatformContext GLPlatformContext::handle() const 248{ 249 return m_contextHandle; 250} 251 252bool GLPlatformContext::isCurrentContext() const 253{ 254 return true; 255} 256 257bool GLPlatformContext::initialize(GLPlatformSurface*, PlatformContext) 258{ 259 return true; 260} 261 262GLPlatformContext* GLPlatformContext::getCurrent() 263{ 264 return m_currentContext; 265} 266 267bool GLPlatformContext::platformMakeCurrent(GLPlatformSurface*) 268{ 269 return true; 270} 271 272void GLPlatformContext::platformReleaseCurrent() 273{ 274 notImplemented(); 275} 276 277void GLPlatformContext::destroy() 278{ 279 m_contextHandle = 0; 280 m_resetLostContext = false; 281} 282 283} // namespace WebCore 284 285#endif 286