Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / platform / graphics / glx / GLContextGLX.cpp
1 /*
2  * Copyright (C) 2011, 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 "GLContextGLX.h"
21
22 #if USE(GLX)
23 #include "GraphicsContext3D.h"
24 #include "OpenGLShims.h"
25 #include "PlatformDisplayX11.h"
26 #include <GL/glx.h>
27 #include <cairo.h>
28
29 #if ENABLE(ACCELERATED_2D_CANVAS)
30 #include <cairo-gl.h>
31 #endif
32
33 namespace WebCore {
34
35 std::unique_ptr<GLContextGLX> GLContextGLX::createWindowContext(XID window, GLContext* sharingContext)
36 {
37     Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
38     XWindowAttributes attributes;
39     if (!XGetWindowAttributes(display, window, &attributes))
40         return nullptr;
41
42     XVisualInfo visualInfo;
43     visualInfo.visualid = XVisualIDFromVisual(attributes.visual);
44
45     int numReturned = 0;
46     XUniquePtr<XVisualInfo> visualInfoList(XGetVisualInfo(display, VisualIDMask, &visualInfo, &numReturned));
47
48     GLXContext glxSharingContext = sharingContext ? static_cast<GLContextGLX*>(sharingContext)->m_context.get() : nullptr;
49     XUniqueGLXContext context(glXCreateContext(display, visualInfoList.get(), glxSharingContext, True));
50     if (!context)
51         return nullptr;
52
53     return std::make_unique<GLContextGLX>(WTFMove(context), window);
54 }
55
56 std::unique_ptr<GLContextGLX> GLContextGLX::createPbufferContext(GLXContext sharingContext)
57 {
58     static const int fbConfigAttributes[] = {
59         GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
60         GLX_RENDER_TYPE, GLX_RGBA_BIT,
61         GLX_RED_SIZE, 1,
62         GLX_GREEN_SIZE, 1,
63         GLX_BLUE_SIZE, 1,
64         GLX_ALPHA_SIZE, 1,
65         GLX_DOUBLEBUFFER, GL_FALSE,
66         0
67     };
68
69     int returnedElements;
70     Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
71     XUniquePtr<GLXFBConfig> configs(glXChooseFBConfig(display, 0, fbConfigAttributes, &returnedElements));
72     if (!returnedElements)
73         return nullptr;
74
75     // We will be rendering to a texture, so our pbuffer does not need to be large.
76     static const int pbufferAttributes[] = { GLX_PBUFFER_WIDTH, 1, GLX_PBUFFER_HEIGHT, 1, 0 };
77     XUniqueGLXPbuffer pbuffer(glXCreatePbuffer(display, configs.get()[0], pbufferAttributes));
78     if (!pbuffer)
79         return nullptr;
80
81     XUniqueGLXContext context(glXCreateNewContext(display, configs.get()[0], GLX_RGBA_TYPE, sharingContext, GL_TRUE));
82     if (!context)
83         return nullptr;
84
85     return std::make_unique<GLContextGLX>(WTFMove(context), WTFMove(pbuffer));
86 }
87
88 std::unique_ptr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext sharingContext)
89 {
90     static int visualAttributes[] = {
91         GLX_RGBA,
92         GLX_RED_SIZE, 1,
93         GLX_GREEN_SIZE, 1,
94         GLX_BLUE_SIZE, 1,
95         GLX_ALPHA_SIZE, 1,
96         0
97     };
98
99     Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
100     XUniquePtr<XVisualInfo> visualInfo(glXChooseVisual(display, DefaultScreen(display), visualAttributes));
101     if (!visualInfo)
102         return nullptr;
103
104     XUniqueGLXContext context(glXCreateContext(display, visualInfo.get(), sharingContext, GL_TRUE));
105     if (!context)
106         return nullptr;
107
108     XUniquePixmap pixmap(XCreatePixmap(display, DefaultRootWindow(display), 1, 1, visualInfo->depth));
109     if (!pixmap)
110         return nullptr;
111
112     XUniqueGLXPixmap glxPixmap(glXCreateGLXPixmap(display, visualInfo.get(), pixmap.get()));
113     if (!glxPixmap)
114         return nullptr;
115
116     return std::make_unique<GLContextGLX>(WTFMove(context), WTFMove(pixmap), WTFMove(glxPixmap));
117 }
118
119 std::unique_ptr<GLContextGLX> GLContextGLX::createContext(XID window, GLContext* sharingContext)
120 {
121     static bool initialized = false;
122     static bool success = true;
123     if (!initialized) {
124         success = initializeOpenGLShims();
125         initialized = true;
126     }
127     if (!success)
128         return nullptr;
129
130     GLXContext glxSharingContext = sharingContext ? static_cast<GLContextGLX*>(sharingContext)->m_context.get() : nullptr;
131     auto context = window ? createWindowContext(window, sharingContext) : nullptr;
132     if (!context)
133         context = createPbufferContext(glxSharingContext);
134     if (!context)
135         context = createPixmapContext(glxSharingContext);
136     if (!context)
137         return nullptr;
138
139     return WTFMove(context);
140 }
141
142 GLContextGLX::GLContextGLX(XUniqueGLXContext&& context, XID window)
143     : m_context(WTFMove(context))
144     , m_window(window)
145 {
146 }
147
148 GLContextGLX::GLContextGLX(XUniqueGLXContext&& context, XUniqueGLXPbuffer&& pbuffer)
149     : m_context(WTFMove(context))
150     , m_pbuffer(WTFMove(pbuffer))
151 {
152 }
153
154 GLContextGLX::GLContextGLX(XUniqueGLXContext&& context, XUniquePixmap&& pixmap, XUniqueGLXPixmap&& glxPixmap)
155     : m_context(WTFMove(context))
156     , m_pixmap(WTFMove(pixmap))
157     , m_glxPixmap(WTFMove(glxPixmap))
158 {
159 }
160
161 GLContextGLX::~GLContextGLX()
162 {
163     if (m_cairoDevice)
164         cairo_device_destroy(m_cairoDevice);
165
166     if (m_context) {
167         // This may be necessary to prevent crashes with NVidia's closed source drivers. Originally
168         // from Mozilla's 3D canvas implementation at: http://bitbucket.org/ilmari/canvas3d/
169         Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
170         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
171         glXMakeCurrent(display, None, None);
172     }
173 }
174
175 bool GLContextGLX::canRenderToDefaultFramebuffer()
176 {
177     return m_window;
178 }
179
180 IntSize GLContextGLX::defaultFrameBufferSize()
181 {
182     if (!canRenderToDefaultFramebuffer() || !m_window)
183         return IntSize();
184
185     int x, y;
186     Window rootWindow;
187     unsigned int width, height, borderWidth, depth;
188     Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
189     if (!XGetGeometry(display, m_window, &rootWindow, &x, &y, &width, &height, &borderWidth, &depth))
190         return IntSize();
191
192     return IntSize(width, height);
193 }
194
195 bool GLContextGLX::makeContextCurrent()
196 {
197     ASSERT(m_context && (m_window || m_pbuffer || m_glxPixmap));
198
199     GLContext::makeContextCurrent();
200     if (glXGetCurrentContext() == m_context.get())
201         return true;
202
203     Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
204     if (m_window)
205         return glXMakeCurrent(display, m_window, m_context.get());
206
207     if (m_pbuffer)
208         return glXMakeCurrent(display, m_pbuffer.get(), m_context.get());
209
210     return ::glXMakeCurrent(display, m_glxPixmap.get(), m_context.get());
211 }
212
213 void GLContextGLX::swapBuffers()
214 {
215     if (m_window)
216         glXSwapBuffers(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native(), m_window);
217 }
218
219 void GLContextGLX::waitNative()
220 {
221     glXWaitX();
222 }
223
224 cairo_device_t* GLContextGLX::cairoDevice()
225 {
226     if (m_cairoDevice)
227         return m_cairoDevice;
228
229 #if ENABLE(ACCELERATED_2D_CANVAS) && CAIRO_HAS_GLX_FUNCTIONS
230     m_cairoDevice = cairo_glx_device_create(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native(), m_context.get());
231 #endif
232
233     return m_cairoDevice;
234 }
235
236 #if ENABLE(GRAPHICS_CONTEXT_3D)
237 PlatformGraphicsContext3D GLContextGLX::platformContext()
238 {
239     return m_context.get();
240 }
241 #endif
242
243 } // namespace WebCore
244
245 #endif // USE(GLX)