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