bce042583791d223814f6a49d5360f77e0ef65e5
[WebKit-https.git] / Source / WebCore / platform / graphics / opengl / GLPlatformContext.cpp
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 #include "GLPlatformContext.h"
28
29 #if USE(ACCELERATED_COMPOSITING)
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
39 namespace WebCore {
40
41 #if USE(OPENGL_ES_2)
42 static PFNGLGETGRAPHICSRESETSTATUSEXTPROC glGetGraphicsResetStatus = 0;
43 #else
44 static PFNGLGETGRAPHICSRESETSTATUSARBPROC glGetGraphicsResetStatus = 0;
45 #endif
46 static GLPlatformContext* m_currentContext = 0;
47
48 class GLCurrentContextWrapper : public GLPlatformContext {
49
50 public:
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
66 static PassOwnPtr<GLPlatformContext> createOffScreenContext()
67 {
68 #if USE(GLX)
69     return adoptPtr(new GLXOffScreenContext());
70 #elif USE(EGL)
71     return adoptPtr(new EGLOffScreenContext());
72 #endif
73
74     return nullptr;
75 }
76
77 static 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
90 static 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
105 PassOwnPtr<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         if (OwnPtr<GLPlatformContext> context = createOffScreenContext())
115             return context.release();
116         break;
117     case GraphicsContext3D::RenderToCurrentGLContext:
118         if (OwnPtr<GLPlatformContext> context = adoptPtr(new GLCurrentContextWrapper()))
119             return context.release();
120         break;
121     case GraphicsContext3D::RenderDirectlyToHostWindow:
122         ASSERT_NOT_REACHED();
123         break;
124     }
125
126     return nullptr;
127 }
128
129 bool GLPlatformContext::supportsGLExtension(const String& name)
130 {
131     static HashSet<String> supportedExtensions;
132
133     if (!supportedExtensions.size()) {
134         String rawExtensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS));
135         supportedExtensions = parseExtensions(rawExtensions);
136     }
137
138     if (supportedExtensions.contains(name))
139         return true;
140
141     return false;
142 }
143
144 #if USE(EGL)
145 bool GLPlatformContext::supportsEGLExtension(EGLDisplay display, const String& name)
146 {
147     static HashSet<String> supportedExtensions;
148
149     if (!supportedExtensions.size()) {
150         if (display == EGL_NO_DISPLAY)
151             return false;
152
153         String rawExtensions = reinterpret_cast<const char*>(eglQueryString(display, EGL_EXTENSIONS));
154         supportedExtensions = parseExtensions(rawExtensions);
155     }
156
157     if (supportedExtensions.contains(name))
158         return true;
159
160     return false;
161 }
162 #endif
163
164 #if USE(GLX)
165 bool GLPlatformContext::supportsGLXExtension(Display* display, const String& name)
166 {
167     static HashSet<String> supportedExtensions;
168
169     if (!supportedExtensions.size()) {
170         if (!display)
171             return false;
172
173         String rawExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
174         supportedExtensions = parseExtensions(rawExtensions);
175     }
176
177     if (supportedExtensions.contains(name))
178         return true;
179
180     return false;
181 }
182 #endif
183
184 GLPlatformContext::GLPlatformContext()
185     : m_contextHandle(0)
186     , m_resetLostContext(false)
187 {
188 }
189
190 GLPlatformContext::~GLPlatformContext()
191 {
192     if (this == m_currentContext)
193         m_currentContext = 0;
194 }
195
196 bool GLPlatformContext::makeCurrent(GLPlatformSurface* surface)
197 {
198     m_contextLost = false;
199
200     if (isCurrentContext())
201         return true;
202
203     m_currentContext = 0;
204
205     if (!surface || (surface && !surface->drawable()))
206         platformReleaseCurrent();
207     else if (platformMakeCurrent(surface))
208         m_currentContext = this;
209
210     if (m_resetLostContext) {
211         resolveResetStatusExtension();
212
213         if (glGetGraphicsResetStatus) {
214             GLenum status = glGetGraphicsResetStatus();
215
216             switch (status) {
217             case PLATFORMCONTEXT_NO_ERROR:
218                 break;
219             case PLATFORMCONTEXT_GUILTY_CONTEXT_RESET:
220                 m_contextLost = true;
221                 break;
222             case PLATFORMCONTEXT_INNOCENT_CONTEXT_RESET:
223                 break;
224             case PLATFORMCONTEXT_UNKNOWN_CONTEXT_RESET:
225                 m_contextLost = true;
226                 break;
227             default:
228                 break;
229             }
230         }
231     }
232
233     return m_currentContext;
234 }
235
236 bool GLPlatformContext::isValid() const
237 {
238     return !m_contextLost;
239 }
240
241 void GLPlatformContext::releaseCurrent()
242 {
243     if (!isCurrentContext())
244         return;
245
246     m_currentContext = 0;
247     platformReleaseCurrent();
248 }
249
250 PlatformContext GLPlatformContext::handle() const
251 {
252     return m_contextHandle;
253 }
254
255 bool GLPlatformContext::isCurrentContext() const
256 {
257     return true;
258 }
259
260 bool GLPlatformContext::initialize(GLPlatformSurface*, PlatformContext)
261 {
262     return true;
263 }
264
265 GLPlatformContext* GLPlatformContext::getCurrent()
266 {
267     return m_currentContext;
268 }
269
270 bool GLPlatformContext::platformMakeCurrent(GLPlatformSurface*)
271 {
272     return true;
273 }
274
275 void GLPlatformContext::platformReleaseCurrent()
276 {
277     notImplemented();
278 }
279
280 void GLPlatformContext::destroy()
281 {
282     m_contextHandle = 0;
283     m_resetLostContext = false;
284
285     if (this == m_currentContext)
286         m_currentContext = 0;
287 }
288
289 } // namespace WebCore
290
291 #endif