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/video_frame_capturer.h" | 5 #include "remoting/host/video_frame_capturer.h" |
| 6 | 6 |
| 7 #include <ApplicationServices/ApplicationServices.h> | 7 #include <ApplicationServices/ApplicationServices.h> |
| 8 #include <Cocoa/Cocoa.h> | 8 #include <Cocoa/Cocoa.h> |
| 9 #include <dlfcn.h> | 9 #include <dlfcn.h> |
| 10 #include <IOKit/pwr_mgt/IOPMLib.h> | 10 #include <IOKit/pwr_mgt/IOPMLib.h> |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 VideoFrameBuffer() : | 47 VideoFrameBuffer() : |
| 48 size_(SkISize::Make(0, 0)), | 48 size_(SkISize::Make(0, 0)), |
| 49 dpi_(SkIPoint::Make(0, 0)), | 49 dpi_(SkIPoint::Make(0, 0)), |
| 50 bytes_per_row_(0), | 50 bytes_per_row_(0), |
| 51 needs_update_(true) { | 51 needs_update_(true) { |
| 52 } | 52 } |
| 53 | 53 |
| 54 // If the buffer is marked as needing to be updated (for example after the | 54 // If the buffer is marked as needing to be updated (for example after the |
| 55 // screen mode changes) and is the wrong size, then release the old buffer | 55 // screen mode changes) and is the wrong size, then release the old buffer |
| 56 // and create a new one. | 56 // and create a new one. |
| 57 void Update() { | 57 void Update(const SkISize& size) { |
| 58 if (needs_update_) { | 58 if (needs_update_) { |
| 59 needs_update_ = false; | 59 needs_update_ = false; |
| 60 CGDirectDisplayID mainDevice = CGMainDisplayID(); | 60 if (size != size_) { |
| 61 int width = CGDisplayPixelsWide(mainDevice); | 61 size_ = size; |
| 62 int height = CGDisplayPixelsHigh(mainDevice); | 62 bytes_per_row_ = size.width() * sizeof(uint32_t); |
| 63 if (width != size_.width() || height != size_.height()) { | 63 size_t buffer_size = size.width() * size.height() * sizeof(uint32_t); |
| 64 size_.set(width, height); | |
| 65 bytes_per_row_ = width * sizeof(uint32_t); | |
| 66 size_t buffer_size = width * height * sizeof(uint32_t); | |
| 67 ptr_.reset(new uint8[buffer_size]); | 64 ptr_.reset(new uint8[buffer_size]); |
| 68 } | 65 } |
| 66 | |
| 67 // TODO(wez): Move the ugly DPI code into a helper. | |
|
Jamie
2012/08/30 20:53:53
Since you mention DPI, does Mac support mixed DPI
Wez
2012/08/31 00:47:42
Not sure, but I suspect they do. My plan is to su
| |
| 69 NSScreen* screen = [NSScreen mainScreen]; | 68 NSScreen* screen = [NSScreen mainScreen]; |
| 70 NSDictionary* attr = [screen deviceDescription]; | 69 NSDictionary* attr = [screen deviceDescription]; |
| 71 NSSize resolution = [[attr objectForKey: NSDeviceResolution] sizeValue]; | 70 NSSize resolution = [[attr objectForKey: NSDeviceResolution] sizeValue]; |
| 72 dpi_.set(resolution.width, resolution.height); | 71 dpi_.set(resolution.width, resolution.height); |
| 73 } | 72 } |
| 74 } | 73 } |
| 75 | 74 |
| 76 SkISize size() const { return size_; } | 75 SkISize size() const { return size_; } |
| 77 SkIPoint dpi() const { return dpi_; } | 76 SkIPoint dpi() const { return dpi_; } |
| 78 int bytes_per_row() const { return bytes_per_row_; } | 77 int bytes_per_row() const { return bytes_per_row_; } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 CGDisplayChangeSummaryFlags flags, | 136 CGDisplayChangeSummaryFlags flags, |
| 138 void *user_parameter); | 137 void *user_parameter); |
| 139 | 138 |
| 140 void ReleaseBuffers(); | 139 void ReleaseBuffers(); |
| 141 | 140 |
| 142 CGLContextObj cgl_context_; | 141 CGLContextObj cgl_context_; |
| 143 static const int kNumBuffers = 2; | 142 static const int kNumBuffers = 2; |
| 144 ScopedPixelBufferObject pixel_buffer_object_; | 143 ScopedPixelBufferObject pixel_buffer_object_; |
| 145 VideoFrameBuffer buffers_[kNumBuffers]; | 144 VideoFrameBuffer buffers_[kNumBuffers]; |
| 146 | 145 |
| 146 // Current display configuration. | |
| 147 std::vector<CGDirectDisplayID> display_ids_; | |
| 148 SkIRect desktop_bounds_; | |
| 149 | |
| 147 // A thread-safe list of invalid rectangles, and the size of the most | 150 // A thread-safe list of invalid rectangles, and the size of the most |
| 148 // recently captured screen. | 151 // recently captured screen. |
| 149 VideoFrameCapturerHelper helper_; | 152 VideoFrameCapturerHelper helper_; |
| 150 | 153 |
| 151 // Callback notified whenever the cursor shape is changed. | 154 // Callback notified whenever the cursor shape is changed. |
| 152 CursorShapeChangedCallback cursor_shape_changed_callback_; | 155 CursorShapeChangedCallback cursor_shape_changed_callback_; |
| 153 | 156 |
| 154 // Image of the last cursor that we sent to the client. | 157 // Image of the last cursor that we sent to the client. |
| 155 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; | 158 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; |
| 156 | 159 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 const CaptureCompletedCallback& callback) { | 287 const CaptureCompletedCallback& callback) { |
| 285 // Only allow captures when the display configuration is not occurring. | 288 // Only allow captures when the display configuration is not occurring. |
| 286 scoped_refptr<CaptureData> data; | 289 scoped_refptr<CaptureData> data; |
| 287 | 290 |
| 288 // Critical section shared with DisplaysReconfigured(...). | 291 // Critical section shared with DisplaysReconfigured(...). |
| 289 CHECK(display_configuration_capture_event_.TimedWait( | 292 CHECK(display_configuration_capture_event_.TimedWait( |
| 290 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); | 293 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); |
| 291 SkRegion region; | 294 SkRegion region; |
| 292 helper_.SwapInvalidRegion(®ion); | 295 helper_.SwapInvalidRegion(®ion); |
| 293 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; | 296 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; |
| 294 current_buffer.Update(); | 297 current_buffer.Update(SkISize::Make(desktop_bounds_.width(), |
| 298 desktop_bounds_.height())); | |
| 295 | 299 |
| 296 bool flip = false; // GL capturers need flipping. | 300 bool flip = false; // GL capturers need flipping. |
| 297 if (base::mac::IsOSLionOrLater()) { | 301 if (base::mac::IsOSLionOrLater()) { |
| 298 // Lion requires us to use their new APIs for doing screen capture. These | 302 // Lion requires us to use their new APIs for doing screen capture. These |
| 299 // APIS currently crash on 10.6.8 if there is no monitor attached. | 303 // APIS currently crash on 10.6.8 if there is no monitor attached. |
| 300 CgBlitPostLion(current_buffer, region); | 304 CgBlitPostLion(current_buffer, region); |
| 301 } else if (cgl_context_) { | 305 } else if (cgl_context_) { |
| 302 flip = true; | 306 flip = true; |
| 303 if (pixel_buffer_object_.get() != 0) { | 307 if (pixel_buffer_object_.get() != 0) { |
| 304 GlBlitFast(current_buffer, region); | 308 GlBlitFast(current_buffer, region); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 glPixelStorei(GL_PACK_SKIP_PIXELS, 0); | 501 glPixelStorei(GL_PACK_SKIP_PIXELS, 0); |
| 498 // Read a block of pixels from the frame buffer. | 502 // Read a block of pixels from the frame buffer. |
| 499 glReadPixels(0, 0, buffer.size().width(), buffer.size().height(), | 503 glReadPixels(0, 0, buffer.size().width(), buffer.size().height(), |
| 500 GL_BGRA, GL_UNSIGNED_BYTE, buffer.ptr()); | 504 GL_BGRA, GL_UNSIGNED_BYTE, buffer.ptr()); |
| 501 glPopClientAttrib(); | 505 glPopClientAttrib(); |
| 502 } | 506 } |
| 503 | 507 |
| 504 void VideoFrameCapturerMac::CgBlitPreLion(const VideoFrameBuffer& buffer, | 508 void VideoFrameCapturerMac::CgBlitPreLion(const VideoFrameBuffer& buffer, |
| 505 const SkRegion& region) { | 509 const SkRegion& region) { |
| 506 const int buffer_height = buffer.size().height(); | 510 const int buffer_height = buffer.size().height(); |
| 507 const int buffer_width = buffer.size().width(); | |
| 508 | 511 |
| 509 // Clip to the size of our current screen. | 512 // Copy the entire contents of the previous capture buffer, to capture over. |
| 510 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); | 513 // TODO(wez): Get rid of this as per crbug.com/145064, or implement |
| 511 | 514 // crbug.com/92354. |
| 512 if (last_buffer_) | 515 if (last_buffer_) |
| 513 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height); | 516 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height); |
| 514 last_buffer_ = buffer.ptr(); | 517 last_buffer_ = buffer.ptr(); |
| 515 CGDirectDisplayID main_display = CGMainDisplayID(); | 518 |
| 519 for (unsigned int d = 0; d < display_ids_.size(); ++d) { | |
| 516 #pragma clang diagnostic push | 520 #pragma clang diagnostic push |
| 517 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 521 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| 518 uint8* display_base_address = | 522 uint8* display_base_address = |
| 519 reinterpret_cast<uint8*>(CGDisplayBaseAddress(main_display)); | 523 reinterpret_cast<uint8*>(CGDisplayBaseAddress(display_ids_[d])); |
| 520 CHECK(display_base_address); | 524 CHECK(display_base_address); |
| 521 int src_bytes_per_row = CGDisplayBytesPerRow(main_display); | 525 int src_bytes_per_row = CGDisplayBytesPerRow(display_ids_[d]); |
| 522 int src_bytes_per_pixel = CGDisplayBitsPerPixel(main_display) / 8; | 526 int src_bytes_per_pixel = CGDisplayBitsPerPixel(display_ids_[d]) / 8; |
| 523 #pragma clang diagnostic pop | 527 #pragma clang diagnostic pop |
| 524 // TODO(hclam): We can reduce the amount of copying here by subtracting | 528 // Determine the position of the display in the buffer. |
| 525 // |capturer_helper_|s region from |last_invalid_region_|. | 529 SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d])); |
| 526 // http://crbug.com/92354 | 530 display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top()); |
| 527 for(SkRegion::Iterator i(region); !i.done(); i.next()) { | 531 |
| 528 SkIRect copy_rect = i.rect(); | 532 // Determine which parts of the blit region, if any, lay within the monitor. |
| 529 if (copy_rect.intersect(clip_rect)) { | 533 SkRegion copy_region; |
| 534 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) | |
| 535 continue; | |
| 536 | |
| 537 // Translate the region to be copied into display-relative coordinates. | |
| 538 copy_region.translate(-display_bounds.left(), -display_bounds.top()); | |
| 539 | |
| 540 // Calculate where in the output buffer the display's origin is. | |
| 541 uint8* out_ptr = buffer.ptr() + | |
| 542 (display_bounds.left() * src_bytes_per_pixel) + | |
| 543 (display_bounds.top() * buffer.bytes_per_row()); | |
| 544 | |
| 545 // Copy the dirty region from the display buffer into our desktop buffer. | |
| 546 for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { | |
| 530 CopyRect(display_base_address, | 547 CopyRect(display_base_address, |
| 531 src_bytes_per_row, | 548 src_bytes_per_row, |
| 532 buffer.ptr(), | 549 out_ptr, |
| 533 buffer.bytes_per_row(), | 550 buffer.bytes_per_row(), |
| 534 src_bytes_per_pixel, | 551 src_bytes_per_pixel, |
| 535 copy_rect); | 552 i.rect()); |
| 536 } | 553 } |
| 537 } | 554 } |
| 538 } | 555 } |
| 539 | 556 |
| 540 void VideoFrameCapturerMac::CgBlitPostLion(const VideoFrameBuffer& buffer, | 557 void VideoFrameCapturerMac::CgBlitPostLion(const VideoFrameBuffer& buffer, |
| 541 const SkRegion& region) { | 558 const SkRegion& region) { |
| 542 const int buffer_height = buffer.size().height(); | 559 const int buffer_height = buffer.size().height(); |
| 543 const int buffer_width = buffer.size().width(); | |
| 544 | 560 |
| 545 // Clip to the size of our current screen. | 561 // Copy the entire contents of the previous capture buffer, to capture over. |
| 546 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); | 562 // TODO(wez): Get rid of this as per crbug.com/145064, or implement |
| 547 | 563 // crbug.com/92354. |
| 548 if (last_buffer_) | 564 if (last_buffer_) |
| 549 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height); | 565 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height); |
| 550 last_buffer_ = buffer.ptr(); | 566 last_buffer_ = buffer.ptr(); |
| 551 CGDirectDisplayID display = CGMainDisplayID(); | 567 |
| 552 base::mac::ScopedCFTypeRef<CGImageRef> image( | 568 for (unsigned int d = 0; d < display_ids_.size(); ++d) { |
| 553 CGDisplayCreateImage(display)); | 569 // Determine the position of the display in the buffer. |
| 554 if (image.get() == NULL) | 570 SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d])); |
| 555 return; | 571 display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top()); |
| 556 CGDataProviderRef provider = CGImageGetDataProvider(image); | 572 |
| 557 base::mac::ScopedCFTypeRef<CFDataRef> data(CGDataProviderCopyData(provider)); | 573 // Determine which parts of the blit region, if any, lay within the monitor. |
| 558 if (data.get() == NULL) | 574 SkRegion copy_region; |
| 559 return; | 575 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) |
| 560 const uint8* display_base_address = CFDataGetBytePtr(data); | 576 continue; |
| 561 int src_bytes_per_row = CGImageGetBytesPerRow(image); | 577 |
| 562 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; | 578 // Translate the region to be copied into display-relative coordinates. |
| 563 // TODO(hclam): We can reduce the amount of copying here by subtracting | 579 copy_region.translate(-display_bounds.left(), -display_bounds.top()); |
|
Jamie
2012/08/30 20:53:53
Is there any value in factoring out the common cod
Wez
2012/08/31 00:47:42
Yes, but I think it's worth holding off until we'v
| |
| 564 // |capturer_helper_|s region from |last_invalid_region_|. | 580 |
| 565 // http://crbug.com/92354 | 581 // Create an image containing a snapshot of the display. |
| 566 for(SkRegion::Iterator i(region); !i.done(); i.next()) { | 582 base::mac::ScopedCFTypeRef<CGImageRef> image( |
| 567 SkIRect copy_rect = i.rect(); | 583 CGDisplayCreateImage(display_ids_[d])); |
| 568 if (copy_rect.intersect(clip_rect)) { | 584 if (image.get() == NULL) |
| 585 continue; | |
| 586 | |
| 587 // Request access to the raw pixel data via the image's DataProvider. | |
| 588 CGDataProviderRef provider = CGImageGetDataProvider(image); | |
| 589 base::mac::ScopedCFTypeRef<CFDataRef> data( | |
| 590 CGDataProviderCopyData(provider)); | |
| 591 if (data.get() == NULL) | |
| 592 continue; | |
| 593 | |
| 594 const uint8* display_base_address = CFDataGetBytePtr(data); | |
| 595 int src_bytes_per_row = CGImageGetBytesPerRow(image); | |
| 596 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; | |
| 597 | |
| 598 // Calculate where in the output buffer the display's origin is. | |
| 599 uint8* out_ptr = buffer.ptr() + | |
| 600 (display_bounds.left() * src_bytes_per_pixel) + | |
| 601 (display_bounds.top() * buffer.bytes_per_row()); | |
| 602 | |
| 603 // Copy the dirty region from the display buffer into our desktop buffer. | |
| 604 for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { | |
| 569 CopyRect(display_base_address, | 605 CopyRect(display_base_address, |
| 570 src_bytes_per_row, | 606 src_bytes_per_row, |
| 571 buffer.ptr(), | 607 out_ptr, |
| 572 buffer.bytes_per_row(), | 608 buffer.bytes_per_row(), |
| 573 src_bytes_per_pixel, | 609 src_bytes_per_pixel, |
| 574 copy_rect); | 610 i.rect()); |
| 575 } | 611 } |
| 576 } | 612 } |
| 577 } | 613 } |
| 578 | 614 |
| 579 const SkISize& VideoFrameCapturerMac::size_most_recent() const { | 615 const SkISize& VideoFrameCapturerMac::size_most_recent() const { |
| 580 return helper_.size_most_recent(); | 616 return helper_.size_most_recent(); |
| 581 } | 617 } |
| 582 | 618 |
| 583 void VideoFrameCapturerMac::ScreenConfigurationChanged() { | 619 void VideoFrameCapturerMac::ScreenConfigurationChanged() { |
| 620 // Release existing buffers, which will be of the wrong size. | |
| 621 // TODO(wez): Don't release buffers unless we find we really need to. | |
|
Jamie
2012/08/30 20:53:53
Is this really a big enough win to warrant a TODO?
Wez
2012/08/31 00:47:42
Done.
| |
| 584 ReleaseBuffers(); | 622 ReleaseBuffers(); |
| 585 helper_.ClearInvalidRegion(); | |
| 586 last_buffer_ = NULL; | 623 last_buffer_ = NULL; |
| 587 | 624 |
| 588 CGDirectDisplayID mainDevice = CGMainDisplayID(); | 625 // Clear the dirty region, in case the display is down-sizing. |
| 589 int width = CGDisplayPixelsWide(mainDevice); | 626 // TODO(wez): Clamp the dirty region to the new display size rather |
| 590 int height = CGDisplayPixelsHigh(mainDevice); | 627 // than clearing it. |
|
Jamie
2012/08/30 20:53:53
Since we invalidate the entire screen below, this
Wez
2012/08/31 00:47:42
In future we may not need to invalidate the whole
| |
| 591 helper_.InvalidateScreen(SkISize::Make(width, height)); | 628 helper_.ClearInvalidRegion(); |
| 629 | |
| 630 // Fetch the list if active displays and calculate their bounds. | |
| 631 CGDisplayCount display_count; | |
| 632 CGError error = CGGetActiveDisplayList(0, NULL, &display_count); | |
| 633 CHECK_EQ(error, CGDisplayNoErr); | |
| 634 | |
| 635 display_ids_.resize(display_count); | |
| 636 error = CGGetActiveDisplayList(display_count, &display_ids_[0], | |
| 637 &display_count); | |
| 638 CHECK_EQ(error, CGDisplayNoErr); | |
| 639 CHECK_EQ(display_count, display_ids_.size()); | |
| 640 | |
| 641 desktop_bounds_ = SkIRect::MakeEmpty(); | |
| 642 for (unsigned int d = 0; d < display_count; ++d) { | |
| 643 CGRect display_bounds = CGDisplayBounds(display_ids_[d]); | |
| 644 desktop_bounds_.join(CGRectToSkIRect(display_bounds)); | |
| 645 } | |
| 646 | |
| 647 // Re-mark the entire desktop as dirty. | |
| 648 helper_.InvalidateScreen(SkISize::Make(desktop_bounds_.width(), | |
| 649 desktop_bounds_.height())); | |
| 650 | |
| 651 LOG(ERROR) << "Desktop bounds are (" << | |
| 652 desktop_bounds_.left() << "," << desktop_bounds_.top() << ")-(" << | |
| 653 desktop_bounds_.right() << "," << desktop_bounds_.bottom() << ")"; | |
|
Jamie
2012/08/30 20:53:53
Left-over debugging?
Wez
2012/08/31 00:47:42
Sure is; removed it on a branch of this CL, left i
| |
| 592 | 654 |
| 593 if (base::mac::IsOSLionOrLater()) { | 655 if (base::mac::IsOSLionOrLater()) { |
| 594 LOG(INFO) << "Using CgBlitPostLion."; | 656 LOG(INFO) << "Using CgBlitPostLion."; |
| 595 // No need for any OpenGL support on Lion | 657 // No need for any OpenGL support on Lion |
| 596 return; | 658 return; |
| 597 } | 659 } |
| 598 | 660 |
| 599 if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) { | 661 if (display_ids_.size() > 1) { |
| 600 LOG(INFO) << "Using CgBlitPreLion."; | 662 LOG(INFO) << "Using CgBlitPreLion (Multi-monitor)."; |
| 601 return; | 663 return; |
| 602 } | 664 } |
| 603 | 665 |
| 666 if (!CGDisplayUsesOpenGLAcceleration(CGMainDisplayID())) { | |
| 667 LOG(INFO) << "Using CgBlitPreLion (OpenGL unavailable)."; | |
| 668 return; | |
| 669 } | |
| 670 | |
| 604 LOG(INFO) << "Using GlBlit"; | 671 LOG(INFO) << "Using GlBlit"; |
| 605 | 672 |
| 606 CGLPixelFormatAttribute attributes[] = { | 673 CGLPixelFormatAttribute attributes[] = { |
| 607 kCGLPFAFullScreen, | 674 kCGLPFAFullScreen, |
| 608 kCGLPFADisplayMask, | 675 kCGLPFADisplayMask, |
| 609 (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice), | 676 (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(0 /*mainDevice*/), |
|
Jamie
2012/08/30 20:53:53
Why this change?
Wez
2012/08/31 00:47:42
Done.
| |
| 610 (CGLPixelFormatAttribute)0 | 677 (CGLPixelFormatAttribute)0 |
| 611 }; | 678 }; |
| 612 CGLPixelFormatObj pixel_format = NULL; | 679 CGLPixelFormatObj pixel_format = NULL; |
| 613 GLint matching_pixel_format_count = 0; | 680 GLint matching_pixel_format_count = 0; |
| 614 CGLError err = CGLChoosePixelFormat(attributes, | 681 CGLError err = CGLChoosePixelFormat(attributes, |
| 615 &pixel_format, | 682 &pixel_format, |
| 616 &matching_pixel_format_count); | 683 &matching_pixel_format_count); |
| 617 DCHECK_EQ(err, kCGLNoError); | 684 DCHECK_EQ(err, kCGLNoError); |
| 618 err = CGLCreateContext(pixel_format, NULL, &cgl_context_); | 685 err = CGLCreateContext(pixel_format, NULL, &cgl_context_); |
| 619 DCHECK_EQ(err, kCGLNoError); | 686 DCHECK_EQ(err, kCGLNoError); |
| 620 CGLDestroyPixelFormat(pixel_format); | 687 CGLDestroyPixelFormat(pixel_format); |
| 621 #pragma clang diagnostic push | 688 #pragma clang diagnostic push |
| 622 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 689 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| 623 // TODO(jamiewalch): The non-deprecated equivalent code is shown below, but | 690 // TODO(jamiewalch): The non-deprecated equivalent code is shown below, but |
| 624 // it causes 10.6 Macs' displays to go black. Find out why. | 691 // it causes 10.6 Macs' displays to go black. Find out why. |
| 625 // | 692 // |
| 626 // CGLSetFullScreenOnDisplay(cgl_context_, | 693 // CGLSetFullScreenOnDisplay(cgl_context_, |
| 627 // CGDisplayIDToOpenGLDisplayMask(mainDevice)); | 694 // CGDisplayIDToOpenGLDisplayMask(mainDevice)); |
| 628 CGLSetFullScreen(cgl_context_); | 695 CGLSetFullScreen(cgl_context_); |
| 629 #pragma clang diagnostic pop | 696 #pragma clang diagnostic pop |
| 630 CGLSetCurrentContext(cgl_context_); | 697 CGLSetCurrentContext(cgl_context_); |
| 631 | 698 |
| 632 size_t buffer_size = width * height * sizeof(uint32_t); | 699 size_t buffer_size = desktop_bounds_.width() * desktop_bounds_.height() * |
| 700 sizeof(uint32_t); | |
| 633 pixel_buffer_object_.Init(cgl_context_, buffer_size); | 701 pixel_buffer_object_.Init(cgl_context_, buffer_size); |
| 634 } | 702 } |
| 635 | 703 |
| 636 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count, | 704 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count, |
| 637 const CGRect* rect_array) { | 705 const CGRect* rect_array) { |
| 638 SkIRect skirect_array[count]; | 706 SkIRect skirect_array[count]; |
| 639 for (CGRectCount i = 0; i < count; ++i) { | 707 for (CGRectCount i = 0; i < count; ++i) { |
| 640 skirect_array[i] = CGRectToSkIRect(rect_array[i]); | 708 skirect_array[i] = CGRectToSkIRect(rect_array[i]); |
| 709 skirect_array[i].offset(-desktop_bounds_.left(), -desktop_bounds_.top()); | |
| 641 } | 710 } |
| 642 SkRegion region; | 711 SkRegion region; |
| 643 region.setRects(skirect_array, count); | 712 region.setRects(skirect_array, count); |
| 644 InvalidateRegion(region); | 713 InvalidateRegion(region); |
| 645 } | 714 } |
| 646 | 715 |
| 647 void VideoFrameCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, | 716 void VideoFrameCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, |
| 648 size_t count, | 717 size_t count, |
| 649 const CGRect* rect_array) { | 718 const CGRect* rect_array) { |
| 650 SkIRect skirect_new_array[count]; | 719 SkIRect skirect_array[count]; |
| 651 for (CGRectCount i = 0; i < count; ++i) { | 720 for (CGRectCount i = 0; i < count; ++i) { |
| 652 CGRect rect = rect_array[i]; | 721 CGRect rect = rect_array[i]; |
| 653 rect = CGRectOffset(rect, delta.dX, delta.dY); | 722 rect = CGRectOffset(rect, delta.dX, delta.dY); |
| 654 skirect_new_array[i] = CGRectToSkIRect(rect); | 723 skirect_array[i] = CGRectToSkIRect(rect); |
| 724 skirect_array[i].offset(-desktop_bounds_.left(), -desktop_bounds_.top()); | |
| 655 } | 725 } |
| 656 SkRegion region; | 726 SkRegion region; |
| 657 region.setRects(skirect_new_array, count); | 727 region.setRects(skirect_array, count); |
| 658 InvalidateRegion(region); | 728 InvalidateRegion(region); |
| 659 } | 729 } |
| 660 | 730 |
| 661 void VideoFrameCapturerMac::DisplaysReconfigured( | 731 void VideoFrameCapturerMac::DisplaysReconfigured( |
| 662 CGDirectDisplayID display, | 732 CGDirectDisplayID display, |
| 663 CGDisplayChangeSummaryFlags flags) { | 733 CGDisplayChangeSummaryFlags flags) { |
| 664 if (display == CGMainDisplayID()) { | 734 if (display == CGMainDisplayID()) { |
| 665 if (flags & kCGDisplayBeginConfigurationFlag) { | 735 if (flags & kCGDisplayBeginConfigurationFlag) { |
| 666 // Wait on |display_configuration_capture_event_| to prevent more | 736 // Wait on |display_configuration_capture_event_| to prevent more |
| 667 // captures from occurring on a different thread while the displays | 737 // captures from occurring on a different thread while the displays |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 710 VideoFrameCapturer* VideoFrameCapturer::Create() { | 780 VideoFrameCapturer* VideoFrameCapturer::Create() { |
| 711 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac(); | 781 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac(); |
| 712 if (!capturer->Init()) { | 782 if (!capturer->Init()) { |
| 713 delete capturer; | 783 delete capturer; |
| 714 capturer = NULL; | 784 capturer = NULL; |
| 715 } | 785 } |
| 716 return capturer; | 786 return capturer; |
| 717 } | 787 } |
| 718 | 788 |
| 719 } // namespace remoting | 789 } // namespace remoting |
| OLD | NEW |