Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(543)

Side by Side Diff: remoting/host/linux/x_server_pixel_buffer.cc

Issue 11470028: Move screen capturers to remoting/capturer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 #include "remoting/host/linux/x_server_pixel_buffer.h"
6
7 #include <sys/shm.h>
8
9 #include "base/logging.h"
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
59 namespace remoting {
60
61 XServerPixelBuffer::XServerPixelBuffer()
62 : display_(NULL), root_window_(0), x_image_(NULL),
63 shm_segment_info_(NULL), shm_pixmap_(0), shm_gc_(NULL) {
64 }
65
66 XServerPixelBuffer::~XServerPixelBuffer() {
67 Release();
68 }
69
70 void XServerPixelBuffer::Release() {
71 if (x_image_) {
72 XDestroyImage(x_image_);
73 x_image_ = NULL;
74 }
75 if (shm_pixmap_) {
76 XFreePixmap(display_, shm_pixmap_);
77 shm_pixmap_ = 0;
78 }
79 if (shm_gc_) {
80 XFreeGC(display_, shm_gc_);
81 shm_gc_ = NULL;
82 }
83 if (shm_segment_info_) {
84 if (shm_segment_info_->shmaddr != reinterpret_cast<char*>(-1))
85 shmdt(shm_segment_info_->shmaddr);
86 if (shm_segment_info_->shmid != -1)
87 shmctl(shm_segment_info_->shmid, IPC_RMID, 0);
88 delete shm_segment_info_;
89 shm_segment_info_ = NULL;
90 }
91 }
92
93 void XServerPixelBuffer::Init(Display* display) {
94 Release();
95 display_ = display;
96 int default_screen = DefaultScreen(display_);
97 root_window_ = RootWindow(display_, default_screen);
98 InitShm(default_screen);
99 }
100
101 void XServerPixelBuffer::InitShm(int screen) {
102 XWindowAttributes root_attr;
103 XGetWindowAttributes(display_, root_window_, &root_attr);
104 int width = root_attr.width, height = root_attr.height;
105 Visual* default_visual = DefaultVisual(display_, screen);
106 int default_depth = DefaultDepth(display_, screen);
107
108 int major, minor;
109 Bool havePixmaps;
110 if (!XShmQueryVersion(display_, &major, &minor, &havePixmaps))
111 // Shared memory not supported. CaptureRect will use the XImage API instead.
112 return;
113
114 bool using_shm = false;
115 shm_segment_info_ = new XShmSegmentInfo;
116 shm_segment_info_->shmid = -1;
117 shm_segment_info_->shmaddr = reinterpret_cast<char*>(-1);
118 shm_segment_info_->readOnly = False;
119 x_image_ = XShmCreateImage(display_, default_visual, default_depth, ZPixmap,
120 0, shm_segment_info_, width, height);
121 if (x_image_) {
122 shm_segment_info_->shmid = shmget(
123 IPC_PRIVATE, x_image_->bytes_per_line * x_image_->height,
124 IPC_CREAT | 0600);
125 if (shm_segment_info_->shmid != -1) {
126 shm_segment_info_->shmaddr = x_image_->data =
127 reinterpret_cast<char*>(shmat(shm_segment_info_->shmid, 0, 0));
128 if (x_image_->data != reinterpret_cast<char*>(-1)) {
129 EnableXServerErrorTrap();
130 using_shm = XShmAttach(display_, shm_segment_info_);
131 XSync(display_, False);
132 if (GetLastXServerError() != 0)
133 using_shm = false;
134 if (using_shm) {
135 VLOG(1) << "Using X shared memory segment "
136 << shm_segment_info_->shmid;
137 }
138 }
139 } else {
140 LOG(WARNING) << "Failed to get shared memory segment. "
141 "Performance may be degraded.";
142 }
143 }
144
145 if (!using_shm) {
146 LOG(WARNING) << "Not using shared memory. Performance may be degraded.";
147 Release();
148 return;
149 }
150
151 if (havePixmaps)
152 havePixmaps = InitPixmaps(width, height, default_depth);
153
154 shmctl(shm_segment_info_->shmid, IPC_RMID, 0);
155 shm_segment_info_->shmid = -1;
156
157 VLOG(1) << "Using X shared memory extension v" << major << "." << minor
158 << " with" << (havePixmaps?"":"out") << " pixmaps.";
159 }
160
161 bool XServerPixelBuffer::InitPixmaps(int width, int height, int depth) {
162 if (XShmPixmapFormat(display_) != ZPixmap)
163 return false;
164
165 EnableXServerErrorTrap();
166 shm_pixmap_ = XShmCreatePixmap(display_, root_window_,
167 shm_segment_info_->shmaddr,
168 shm_segment_info_,
169 width, height, depth);
170 XSync(display_, False);
171 if (GetLastXServerError() != 0) {
172 // |shm_pixmap_| is not not valid because the request was not processed
173 // by the X Server, so zero it.
174 shm_pixmap_ = 0;
175 return false;
176 }
177
178 EnableXServerErrorTrap();
179 XGCValues shm_gc_values;
180 shm_gc_values.subwindow_mode = IncludeInferiors;
181 shm_gc_values.graphics_exposures = False;
182 shm_gc_ = XCreateGC(display_, root_window_,
183 GCSubwindowMode | GCGraphicsExposures,
184 &shm_gc_values);
185 XSync(display_, False);
186 if (GetLastXServerError() != 0) {
187 XFreePixmap(display_, shm_pixmap_);
188 shm_pixmap_ = 0;
189 shm_gc_ = 0; // See shm_pixmap_ comment above.
190 return false;
191 }
192
193 return true;
194 }
195
196 void XServerPixelBuffer::Synchronize() {
197 if (shm_segment_info_ && !shm_pixmap_) {
198 // XShmGetImage can fail if the display is being reconfigured.
199 EnableXServerErrorTrap();
200 XShmGetImage(display_, root_window_, x_image_, 0, 0, AllPlanes);
201 GetLastXServerError();
202 }
203 }
204
205 uint8* XServerPixelBuffer::CaptureRect(const SkIRect& rect) {
206 if (shm_segment_info_) {
207 if (shm_pixmap_) {
208 XCopyArea(display_, root_window_, shm_pixmap_, shm_gc_,
209 rect.fLeft, rect.fTop, rect.width(), rect.height(),
210 rect.fLeft, rect.fTop);
211 XSync(display_, False);
212 }
213 return reinterpret_cast<uint8*>(x_image_->data) +
214 rect.fTop * x_image_->bytes_per_line +
215 rect.fLeft * x_image_->bits_per_pixel / 8;
216 } else {
217 if (x_image_)
218 XDestroyImage(x_image_);
219 x_image_ = XGetImage(display_, root_window_, rect.fLeft, rect.fTop,
220 rect.width(), rect.height(), AllPlanes, ZPixmap);
221 return reinterpret_cast<uint8*>(x_image_->data);
222 }
223 }
224
225 int XServerPixelBuffer::GetStride() const {
226 return x_image_->bytes_per_line;
227 }
228
229 int XServerPixelBuffer::GetDepth() const {
230 return x_image_->depth;
231 }
232
233 int XServerPixelBuffer::GetBitsPerPixel() const {
234 return x_image_->bits_per_pixel;
235 }
236
237 int XServerPixelBuffer::GetRedMask() const {
238 return x_image_->red_mask;
239 }
240
241 int XServerPixelBuffer::GetBlueMask() const {
242 return x_image_->blue_mask;
243 }
244
245 int XServerPixelBuffer::GetGreenMask() const {
246 return x_image_->green_mask;
247 }
248
249 int XServerPixelBuffer::GetRedShift() const {
250 return ffs(x_image_->red_mask) - 1;
251 }
252
253 int XServerPixelBuffer::GetBlueShift() const {
254 return ffs(x_image_->blue_mask) - 1;
255 }
256
257 int XServerPixelBuffer::GetGreenShift() const {
258 return ffs(x_image_->green_mask) - 1;
259 }
260
261 bool XServerPixelBuffer::IsRgb() const {
262 return GetRedShift() == 16 && GetGreenShift() == 8 && GetBlueShift() == 0;
263 }
264
265 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698