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::createOffScreenWindow(uint32_t* handleId, const XVisualInfo& visInfo, const IntSize& size)
145 #if USE(GRAPHICS_SURFACE)
146 Display* display = nativeDisplay();
150 if (!visInfo.visual) {
151 LOG_ERROR("Failed to find valid XVisual.");
155 Window xWindow = offscreenRootWindow();
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);
169 LOG_ERROR("Failed to create offscreen window.");
173 XSetWindowBackgroundPixmap(display, tempHandleId, 0);
174 XCompositeRedirectWindow(display, tempHandleId, CompositeRedirectManual);
175 XMapWindow(display, tempHandleId);
176 *handleId = tempHandleId;
178 UNUSED_PARAM(handleId);
179 UNUSED_PARAM(visInfo);
185 void X11Helper::createOffScreenWindow(uint32_t* handleId, const EGLint id, const IntSize& size)
187 VisualID visualId = static_cast<VisualID>(id);
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;
200 if (matchingVisuals) {
201 for (int i = 0; i< matchingCount; i++) {
202 XVisualInfo* temp = &matchingVisuals[i];
204 if (isXRenderExtensionSupported()) {
205 XRenderPictFormat* format = XRenderFindVisualFormat(nativeDisplay(), temp->visual);
206 if (format && format->direct.alphaMask > 0) {
212 if (temp->depth == 32) {
219 createOffScreenWindow(handleId, *foundVisual, size);
224 void X11Helper::destroyWindow(const uint32_t windowId)
229 Display* display = nativeDisplay();
233 XDestroyWindow(display, windowId);
236 bool X11Helper::isXRenderExtensionSupported()
238 static bool queryDone = false;
239 static bool supportsXRenderExtension = false;
243 #if USE(GRAPHICS_SURFACE)
244 Display* display = nativeDisplay();
247 int eventBasep, errorBasep;
248 supportsXRenderExtension = XRenderQueryExtension(display, &eventBasep, &errorBasep);
253 return supportsXRenderExtension;
256 Display* X11Helper::nativeDisplay()
258 // Display connection will only be broken at program shutdown.
259 static DisplayConnection displayConnection;
260 return displayConnection.display();
263 Window X11Helper::offscreenRootWindow()
265 static OffScreenRootWindow offscreenWindow;
266 return offscreenWindow.rootWindow();