Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/capturer.h" | 5 #include "remoting/host/capturer.h" |
| 6 | 6 |
| 7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
| 8 #include <X11/Xutil.h> | 8 #include <X11/Xutil.h> |
| 9 #include <X11/extensions/Xdamage.h> | 9 #include <X11/extensions/Xdamage.h> |
| 10 #include <X11/extensions/Xfixes.h> | |
| 10 | 11 |
| 11 #include <set> | 12 #include <set> |
| 12 | 13 |
| 13 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
| 14 #include "base/logging.h" | 15 #include "base/logging.h" |
| 15 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 17 #include "remoting/base/capture_data.h" | |
| 18 #include "remoting/base/cursor_shape_data.h" | |
| 16 #include "remoting/host/capturer_helper.h" | 19 #include "remoting/host/capturer_helper.h" |
| 17 #include "remoting/host/differ.h" | 20 #include "remoting/host/differ.h" |
| 18 #include "remoting/host/x_server_pixel_buffer.h" | 21 #include "remoting/host/x_server_pixel_buffer.h" |
| 19 | 22 |
| 20 namespace remoting { | 23 namespace remoting { |
| 21 | 24 |
| 22 namespace { | 25 namespace { |
| 23 | 26 |
| 24 static const int kBytesPerPixel = 4; | 27 static const int kBytesPerPixel = 4; |
| 25 | 28 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 class CapturerLinux : public Capturer { | 73 class CapturerLinux : public Capturer { |
| 71 public: | 74 public: |
| 72 CapturerLinux(); | 75 CapturerLinux(); |
| 73 virtual ~CapturerLinux(); | 76 virtual ~CapturerLinux(); |
| 74 | 77 |
| 75 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? | 78 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? |
| 76 | 79 |
| 77 // Capturer interface. | 80 // Capturer interface. |
| 78 virtual void Start() OVERRIDE; | 81 virtual void Start() OVERRIDE; |
| 79 virtual void Stop() OVERRIDE; | 82 virtual void Stop() OVERRIDE; |
| 83 virtual void SetCursorShapeChangedCallback( | |
| 84 const CursorShapeChangedCallback& callback) OVERRIDE; | |
| 80 virtual void ScreenConfigurationChanged() OVERRIDE; | 85 virtual void ScreenConfigurationChanged() OVERRIDE; |
| 81 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; | 86 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; |
| 82 virtual void ClearInvalidRegion() OVERRIDE; | 87 virtual void ClearInvalidRegion() OVERRIDE; |
| 83 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; | 88 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; |
| 84 virtual void InvalidateScreen(const SkISize& size) OVERRIDE; | 89 virtual void InvalidateScreen(const SkISize& size) OVERRIDE; |
| 85 virtual void InvalidateFullScreen() OVERRIDE; | 90 virtual void InvalidateFullScreen() OVERRIDE; |
| 86 virtual void CaptureInvalidRegion( | 91 virtual void CaptureInvalidRegion( |
| 87 const CaptureCompletedCallback& callback) OVERRIDE; | 92 const CaptureCompletedCallback& callback) OVERRIDE; |
| 88 virtual const SkISize& size_most_recent() const OVERRIDE; | 93 virtual const SkISize& size_most_recent() const OVERRIDE; |
| 89 | 94 |
| 90 private: | 95 private: |
| 91 void InitXDamage(); | 96 void InitXDamage(); |
| 92 | 97 |
| 93 // Read and handle all currently-pending XEvents. | 98 // Read and handle all currently-pending XEvents. |
| 94 // In the DAMAGE case, process the XDamage events and store the resulting | 99 // In the DAMAGE case, process the XDamage events and store the resulting |
| 95 // damage rectangles in the CapturerHelper. | 100 // damage rectangles in the CapturerHelper. |
| 96 // In all cases, call ScreenConfigurationChanged() in response to any | 101 // In all cases, call ScreenConfigurationChanged() in response to any |
| 97 // ConfigNotify events. | 102 // ConfigNotify events. |
| 98 void ProcessPendingXEvents(); | 103 void ProcessPendingXEvents(); |
| 99 | 104 |
| 100 // Capture screen pixels, and return the data in a new CaptureData object, | 105 // Capture screen pixels, and return the data in a new CaptureData object, |
| 101 // to be freed by the caller. | 106 // to be freed by the caller. |
| 102 // In the DAMAGE case, the CapturerHelper already holds the list of invalid | 107 // In the DAMAGE case, the CapturerHelper already holds the list of invalid |
| 103 // rectangles from ProcessPendingXEvents(). | 108 // rectangles from ProcessPendingXEvents(). |
| 104 // In the non-DAMAGE case, this captures the whole screen, then calculates | 109 // In the non-DAMAGE case, this captures the whole screen, then calculates |
| 105 // some invalid rectangles that include any differences between this and the | 110 // some invalid rectangles that include any differences between this and the |
| 106 // previous capture. | 111 // previous capture. |
| 107 CaptureData* CaptureFrame(); | 112 CaptureData* CaptureFrame(); |
| 108 | 113 |
| 114 // Capture the cursor image and call the CursorShapeChangedCallback if it | |
| 115 // has been set (using SetCursorShapeChangedCallback). | |
| 116 void CaptureCursor(); | |
| 117 | |
| 109 // Synchronize the current buffer with |last_buffer_|, by copying pixels from | 118 // Synchronize the current buffer with |last_buffer_|, by copying pixels from |
| 110 // the area of |last_invalid_rects|. | 119 // the area of |last_invalid_rects|. |
| 111 // Note this only works on the assumption that kNumBuffers == 2, as | 120 // Note this only works on the assumption that kNumBuffers == 2, as |
| 112 // |last_invalid_rects| holds the differences from the previous buffer and | 121 // |last_invalid_rects| holds the differences from the previous buffer and |
| 113 // the one prior to that (which will then be the current buffer). | 122 // the one prior to that (which will then be the current buffer). |
| 114 void SynchronizeFrame(); | 123 void SynchronizeFrame(); |
| 115 | 124 |
| 116 void DeinitXlib(); | 125 void DeinitXlib(); |
| 117 | 126 |
| 118 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into | 127 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into |
| 119 // |capture_data|. | 128 // |capture_data|. |
| 120 void CaptureRect(const SkIRect& rect, CaptureData* capture_data); | 129 void CaptureRect(const SkIRect& rect, CaptureData* capture_data); |
| 121 | 130 |
| 122 // We expose two forms of blitting to handle variations in the pixel format. | 131 // We expose two forms of blitting to handle variations in the pixel format. |
| 123 // In FastBlit, the operation is effectively a memcpy. | 132 // In FastBlit, the operation is effectively a memcpy. |
| 124 void FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); | 133 void FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); |
| 125 void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); | 134 void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); |
| 126 | 135 |
| 127 // X11 graphics context. | 136 // X11 graphics context. |
| 128 Display* display_; | 137 Display* display_; |
| 129 GC gc_; | 138 GC gc_; |
| 130 Window root_window_; | 139 Window root_window_; |
| 131 | 140 |
| 141 // XFixes. | |
| 142 bool has_xfixes_; | |
| 143 int xfixes_event_base_; | |
| 144 int xfixes_error_base_; | |
| 145 | |
| 132 // XDamage information. | 146 // XDamage information. |
| 133 bool use_damage_; | 147 bool use_damage_; |
| 134 Damage damage_handle_; | 148 Damage damage_handle_; |
| 135 int damage_event_base_; | 149 int damage_event_base_; |
| 136 int damage_error_base_; | 150 int damage_error_base_; |
| 137 XserverRegion damage_region_; | 151 XserverRegion damage_region_; |
| 138 | 152 |
| 139 // Access to the X Server's pixel buffer. | 153 // Access to the X Server's pixel buffer. |
| 140 XServerPixelBuffer x_server_pixel_buffer_; | 154 XServerPixelBuffer x_server_pixel_buffer_; |
| 141 | 155 |
| 142 // A thread-safe list of invalid rectangles, and the size of the most | 156 // A thread-safe list of invalid rectangles, and the size of the most |
| 143 // recently captured screen. | 157 // recently captured screen. |
| 144 CapturerHelper helper_; | 158 CapturerHelper helper_; |
| 145 | 159 |
| 160 // Callback notified whenever the cursor shape is changed. | |
| 161 CursorShapeChangedCallback cursor_shape_changed_callback_; | |
| 162 | |
| 146 // Capture state. | 163 // Capture state. |
| 147 static const int kNumBuffers = 2; | 164 static const int kNumBuffers = 2; |
| 148 VideoFrameBuffer buffers_[kNumBuffers]; | 165 VideoFrameBuffer buffers_[kNumBuffers]; |
| 149 int current_buffer_; | 166 int current_buffer_; |
| 150 | 167 |
| 151 // Format of pixels returned in buffer. | 168 // Format of pixels returned in buffer. |
| 152 media::VideoFrame::Format pixel_format_; | 169 media::VideoFrame::Format pixel_format_; |
| 153 | 170 |
| 154 // Invalid region from the previous capture. This is used to synchronize the | 171 // Invalid region from the previous capture. This is used to synchronize the |
| 155 // current with the last buffer used. | 172 // current with the last buffer used. |
| 156 SkRegion last_invalid_region_; | 173 SkRegion last_invalid_region_; |
| 157 | 174 |
| 158 // Last capture buffer used. | 175 // Last capture buffer used. |
| 159 uint8* last_buffer_; | 176 uint8* last_buffer_; |
| 160 | 177 |
| 161 // |Differ| for use when polling for changes. | 178 // |Differ| for use when polling for changes. |
| 162 scoped_ptr<Differ> differ_; | 179 scoped_ptr<Differ> differ_; |
| 163 | 180 |
| 164 DISALLOW_COPY_AND_ASSIGN(CapturerLinux); | 181 DISALLOW_COPY_AND_ASSIGN(CapturerLinux); |
| 165 }; | 182 }; |
| 166 | 183 |
| 167 CapturerLinux::CapturerLinux() | 184 CapturerLinux::CapturerLinux() |
| 168 : display_(NULL), | 185 : display_(NULL), |
| 169 gc_(NULL), | 186 gc_(NULL), |
| 170 root_window_(BadValue), | 187 root_window_(BadValue), |
| 188 has_xfixes_(false), | |
| 189 xfixes_event_base_(-1), | |
| 190 xfixes_error_base_(-1), | |
| 171 use_damage_(false), | 191 use_damage_(false), |
| 172 damage_handle_(0), | 192 damage_handle_(0), |
| 173 damage_event_base_(-1), | 193 damage_event_base_(-1), |
| 174 damage_error_base_(-1), | 194 damage_error_base_(-1), |
| 175 damage_region_(0), | 195 damage_region_(0), |
| 176 current_buffer_(0), | 196 current_buffer_(0), |
| 177 pixel_format_(media::VideoFrame::RGB32), | 197 pixel_format_(media::VideoFrame::RGB32), |
| 178 last_buffer_(NULL) { | 198 last_buffer_(NULL) { |
| 179 helper_.SetLogGridSize(4); | 199 helper_.SetLogGridSize(4); |
| 180 } | 200 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 201 return false; | 221 return false; |
| 202 } | 222 } |
| 203 | 223 |
| 204 gc_ = XCreateGC(display_, root_window_, 0, NULL); | 224 gc_ = XCreateGC(display_, root_window_, 0, NULL); |
| 205 if (gc_ == NULL) { | 225 if (gc_ == NULL) { |
| 206 LOG(ERROR) << "Unable to get graphics context"; | 226 LOG(ERROR) << "Unable to get graphics context"; |
| 207 DeinitXlib(); | 227 DeinitXlib(); |
| 208 return false; | 228 return false; |
| 209 } | 229 } |
| 210 | 230 |
| 231 // Check for XFixes extension. This is required for cursor shape | |
| 232 // notifications, and for our use of XDamage. | |
| 233 if (XFixesQueryExtension(display_, &xfixes_event_base_, | |
| 234 &xfixes_error_base_)) { | |
| 235 has_xfixes_ = true; | |
| 236 } else { | |
| 237 LOG(INFO) << "X server does not support XFixes."; | |
| 238 } | |
| 239 | |
| 211 if (ShouldUseXDamage()) { | 240 if (ShouldUseXDamage()) { |
| 212 InitXDamage(); | 241 InitXDamage(); |
| 213 } | 242 } |
| 214 | 243 |
| 215 // Register for changes to the dimensions of the root window. | 244 // Register for changes to the dimensions of the root window. |
| 216 XSelectInput(display_, root_window_, StructureNotifyMask); | 245 XSelectInput(display_, root_window_, StructureNotifyMask); |
| 217 | 246 |
| 247 if (has_xfixes_) { | |
| 248 // Register for changes to the cursor shape. | |
| 249 XFixesSelectCursorInput(display_, root_window_, | |
| 250 XFixesDisplayCursorNotifyMask); | |
| 251 } | |
| 252 | |
| 218 return true; | 253 return true; |
| 219 } | 254 } |
| 220 | 255 |
| 221 void CapturerLinux::InitXDamage() { | 256 void CapturerLinux::InitXDamage() { |
| 222 // Check for XFixes and XDamage extensions. If both are found then use | 257 // Our use of XDamage requires XFixes. |
| 223 // XDamage to get explicit notifications of on-screen changes. | 258 if (!has_xfixes_) |
|
Wez
2012/05/23 00:01:57
nit: Use {} consistently with the other if()s belo
garykac
2012/05/26 01:58:01
Done.
| |
| 224 int xfixes_event_base; | |
| 225 int xfixes_error_base; | |
| 226 if (!XFixesQueryExtension(display_, &xfixes_event_base, &xfixes_error_base)) { | |
| 227 LOG(INFO) << "X server does not support XFixes."; | |
| 228 return; | 259 return; |
| 229 } | 260 |
| 261 // Check for XDamage extension. | |
| 230 if (!XDamageQueryExtension(display_, &damage_event_base_, | 262 if (!XDamageQueryExtension(display_, &damage_event_base_, |
| 231 &damage_error_base_)) { | 263 &damage_error_base_)) { |
| 232 LOG(INFO) << "X server does not support XDamage."; | 264 LOG(INFO) << "X server does not support XDamage."; |
| 233 return; | 265 return; |
| 234 } | 266 } |
| 235 | 267 |
| 236 // TODO(lambroslambrou): Disable DAMAGE in situations where it is known | 268 // TODO(lambroslambrou): Disable DAMAGE in situations where it is known |
| 237 // to fail, such as when Desktop Effects are enabled, with graphics | 269 // to fail, such as when Desktop Effects are enabled, with graphics |
| 238 // drivers (nVidia, ATI) that fail to report DAMAGE notifications | 270 // drivers (nVidia, ATI) that fail to report DAMAGE notifications |
| 239 // properly. | 271 // properly. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 257 use_damage_ = true; | 289 use_damage_ = true; |
| 258 LOG(INFO) << "Using XDamage extension."; | 290 LOG(INFO) << "Using XDamage extension."; |
| 259 } | 291 } |
| 260 | 292 |
| 261 void CapturerLinux::Start() { | 293 void CapturerLinux::Start() { |
| 262 } | 294 } |
| 263 | 295 |
| 264 void CapturerLinux::Stop() { | 296 void CapturerLinux::Stop() { |
| 265 } | 297 } |
| 266 | 298 |
| 299 void CapturerLinux::SetCursorShapeChangedCallback( | |
| 300 const CursorShapeChangedCallback& callback) { | |
| 301 cursor_shape_changed_callback_ = callback; | |
| 302 } | |
| 303 | |
| 267 void CapturerLinux::ScreenConfigurationChanged() { | 304 void CapturerLinux::ScreenConfigurationChanged() { |
| 268 last_buffer_ = NULL; | 305 last_buffer_ = NULL; |
| 269 for (int i = 0; i < kNumBuffers; ++i) { | 306 for (int i = 0; i < kNumBuffers; ++i) { |
| 270 buffers_[i].set_needs_update(); | 307 buffers_[i].set_needs_update(); |
| 271 } | 308 } |
| 272 helper_.ClearInvalidRegion(); | 309 helper_.ClearInvalidRegion(); |
| 273 x_server_pixel_buffer_.Init(display_); | 310 x_server_pixel_buffer_.Init(display_); |
| 274 } | 311 } |
| 275 | 312 |
| 276 media::VideoFrame::Format CapturerLinux::pixel_format() const { | 313 media::VideoFrame::Format CapturerLinux::pixel_format() const { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 289 helper_.InvalidateScreen(size); | 326 helper_.InvalidateScreen(size); |
| 290 } | 327 } |
| 291 | 328 |
| 292 void CapturerLinux::InvalidateFullScreen() { | 329 void CapturerLinux::InvalidateFullScreen() { |
| 293 helper_.InvalidateFullScreen(); | 330 helper_.InvalidateFullScreen(); |
| 294 last_buffer_ = NULL; | 331 last_buffer_ = NULL; |
| 295 } | 332 } |
| 296 | 333 |
| 297 void CapturerLinux::CaptureInvalidRegion( | 334 void CapturerLinux::CaptureInvalidRegion( |
| 298 const CaptureCompletedCallback& callback) { | 335 const CaptureCompletedCallback& callback) { |
| 299 // TODO(lambroslambrou): In the non-DAMAGE case, there should be no need | 336 // Process XEvents for XDamage and cursor shape tracking. |
| 300 // for any X event processing in this class. | |
| 301 ProcessPendingXEvents(); | 337 ProcessPendingXEvents(); |
| 302 | 338 |
| 303 // Resize the current buffer if there was a recent change of | 339 // Resize the current buffer if there was a recent change of |
| 304 // screen-resolution. | 340 // screen-resolution. |
| 305 VideoFrameBuffer ¤t = buffers_[current_buffer_]; | 341 VideoFrameBuffer ¤t = buffers_[current_buffer_]; |
| 306 current.Update(display_, root_window_); | 342 current.Update(display_, root_window_); |
| 307 // Also refresh the Differ helper used by CaptureFrame(), if needed. | 343 // Also refresh the Differ helper used by CaptureFrame(), if needed. |
| 308 if (!use_damage_ && !last_buffer_) { | 344 if (!use_damage_ && !last_buffer_) { |
| 309 differ_.reset(new Differ(current.size().width(), current.size().height(), | 345 differ_.reset(new Differ(current.size().width(), current.size().height(), |
| 310 kBytesPerPixel, current.bytes_per_row())); | 346 kBytesPerPixel, current.bytes_per_row())); |
| 311 } | 347 } |
| 312 | 348 |
| 313 scoped_refptr<CaptureData> capture_data(CaptureFrame()); | 349 scoped_refptr<CaptureData> capture_data(CaptureFrame()); |
| 314 | 350 |
| 315 current_buffer_ = (current_buffer_ + 1) % kNumBuffers; | 351 current_buffer_ = (current_buffer_ + 1) % kNumBuffers; |
| 316 | 352 |
| 317 callback.Run(capture_data); | 353 callback.Run(capture_data); |
| 318 } | 354 } |
| 319 | 355 |
| 320 void CapturerLinux::ProcessPendingXEvents() { | 356 void CapturerLinux::ProcessPendingXEvents() { |
| 321 // Find the number of events that are outstanding "now." We don't just loop | 357 // Find the number of events that are outstanding "now." We don't just loop |
| 322 // on XPending because we want to guarantee this terminates. | 358 // on XPending because we want to guarantee this terminates. |
| 323 int events_to_process = XPending(display_); | 359 int events_to_process = XPending(display_); |
| 324 XEvent e; | 360 XEvent e; |
| 325 | 361 |
| 326 for (int i = 0; i < events_to_process; i++) { | 362 for (int i = 0; i < events_to_process; i++) { |
| 327 XNextEvent(display_, &e); | 363 XNextEvent(display_, &e); |
| 328 if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) { | 364 if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) { |
| 329 XDamageNotifyEvent *event = reinterpret_cast<XDamageNotifyEvent*>(&e); | 365 XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e); |
| 330 DCHECK(event->level == XDamageReportNonEmpty); | 366 DCHECK(event->level == XDamageReportNonEmpty); |
| 331 } else if (e.type == ConfigureNotify) { | 367 } else if (e.type == ConfigureNotify) { |
| 332 ScreenConfigurationChanged(); | 368 ScreenConfigurationChanged(); |
| 369 } else if (has_xfixes_ && | |
| 370 e.type == xfixes_event_base_ + XFixesCursorNotify) { | |
| 371 XFixesCursorNotifyEvent* cne; | |
| 372 cne = reinterpret_cast<XFixesCursorNotifyEvent*>(&e); | |
| 373 if (cne->subtype == XFixesDisplayCursorNotify) { | |
| 374 CaptureCursor(); | |
| 375 } | |
| 333 } else { | 376 } else { |
| 334 LOG(WARNING) << "Got unknown event type: " << e.type; | 377 LOG(WARNING) << "Got unknown event type: " << e.type; |
| 335 } | 378 } |
| 336 } | 379 } |
| 337 } | 380 } |
| 338 | 381 |
| 382 void CapturerLinux::CaptureCursor() { | |
| 383 DCHECK(has_xfixes_); | |
| 384 if (cursor_shape_changed_callback_.is_null()) | |
| 385 return; | |
| 386 | |
| 387 XFixesCursorImage* img = XFixesGetCursorImage(display_); | |
| 388 if (!img) | |
|
Wez
2012/05/23 00:01:57
nit: Here and above, use {} consistently with othe
garykac
2012/05/26 01:58:01
Done.
| |
| 389 return; | |
| 390 | |
| 391 SkISize size, hotspot; | |
| 392 size.set(img->width, img->height); | |
| 393 hotspot.set(img->xhot, img->yhot); | |
| 394 const int bytes_per_pixel = 4; | |
| 395 int total_bytes = img->width * img->height * bytes_per_pixel; | |
|
Wez
2012/05/23 00:01:57
nit: Rather than set these up here, why not use e.
garykac
2012/05/26 01:58:01
Done.
| |
| 396 scoped_array<uint8> data(new uint8[total_bytes]); | |
| 397 | |
| 398 // Xlib stores 32-bit data in longs, even if longs are 64-bits long. | |
|
Wez
2012/05/23 00:01:57
nit: I'd recommend simplifying this to use the slo
garykac
2012/05/26 01:58:01
Done.
| |
| 399 if (sizeof(unsigned long) == sizeof(uint32)) { | |
| 400 // Longs are 32-bits, do a simple memcpy. | |
| 401 memcpy(data.get(), img->pixels, total_bytes); | |
| 402 } else { | |
| 403 // Longs are 64-bits, copy each long into a uint32. | |
| 404 unsigned long* src = img->pixels; | |
| 405 uint32* dst = reinterpret_cast<uint32*>(data.get()); | |
| 406 uint32* dst_end = dst + (img->width * img->height); | |
| 407 while (dst < dst_end) { | |
| 408 *dst++ = *src++; | |
| 409 } | |
| 410 } | |
| 411 XFree(img); | |
| 412 | |
| 413 scoped_refptr<CursorShapeData> cursor_data = new CursorShapeData(); | |
| 414 cursor_data->Initialize(data.Pass(), size, hotspot, bytes_per_pixel); | |
| 415 cursor_shape_changed_callback_.Run(cursor_data); | |
| 416 } | |
| 417 | |
| 339 CaptureData* CapturerLinux::CaptureFrame() { | 418 CaptureData* CapturerLinux::CaptureFrame() { |
| 340 VideoFrameBuffer& buffer = buffers_[current_buffer_]; | 419 VideoFrameBuffer& buffer = buffers_[current_buffer_]; |
| 341 DataPlanes planes; | 420 DataPlanes planes; |
| 342 planes.data[0] = buffer.ptr(); | 421 planes.data[0] = buffer.ptr(); |
| 343 planes.strides[0] = buffer.bytes_per_row(); | 422 planes.strides[0] = buffer.bytes_per_row(); |
| 344 | 423 |
| 345 CaptureData* capture_data = new CaptureData(planes, buffer.size(), | 424 CaptureData* capture_data = new CaptureData(planes, buffer.size(), |
| 346 media::VideoFrame::RGB32); | 425 media::VideoFrame::RGB32); |
| 347 | 426 |
| 348 // Pass the screen size to the helper, so it can clip the invalid region if it | 427 // Pass the screen size to the helper, so it can clip the invalid region if it |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 } | 630 } |
| 552 return capturer; | 631 return capturer; |
| 553 } | 632 } |
| 554 | 633 |
| 555 // static | 634 // static |
| 556 void Capturer::EnableXDamage(bool enable) { | 635 void Capturer::EnableXDamage(bool enable) { |
| 557 g_should_use_x_damage = enable; | 636 g_should_use_x_damage = enable; |
| 558 } | 637 } |
| 559 | 638 |
| 560 } // namespace remoting | 639 } // namespace remoting |
| OLD | NEW |