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/capturer/video_frame_capturer.h" | 5 #include "remoting/capturer/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> |
11 #include <OpenGL/CGLMacro.h> | 11 #include <OpenGL/CGLMacro.h> |
12 #include <OpenGL/OpenGL.h> | 12 #include <OpenGL/OpenGL.h> |
13 #include <set> | 13 #include <set> |
14 #include <stddef.h> | 14 #include <stddef.h> |
15 | 15 |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/file_path.h" | 17 #include "base/file_path.h" |
18 #include "base/mac/mac_util.h" | 18 #include "base/mac/mac_util.h" |
19 #include "base/mac/scoped_cftyperef.h" | 19 #include "base/mac/scoped_cftyperef.h" |
20 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
21 #include "base/scoped_native_library.h" | 21 #include "base/scoped_native_library.h" |
22 #include "base/synchronization/waitable_event.h" | 22 #include "base/synchronization/waitable_event.h" |
23 #include "base/time.h" | 23 #include "base/time.h" |
24 #include "remoting/capturer/capture_data.h" | 24 #include "remoting/capturer/capture_data.h" |
| 25 #include "remoting/capturer/mac/desktop_configuration.h" |
25 #include "remoting/capturer/mac/scoped_pixel_buffer_object.h" | 26 #include "remoting/capturer/mac/scoped_pixel_buffer_object.h" |
26 #include "remoting/capturer/mouse_cursor_shape.h" | 27 #include "remoting/capturer/mouse_cursor_shape.h" |
27 #include "remoting/capturer/video_frame.h" | 28 #include "remoting/capturer/video_frame.h" |
28 #include "remoting/capturer/video_frame_capturer_helper.h" | 29 #include "remoting/capturer/video_frame_capturer_helper.h" |
29 #include "remoting/capturer/video_frame_queue.h" | 30 #include "remoting/capturer/video_frame_queue.h" |
| 31 #include "skia/ext/skia_utils_mac.h" |
30 | 32 |
31 namespace remoting { | 33 namespace remoting { |
32 | 34 |
33 namespace { | 35 namespace { |
34 | 36 |
35 // Definitions used to dynamic-link to deprecated OS 10.6 functions. | 37 // Definitions used to dynamic-link to deprecated OS 10.6 functions. |
36 const char* kApplicationServicesLibraryName = | 38 const char* kApplicationServicesLibraryName = |
37 "/System/Library/Frameworks/ApplicationServices.framework/" | 39 "/System/Library/Frameworks/ApplicationServices.framework/" |
38 "ApplicationServices"; | 40 "ApplicationServices"; |
39 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID); | 41 typedef void* (*CGDisplayBaseAddressFunc)(CGDirectDisplayID); |
40 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID); | 42 typedef size_t (*CGDisplayBytesPerRowFunc)(CGDirectDisplayID); |
41 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID); | 43 typedef size_t (*CGDisplayBitsPerPixelFunc)(CGDirectDisplayID); |
42 const char* kOpenGlLibraryName = | 44 const char* kOpenGlLibraryName = |
43 "/System/Library/Frameworks/OpenGL.framework/OpenGL"; | 45 "/System/Library/Frameworks/OpenGL.framework/OpenGL"; |
44 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj); | 46 typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj); |
45 | 47 |
| 48 // Standard DPI for Mac OS X displays with 1:1 backing scale. |
| 49 const int kStandardDPI = 72; |
| 50 |
46 // skia/ext/skia_utils_mac.h only defines CGRectToSkRect(). | 51 // skia/ext/skia_utils_mac.h only defines CGRectToSkRect(). |
47 SkIRect CGRectToSkIRect(const CGRect& rect) { | 52 SkIRect CGRectToSkIRect(const CGRect& rect) { |
48 SkIRect sk_rect = { | 53 SkIRect result; |
49 SkScalarRound(rect.origin.x), | 54 gfx::CGRectToSkRect(rect).round(&result); |
50 SkScalarRound(rect.origin.y), | 55 return result; |
51 SkScalarRound(rect.origin.x + rect.size.width), | 56 } |
52 SkScalarRound(rect.origin.y + rect.size.height) | 57 |
| 58 // Scales all coordinates of an SkRect by a specified factor. |
| 59 SkRect ScaleSkRect(const SkRect& rect, float scale) { |
| 60 SkRect result = { |
| 61 rect.left() * scale, rect.top() * scale, |
| 62 rect.right() * scale, rect.bottom() * scale |
53 }; | 63 }; |
54 return sk_rect; | 64 return result; |
55 } | 65 } |
56 | 66 |
57 // Copy pixels in the |rect| from |src_place| to |dest_plane|. | 67 // Copy pixels in the |rect| from |src_place| to |dest_plane|. |
58 void CopyRect(const uint8* src_plane, | 68 void CopyRect(const uint8* src_plane, |
59 int src_plane_stride, | 69 int src_plane_stride, |
60 uint8* dest_plane, | 70 uint8* dest_plane, |
61 int dest_plane_stride, | 71 int dest_plane_stride, |
62 int bytes_per_pixel, | 72 int bytes_per_pixel, |
63 const SkIRect& rect) { | 73 const SkIRect& rect) { |
64 // Get the address of the starting point. | 74 // Get the address of the starting point. |
(...skipping 12 matching lines...) Expand all Loading... |
77 dest_plane += dest_plane_stride; | 87 dest_plane += dest_plane_stride; |
78 } | 88 } |
79 } | 89 } |
80 | 90 |
81 // The amount of time allowed for displays to reconfigure. | 91 // The amount of time allowed for displays to reconfigure. |
82 const int64 kDisplayConfigurationEventTimeoutInSeconds = 10; | 92 const int64 kDisplayConfigurationEventTimeoutInSeconds = 10; |
83 | 93 |
84 // A class representing a full-frame pixel buffer. | 94 // A class representing a full-frame pixel buffer. |
85 class VideoFrameMac : public VideoFrame { | 95 class VideoFrameMac : public VideoFrame { |
86 public: | 96 public: |
87 explicit VideoFrameMac(const SkISize& size); | 97 explicit VideoFrameMac(const MacDesktopConfiguration& desktop_config); |
88 virtual ~VideoFrameMac(); | 98 virtual ~VideoFrameMac(); |
89 | 99 |
90 const SkIPoint& dpi() const { return dpi_; } | 100 const SkIPoint& dpi() const { return dpi_; } |
91 | 101 |
92 private: | 102 private: |
93 // Allocated pixel buffer. | 103 // Allocated pixel buffer. |
94 scoped_array<uint8> data_; | 104 scoped_array<uint8> data_; |
95 | 105 |
96 // DPI settings for this buffer. | 106 // DPI settings for this buffer. |
97 SkIPoint dpi_; | 107 SkIPoint dpi_; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 | 155 |
146 Delegate* delegate_; | 156 Delegate* delegate_; |
147 | 157 |
148 CGLContextObj cgl_context_; | 158 CGLContextObj cgl_context_; |
149 ScopedPixelBufferObject pixel_buffer_object_; | 159 ScopedPixelBufferObject pixel_buffer_object_; |
150 | 160 |
151 // Queue of the frames buffers. | 161 // Queue of the frames buffers. |
152 VideoFrameQueue queue_; | 162 VideoFrameQueue queue_; |
153 | 163 |
154 // Current display configuration. | 164 // Current display configuration. |
155 std::vector<CGDirectDisplayID> display_ids_; | 165 MacDesktopConfiguration desktop_config_; |
156 SkIRect desktop_bounds_; | |
157 | 166 |
158 // A thread-safe list of invalid rectangles, and the size of the most | 167 // A thread-safe list of invalid rectangles, and the size of the most |
159 // recently captured screen. | 168 // recently captured screen. |
160 VideoFrameCapturerHelper helper_; | 169 VideoFrameCapturerHelper helper_; |
161 | 170 |
162 // Image of the last cursor that we sent to the client. | 171 // Image of the last cursor that we sent to the client. |
163 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; | 172 base::mac::ScopedCFTypeRef<CGImageRef> current_cursor_; |
164 | 173 |
165 // Contains an invalid region from the previous capture. | 174 // Contains an invalid region from the previous capture. |
166 SkRegion last_invalid_region_; | 175 SkRegion last_invalid_region_; |
(...skipping 16 matching lines...) Expand all Loading... |
183 base::ScopedNativeLibrary app_services_library_; | 192 base::ScopedNativeLibrary app_services_library_; |
184 CGDisplayBaseAddressFunc cg_display_base_address_; | 193 CGDisplayBaseAddressFunc cg_display_base_address_; |
185 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; | 194 CGDisplayBytesPerRowFunc cg_display_bytes_per_row_; |
186 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; | 195 CGDisplayBitsPerPixelFunc cg_display_bits_per_pixel_; |
187 base::ScopedNativeLibrary opengl_library_; | 196 base::ScopedNativeLibrary opengl_library_; |
188 CGLSetFullScreenFunc cgl_set_full_screen_; | 197 CGLSetFullScreenFunc cgl_set_full_screen_; |
189 | 198 |
190 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac); | 199 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac); |
191 }; | 200 }; |
192 | 201 |
193 VideoFrameMac::VideoFrameMac(const SkISize& size) { | 202 VideoFrameMac::VideoFrameMac(const MacDesktopConfiguration& desktop_config) { |
| 203 SkISize size = SkISize::Make(desktop_config.pixel_bounds.width(), |
| 204 desktop_config.pixel_bounds.height()); |
194 set_bytes_per_row(size.width() * sizeof(uint32_t)); | 205 set_bytes_per_row(size.width() * sizeof(uint32_t)); |
195 set_dimensions(size); | 206 set_dimensions(size); |
196 | 207 |
197 size_t buffer_size = size.width() * size.height() * sizeof(uint32_t); | 208 size_t buffer_size = size.width() * size.height() * sizeof(uint32_t); |
198 data_.reset(new uint8[buffer_size]); | 209 data_.reset(new uint8[buffer_size]); |
199 set_pixels(data_.get()); | 210 set_pixels(data_.get()); |
200 | 211 |
201 // TODO(wez): Move the ugly DPI code into a helper. | 212 dpi_ = SkIPoint::Make(kStandardDPI * desktop_config.dip_to_pixel_scale, |
202 NSScreen* screen = [NSScreen mainScreen]; | 213 kStandardDPI * desktop_config.dip_to_pixel_scale); |
203 NSDictionary* attr = [screen deviceDescription]; | |
204 NSSize resolution = [[attr objectForKey: NSDeviceResolution] sizeValue]; | |
205 dpi_.set(resolution.width, resolution.height); | |
206 } | 214 } |
207 | 215 |
208 VideoFrameMac::~VideoFrameMac() { | 216 VideoFrameMac::~VideoFrameMac() { |
209 } | 217 } |
210 | 218 |
211 VideoFrameCapturerMac::VideoFrameCapturerMac() | 219 VideoFrameCapturerMac::VideoFrameCapturerMac() |
212 : delegate_(NULL), | 220 : delegate_(NULL), |
213 cgl_context_(NULL), | 221 cgl_context_(NULL), |
214 display_configuration_capture_event_(false, true), | 222 display_configuration_capture_event_(false, true), |
215 power_assertion_id_display_(kIOPMNullAssertionID), | 223 power_assertion_id_display_(kIOPMNullAssertionID), |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 base::TimeDelta::FromSeconds( | 329 base::TimeDelta::FromSeconds( |
322 kDisplayConfigurationEventTimeoutInSeconds))); | 330 kDisplayConfigurationEventTimeoutInSeconds))); |
323 | 331 |
324 SkRegion region; | 332 SkRegion region; |
325 helper_.SwapInvalidRegion(®ion); | 333 helper_.SwapInvalidRegion(®ion); |
326 | 334 |
327 // If the current buffer is from an older generation then allocate a new one. | 335 // If the current buffer is from an older generation then allocate a new one. |
328 // Note that we can't reallocate other buffers at this point, since the caller | 336 // Note that we can't reallocate other buffers at this point, since the caller |
329 // may still be reading from them. | 337 // may still be reading from them. |
330 if (queue_.current_frame_needs_update()) { | 338 if (queue_.current_frame_needs_update()) { |
331 scoped_ptr<VideoFrameMac> buffer(new VideoFrameMac( | 339 scoped_ptr<VideoFrameMac> buffer(new VideoFrameMac(desktop_config_)); |
332 SkISize::Make(desktop_bounds_.width(), desktop_bounds_.height()))); | |
333 queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>()); | 340 queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>()); |
334 } | 341 } |
335 | 342 |
336 VideoFrame* current_buffer = queue_.current_frame(); | 343 VideoFrame* current_buffer = queue_.current_frame(); |
337 | 344 |
338 bool flip = false; // GL capturers need flipping. | 345 bool flip = false; // GL capturers need flipping. |
339 if (base::mac::IsOSLionOrLater()) { | 346 if (base::mac::IsOSLionOrLater()) { |
340 // Lion requires us to use their new APIs for doing screen capture. These | 347 // Lion requires us to use their new APIs for doing screen capture. These |
341 // APIS currently crash on 10.6.8 if there is no monitor attached. | 348 // APIS currently crash on 10.6.8 if there is no monitor attached. |
342 CgBlitPostLion(*current_buffer, region); | 349 CgBlitPostLion(*current_buffer, region); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 | 552 |
546 // Copy the entire contents of the previous capture buffer, to capture over. | 553 // Copy the entire contents of the previous capture buffer, to capture over. |
547 // TODO(wez): Get rid of this as per crbug.com/145064, or implement | 554 // TODO(wez): Get rid of this as per crbug.com/145064, or implement |
548 // crbug.com/92354. | 555 // crbug.com/92354. |
549 if (queue_.previous_frame()) { | 556 if (queue_.previous_frame()) { |
550 memcpy(buffer.pixels(), | 557 memcpy(buffer.pixels(), |
551 queue_.previous_frame()->pixels(), | 558 queue_.previous_frame()->pixels(), |
552 buffer.bytes_per_row() * buffer_height); | 559 buffer.bytes_per_row() * buffer_height); |
553 } | 560 } |
554 | 561 |
555 for (unsigned int d = 0; d < display_ids_.size(); ++d) { | 562 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { |
| 563 const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; |
| 564 |
556 // Use deprecated APIs to determine the display buffer layout. | 565 // Use deprecated APIs to determine the display buffer layout. |
557 DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && | 566 DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && |
558 cg_display_bits_per_pixel_); | 567 cg_display_bits_per_pixel_); |
559 uint8* display_base_address = | 568 uint8* display_base_address = |
560 reinterpret_cast<uint8*>((*cg_display_base_address_)(display_ids_[d])); | 569 reinterpret_cast<uint8*>((*cg_display_base_address_)(display_config.id)); |
561 CHECK(display_base_address); | 570 CHECK(display_base_address); |
562 int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_ids_[d]); | 571 int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_config.id); |
563 int src_bytes_per_pixel = | 572 int src_bytes_per_pixel = |
564 (*cg_display_bits_per_pixel_)(display_ids_[d]) / 8; | 573 (*cg_display_bits_per_pixel_)(display_config.id) / 8; |
565 | 574 |
566 // Determine the position of the display in the buffer. | 575 // Determine the display's position relative to the desktop, in pixels. |
567 SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d])); | 576 SkIRect display_bounds = display_config.pixel_bounds; |
568 display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top()); | 577 display_bounds.offset(-desktop_config_.pixel_bounds.left(), |
| 578 -desktop_config_.pixel_bounds.top()); |
569 | 579 |
570 // Determine which parts of the blit region, if any, lay within the monitor. | 580 // Determine which parts of the blit region, if any, lay within the monitor. |
571 SkRegion copy_region; | 581 SkRegion copy_region; |
572 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) | 582 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) |
573 continue; | 583 continue; |
574 | 584 |
575 // Translate the region to be copied into display-relative coordinates. | 585 // Translate the region to be copied into display-relative coordinates. |
576 copy_region.translate(-display_bounds.left(), -display_bounds.top()); | 586 copy_region.translate(-desktop_config_.pixel_bounds.left(), |
| 587 -desktop_config_.pixel_bounds.top()); |
577 | 588 |
578 // Calculate where in the output buffer the display's origin is. | 589 // Calculate where in the output buffer the display's origin is. |
579 uint8* out_ptr = buffer.pixels() + | 590 uint8* out_ptr = buffer.pixels() + |
580 (display_bounds.left() * src_bytes_per_pixel) + | 591 (display_bounds.left() * src_bytes_per_pixel) + |
581 (display_bounds.top() * buffer.bytes_per_row()); | 592 (display_bounds.top() * buffer.bytes_per_row()); |
582 | 593 |
583 // Copy the dirty region from the display buffer into our desktop buffer. | 594 // Copy the dirty region from the display buffer into our desktop buffer. |
584 for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { | 595 for(SkRegion::Iterator i(copy_region); !i.done(); i.next()) { |
585 CopyRect(display_base_address, | 596 CopyRect(display_base_address, |
586 src_bytes_per_row, | 597 src_bytes_per_row, |
(...skipping 11 matching lines...) Expand all Loading... |
598 | 609 |
599 // Copy the entire contents of the previous capture buffer, to capture over. | 610 // Copy the entire contents of the previous capture buffer, to capture over. |
600 // TODO(wez): Get rid of this as per crbug.com/145064, or implement | 611 // TODO(wez): Get rid of this as per crbug.com/145064, or implement |
601 // crbug.com/92354. | 612 // crbug.com/92354. |
602 if (queue_.previous_frame()) { | 613 if (queue_.previous_frame()) { |
603 memcpy(buffer.pixels(), | 614 memcpy(buffer.pixels(), |
604 queue_.previous_frame()->pixels(), | 615 queue_.previous_frame()->pixels(), |
605 buffer.bytes_per_row() * buffer_height); | 616 buffer.bytes_per_row() * buffer_height); |
606 } | 617 } |
607 | 618 |
608 for (unsigned int d = 0; d < display_ids_.size(); ++d) { | 619 for (size_t i = 0; i < desktop_config_.displays.size(); ++i) { |
609 // Determine the position of the display in the buffer. | 620 const MacDisplayConfiguration& display_config = desktop_config_.displays[i]; |
610 SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d])); | 621 |
611 display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top()); | 622 // Determine the display's position relative to the desktop, in pixels. |
| 623 SkIRect display_bounds = display_config.pixel_bounds; |
| 624 display_bounds.offset(-desktop_config_.pixel_bounds.left(), |
| 625 -desktop_config_.pixel_bounds.top()); |
612 | 626 |
613 // Determine which parts of the blit region, if any, lay within the monitor. | 627 // Determine which parts of the blit region, if any, lay within the monitor. |
614 SkRegion copy_region; | 628 SkRegion copy_region; |
615 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) | 629 if (!copy_region.op(region, display_bounds, SkRegion::kIntersect_Op)) |
616 continue; | 630 continue; |
617 | 631 |
618 // Translate the region to be copied into display-relative coordinates. | 632 // Translate the region to be copied into display-relative coordinates. |
619 copy_region.translate(-display_bounds.left(), -display_bounds.top()); | 633 copy_region.translate(-desktop_config_.pixel_bounds.left(), |
| 634 -desktop_config_.pixel_bounds.top()); |
620 | 635 |
621 // Create an image containing a snapshot of the display. | 636 // Create an image containing a snapshot of the display. |
622 base::mac::ScopedCFTypeRef<CGImageRef> image( | 637 base::mac::ScopedCFTypeRef<CGImageRef> image( |
623 CGDisplayCreateImage(display_ids_[d])); | 638 CGDisplayCreateImage(display_config.id)); |
624 if (image.get() == NULL) | 639 if (image.get() == NULL) |
625 continue; | 640 continue; |
626 | 641 |
627 // Request access to the raw pixel data via the image's DataProvider. | 642 // Request access to the raw pixel data via the image's DataProvider. |
628 CGDataProviderRef provider = CGImageGetDataProvider(image); | 643 CGDataProviderRef provider = CGImageGetDataProvider(image); |
629 base::mac::ScopedCFTypeRef<CFDataRef> data( | 644 base::mac::ScopedCFTypeRef<CFDataRef> data( |
630 CGDataProviderCopyData(provider)); | 645 CGDataProviderCopyData(provider)); |
631 if (data.get() == NULL) | 646 if (data.get() == NULL) |
632 continue; | 647 continue; |
633 | 648 |
(...skipping 18 matching lines...) Expand all Loading... |
652 } | 667 } |
653 } | 668 } |
654 | 669 |
655 void VideoFrameCapturerMac::ScreenConfigurationChanged() { | 670 void VideoFrameCapturerMac::ScreenConfigurationChanged() { |
656 // Release existing buffers, which will be of the wrong size. | 671 // Release existing buffers, which will be of the wrong size. |
657 ReleaseBuffers(); | 672 ReleaseBuffers(); |
658 | 673 |
659 // Clear the dirty region, in case the display is down-sizing. | 674 // Clear the dirty region, in case the display is down-sizing. |
660 helper_.ClearInvalidRegion(); | 675 helper_.ClearInvalidRegion(); |
661 | 676 |
662 // Fetch the list if active displays and calculate their bounds. | 677 // Refresh the cached desktop configuration. |
663 CGDisplayCount display_count; | 678 desktop_config_ = MacDesktopConfiguration::GetCurrent(); |
664 CGError error = CGGetActiveDisplayList(0, NULL, &display_count); | |
665 CHECK_EQ(error, CGDisplayNoErr); | |
666 | |
667 display_ids_.resize(display_count); | |
668 error = CGGetActiveDisplayList(display_count, &display_ids_[0], | |
669 &display_count); | |
670 CHECK_EQ(error, CGDisplayNoErr); | |
671 CHECK_EQ(display_count, display_ids_.size()); | |
672 | |
673 desktop_bounds_ = SkIRect::MakeEmpty(); | |
674 for (unsigned int d = 0; d < display_count; ++d) { | |
675 CGRect display_bounds = CGDisplayBounds(display_ids_[d]); | |
676 desktop_bounds_.join(CGRectToSkIRect(display_bounds)); | |
677 } | |
678 | 679 |
679 // Re-mark the entire desktop as dirty. | 680 // Re-mark the entire desktop as dirty. |
680 helper_.InvalidateScreen(SkISize::Make(desktop_bounds_.width(), | 681 helper_.InvalidateScreen( |
681 desktop_bounds_.height())); | 682 SkISize::Make(desktop_config_.pixel_bounds.width(), |
| 683 desktop_config_.pixel_bounds.height())); |
682 | 684 |
683 // Make sure the frame buffers will be reallocated. | 685 // Make sure the frame buffers will be reallocated. |
684 queue_.SetAllFramesNeedUpdate(); | 686 queue_.SetAllFramesNeedUpdate(); |
685 | 687 |
686 // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's | 688 // CgBlitPostLion uses CGDisplayCreateImage() to snapshot each display's |
687 // contents. Although the API exists in OS 10.6, it crashes the caller if | 689 // contents. Although the API exists in OS 10.6, it crashes the caller if |
688 // the machine has no monitor connected, so we fall back to depcreated APIs | 690 // the machine has no monitor connected, so we fall back to depcreated APIs |
689 // when running on 10.6. | 691 // when running on 10.6. |
690 if (base::mac::IsOSLionOrLater()) { | 692 if (base::mac::IsOSLionOrLater()) { |
691 LOG(INFO) << "Using CgBlitPostLion."; | 693 LOG(INFO) << "Using CgBlitPostLion."; |
(...skipping 18 matching lines...) Expand all Loading... |
710 app_services_library_.GetFunctionPointer("CGDisplayBaseAddress")); | 712 app_services_library_.GetFunctionPointer("CGDisplayBaseAddress")); |
711 cg_display_bytes_per_row_ = reinterpret_cast<CGDisplayBytesPerRowFunc>( | 713 cg_display_bytes_per_row_ = reinterpret_cast<CGDisplayBytesPerRowFunc>( |
712 app_services_library_.GetFunctionPointer("CGDisplayBytesPerRow")); | 714 app_services_library_.GetFunctionPointer("CGDisplayBytesPerRow")); |
713 cg_display_bits_per_pixel_ = reinterpret_cast<CGDisplayBitsPerPixelFunc>( | 715 cg_display_bits_per_pixel_ = reinterpret_cast<CGDisplayBitsPerPixelFunc>( |
714 app_services_library_.GetFunctionPointer("CGDisplayBitsPerPixel")); | 716 app_services_library_.GetFunctionPointer("CGDisplayBitsPerPixel")); |
715 cgl_set_full_screen_ = reinterpret_cast<CGLSetFullScreenFunc>( | 717 cgl_set_full_screen_ = reinterpret_cast<CGLSetFullScreenFunc>( |
716 opengl_library_.GetFunctionPointer("CGLSetFullScreen")); | 718 opengl_library_.GetFunctionPointer("CGLSetFullScreen")); |
717 CHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && | 719 CHECK(cg_display_base_address_ && cg_display_bytes_per_row_ && |
718 cg_display_bits_per_pixel_ && cgl_set_full_screen_); | 720 cg_display_bits_per_pixel_ && cgl_set_full_screen_); |
719 | 721 |
720 if (display_ids_.size() > 1) { | 722 if (desktop_config_.displays.size() > 1) { |
721 LOG(INFO) << "Using CgBlitPreLion (Multi-monitor)."; | 723 LOG(INFO) << "Using CgBlitPreLion (Multi-monitor)."; |
722 return; | 724 return; |
723 } | 725 } |
724 | 726 |
725 CGDirectDisplayID mainDevice = CGMainDisplayID(); | 727 CGDirectDisplayID mainDevice = CGMainDisplayID(); |
726 if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) { | 728 if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) { |
727 LOG(INFO) << "Using CgBlitPreLion (OpenGL unavailable)."; | 729 LOG(INFO) << "Using CgBlitPreLion (OpenGL unavailable)."; |
728 return; | 730 return; |
729 } | 731 } |
730 | 732 |
(...skipping 10 matching lines...) Expand all Loading... |
741 CGLError err = CGLChoosePixelFormat(attributes, | 743 CGLError err = CGLChoosePixelFormat(attributes, |
742 &pixel_format, | 744 &pixel_format, |
743 &matching_pixel_format_count); | 745 &matching_pixel_format_count); |
744 DCHECK_EQ(err, kCGLNoError); | 746 DCHECK_EQ(err, kCGLNoError); |
745 err = CGLCreateContext(pixel_format, NULL, &cgl_context_); | 747 err = CGLCreateContext(pixel_format, NULL, &cgl_context_); |
746 DCHECK_EQ(err, kCGLNoError); | 748 DCHECK_EQ(err, kCGLNoError); |
747 CGLDestroyPixelFormat(pixel_format); | 749 CGLDestroyPixelFormat(pixel_format); |
748 (*cgl_set_full_screen_)(cgl_context_); | 750 (*cgl_set_full_screen_)(cgl_context_); |
749 CGLSetCurrentContext(cgl_context_); | 751 CGLSetCurrentContext(cgl_context_); |
750 | 752 |
751 size_t buffer_size = desktop_bounds_.width() * desktop_bounds_.height() * | 753 size_t buffer_size = desktop_config_.pixel_bounds.width() * |
| 754 desktop_config_.pixel_bounds.height() * |
752 sizeof(uint32_t); | 755 sizeof(uint32_t); |
753 pixel_buffer_object_.Init(cgl_context_, buffer_size); | 756 pixel_buffer_object_.Init(cgl_context_, buffer_size); |
754 } | 757 } |
755 | 758 |
756 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count, | 759 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count, |
757 const CGRect* rect_array) { | 760 const CGRect* rect_array) { |
758 if (desktop_bounds_.isEmpty()) { | 761 if (desktop_config_.pixel_bounds.isEmpty()) { |
759 return; | 762 return; |
760 } | 763 } |
761 SkIRect skirect_array[count]; | 764 SkIRect skirect_array[count]; |
| 765 |
762 for (CGRectCount i = 0; i < count; ++i) { | 766 for (CGRectCount i = 0; i < count; ++i) { |
763 skirect_array[i] = CGRectToSkIRect(rect_array[i]); | 767 SkRect sk_rect = gfx::CGRectToSkRect(rect_array[i]); |
764 skirect_array[i].offset(-desktop_bounds_.left(), -desktop_bounds_.top()); | 768 |
| 769 // Convert from Density-Independent Pixel to physical pixel coordinates. |
| 770 sk_rect = ScaleSkRect(sk_rect, desktop_config_.dip_to_pixel_scale); |
| 771 sk_rect.round(&skirect_array[i]); |
| 772 |
| 773 // Translate from local desktop to capturer framebuffer coordinates. |
| 774 skirect_array[i].offset(-desktop_config_.pixel_bounds.left(), |
| 775 -desktop_config_.pixel_bounds.top()); |
765 } | 776 } |
| 777 |
766 SkRegion region; | 778 SkRegion region; |
767 region.setRects(skirect_array, count); | 779 region.setRects(skirect_array, count); |
768 InvalidateRegion(region); | 780 InvalidateRegion(region); |
769 } | 781 } |
770 | 782 |
771 void VideoFrameCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, | 783 void VideoFrameCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, |
772 size_t count, | 784 size_t count, |
773 const CGRect* rect_array) { | 785 const CGRect* rect_array) { |
774 SkIRect skirect_array[count]; | 786 // Translate |rect_array| to identify the move's destination. |
| 787 CGRect refresh_rects[count]; |
775 for (CGRectCount i = 0; i < count; ++i) { | 788 for (CGRectCount i = 0; i < count; ++i) { |
776 CGRect rect = rect_array[i]; | 789 refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY); |
777 rect = CGRectOffset(rect, delta.dX, delta.dY); | |
778 skirect_array[i] = CGRectToSkIRect(rect); | |
779 skirect_array[i].offset(-desktop_bounds_.left(), -desktop_bounds_.top()); | |
780 } | 790 } |
781 SkRegion region; | 791 |
782 region.setRects(skirect_array, count); | 792 // Currently we just treat move events the same as refreshes. |
783 InvalidateRegion(region); | 793 ScreenRefresh(count, refresh_rects); |
784 } | 794 } |
785 | 795 |
786 void VideoFrameCapturerMac::DisplaysReconfigured( | 796 void VideoFrameCapturerMac::DisplaysReconfigured( |
787 CGDirectDisplayID display, | 797 CGDirectDisplayID display, |
788 CGDisplayChangeSummaryFlags flags) { | 798 CGDisplayChangeSummaryFlags flags) { |
789 if (flags & kCGDisplayBeginConfigurationFlag) { | 799 if (flags & kCGDisplayBeginConfigurationFlag) { |
790 if (reconfiguring_displays_.empty()) { | 800 if (reconfiguring_displays_.empty()) { |
791 // If this is the first display to start reconfiguring then wait on | 801 // If this is the first display to start reconfiguring then wait on |
792 // |display_configuration_capture_event_| to block the capture thread | 802 // |display_configuration_capture_event_| to block the capture thread |
793 // from accessing display memory until the reconfiguration completes. | 803 // from accessing display memory until the reconfiguration completes. |
(...skipping 13 matching lines...) Expand all Loading... |
807 display_configuration_capture_event_.Signal(); | 817 display_configuration_capture_event_.Signal(); |
808 } | 818 } |
809 } | 819 } |
810 } | 820 } |
811 | 821 |
812 void VideoFrameCapturerMac::ScreenRefreshCallback(CGRectCount count, | 822 void VideoFrameCapturerMac::ScreenRefreshCallback(CGRectCount count, |
813 const CGRect* rect_array, | 823 const CGRect* rect_array, |
814 void* user_parameter) { | 824 void* user_parameter) { |
815 VideoFrameCapturerMac* capturer = reinterpret_cast<VideoFrameCapturerMac*>( | 825 VideoFrameCapturerMac* capturer = reinterpret_cast<VideoFrameCapturerMac*>( |
816 user_parameter); | 826 user_parameter); |
817 if (capturer->desktop_bounds_.isEmpty()) { | 827 if (capturer->desktop_config_.pixel_bounds.isEmpty()) { |
818 capturer->ScreenConfigurationChanged(); | 828 capturer->ScreenConfigurationChanged(); |
819 } | 829 } |
820 capturer->ScreenRefresh(count, rect_array); | 830 capturer->ScreenRefresh(count, rect_array); |
821 } | 831 } |
822 | 832 |
823 void VideoFrameCapturerMac::ScreenUpdateMoveCallback( | 833 void VideoFrameCapturerMac::ScreenUpdateMoveCallback( |
824 CGScreenUpdateMoveDelta delta, | 834 CGScreenUpdateMoveDelta delta, |
825 size_t count, | 835 size_t count, |
826 const CGRect* rect_array, | 836 const CGRect* rect_array, |
827 void* user_parameter) { | 837 void* user_parameter) { |
(...skipping 22 matching lines...) Expand all Loading... |
850 } | 860 } |
851 | 861 |
852 // static | 862 // static |
853 scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::CreateWithFactory( | 863 scoped_ptr<VideoFrameCapturer> VideoFrameCapturer::CreateWithFactory( |
854 SharedBufferFactory* shared_buffer_factory) { | 864 SharedBufferFactory* shared_buffer_factory) { |
855 NOTIMPLEMENTED(); | 865 NOTIMPLEMENTED(); |
856 return scoped_ptr<VideoFrameCapturer>(); | 866 return scoped_ptr<VideoFrameCapturer>(); |
857 } | 867 } |
858 | 868 |
859 } // namespace remoting | 869 } // namespace remoting |
OLD | NEW |