Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(966)

Side by Side Diff: remoting/capturer/video_frame_capturer_mac.mm

Issue 12040058: Add support for high-DPI hosts under Mac OS X. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix for OS X 10.6. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
321 base::TimeDelta::FromSeconds( 325 base::TimeDelta::FromSeconds(
322 kDisplayConfigurationEventTimeoutInSeconds))); 326 kDisplayConfigurationEventTimeoutInSeconds)));
323 327
324 SkRegion region; 328 SkRegion region;
325 helper_.SwapInvalidRegion(&region); 329 helper_.SwapInvalidRegion(&region);
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698