Index: chrome/common/x11_util.cc |
diff --git a/chrome/common/x11_util.cc b/chrome/common/x11_util.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5a238782c5464faf09872fc644c2b590acabcf23 |
--- /dev/null |
+++ b/chrome/common/x11_util.cc |
@@ -0,0 +1,181 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// This file defines utility functions for X11 (Linux only). This code has been |
+// ported from XCB since we can't use XCB on Ubuntu while its 32-bit support |
+// remains woefully incomplete. |
+ |
+#include "chrome/common/x11_util.h" |
+#include "chrome/common/x11_util_internal.h" |
+ |
+#include <string.h> |
+ |
+#include <gdk/gdk.h> |
+#include <gdk/gdkx.h> |
+#include <gtk/gtk.h> |
+ |
+#include <sys/ipc.h> |
+#include <sys/shm.h> |
+ |
+#include "base/logging.h" |
+#include "base/gfx/size.h" |
+ |
+namespace x11_util { |
+ |
+Display* GetXDisplay() { |
+ static Display* display = NULL; |
+ |
+ if (!display) |
+ display = gdk_x11_get_default_xdisplay(); |
+ |
+ return display; |
+} |
+ |
+static bool DoQuerySharedMemorySupport(Display* dpy) { |
+ int dummy; |
+ Bool pixmaps_supported; |
+ // Query the server's support for shared memory |
+ if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported)) |
+ return false; |
+ // If the server doesn't support shared memory, give up. (Note that if |
+ // |shared_pixmaps| is true, it just means that the server /supports/ shared |
+ // memory, not that it will work on this connection.) |
+ if (!pixmaps_supported) |
+ return false; |
+ |
+ // Next we probe to see if shared memory will really work |
+ int shmkey = shmget(IPC_PRIVATE, 1, 0666); |
+ if (shmkey == -1) |
+ return false; |
+ void* address = shmat(shmkey, NULL, 0); |
+ // Mark the shared memory region for deletion |
+ shmctl(shmkey, IPC_RMID, NULL); |
+ |
+ XShmSegmentInfo shminfo; |
+ memset(&shminfo, 0, sizeof(shminfo)); |
+ shminfo.shmid = shmkey; |
+ |
+ gdk_error_trap_push(); |
+ bool result = XShmAttach(dpy, &shminfo); |
+ XSync(dpy, False); |
+ if (gdk_error_trap_pop()) |
+ result = false; |
+ shmdt(address); |
+ if (!result) |
+ return false; |
+ |
+ XShmDetach(dpy, &shminfo); |
+ return true; |
+} |
+ |
+bool QuerySharedMemorySupport(Display* dpy) { |
+ static bool shared_memory_support = false; |
+ static bool shared_memory_support_cached = false; |
+ |
+ if (shared_memory_support_cached) |
+ return shared_memory_support; |
+ |
+ shared_memory_support = DoQuerySharedMemorySupport(dpy); |
+ shared_memory_support_cached = true; |
+ |
+ return shared_memory_support; |
+} |
+ |
+XID GetX11WindowFromGtkWidget(GtkWidget* widget) { |
+ return GDK_WINDOW_XID(widget->window); |
+} |
+ |
+void* GetVisualFromGtkWidget(GtkWidget* widget) { |
+ return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); |
+} |
+ |
+XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { |
+ static XRenderPictFormat* pictformat = NULL; |
+ if (pictformat) |
+ return pictformat; |
+ |
+ int dummy; |
+ if (!XRenderQueryExtension(dpy, &dummy, &dummy)) |
+ CHECK(false) << "XRENDER not supported on display"; |
+ |
+ pictformat = XRenderFindVisualFormat(dpy, visual); |
+ CHECK(pictformat) << "XRENDER does not support default visual"; |
+ |
+ return pictformat; |
+} |
+ |
+XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { |
+ static XRenderPictFormat* pictformat = NULL; |
+ if (pictformat) |
+ return pictformat; |
+ |
+ // First look for a 32-bit format which ignores the alpha value |
+ XRenderPictFormat templ; |
+ templ.depth = 32; |
+ templ.type = PictTypeDirect; |
+ templ.direct.red = 0; |
+ templ.direct.green = 8; |
+ templ.direct.blue = 16; |
+ templ.direct.redMask = 0xff; |
+ templ.direct.greenMask = 0xff; |
+ templ.direct.blueMask = 0xff; |
+ templ.direct.alphaMask = 0; |
+ |
+ static const unsigned long kMask = |
+ PictFormatType | PictFormatDepth | |
+ PictFormatRed | PictFormatRedMask | |
+ PictFormatGreen | PictFormatGreenMask | |
+ PictFormatBlue | PictFormatBlueMask | |
+ PictFormatAlphaMask; |
+ |
+ pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */); |
+ CHECK(pictformat) << "XRENDER doesn't not support a Skia compatable format"; |
+ // TODO(agl): fallback to a picture format with an alpha channel |
+ |
+ return pictformat; |
+} |
+ |
+XID AttachSharedMemory(Display* display, int shared_memory_key) { |
+ DCHECK(QuerySharedMemorySupport(display)); |
+ |
+ XShmSegmentInfo shminfo; |
+ memset(&shminfo, 0, sizeof(shminfo)); |
+ shminfo.shmid = shared_memory_key; |
+ |
+ // This function is only called if QuerySharedMemorySupport returned true. In |
+ // which case we've already succeeded in having the X server attach to one of |
+ // our shared memory segments. |
+ if (!XShmAttach(display, &shminfo)) |
+ NOTREACHED(); |
+ |
+ return shminfo.shmseg; |
+} |
+ |
+void DetachSharedMemory(Display* display, XID shmseg) { |
+ DCHECK(QuerySharedMemorySupport(display)); |
+ |
+ XShmSegmentInfo shminfo; |
+ memset(&shminfo, 0, sizeof(shminfo)); |
+ shminfo.shmseg = shmseg; |
+ |
+ if (!XShmDetach(display, &shminfo)) |
+ NOTREACHED(); |
+} |
+ |
+XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) { |
+ XID picture = XRenderCreatePicture( |
+ display, pixmap, GetRenderARGB32Format(display), 0, NULL); |
+ |
+ return picture; |
+} |
+ |
+void FreePicture(Display* display, XID picture) { |
+ XRenderFreePicture(display, picture); |
+} |
+ |
+void FreePixmap(Display* display, XID pixmap) { |
+ XFreePixmap(display, pixmap); |
+} |
+ |
+} // namespace x11_util |