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

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

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

Powered by Google App Engine
This is Rietveld 408576698