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

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 indent 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
« no previous file with comments | « remoting/capturer/mac/desktop_configuration.mm ('k') | remoting/host/event_executor_mac.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
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
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
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
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
321 base::TimeDelta::FromSeconds( 329 base::TimeDelta::FromSeconds(
322 kDisplayConfigurationEventTimeoutInSeconds))); 330 kDisplayConfigurationEventTimeoutInSeconds)));
323 331
324 SkRegion region; 332 SkRegion region;
325 helper_.SwapInvalidRegion(&region); 333 helper_.SwapInvalidRegion(&region);
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « remoting/capturer/mac/desktop_configuration.mm ('k') | remoting/host/event_executor_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698