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