OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // This file defines utility functions for X11 (Linux only). This code has been |
| 6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support |
| 7 // remains woefully incomplete. |
| 8 |
| 9 #include "chrome/common/x11_util.h" |
| 10 #include "chrome/common/x11_util_internal.h" |
| 11 |
| 12 #include <string.h> |
| 13 |
| 14 #include <gdk/gdk.h> |
| 15 #include <gdk/gdkx.h> |
| 16 #include <gtk/gtk.h> |
| 17 |
| 18 #include <sys/ipc.h> |
| 19 #include <sys/shm.h> |
| 20 |
| 21 #include "base/logging.h" |
| 22 #include "base/gfx/size.h" |
| 23 |
| 24 namespace x11_util { |
| 25 |
| 26 Display* GetXDisplay() { |
| 27 static Display* display = NULL; |
| 28 |
| 29 if (!display) |
| 30 display = gdk_x11_get_default_xdisplay(); |
| 31 |
| 32 return display; |
| 33 } |
| 34 |
| 35 static bool DoQuerySharedMemorySupport(Display* dpy) { |
| 36 int dummy; |
| 37 Bool pixmaps_supported; |
| 38 // Query the server's support for shared memory |
| 39 if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported)) |
| 40 return false; |
| 41 // If the server doesn't support shared memory, give up. (Note that if |
| 42 // |shared_pixmaps| is true, it just means that the server /supports/ shared |
| 43 // memory, not that it will work on this connection.) |
| 44 if (!pixmaps_supported) |
| 45 return false; |
| 46 |
| 47 // Next we probe to see if shared memory will really work |
| 48 int shmkey = shmget(IPC_PRIVATE, 1, 0666); |
| 49 if (shmkey == -1) |
| 50 return false; |
| 51 void* address = shmat(shmkey, NULL, 0); |
| 52 // Mark the shared memory region for deletion |
| 53 shmctl(shmkey, IPC_RMID, NULL); |
| 54 |
| 55 XShmSegmentInfo shminfo; |
| 56 memset(&shminfo, 0, sizeof(shminfo)); |
| 57 shminfo.shmid = shmkey; |
| 58 |
| 59 gdk_error_trap_push(); |
| 60 bool result = XShmAttach(dpy, &shminfo); |
| 61 XSync(dpy, False); |
| 62 if (gdk_error_trap_pop()) |
| 63 result = false; |
| 64 shmdt(address); |
| 65 if (!result) |
| 66 return false; |
| 67 |
| 68 XShmDetach(dpy, &shminfo); |
| 69 return true; |
| 70 } |
| 71 |
| 72 bool QuerySharedMemorySupport(Display* dpy) { |
| 73 static bool shared_memory_support = false; |
| 74 static bool shared_memory_support_cached = false; |
| 75 |
| 76 if (shared_memory_support_cached) |
| 77 return shared_memory_support; |
| 78 |
| 79 shared_memory_support = DoQuerySharedMemorySupport(dpy); |
| 80 shared_memory_support_cached = true; |
| 81 |
| 82 return shared_memory_support; |
| 83 } |
| 84 |
| 85 XID GetX11WindowFromGtkWidget(GtkWidget* widget) { |
| 86 return GDK_WINDOW_XID(widget->window); |
| 87 } |
| 88 |
| 89 void* GetVisualFromGtkWidget(GtkWidget* widget) { |
| 90 return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); |
| 91 } |
| 92 |
| 93 XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { |
| 94 static XRenderPictFormat* pictformat = NULL; |
| 95 if (pictformat) |
| 96 return pictformat; |
| 97 |
| 98 int dummy; |
| 99 if (!XRenderQueryExtension(dpy, &dummy, &dummy)) |
| 100 CHECK(false) << "XRENDER not supported on display"; |
| 101 |
| 102 pictformat = XRenderFindVisualFormat(dpy, visual); |
| 103 CHECK(pictformat) << "XRENDER does not support default visual"; |
| 104 |
| 105 return pictformat; |
| 106 } |
| 107 |
| 108 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { |
| 109 static XRenderPictFormat* pictformat = NULL; |
| 110 if (pictformat) |
| 111 return pictformat; |
| 112 |
| 113 // First look for a 32-bit format which ignores the alpha value |
| 114 XRenderPictFormat templ; |
| 115 templ.depth = 32; |
| 116 templ.type = PictTypeDirect; |
| 117 templ.direct.red = 0; |
| 118 templ.direct.green = 8; |
| 119 templ.direct.blue = 16; |
| 120 templ.direct.redMask = 0xff; |
| 121 templ.direct.greenMask = 0xff; |
| 122 templ.direct.blueMask = 0xff; |
| 123 templ.direct.alphaMask = 0; |
| 124 |
| 125 static const unsigned long kMask = |
| 126 PictFormatType | PictFormatDepth | |
| 127 PictFormatRed | PictFormatRedMask | |
| 128 PictFormatGreen | PictFormatGreenMask | |
| 129 PictFormatBlue | PictFormatBlueMask | |
| 130 PictFormatAlphaMask; |
| 131 |
| 132 pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */); |
| 133 CHECK(pictformat) << "XRENDER doesn't not support a Skia compatable format"; |
| 134 // TODO(agl): fallback to a picture format with an alpha channel |
| 135 |
| 136 return pictformat; |
| 137 } |
| 138 |
| 139 XID AttachSharedMemory(Display* display, int shared_memory_key) { |
| 140 DCHECK(QuerySharedMemorySupport(display)); |
| 141 |
| 142 XShmSegmentInfo shminfo; |
| 143 memset(&shminfo, 0, sizeof(shminfo)); |
| 144 shminfo.shmid = shared_memory_key; |
| 145 |
| 146 // This function is only called if QuerySharedMemorySupport returned true. In |
| 147 // which case we've already succeeded in having the X server attach to one of |
| 148 // our shared memory segments. |
| 149 if (!XShmAttach(display, &shminfo)) |
| 150 NOTREACHED(); |
| 151 |
| 152 return shminfo.shmseg; |
| 153 } |
| 154 |
| 155 void DetachSharedMemory(Display* display, XID shmseg) { |
| 156 DCHECK(QuerySharedMemorySupport(display)); |
| 157 |
| 158 XShmSegmentInfo shminfo; |
| 159 memset(&shminfo, 0, sizeof(shminfo)); |
| 160 shminfo.shmseg = shmseg; |
| 161 |
| 162 if (!XShmDetach(display, &shminfo)) |
| 163 NOTREACHED(); |
| 164 } |
| 165 |
| 166 XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) { |
| 167 XID picture = XRenderCreatePicture( |
| 168 display, pixmap, GetRenderARGB32Format(display), 0, NULL); |
| 169 |
| 170 return picture; |
| 171 } |
| 172 |
| 173 void FreePicture(Display* display, XID picture) { |
| 174 XRenderFreePicture(display, picture); |
| 175 } |
| 176 |
| 177 void FreePixmap(Display* display, XID pixmap) { |
| 178 XFreePixmap(display, pixmap); |
| 179 } |
| 180 |
| 181 } // namespace x11_util |
OLD | NEW |