2 * Copyright (C) 2013 Intel Corporation. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "X11Helper.h"
31 // Used for handling XError.
32 static bool validOperation = true;
33 static int handleXPixmapCreationError(Display*, XErrorEvent* event)
35 if (event->error_code == BadMatch || event->error_code == BadWindow || event->error_code == BadAlloc) {
36 validOperation = false;
38 switch (event->error_code) {
40 LOG_ERROR("BadMatch.");
43 LOG_ERROR("BadWindow.");
46 LOG_ERROR("BadAlloc.");
56 struct DisplayConnection {
59 m_display = XOpenDisplay(0);
62 LOG_ERROR("Failed to make connection with X");
67 XCloseDisplay(m_display);
70 Display* display() { return m_display; }
75 struct OffScreenRootWindow {
80 Display* dpy = X11Helper::nativeDisplay();
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);
92 LOG_ERROR("Failed to create offscreen root window.");
95 ~OffScreenRootWindow()
97 if (!X11Helper::nativeDisplay())
101 XUnmapWindow(X11Helper::nativeDisplay(), m_window);
102 XDestroyWindow(X11Helper::nativeDisplay(), m_window);
116 ScopedXPixmapCreationErrorHandler::ScopedXPixmapCreationErrorHandler()
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);
123 ScopedXPixmapCreationErrorHandler::~ScopedXPixmapCreationErrorHandler()
125 // Restore the original handler.
126 XSetErrorHandler(m_previousErrorHandler);
129 bool ScopedXPixmapCreationErrorHandler::isValidOperation() const
131 validOperation = true;
132 // XSync is needed to catch possible errors as they are generated asynchronously.
133 XSync(X11Helper::nativeDisplay(), false);
134 return validOperation;
137 void X11Helper::resizeWindow(const IntRect& newRect, const uint32_t windowId)
139 XResizeWindow(nativeDisplay(), windowId, newRect.width(), newRect.height());
140 XFlush(nativeDisplay());
143 void X11Helper::createPixmap(Pixmap* handleId, const XVisualInfo& visualInfo, const IntSize& size)
145 Display* display = nativeDisplay();
149 if (!visualInfo.visual) {
150 LOG_ERROR("Failed to find valid XVisual.");
154 Window xWindow = offscreenRootWindow();
156 LOG_ERROR("Failed to create offscreen root window.");
160 Pixmap tempHandleId = XCreatePixmap(display, xWindow, size.width(), size.height(), visualInfo.depth);
163 LOG_ERROR("Failed to create offscreen pixmap.");
167 *handleId = tempHandleId;
168 XSync(X11Helper::nativeDisplay(), false);
171 void X11Helper::destroyPixmap(const uint32_t pixmapId)
176 Display* display = nativeDisplay();
180 XFreePixmap(display, pixmapId);
181 XSync(X11Helper::nativeDisplay(), false);
184 void X11Helper::createOffScreenWindow(uint32_t* handleId, const XVisualInfo& visInfo, const IntSize& size)
186 #if USE(GRAPHICS_SURFACE)
187 Display* display = nativeDisplay();
191 if (!visInfo.visual) {
192 LOG_ERROR("Failed to find valid XVisual.");
196 Window xWindow = offscreenRootWindow();
200 Colormap cmap = XCreateColormap(display, xWindow, visInfo.visual, AllocNone);
201 XSetWindowAttributes attribute;
202 attribute.background_pixel = WhitePixel(display, 0);
203 attribute.border_pixel = BlackPixel(display, 0);
204 attribute.colormap = cmap;
205 attribute.event_mask = ResizeRedirectMask;
206 uint32_t tempHandleId = XCreateWindow(display, xWindow, 0, 0, size.width(), size.height(), 0, visInfo.depth, InputOutput, visInfo.visual, CWBackPixel | CWBorderPixel | CWColormap, &attribute);
209 LOG_ERROR("Failed to create offscreen window.");
213 XSetWindowBackgroundPixmap(display, tempHandleId, 0);
214 XCompositeRedirectWindow(display, tempHandleId, CompositeRedirectManual);
215 XMapWindow(display, tempHandleId);
216 *handleId = tempHandleId;
218 UNUSED_PARAM(handleId);
219 UNUSED_PARAM(visInfo);
225 void X11Helper::createOffScreenWindow(uint32_t* handleId, const EGLint id, bool supportsAlpha, const IntSize& size)
227 #if USE(GRAPHICS_SURFACE)
228 VisualID visualId = static_cast<VisualID>(id);
233 // EGL has suggested a visual id, so get the rest of the visual info for that id.
234 XVisualInfo visualInfoTemplate;
235 memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
236 visualInfoTemplate.visualid = visualId;
237 int matchingCount = 0;
238 OwnPtrX11<XVisualInfo> matchingVisuals(XGetVisualInfo(nativeDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount));
239 XVisualInfo* foundVisual = 0;
241 if (matchingVisuals) {
242 for (int i = 0; i< matchingCount; i++) {
243 XVisualInfo* temp = &matchingVisuals[i];
245 if (isXRenderExtensionSupported()) {
246 XRenderPictFormat* format = XRenderFindVisualFormat(nativeDisplay(), temp->visual);
250 if (temp->depth == 32 && format->direct.alphaMask > 0)
252 } else if (!format->direct.alphaMask)
260 int matchingdepth = supportsAlpha ? 32 : 24;
262 if (temp->depth == matchingdepth) {
269 createOffScreenWindow(handleId, *foundVisual, size);
272 UNUSED_PARAM(handleId);
279 void X11Helper::destroyWindow(const uint32_t windowId)
284 Display* display = nativeDisplay();
288 XDestroyWindow(display, windowId);
291 bool X11Helper::isXRenderExtensionSupported()
293 static bool queryDone = false;
294 static bool supportsXRenderExtension = false;
298 #if USE(GRAPHICS_SURFACE)
299 Display* display = nativeDisplay();
302 int eventBasep, errorBasep;
303 supportsXRenderExtension = XRenderQueryExtension(display, &eventBasep, &errorBasep);
308 return supportsXRenderExtension;
311 Display* X11Helper::nativeDisplay()
313 // Display connection will only be broken at program shutdown.
314 static DisplayConnection displayConnection;
315 return displayConnection.display();
318 Window X11Helper::offscreenRootWindow()
320 static OffScreenRootWindow offscreenWindow;
321 return offscreenWindow.rootWindow();