| 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/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 | 10 |
| 11 #include <set> | 11 #include <set> |
| 12 | 12 |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "remoting/base/types.h" |
| 16 #include "remoting/host/capturer_helper.h" | 17 #include "remoting/host/capturer_helper.h" |
| 17 #include "remoting/host/differ.h" | 18 #include "remoting/host/differ.h" |
| 18 #include "remoting/host/x_server_pixel_buffer.h" | 19 #include "remoting/host/x_server_pixel_buffer.h" |
| 19 | 20 |
| 20 namespace remoting { | 21 namespace remoting { |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 static const int kBytesPerPixel = 4; | 25 static const int kBytesPerPixel = 4; |
| 25 | 26 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 // A class to perform capturing for Linux. | 68 // A class to perform capturing for Linux. |
| 68 class CapturerLinux : public Capturer { | 69 class CapturerLinux : public Capturer { |
| 69 public: | 70 public: |
| 70 CapturerLinux(); | 71 CapturerLinux(); |
| 71 virtual ~CapturerLinux(); | 72 virtual ~CapturerLinux(); |
| 72 | 73 |
| 73 | 74 |
| 74 // Capturer interface. | 75 // Capturer interface. |
| 75 virtual void ScreenConfigurationChanged() OVERRIDE; | 76 virtual void ScreenConfigurationChanged() OVERRIDE; |
| 76 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; | 77 virtual media::VideoFrame::Format pixel_format() const OVERRIDE; |
| 77 virtual void ClearInvalidRegion() OVERRIDE; | 78 virtual void ClearInvalidRects() OVERRIDE; |
| 78 virtual void InvalidateRegion(const SkRegion& invalid_region) OVERRIDE; | 79 virtual void InvalidateRects(const InvalidRects& inval_rects) OVERRIDE; |
| 79 virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; | 80 virtual void InvalidateScreen(const gfx::Size& size) OVERRIDE; |
| 80 virtual void InvalidateFullScreen() OVERRIDE; | 81 virtual void InvalidateFullScreen() OVERRIDE; |
| 81 virtual void CaptureInvalidRegion(CaptureCompletedCallback* callback) | 82 virtual void CaptureInvalidRects(CaptureCompletedCallback* callback) OVERRIDE; |
| 82 OVERRIDE; | |
| 83 virtual const gfx::Size& size_most_recent() const OVERRIDE; | 83 virtual const gfx::Size& size_most_recent() const OVERRIDE; |
| 84 | 84 |
| 85 private: | 85 private: |
| 86 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? | 86 bool Init(); // TODO(ajwong): Do we really want this to be synchronous? |
| 87 | 87 |
| 88 void InitXDamage(); | 88 void InitXDamage(); |
| 89 | 89 |
| 90 // Read and handle all currently-pending XEvents. | 90 // Read and handle all currently-pending XEvents. |
| 91 // In the DAMAGE case, process the XDamage events and store the resulting | 91 // In the DAMAGE case, process the XDamage events and store the resulting |
| 92 // damage rectangles in the CapturerHelper. | 92 // damage rectangles in the CapturerHelper. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 107 // the area of |last_invalid_rects|. | 107 // the area of |last_invalid_rects|. |
| 108 // Note this only works on the assumption that kNumBuffers == 2, as | 108 // Note this only works on the assumption that kNumBuffers == 2, as |
| 109 // |last_invalid_rects| holds the differences from the previous buffer and | 109 // |last_invalid_rects| holds the differences from the previous buffer and |
| 110 // the one prior to that (which will then be the current buffer). | 110 // the one prior to that (which will then be the current buffer). |
| 111 void SynchronizeFrame(); | 111 void SynchronizeFrame(); |
| 112 | 112 |
| 113 void DeinitXlib(); | 113 void DeinitXlib(); |
| 114 | 114 |
| 115 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into | 115 // Capture a rectangle from |x_server_pixel_buffer_|, and copy the data into |
| 116 // |capture_data|. | 116 // |capture_data|. |
| 117 void CaptureRect(const SkIRect& rect, CaptureData* capture_data); | 117 void CaptureRect(const gfx::Rect& rect, CaptureData* capture_data); |
| 118 | 118 |
| 119 // We expose two forms of blitting to handle variations in the pixel format. | 119 // We expose two forms of blitting to handle variations in the pixel format. |
| 120 // In FastBlit, the operation is effectively a memcpy. | 120 // In FastBlit, the operation is effectively a memcpy. |
| 121 void FastBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); | 121 void FastBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data); |
| 122 void SlowBlit(uint8* image, const SkIRect& rect, CaptureData* capture_data); | 122 void SlowBlit(uint8* image, const gfx::Rect& rect, CaptureData* capture_data); |
| 123 | 123 |
| 124 // X11 graphics context. | 124 // X11 graphics context. |
| 125 Display* display_; | 125 Display* display_; |
| 126 GC gc_; | 126 GC gc_; |
| 127 Window root_window_; | 127 Window root_window_; |
| 128 | 128 |
| 129 // XDamage information. | 129 // XDamage information. |
| 130 bool use_damage_; | 130 bool use_damage_; |
| 131 Damage damage_handle_; | 131 Damage damage_handle_; |
| 132 int damage_event_base_; | 132 int damage_event_base_; |
| 133 int damage_error_base_; | 133 int damage_error_base_; |
| 134 | 134 |
| 135 // Access to the X Server's pixel buffer. | 135 // Access to the X Server's pixel buffer. |
| 136 XServerPixelBuffer x_server_pixel_buffer_; | 136 XServerPixelBuffer x_server_pixel_buffer_; |
| 137 | 137 |
| 138 // A thread-safe list of invalid rectangles, and the size of the most | 138 // A thread-safe list of invalid rectangles, and the size of the most |
| 139 // recently captured screen. | 139 // recently captured screen. |
| 140 CapturerHelper helper_; | 140 CapturerHelper helper_; |
| 141 | 141 |
| 142 // Capture state. | 142 // Capture state. |
| 143 static const int kNumBuffers = 2; | 143 static const int kNumBuffers = 2; |
| 144 VideoFrameBuffer buffers_[kNumBuffers]; | 144 VideoFrameBuffer buffers_[kNumBuffers]; |
| 145 int current_buffer_; | 145 int current_buffer_; |
| 146 | 146 |
| 147 // Format of pixels returned in buffer. | 147 // Format of pixels returned in buffer. |
| 148 media::VideoFrame::Format pixel_format_; | 148 media::VideoFrame::Format pixel_format_; |
| 149 | 149 |
| 150 // Invalid region from the previous capture. This is used to synchronize the | 150 // Invalid rects in the last capture. This is used to synchronize current with |
| 151 // current with the last buffer used. | 151 // the previous buffer used. |
| 152 SkRegion last_invalid_region_; | 152 InvalidRects last_invalid_rects_; |
| 153 | 153 |
| 154 // Last capture buffer used. | 154 // Last capture buffer used. |
| 155 uint8* last_buffer_; | 155 uint8* last_buffer_; |
| 156 | 156 |
| 157 // |Differ| for use when polling for changes. | 157 // |Differ| for use when polling for changes. |
| 158 scoped_ptr<Differ> differ_; | 158 scoped_ptr<Differ> differ_; |
| 159 | 159 |
| 160 DISALLOW_COPY_AND_ASSIGN(CapturerLinux); | 160 DISALLOW_COPY_AND_ASSIGN(CapturerLinux); |
| 161 }; | 161 }; |
| 162 | 162 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 } else { | 233 } else { |
| 234 LOG(INFO) << "Server does not support XDamage."; | 234 LOG(INFO) << "Server does not support XDamage."; |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 | 237 |
| 238 void CapturerLinux::ScreenConfigurationChanged() { | 238 void CapturerLinux::ScreenConfigurationChanged() { |
| 239 last_buffer_ = NULL; | 239 last_buffer_ = NULL; |
| 240 for (int i = 0; i < kNumBuffers; ++i) { | 240 for (int i = 0; i < kNumBuffers; ++i) { |
| 241 buffers_[i].set_needs_update(); | 241 buffers_[i].set_needs_update(); |
| 242 } | 242 } |
| 243 helper_.ClearInvalidRegion(); | 243 InvalidRects rects; |
| 244 helper_.SwapInvalidRects(rects); |
| 244 x_server_pixel_buffer_.Init(display_); | 245 x_server_pixel_buffer_.Init(display_); |
| 245 } | 246 } |
| 246 | 247 |
| 247 media::VideoFrame::Format CapturerLinux::pixel_format() const { | 248 media::VideoFrame::Format CapturerLinux::pixel_format() const { |
| 248 return pixel_format_; | 249 return pixel_format_; |
| 249 } | 250 } |
| 250 | 251 |
| 251 void CapturerLinux::ClearInvalidRegion() { | 252 void CapturerLinux::ClearInvalidRects() { |
| 252 helper_.ClearInvalidRegion(); | 253 helper_.ClearInvalidRects(); |
| 253 } | 254 } |
| 254 | 255 |
| 255 void CapturerLinux::InvalidateRegion(const SkRegion& invalid_region) { | 256 void CapturerLinux::InvalidateRects(const InvalidRects& inval_rects) { |
| 256 helper_.InvalidateRegion(invalid_region); | 257 helper_.InvalidateRects(inval_rects); |
| 257 } | 258 } |
| 258 | 259 |
| 259 void CapturerLinux::InvalidateScreen(const gfx::Size& size) { | 260 void CapturerLinux::InvalidateScreen(const gfx::Size& size) { |
| 260 helper_.InvalidateScreen(size); | 261 helper_.InvalidateScreen(size); |
| 261 } | 262 } |
| 262 | 263 |
| 263 void CapturerLinux::InvalidateFullScreen() { | 264 void CapturerLinux::InvalidateFullScreen() { |
| 264 helper_.InvalidateFullScreen(); | 265 helper_.InvalidateFullScreen(); |
| 265 last_buffer_ = NULL; | 266 last_buffer_ = NULL; |
| 266 } | 267 } |
| 267 | 268 |
| 268 void CapturerLinux::CaptureInvalidRegion( | 269 void CapturerLinux::CaptureInvalidRects( |
| 269 CaptureCompletedCallback* callback) { | 270 CaptureCompletedCallback* callback) { |
| 270 scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); | 271 scoped_ptr<CaptureCompletedCallback> callback_deleter(callback); |
| 271 | 272 |
| 272 // TODO(lambroslambrou): In the non-DAMAGE case, there should be no need | 273 // TODO(lambroslambrou): In the non-DAMAGE case, there should be no need |
| 273 // for any X event processing in this class. | 274 // for any X event processing in this class. |
| 274 ProcessPendingXEvents(); | 275 ProcessPendingXEvents(); |
| 275 | 276 |
| 276 // Resize the current buffer if there was a recent change of | 277 // Resize the current buffer if there was a recent change of |
| 277 // screen-resolution. | 278 // screen-resolution. |
| 278 VideoFrameBuffer ¤t = buffers_[current_buffer_]; | 279 VideoFrameBuffer ¤t = buffers_[current_buffer_]; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 289 helper_.set_size_most_recent(capture_data->size()); | 290 helper_.set_size_most_recent(capture_data->size()); |
| 290 | 291 |
| 291 callback->Run(capture_data); | 292 callback->Run(capture_data); |
| 292 } | 293 } |
| 293 | 294 |
| 294 void CapturerLinux::ProcessPendingXEvents() { | 295 void CapturerLinux::ProcessPendingXEvents() { |
| 295 // Find the number of events that are outstanding "now." We don't just loop | 296 // Find the number of events that are outstanding "now." We don't just loop |
| 296 // on XPending because we want to guarantee this terminates. | 297 // on XPending because we want to guarantee this terminates. |
| 297 int events_to_process = XPending(display_); | 298 int events_to_process = XPending(display_); |
| 298 XEvent e; | 299 XEvent e; |
| 299 SkRegion invalid_region; | 300 InvalidRects invalid_rects; |
| 300 | 301 |
| 301 for (int i = 0; i < events_to_process; i++) { | 302 for (int i = 0; i < events_to_process; i++) { |
| 302 XNextEvent(display_, &e); | 303 XNextEvent(display_, &e); |
| 303 if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) { | 304 if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) { |
| 304 XDamageNotifyEvent *event = reinterpret_cast<XDamageNotifyEvent*>(&e); | 305 XDamageNotifyEvent *event = reinterpret_cast<XDamageNotifyEvent*>(&e); |
| 305 | 306 |
| 306 // TODO(hclam): Perform more checks on the rect. | 307 // TODO(hclam): Perform more checks on the rect. |
| 307 if (event->area.width <= 0 || event->area.height <= 0) | 308 if (event->area.width <= 0 || event->area.height <= 0) |
| 308 continue; | 309 continue; |
| 309 | 310 |
| 310 SkIRect damage_rect = SkIRect::MakeXYWH(event->area.x, | 311 gfx::Rect damage_rect(event->area.x, event->area.y, event->area.width, |
| 311 event->area.y, | 312 event->area.height); |
| 312 event->area.width, | 313 invalid_rects.insert(damage_rect); |
| 313 event->area.height); | 314 VLOG(3) << "Damage received for rect at (" |
| 314 invalid_region.op(damage_rect, SkRegion::kUnion_Op); | 315 << damage_rect.x() << "," << damage_rect.y() << ") size (" |
| 315 DVLOG(3) << "Damage received for rect at (" | 316 << damage_rect.width() << "," << damage_rect.height() << ")"; |
| 316 << damage_rect.fLeft << "," << damage_rect.fTop << ") size (" | |
| 317 << damage_rect.width() << "," << damage_rect.height() << ")"; | |
| 318 } else if (e.type == ConfigureNotify) { | 317 } else if (e.type == ConfigureNotify) { |
| 319 ScreenConfigurationChanged(); | 318 ScreenConfigurationChanged(); |
| 320 invalid_region.setEmpty(); | 319 invalid_rects.clear(); |
| 321 } else { | 320 } else { |
| 322 LOG(WARNING) << "Got unknown event type: " << e.type; | 321 LOG(WARNING) << "Got unknown event type: " << e.type; |
| 323 } | 322 } |
| 324 } | 323 } |
| 325 | 324 |
| 326 helper_.InvalidateRegion(invalid_region); | 325 helper_.InvalidateRects(invalid_rects); |
| 327 } | 326 } |
| 328 | 327 |
| 329 CaptureData* CapturerLinux::CaptureFrame() { | 328 CaptureData* CapturerLinux::CaptureFrame() { |
| 330 VideoFrameBuffer& buffer = buffers_[current_buffer_]; | 329 VideoFrameBuffer& buffer = buffers_[current_buffer_]; |
| 331 DataPlanes planes; | 330 DataPlanes planes; |
| 332 planes.data[0] = buffer.ptr(); | 331 planes.data[0] = buffer.ptr(); |
| 333 planes.strides[0] = buffer.bytes_per_row(); | 332 planes.strides[0] = buffer.bytes_per_row(); |
| 334 | 333 |
| 335 CaptureData* capture_data = new CaptureData(planes, buffer.size(), | 334 CaptureData* capture_data = new CaptureData(planes, buffer.size(), |
| 336 media::VideoFrame::RGB32); | 335 media::VideoFrame::RGB32); |
| 337 | 336 |
| 338 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame | 337 // In the DAMAGE case, ensure the frame is up-to-date with the previous frame |
| 339 // if any. If there isn't a previous frame, that means a screen-resolution | 338 // if any. If there isn't a previous frame, that means a screen-resolution |
| 340 // change occurred, and |invalid_rects| will be updated to include the whole | 339 // change occurred, and |invalid_rects| will be updated to include the whole |
| 341 // screen. | 340 // screen. |
| 342 if (use_damage_ && last_buffer_) | 341 if (use_damage_ && last_buffer_) |
| 343 SynchronizeFrame(); | 342 SynchronizeFrame(); |
| 344 | 343 |
| 345 SkRegion invalid_region; | 344 InvalidRects invalid_rects; |
| 346 | 345 |
| 347 x_server_pixel_buffer_.Synchronize(); | 346 x_server_pixel_buffer_.Synchronize(); |
| 348 if (use_damage_ && last_buffer_) { | 347 if (use_damage_ && last_buffer_) { |
| 349 helper_.SwapInvalidRegion(&invalid_region); | 348 helper_.SwapInvalidRects(invalid_rects); |
| 350 for (SkRegion::Iterator it(invalid_region); !it.done(); it.next()) { | 349 for (InvalidRects::const_iterator it = invalid_rects.begin(); |
| 351 CaptureRect(it.rect(), capture_data); | 350 it != invalid_rects.end(); |
| 351 ++it) { |
| 352 CaptureRect(*it, capture_data); |
| 352 } | 353 } |
| 353 // TODO(ajwong): We should only repair the rects that were copied! | 354 // TODO(ajwong): We should only repair the rects that were copied! |
| 354 XDamageSubtract(display_, damage_handle_, None, None); | 355 XDamageSubtract(display_, damage_handle_, None, None); |
| 355 } else { | 356 } else { |
| 356 // Doing full-screen polling, or this is the first capture after a | 357 // Doing full-screen polling, or this is the first capture after a |
| 357 // screen-resolution change. In either case, need a full-screen capture. | 358 // screen-resolution change. In either case, need a full-screen capture. |
| 358 SkIRect screen_rect = SkIRect::MakeWH(buffer.size().width(), | 359 gfx::Rect screen_rect(buffer.size()); |
| 359 buffer.size().height()); | |
| 360 CaptureRect(screen_rect, capture_data); | 360 CaptureRect(screen_rect, capture_data); |
| 361 | 361 |
| 362 if (last_buffer_) { | 362 if (last_buffer_) { |
| 363 // Full-screen polling, so calculate the invalid rects here, based on the | 363 // Full-screen polling, so calculate the invalid rects here, based on the |
| 364 // changed pixels between current and previous buffers. | 364 // changed pixels between current and previous buffers. |
| 365 DCHECK(differ_ != NULL); | 365 DCHECK(differ_ != NULL); |
| 366 differ_->CalcDirtyRegion(last_buffer_, buffer.ptr(), &invalid_region); | 366 differ_->CalcDirtyRects(last_buffer_, buffer.ptr(), &invalid_rects); |
| 367 } else { | 367 } else { |
| 368 // No previous buffer, so always invalidate the whole screen, whether | 368 // No previous buffer, so always invalidate the whole screen, whether |
| 369 // or not DAMAGE is being used. DAMAGE doesn't necessarily send a | 369 // or not DAMAGE is being used. DAMAGE doesn't necessarily send a |
| 370 // full-screen notification after a screen-resolution change, so | 370 // full-screen notification after a screen-resolution change, so |
| 371 // this is done here. | 371 // this is done here. |
| 372 invalid_region.op(screen_rect, SkRegion::kUnion_Op); | 372 invalid_rects.insert(screen_rect); |
| 373 } | 373 } |
| 374 } | 374 } |
| 375 | 375 |
| 376 capture_data->mutable_dirty_region() = invalid_region; | 376 capture_data->mutable_dirty_rects() = invalid_rects; |
| 377 last_invalid_region_ = invalid_region; | 377 last_invalid_rects_ = invalid_rects; |
| 378 last_buffer_ = buffer.ptr(); | 378 last_buffer_ = buffer.ptr(); |
| 379 return capture_data; | 379 return capture_data; |
| 380 } | 380 } |
| 381 | 381 |
| 382 void CapturerLinux::SynchronizeFrame() { | 382 void CapturerLinux::SynchronizeFrame() { |
| 383 // Synchronize the current buffer with the previous one since we do not | 383 // Synchronize the current buffer with the last one since we do not capture |
| 384 // capture the entire desktop. Note that encoder may be reading from the | 384 // the entire desktop. Note that encoder may be reading from the previous |
| 385 // previous buffer at this time so thread access complaints are false | 385 // buffer at this time so thread access complaints are false positives. |
| 386 // positives. | |
| 387 | 386 |
| 388 // TODO(hclam): We can reduce the amount of copying here by subtracting | 387 // TODO(hclam): We can reduce the amount of copying here by subtracting |
| 389 // |capturer_helper_|s region from |last_invalid_region_|. | 388 // |rects| from |last_invalid_rects_|. |
| 390 // http://crbug.com/92354 | |
| 391 DCHECK(last_buffer_); | 389 DCHECK(last_buffer_); |
| 392 VideoFrameBuffer& buffer = buffers_[current_buffer_]; | 390 VideoFrameBuffer& buffer = buffers_[current_buffer_]; |
| 393 for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) { | 391 for (InvalidRects::const_iterator it = last_invalid_rects_.begin(); |
| 394 const SkIRect& r = it.rect(); | 392 it != last_invalid_rects_.end(); |
| 395 int offset = r.fTop * buffer.bytes_per_row() + r.fLeft * kBytesPerPixel; | 393 ++it) { |
| 396 for (int i = 0; i < r.height(); ++i) { | 394 int offset = it->y() * buffer.bytes_per_row() + it->x() * kBytesPerPixel; |
| 395 for (int i = 0; i < it->height(); ++i) { |
| 397 memcpy(buffer.ptr() + offset, last_buffer_ + offset, | 396 memcpy(buffer.ptr() + offset, last_buffer_ + offset, |
| 398 r.width() * kBytesPerPixel); | 397 it->width() * kBytesPerPixel); |
| 399 offset += buffer.size().width() * kBytesPerPixel; | 398 offset += buffer.size().width() * kBytesPerPixel; |
| 400 } | 399 } |
| 401 } | 400 } |
| 402 } | 401 } |
| 403 | 402 |
| 404 void CapturerLinux::DeinitXlib() { | 403 void CapturerLinux::DeinitXlib() { |
| 405 if (gc_) { | 404 if (gc_) { |
| 406 XFreeGC(display_, gc_); | 405 XFreeGC(display_, gc_); |
| 407 gc_ = NULL; | 406 gc_ = NULL; |
| 408 } | 407 } |
| 409 | 408 |
| 410 if (display_) { | 409 if (display_) { |
| 411 XCloseDisplay(display_); | 410 XCloseDisplay(display_); |
| 412 display_ = NULL; | 411 display_ = NULL; |
| 413 } | 412 } |
| 414 } | 413 } |
| 415 | 414 |
| 416 void CapturerLinux::CaptureRect(const SkIRect& rect, | 415 void CapturerLinux::CaptureRect(const gfx::Rect& rect, |
| 417 CaptureData* capture_data) { | 416 CaptureData* capture_data) { |
| 418 uint8* image = x_server_pixel_buffer_.CaptureRect(rect); | 417 uint8* image = x_server_pixel_buffer_.CaptureRect(rect); |
| 419 int depth = x_server_pixel_buffer_.GetDepth(); | 418 int depth = x_server_pixel_buffer_.GetDepth(); |
| 420 int bpp = x_server_pixel_buffer_.GetBitsPerPixel(); | 419 int bpp = x_server_pixel_buffer_.GetBitsPerPixel(); |
| 421 bool is_rgb = x_server_pixel_buffer_.IsRgb(); | 420 bool is_rgb = x_server_pixel_buffer_.IsRgb(); |
| 422 if ((depth == 24 || depth == 32) && bpp == 32 && is_rgb) { | 421 if ((depth == 24 || depth == 32) && bpp == 32 && is_rgb) { |
| 423 DVLOG(3) << "Fast blitting"; | 422 VLOG(3) << "Fast blitting"; |
| 424 FastBlit(image, rect, capture_data); | 423 FastBlit(image, rect, capture_data); |
| 425 } else { | 424 } else { |
| 426 DVLOG(3) << "Slow blitting"; | 425 VLOG(3) << "Slow blitting"; |
| 427 SlowBlit(image, rect, capture_data); | 426 SlowBlit(image, rect, capture_data); |
| 428 } | 427 } |
| 429 } | 428 } |
| 430 | 429 |
| 431 void CapturerLinux::FastBlit(uint8* image, const SkIRect& rect, | 430 void CapturerLinux::FastBlit(uint8* image, const gfx::Rect& rect, |
| 432 CaptureData* capture_data) { | 431 CaptureData* capture_data) { |
| 433 uint8* src_pos = image; | 432 uint8* src_pos = image; |
| 434 int src_stride = x_server_pixel_buffer_.GetStride(); | 433 int src_stride = x_server_pixel_buffer_.GetStride(); |
| 435 int dst_x = rect.fLeft, dst_y = rect.fTop; | 434 int dst_x = rect.x(), dst_y = rect.y(); |
| 436 | 435 |
| 437 DataPlanes planes = capture_data->data_planes(); | 436 DataPlanes planes = capture_data->data_planes(); |
| 438 uint8* dst_buffer = planes.data[0]; | 437 uint8* dst_buffer = planes.data[0]; |
| 439 | 438 |
| 440 const int dst_stride = planes.strides[0]; | 439 const int dst_stride = planes.strides[0]; |
| 441 | 440 |
| 442 uint8* dst_pos = dst_buffer + dst_stride * dst_y; | 441 uint8* dst_pos = dst_buffer + dst_stride * dst_y; |
| 443 dst_pos += dst_x * kBytesPerPixel; | 442 dst_pos += dst_x * kBytesPerPixel; |
| 444 | 443 |
| 445 int height = rect.height(), row_bytes = rect.width() * kBytesPerPixel; | 444 int height = rect.height(), row_bytes = rect.width() * kBytesPerPixel; |
| 446 for (int y = 0; y < height; ++y) { | 445 for (int y = 0; y < height; ++y) { |
| 447 memcpy(dst_pos, src_pos, row_bytes); | 446 memcpy(dst_pos, src_pos, row_bytes); |
| 448 src_pos += src_stride; | 447 src_pos += src_stride; |
| 449 dst_pos += dst_stride; | 448 dst_pos += dst_stride; |
| 450 } | 449 } |
| 451 } | 450 } |
| 452 | 451 |
| 453 void CapturerLinux::SlowBlit(uint8* image, const SkIRect& rect, | 452 void CapturerLinux::SlowBlit(uint8* image, const gfx::Rect& rect, |
| 454 CaptureData* capture_data) { | 453 CaptureData* capture_data) { |
| 455 DataPlanes planes = capture_data->data_planes(); | 454 DataPlanes planes = capture_data->data_planes(); |
| 456 uint8* dst_buffer = planes.data[0]; | 455 uint8* dst_buffer = planes.data[0]; |
| 457 const int dst_stride = planes.strides[0]; | 456 const int dst_stride = planes.strides[0]; |
| 458 int src_stride = x_server_pixel_buffer_.GetStride(); | 457 int src_stride = x_server_pixel_buffer_.GetStride(); |
| 459 int dst_x = rect.fLeft, dst_y = rect.fTop; | 458 int dst_x = rect.x(), dst_y = rect.y(); |
| 460 int width = rect.width(), height = rect.height(); | 459 int width = rect.width(), height = rect.height(); |
| 461 | 460 |
| 462 unsigned int red_mask = x_server_pixel_buffer_.GetRedMask(); | 461 unsigned int red_mask = x_server_pixel_buffer_.GetRedMask(); |
| 463 unsigned int blue_mask = x_server_pixel_buffer_.GetBlueMask(); | 462 unsigned int blue_mask = x_server_pixel_buffer_.GetBlueMask(); |
| 464 unsigned int green_mask = x_server_pixel_buffer_.GetGreenMask(); | 463 unsigned int green_mask = x_server_pixel_buffer_.GetGreenMask(); |
| 465 unsigned int red_shift = x_server_pixel_buffer_.GetRedShift(); | 464 unsigned int red_shift = x_server_pixel_buffer_.GetRedShift(); |
| 466 unsigned int blue_shift = x_server_pixel_buffer_.GetBlueShift(); | 465 unsigned int blue_shift = x_server_pixel_buffer_.GetBlueShift(); |
| 467 unsigned int green_shift = x_server_pixel_buffer_.GetGreenShift(); | 466 unsigned int green_shift = x_server_pixel_buffer_.GetGreenShift(); |
| 468 | 467 |
| 469 unsigned int max_red = red_mask >> red_shift; | 468 unsigned int max_red = red_mask >> red_shift; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 } | 505 } |
| 507 | 506 |
| 508 } // namespace | 507 } // namespace |
| 509 | 508 |
| 510 // static | 509 // static |
| 511 Capturer* Capturer::Create() { | 510 Capturer* Capturer::Create() { |
| 512 return new CapturerLinux(); | 511 return new CapturerLinux(); |
| 513 } | 512 } |
| 514 | 513 |
| 515 } // namespace remoting | 514 } // namespace remoting |
| OLD | NEW |