ced7bb8574577d8cf7b85e71a86bb96347dc9621
[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 #if HAVE(GLX)
40 #include <GL/glx.h>
41 #endif
42
43 namespace WebCore {
44
45 #if USE(OPENGL_ES_2)
46 static PFNGLGETGRAPHICSRESETSTATUSEXTPROC glGetGraphicsResetStatus = 0;
47 #else
48 static PFNGLGETGRAPHICSRESETSTATUSARBPROC glGetGraphicsResetStatus = 0;
49 #endif
50 static GLPlatformContext* m_currentContext = 0;
51
52 class GLCurrentContextWrapper : public GLPlatformContext {
53
54 public:
55     GLCurrentContextWrapper()
56         : GLPlatformContext()
57     {
58         // FIXME:: This is a workaround until support to build evas with EGL has been added.
59 #if USE(GLX) || PLATFORM(EFL)
60         m_contextHandle = glXGetCurrentContext();
61 #elif USE(EGL)
62         m_contextHandle = eglGetCurrentContext();
63 #endif
64         if (m_contextHandle)
65             m_currentContext = this;
66     }
67
68     virtual ~GLCurrentContextWrapper() { }
69 };
70
71 static PassOwnPtr<GLPlatformContext> createOffScreenContext()
72 {
73 #if USE(GLX)
74     return adoptPtr(new GLXOffScreenContext());
75 #elif USE(EGL)
76     return adoptPtr(new EGLOffScreenContext());
77 #endif
78
79     return nullptr;
80 }
81
82 static HashSet<String> parseExtensions(const String& extensionsString)
83 {
84     Vector<String> extNames;
85     extensionsString.split(" ", extNames);
86     HashSet<String> splitExtNames;
87     unsigned size = extNames.size();
88     for (unsigned i = 0; i < size; ++i)
89         splitExtNames.add(extNames[i]);
90     extNames.clear();
91
92     return splitExtNames;
93 }
94
95 static void resolveResetStatusExtension()
96 {
97     static bool resolvedRobustnessExtension = false;
98     if (!resolvedRobustnessExtension) {
99         resolvedRobustnessExtension = true;
100 #if USE(OPENGL_ES_2)
101         glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSEXTPROC>(eglGetProcAddress("glGetGraphicsResetStatusEXT"));
102 #elif USE(EGL)
103         glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSARBPROC>(eglGetProcAddress("glGetGraphicsResetStatusARB"));
104 #elif USE(GLX)
105         glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSARBPROC>(glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("glGetGraphicsResetStatusARB")));
106 #endif
107     }
108 }
109
110 PassOwnPtr<GLPlatformContext> GLPlatformContext::createContext(GraphicsContext3D::RenderStyle renderStyle)
111 {
112 #if !USE(OPENGL_ES_2)
113     if (!initializeOpenGLShims())
114         return nullptr;
115 #endif
116
117     switch (renderStyle) {
118     case GraphicsContext3D::RenderOffscreen:
119         if (OwnPtr<GLPlatformContext> context = createOffScreenContext())
120             return context.release();
121         break;
122     case GraphicsContext3D::RenderToCurrentGLContext:
123         if (OwnPtr<GLPlatformContext> context = adoptPtr(new GLCurrentContextWrapper()))
124             return context.release();
125         break;
126     case GraphicsContext3D::RenderDirectlyToHostWindow:
127         ASSERT_NOT_REACHED();
128         break;
129     }
130
131     return nullptr;
132 }
133
134 bool GLPlatformContext::supportsGLExtension(const String& name)
135 {
136     static HashSet<String> supportedExtensions;
137
138     if (!supportedExtensions.size()) {
139         String rawExtensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS));
140         supportedExtensions = parseExtensions(rawExtensions);
141     }
142
143     if (supportedExtensions.contains(name))
144         return true;
145
146     return false;
147 }
148
149 #if USE(EGL)
150 bool GLPlatformContext::supportsEGLExtension(EGLDisplay display, const String& name)
151 {
152     static HashSet<String> supportedExtensions;
153
154     if (!supportedExtensions.size()) {
155         if (display == EGL_NO_DISPLAY)
156             return false;
157
158         String rawExtensions = reinterpret_cast<const char*>(eglQueryString(display, EGL_EXTENSIONS));
159         supportedExtensions = parseExtensions(rawExtensions);
160     }
161
162     if (supportedExtensions.contains(name))
163         return true;
164
165     return false;
166 }
167 #endif
168
169 #if USE(GLX)
170 bool GLPlatformContext::supportsGLXExtension(Display* display, const String& name)
171 {
172     static HashSet<String> supportedExtensions;
173
174     if (!supportedExtensions.size()) {
175         if (!display)
176             return false;
177
178         String rawExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
179         supportedExtensions = parseExtensions(rawExtensions);
180     }
181
182     if (supportedExtensions.contains(name))
183         return true;
184
185     return false;
186 }
187 #endif
188
189 GLPlatformContext::GLPlatformContext()
190     : m_contextHandle(0)
191     , m_resetLostContext(false)
192 {
193 }
194
195 GLPlatformContext::~GLPlatformContext()
196 {
197     if (this == m_currentContext)
198         m_currentContext = 0;
199 }
200
201 bool GLPlatformContext::makeCurrent(GLPlatformSurface* surface)
202 {
203     m_contextLost = false;
204
205     if (isCurrentContext())
206         return true;
207
208     m_currentContext = 0;
209
210     if (!surface || (surface && !surface->drawable()))
211         platformReleaseCurrent();
212     else if (platformMakeCurrent(surface))
213         m_currentContext = this;
214
215     if (m_resetLostContext) {
216         resolveResetStatusExtension();
217
218         if (glGetGraphicsResetStatus) {
219             GLenum status = glGetGraphicsResetStatus();
220
221             switch (status) {
222             case PLATFORMCONTEXT_NO_ERROR:
223                 break;
224             case PLATFORMCONTEXT_GUILTY_CONTEXT_RESET:
225                 m_contextLost = true;
226                 break;
227             case PLATFORMCONTEXT_INNOCENT_CONTEXT_RESET:
228                 break;
229             case PLATFORMCONTEXT_UNKNOWN_CONTEXT_RESET:
230                 m_contextLost = true;
231                 break;
232             default:
233                 break;
234             }
235         }
236     }
237
238     return m_currentContext;
239 }
240
241 bool GLPlatformContext::isValid() const
242 {
243     return !m_contextLost;
244 }
245
246 void GLPlatformContext::releaseCurrent()
247 {
248     if (!isCurrentContext())
249         return;
250
251     m_currentContext = 0;
252     platformReleaseCurrent();
253 }
254
255 PlatformContext GLPlatformContext::handle() const
256 {
257     return m_contextHandle;
258 }
259
260 bool GLPlatformContext::isCurrentContext() const
261 {
262     return true;
263 }
264
265 bool GLPlatformContext::initialize(GLPlatformSurface*, PlatformContext)
266 {
267     return true;
268 }
269
270 GLPlatformContext* GLPlatformContext::getCurrent()
271 {
272     return m_currentContext;
273 }
274
275 bool GLPlatformContext::platformMakeCurrent(GLPlatformSurface*)
276 {
277     return true;
278 }
279
280 void GLPlatformContext::platformReleaseCurrent()
281 {
282     notImplemented();
283 }
284
285 void GLPlatformContext::destroy()
286 {
287     m_contextHandle = 0;
288     m_resetLostContext = false;
289
290     if (this == m_currentContext)
291         m_currentContext = 0;
292 }
293
294 } // namespace WebCore
295
296 #endif