diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-25 20:34:04 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-25 20:34:04 +0000 |
commit | 214559a75e57b79101f3c70b08d1aa98102c520a (patch) | |
tree | d065c0e83fb5328b4e123928cd99c310334b78d6 /chrome/common/x11_util.cc | |
parent | c98fe6fa60b3262364158809ca0d462f1009709f (diff) | |
download | chromium_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.cc | 181 |
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 |