summaryrefslogtreecommitdiffstats
path: root/chrome/common/x11_util.cc
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-25 20:34:04 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-25 20:34:04 +0000
commit214559a75e57b79101f3c70b08d1aa98102c520a (patch)
treed065c0e83fb5328b4e123928cd99c310334b78d6 /chrome/common/x11_util.cc
parentc98fe6fa60b3262364158809ca0d462f1009709f (diff)
downloadchromium_src-214559a75e57b79101f3c70b08d1aa98102c520a.zip
chromium_src-214559a75e57b79101f3c70b08d1aa98102c520a.tar.gz
chromium_src-214559a75e57b79101f3c70b08d1aa98102c520a.tar.bz2
Linux: server side backing stores
This converts Linux to using server-side backing stores. Rather than keeping a backing store in heap memory in the browser, we create a pixmap in the X server. This means that expose messages don't require us to transport any images to the X server, we can just direct it to paint from the pixmap. Also, scrolling can be performed server side also. This greatly improves performance over remote X. Also, shared memory transport to the X server is implemented. Shared memory segments can be created in the renderer and mapped directly into the X server. Review URL: http://codereview.chromium.org/27147 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10369 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/x11_util.cc')
-rw-r--r--chrome/common/x11_util.cc181
1 files changed, 181 insertions, 0 deletions
diff --git a/chrome/common/x11_util.cc b/chrome/common/x11_util.cc
new file mode 100644
index 0000000..5a23878
--- /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