OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/x_server_pixel_buffer.h" | 5 #include "remoting/host/x_server_pixel_buffer.h" |
6 | 6 |
7 #include <gdk/gdk.h> | |
8 #include <sys/shm.h> | 7 #include <sys/shm.h> |
9 | 8 |
10 #include "base/logging.h" | 9 #include "base/logging.h" |
11 | 10 |
| 11 #if defined(TOOLKIT_GTK) |
| 12 #include <gdk/gdk.h> |
| 13 #else // !defined(TOOLKIT_GTK) |
| 14 #include <X11/Xlib.h> |
| 15 #endif // !defined(TOOLKIT_GTK) |
| 16 |
| 17 namespace { |
| 18 |
| 19 #if defined(TOOLKIT_GTK) |
| 20 // GDK sets error handler for Xlib errors, so we need to use it to |
| 21 // trap X errors when this code is compiled with GTK. |
| 22 void EnableXServerErrorTrap() { |
| 23 gdk_error_trap_push(); |
| 24 } |
| 25 |
| 26 int GetLastXServerError() { |
| 27 return gdk_error_trap_pop(); |
| 28 } |
| 29 |
| 30 #else // !defined(TOOLKIT_GTK) |
| 31 |
| 32 static bool g_xserver_error_trap_enabled = false; |
| 33 static int g_last_xserver_error_code = 0; |
| 34 |
| 35 int XServerErrorHandler(Display* display, XErrorEvent* error_event) { |
| 36 DCHECK(g_xserver_error_trap_enabled); |
| 37 g_last_xserver_error_code = error_event->error_code; |
| 38 return 0; |
| 39 } |
| 40 |
| 41 void EnableXServerErrorTrap() { |
| 42 DCHECK(!g_xserver_error_trap_enabled); |
| 43 XSetErrorHandler(&XServerErrorHandler); |
| 44 g_xserver_error_trap_enabled = true; |
| 45 g_last_xserver_error_code = 0; |
| 46 } |
| 47 |
| 48 int GetLastXServerError() { |
| 49 DCHECK(g_xserver_error_trap_enabled); |
| 50 XSetErrorHandler(NULL); |
| 51 g_xserver_error_trap_enabled = false; |
| 52 return g_last_xserver_error_code; |
| 53 } |
| 54 |
| 55 #endif // !defined(TOOLKIT_GTK) |
| 56 |
| 57 } // namespace |
| 58 |
12 namespace remoting { | 59 namespace remoting { |
13 | 60 |
14 XServerPixelBuffer::XServerPixelBuffer() | 61 XServerPixelBuffer::XServerPixelBuffer() |
15 : display_(NULL), root_window_(0), x_image_(NULL), | 62 : display_(NULL), root_window_(0), x_image_(NULL), |
16 shm_segment_info_(NULL), shm_pixmap_(0), shm_gc_(NULL) { | 63 shm_segment_info_(NULL), shm_pixmap_(0), shm_gc_(NULL) { |
17 } | 64 } |
18 | 65 |
19 XServerPixelBuffer::~XServerPixelBuffer() { | 66 XServerPixelBuffer::~XServerPixelBuffer() { |
20 Release(); | 67 Release(); |
21 } | 68 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 x_image_ = XShmCreateImage(display_, default_visual, default_depth, ZPixmap, | 119 x_image_ = XShmCreateImage(display_, default_visual, default_depth, ZPixmap, |
73 0, shm_segment_info_, width, height); | 120 0, shm_segment_info_, width, height); |
74 if (x_image_) { | 121 if (x_image_) { |
75 shm_segment_info_->shmid = shmget( | 122 shm_segment_info_->shmid = shmget( |
76 IPC_PRIVATE, x_image_->bytes_per_line * x_image_->height, | 123 IPC_PRIVATE, x_image_->bytes_per_line * x_image_->height, |
77 IPC_CREAT | 0666); | 124 IPC_CREAT | 0666); |
78 if (shm_segment_info_->shmid != -1) { | 125 if (shm_segment_info_->shmid != -1) { |
79 shm_segment_info_->shmaddr = x_image_->data = | 126 shm_segment_info_->shmaddr = x_image_->data = |
80 reinterpret_cast<char*>(shmat(shm_segment_info_->shmid, 0, 0)); | 127 reinterpret_cast<char*>(shmat(shm_segment_info_->shmid, 0, 0)); |
81 if (x_image_->data != reinterpret_cast<char*>(-1)) { | 128 if (x_image_->data != reinterpret_cast<char*>(-1)) { |
82 gdk_error_trap_push(); | 129 EnableXServerErrorTrap(); |
83 using_shm = XShmAttach(display_, shm_segment_info_); | 130 using_shm = XShmAttach(display_, shm_segment_info_); |
84 XSync(display_, False); | 131 XSync(display_, False); |
85 if (gdk_error_trap_pop() != 0) | 132 if (GetLastXServerError() != 0) |
86 using_shm = false; | 133 using_shm = false; |
87 } | 134 } |
88 } | 135 } |
89 } | 136 } |
90 | 137 |
91 if (!using_shm) { | 138 if (!using_shm) { |
92 VLOG(1) << "Not using shared memory."; | 139 VLOG(1) << "Not using shared memory."; |
93 Release(); | 140 Release(); |
94 return; | 141 return; |
95 } | 142 } |
96 | 143 |
97 if (havePixmaps) | 144 if (havePixmaps) |
98 havePixmaps = InitPixmaps(width, height, default_depth); | 145 havePixmaps = InitPixmaps(width, height, default_depth); |
99 | 146 |
100 shmctl(shm_segment_info_->shmid, IPC_RMID, 0); | 147 shmctl(shm_segment_info_->shmid, IPC_RMID, 0); |
101 shm_segment_info_->shmid = -1; | 148 shm_segment_info_->shmid = -1; |
102 | 149 |
103 VLOG(1) << "Using X shared memory extension v" << major << "." << minor | 150 VLOG(1) << "Using X shared memory extension v" << major << "." << minor |
104 << " with" << (havePixmaps?"":"out") << " pixmaps."; | 151 << " with" << (havePixmaps?"":"out") << " pixmaps."; |
105 } | 152 } |
106 | 153 |
107 bool XServerPixelBuffer::InitPixmaps(int width, int height, int depth) { | 154 bool XServerPixelBuffer::InitPixmaps(int width, int height, int depth) { |
108 if (XShmPixmapFormat(display_) != ZPixmap) | 155 if (XShmPixmapFormat(display_) != ZPixmap) |
109 return false; | 156 return false; |
110 | 157 |
111 gdk_error_trap_push(); | 158 EnableXServerErrorTrap(); |
112 shm_pixmap_ = XShmCreatePixmap(display_, root_window_, | 159 shm_pixmap_ = XShmCreatePixmap(display_, root_window_, |
113 shm_segment_info_->shmaddr, | 160 shm_segment_info_->shmaddr, |
114 shm_segment_info_, | 161 shm_segment_info_, |
115 width, height, depth); | 162 width, height, depth); |
116 XSync(display_, False); | 163 XSync(display_, False); |
117 if (gdk_error_trap_pop() != 0) { | 164 if (GetLastXServerError() != 0) { |
118 // |shm_pixmap_| is not not valid because the request was not processed | 165 // |shm_pixmap_| is not not valid because the request was not processed |
119 // by the X Server, so zero it. | 166 // by the X Server, so zero it. |
120 shm_pixmap_ = 0; | 167 shm_pixmap_ = 0; |
121 return false; | 168 return false; |
122 } | 169 } |
123 | 170 |
124 gdk_error_trap_push(); | 171 EnableXServerErrorTrap(); |
125 XGCValues shm_gc_values; | 172 XGCValues shm_gc_values; |
126 shm_gc_values.subwindow_mode = IncludeInferiors; | 173 shm_gc_values.subwindow_mode = IncludeInferiors; |
127 shm_gc_values.graphics_exposures = False; | 174 shm_gc_values.graphics_exposures = False; |
128 shm_gc_ = XCreateGC(display_, root_window_, | 175 shm_gc_ = XCreateGC(display_, root_window_, |
129 GCSubwindowMode | GCGraphicsExposures, | 176 GCSubwindowMode | GCGraphicsExposures, |
130 &shm_gc_values); | 177 &shm_gc_values); |
131 XSync(display_, False); | 178 XSync(display_, False); |
132 if (gdk_error_trap_pop() != 0) { | 179 if (GetLastXServerError() != 0) { |
133 XFreePixmap(display_, shm_pixmap_); | 180 XFreePixmap(display_, shm_pixmap_); |
134 shm_pixmap_ = 0; | 181 shm_pixmap_ = 0; |
135 shm_gc_ = 0; // See shm_pixmap_ comment above. | 182 shm_gc_ = 0; // See shm_pixmap_ comment above. |
136 return false; | 183 return false; |
137 } | 184 } |
138 | 185 |
139 return true; | 186 return true; |
140 } | 187 } |
141 | 188 |
142 void XServerPixelBuffer::Synchronize() { | 189 void XServerPixelBuffer::Synchronize() { |
143 if (shm_segment_info_ && !shm_pixmap_) { | 190 if (shm_segment_info_ && !shm_pixmap_) { |
144 // XShmGetImage can fail if the display is being reconfigured. | 191 // XShmGetImage can fail if the display is being reconfigured. |
145 gdk_error_trap_push(); | 192 EnableXServerErrorTrap(); |
146 XShmGetImage(display_, root_window_, x_image_, 0, 0, AllPlanes); | 193 XShmGetImage(display_, root_window_, x_image_, 0, 0, AllPlanes); |
147 gdk_error_trap_pop(); | 194 GetLastXServerError(); |
148 } | 195 } |
149 } | 196 } |
150 | 197 |
151 uint8* XServerPixelBuffer::CaptureRect(const SkIRect& rect) { | 198 uint8* XServerPixelBuffer::CaptureRect(const SkIRect& rect) { |
152 if (shm_segment_info_) { | 199 if (shm_segment_info_) { |
153 if (shm_pixmap_) { | 200 if (shm_pixmap_) { |
154 XCopyArea(display_, root_window_, shm_pixmap_, shm_gc_, | 201 XCopyArea(display_, root_window_, shm_pixmap_, shm_gc_, |
155 rect.fLeft, rect.fTop, rect.width(), rect.height(), | 202 rect.fLeft, rect.fTop, rect.width(), rect.height(), |
156 rect.fLeft, rect.fTop); | 203 rect.fLeft, rect.fTop); |
157 XSync(display_, False); | 204 XSync(display_, False); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 | 249 |
203 int XServerPixelBuffer::GetGreenShift() const { | 250 int XServerPixelBuffer::GetGreenShift() const { |
204 return ffs(x_image_->green_mask) - 1; | 251 return ffs(x_image_->green_mask) - 1; |
205 } | 252 } |
206 | 253 |
207 bool XServerPixelBuffer::IsRgb() const { | 254 bool XServerPixelBuffer::IsRgb() const { |
208 return GetRedShift() == 16 && GetGreenShift() == 8 && GetBlueShift() == 0; | 255 return GetRedShift() == 16 && GetGreenShift() == 8 && GetBlueShift() == 0; |
209 } | 256 } |
210 | 257 |
211 } // namespace remoting | 258 } // namespace remoting |
OLD | NEW |