Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / platform / graphics / egl / GLContextEGL.cpp
1 /*
2  * Copyright (C) 2012 Igalia, S.L.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "config.h"
20 #include "GLContextEGL.h"
21
22 #if USE(EGL)
23
24 #include "GraphicsContext3D.h"
25 #include "PlatformDisplay.h"
26
27 #if USE(CAIRO)
28 #include <cairo.h>
29 #endif
30
31 #if USE(OPENGL_ES_2)
32 #include <GLES2/gl2.h>
33 #include <GLES2/gl2ext.h>
34 #else
35 #include "OpenGLShims.h"
36 #endif
37
38 #if PLATFORM(X11)
39 #include "PlatformDisplayX11.h"
40 #include <X11/Xlib.h>
41 #endif
42
43 #if ENABLE(ACCELERATED_2D_CANVAS)
44 // cairo-gl.h includes some definitions from GLX that conflict with
45 // the ones provided by us. Since GLContextEGL doesn't use any GLX
46 // functions we can safely disable them.
47 #undef CAIRO_HAS_GLX_FUNCTIONS
48 #include <cairo-gl.h>
49 #endif
50
51 namespace WebCore {
52
53 static EGLDisplay sharedEGLDisplay()
54 {
55     return PlatformDisplay::sharedDisplay().eglDisplay();
56 }
57
58 static const EGLint gContextAttributes[] = {
59 #if USE(OPENGL_ES_2)
60     EGL_CONTEXT_CLIENT_VERSION, 2,
61 #endif
62     EGL_NONE
63 };
64
65 static bool getEGLConfig(EGLConfig* config, GLContextEGL::EGLSurfaceType surfaceType)
66 {
67     EGLint attributeList[] = {
68 #if USE(OPENGL_ES_2)
69         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
70 #else
71         EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
72 #endif
73         EGL_RED_SIZE, 8,
74         EGL_GREEN_SIZE, 8,
75         EGL_BLUE_SIZE, 8,
76         EGL_STENCIL_SIZE, 8,
77         EGL_ALPHA_SIZE, 8,
78         EGL_SURFACE_TYPE, EGL_NONE,
79         EGL_NONE
80     };
81
82     switch (surfaceType) {
83     case GLContextEGL::PbufferSurface:
84         attributeList[13] = EGL_PBUFFER_BIT;
85         break;
86     case GLContextEGL::PixmapSurface:
87         attributeList[13] = EGL_PIXMAP_BIT;
88         break;
89     case GLContextEGL::WindowSurface:
90         attributeList[13] = EGL_WINDOW_BIT;
91         break;
92     }
93
94     EGLint numberConfigsReturned;
95     return eglChooseConfig(sharedEGLDisplay(), attributeList, config, 1, &numberConfigsReturned) && numberConfigsReturned;
96 }
97
98 std::unique_ptr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowType window, GLContext* sharingContext, std::unique_ptr<GLContext::Data>&& contextData)
99 {
100     EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0;
101
102     EGLDisplay display = sharedEGLDisplay();
103     if (display == EGL_NO_DISPLAY)
104         return nullptr;
105
106     EGLConfig config;
107     if (!getEGLConfig(&config, WindowSurface))
108         return nullptr;
109
110     EGLContext context = eglCreateContext(display, config, eglSharingContext, gContextAttributes);
111     if (context == EGL_NO_CONTEXT)
112         return nullptr;
113
114     EGLSurface surface = eglCreateWindowSurface(display, config, window, 0);
115     if (surface == EGL_NO_SURFACE) {
116         eglDestroyContext(display, context);
117         return nullptr;
118     }
119
120     auto glContext = std::make_unique<GLContextEGL>(context, surface, WindowSurface);
121     glContext->m_contextData = WTFMove(contextData);
122     return glContext;
123 }
124
125 std::unique_ptr<GLContextEGL> GLContextEGL::createPbufferContext(EGLContext sharingContext)
126 {
127     EGLDisplay display = sharedEGLDisplay();
128     if (display == EGL_NO_DISPLAY)
129         return nullptr;
130
131     EGLConfig config;
132     if (!getEGLConfig(&config, PbufferSurface))
133         return nullptr;
134
135     EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
136     if (context == EGL_NO_CONTEXT)
137         return nullptr;
138
139     static const int pbufferAttributes[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
140     EGLSurface surface = eglCreatePbufferSurface(display, config, pbufferAttributes);
141     if (surface == EGL_NO_SURFACE) {
142         eglDestroyContext(display, context);
143         return nullptr;
144     }
145
146     return std::make_unique<GLContextEGL>(context, surface, PbufferSurface);
147 }
148
149 #if PLATFORM(X11)
150 std::unique_ptr<GLContextEGL> GLContextEGL::createPixmapContext(EGLContext sharingContext)
151 {
152     EGLDisplay display = sharedEGLDisplay();
153     if (display == EGL_NO_DISPLAY)
154         return nullptr;
155
156     EGLConfig config;
157     if (!getEGLConfig(&config, PixmapSurface))
158         return nullptr;
159
160     EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
161     if (context == EGL_NO_CONTEXT)
162         return nullptr;
163
164     EGLint depth;
165     if (!eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth)) {
166         eglDestroyContext(display, context);
167         return nullptr;
168     }
169
170     Display* x11Display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
171     XUniquePixmap pixmap = XCreatePixmap(x11Display, DefaultRootWindow(x11Display), 1, 1, depth);
172     if (!pixmap) {
173         eglDestroyContext(display, context);
174         return nullptr;
175     }
176
177     EGLSurface surface = eglCreatePixmapSurface(display, config, reinterpret_cast<EGLNativePixmapType>(pixmap.get()), 0);
178     if (surface == EGL_NO_SURFACE) {
179         eglDestroyContext(display, context);
180         return nullptr;
181     }
182
183     return std::make_unique<GLContextEGL>(context, surface, WTFMove(pixmap));
184 }
185 #endif // PLATFORM(X11)
186
187 std::unique_ptr<GLContextEGL> GLContextEGL::createContext(EGLNativeWindowType window, GLContext* sharingContext)
188 {
189     if (!sharedEGLDisplay())
190         return nullptr;
191
192     static bool initialized = false;
193     static bool success = true;
194     if (!initialized) {
195 #if !USE(OPENGL_ES_2)
196         success = initializeOpenGLShims();
197 #endif
198         initialized = true;
199     }
200     if (!success)
201         return nullptr;
202
203     EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0;
204     auto context = window ? createWindowContext(window, sharingContext) : nullptr;
205 #if PLATFORM(X11)
206     if (!context)
207         context = createPixmapContext(eglSharingContext);
208 #endif
209     if (!context)
210         context = createPbufferContext(eglSharingContext);
211
212     return WTFMove(context);
213 }
214
215 GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, EGLSurfaceType type)
216     : m_context(context)
217     , m_surface(surface)
218     , m_type(type)
219 {
220     ASSERT(type != PixmapSurface);
221 }
222
223 #if PLATFORM(X11)
224 GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, XUniquePixmap&& pixmap)
225     : m_context(context)
226     , m_surface(surface)
227     , m_type(PixmapSurface)
228     , m_pixmap(WTFMove(pixmap))
229 {
230 }
231 #endif
232
233 GLContextEGL::~GLContextEGL()
234 {
235 #if USE(CAIRO)
236     if (m_cairoDevice)
237         cairo_device_destroy(m_cairoDevice);
238 #endif
239
240     EGLDisplay display = sharedEGLDisplay();
241     if (m_context) {
242         glBindFramebuffer(GL_FRAMEBUFFER, 0);
243         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
244         eglDestroyContext(display, m_context);
245     }
246
247     if (m_surface)
248         eglDestroySurface(display, m_surface);
249 }
250
251 bool GLContextEGL::canRenderToDefaultFramebuffer()
252 {
253     return m_type == WindowSurface;
254 }
255
256 IntSize GLContextEGL::defaultFrameBufferSize()
257 {
258     if (!canRenderToDefaultFramebuffer())
259         return IntSize();
260
261     EGLint width, height;
262     if (!eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_WIDTH, &width)
263         || !eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_HEIGHT, &height))
264         return IntSize();
265
266     return IntSize(width, height);
267 }
268
269 bool GLContextEGL::makeContextCurrent()
270 {
271     ASSERT(m_context && m_surface);
272
273     GLContext::makeContextCurrent();
274     if (eglGetCurrentContext() == m_context)
275         return true;
276
277     return eglMakeCurrent(sharedEGLDisplay(), m_surface, m_surface, m_context);
278 }
279
280 void GLContextEGL::swapBuffers()
281 {
282     ASSERT(m_surface);
283     eglSwapBuffers(sharedEGLDisplay(), m_surface);
284 }
285
286 void GLContextEGL::waitNative()
287 {
288     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
289 }
290
291 #if USE(CAIRO)
292 cairo_device_t* GLContextEGL::cairoDevice()
293 {
294     if (m_cairoDevice)
295         return m_cairoDevice;
296
297 #if ENABLE(ACCELERATED_2D_CANVAS)
298     m_cairoDevice = cairo_egl_device_create(sharedEGLDisplay(), m_context);
299 #endif
300
301     return m_cairoDevice;
302 }
303 #endif
304
305 #if ENABLE(GRAPHICS_CONTEXT_3D)
306 PlatformGraphicsContext3D GLContextEGL::platformContext()
307 {
308     return m_context;
309 }
310 #endif
311
312 } // namespace WebCore
313
314 #endif // USE(EGL)