[EFL][Qt][WebGL] Share the common code between GraphicsSurfaceGLX and X11WindowResources.
[WebKit-https.git] / Source / WebCore / platform / graphics / surfaces / glx / X11Helper.cpp
1 /*
2  * Copyright (C) 2013 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 "X11Helper.h"
28
29 namespace WebCore {
30
31 // Used for handling XError.
32 static bool validOperation = true;
33 static int handleXPixmapCreationError(Display*, XErrorEvent* event)
34 {
35     if (event->error_code == BadMatch || event->error_code == BadWindow || event->error_code == BadAlloc) {
36         validOperation = false;
37
38         switch (event->error_code) {
39         case BadMatch:
40             LOG_ERROR("BadMatch.");
41             break;
42         case BadWindow:
43             LOG_ERROR("BadWindow.");
44             break;
45         case BadAlloc:
46             LOG_ERROR("BadAlloc.");
47             break;
48         default:
49             break;
50         }
51     }
52
53     return 0;
54 }
55
56 struct DisplayConnection {
57     DisplayConnection()
58     {
59         m_display = XOpenDisplay(0);
60
61         if (!m_display)
62             LOG_ERROR("Failed to make connection with X");
63     }
64
65     ~DisplayConnection()
66     {
67         XCloseDisplay(m_display);
68     }
69
70     Display* display() { return m_display; }
71 private:
72     Display* m_display;
73 };
74
75 struct OffScreenRootWindow {
76
77     OffScreenRootWindow()
78     {
79         m_window = 0;
80         Display* dpy = X11Helper::nativeDisplay();
81         if (!dpy)
82             return;
83
84         XSetWindowAttributes attributes;
85         attributes.override_redirect = true;
86         m_window = XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy), -1, -1, 1, 1, 0, BlackPixel(dpy, 0), WhitePixel(dpy, 0));
87         // From http://tronche.com/gui/x/xlib/window/attributes/
88         XChangeWindowAttributes(dpy, m_window, CWOverrideRedirect, &attributes);
89         XMapWindow(dpy, m_window);
90
91         if (!m_window)
92             LOG_ERROR("Failed to create offscreen root window.");
93     }
94
95     ~OffScreenRootWindow()
96     {
97         if (!X11Helper::nativeDisplay())
98             return;
99
100         if (m_window) {
101             XUnmapWindow(X11Helper::nativeDisplay(), m_window);
102             XDestroyWindow(X11Helper::nativeDisplay(), m_window);
103             m_window = 0;
104         }
105     }
106
107     Window rootWindow()
108     {
109         return m_window;
110     }
111
112 private:
113     Window m_window;
114 };
115
116 ScopedXPixmapCreationErrorHandler::ScopedXPixmapCreationErrorHandler()
117 {
118     // XSync must be called to ensure that current errors are handled by the original handler.
119     XSync(X11Helper::nativeDisplay(), false);
120     m_previousErrorHandler = XSetErrorHandler(handleXPixmapCreationError);
121 }
122
123 ScopedXPixmapCreationErrorHandler::~ScopedXPixmapCreationErrorHandler()
124 {
125     // Restore the original handler.
126     XSetErrorHandler(m_previousErrorHandler);
127 }
128
129 bool ScopedXPixmapCreationErrorHandler::isValidOperation() const
130 {
131     validOperation = true;
132     // XSync is needed to catch possible errors as they are generated asynchronously.
133     XSync(X11Helper::nativeDisplay(), false);
134     return validOperation;
135 }
136
137 void X11Helper::resizeWindow(const IntRect& newRect, const uint32_t windowId)
138 {
139     XResizeWindow(nativeDisplay(), windowId, newRect.width(), newRect.height());
140     XFlush(nativeDisplay());
141 }
142
143 void X11Helper::createOffScreenWindow(uint32_t* handleId, const XVisualInfo& visInfo, const IntSize& size)
144 {
145 #if USE(GRAPHICS_SURFACE)
146     Display* display = nativeDisplay();
147     if (!display)
148         return;
149
150     if (!visInfo.visual) {
151         LOG_ERROR("Failed to find valid XVisual.");
152         return;
153     }
154
155     Window xWindow = offscreenRootWindow();
156     if (!xWindow)
157         return;
158
159     Colormap cmap = XCreateColormap(display, xWindow, visInfo.visual, AllocNone);
160     XSetWindowAttributes attribute;
161     attribute.background_pixel = WhitePixel(display, 0);
162     attribute.border_pixel = BlackPixel(display, 0);
163     attribute.colormap = cmap;
164     attribute.event_mask = ResizeRedirectMask;
165     uint32_t tempHandleId;
166     tempHandleId = XCreateWindow(display, xWindow, 0, 0, size.width(), size.height(), 0, visInfo.depth, InputOutput, visInfo.visual, CWBackPixel | CWBorderPixel | CWColormap, &attribute);
167
168     if (!tempHandleId) {
169         LOG_ERROR("Failed to create offscreen window.");
170         return;
171     }
172
173     XSetWindowBackgroundPixmap(display, tempHandleId, 0);
174     XCompositeRedirectWindow(display, tempHandleId, CompositeRedirectManual);
175     XMapWindow(display, tempHandleId);
176     *handleId = tempHandleId;
177 #else
178     UNUSED_PARAM(handleId);
179     UNUSED_PARAM(visInfo);
180     UNUSED_PARAM(size);
181 #endif
182 }
183
184 #if USE(EGL)
185 void X11Helper::createOffScreenWindow(uint32_t* handleId, const EGLint id, const IntSize& size)
186 {
187     VisualID visualId = static_cast<VisualID>(id);
188
189     if (!visualId)
190         return;
191
192     // EGL has suggested a visual id, so get the rest of the visual info for that id.
193     XVisualInfo visualInfoTemplate;
194     memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
195     visualInfoTemplate.visualid = visualId;
196     int matchingCount = 0;
197     OwnPtrX11<XVisualInfo> matchingVisuals(XGetVisualInfo(nativeDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount));
198     XVisualInfo* foundVisual = 0;
199
200     if (matchingVisuals) {
201         for (int i = 0; i< matchingCount; i++) {
202             XVisualInfo* temp = &matchingVisuals[i];
203
204             if (isXRenderExtensionSupported()) {
205                 XRenderPictFormat* format = XRenderFindVisualFormat(nativeDisplay(), temp->visual);
206                 if (format && format->direct.alphaMask > 0) {
207                     foundVisual = temp;
208                     break;
209                 }
210             }
211
212             if (temp->depth == 32) {
213                 foundVisual = temp;
214                 break;
215             }
216         }
217
218         if (foundVisual)
219             createOffScreenWindow(handleId, *foundVisual, size);
220     }
221 }
222 #endif
223
224 void X11Helper::destroyWindow(const uint32_t windowId)
225 {
226     if (!windowId)
227         return;
228
229     Display* display = nativeDisplay();
230     if (!display)
231         return;
232
233     XDestroyWindow(display, windowId);
234 }
235
236 bool X11Helper::isXRenderExtensionSupported()
237 {
238     static bool queryDone = false;
239     static bool supportsXRenderExtension = false;
240
241     if (!queryDone) {
242         queryDone = true;
243 #if USE(GRAPHICS_SURFACE)
244         Display* display = nativeDisplay();
245
246         if (display) {
247             int eventBasep, errorBasep;
248             supportsXRenderExtension = XRenderQueryExtension(display, &eventBasep, &errorBasep);
249         }
250 #endif
251     }
252
253     return supportsXRenderExtension;
254 }
255
256 Display* X11Helper::nativeDisplay()
257 {
258     // Display connection will only be broken at program shutdown.
259     static DisplayConnection displayConnection;
260     return displayConnection.display();
261 }
262
263 Window X11Helper::offscreenRootWindow()
264 {
265     static OffScreenRootWindow offscreenWindow;
266     return offscreenWindow.rootWindow();
267 }
268
269 }