| 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
|
|
|