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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: remoting/capturer/video_frame_capturer_mac.mm
diff --git a/remoting/capturer/video_frame_capturer_mac.mm b/remoting/capturer/video_frame_capturer_mac.mm
index 8b10cac31431364ee152a0c1f24d7726823ccc2a..ce06dbe9080f8e3d750776fb78c0954afcd23ca8 100644
--- a/remoting/capturer/video_frame_capturer_mac.mm
+++ b/remoting/capturer/video_frame_capturer_mac.mm
@@ -22,11 +22,13 @@
#include "base/synchronization/waitable_event.h"
#include "base/time.h"
#include "remoting/capturer/capture_data.h"
+#include "remoting/capturer/mac/desktop_configuration.h"
#include "remoting/capturer/mac/scoped_pixel_buffer_object.h"
#include "remoting/capturer/mouse_cursor_shape.h"
#include "remoting/capturer/video_frame.h"
#include "remoting/capturer/video_frame_capturer_helper.h"
#include "remoting/capturer/video_frame_queue.h"
+#include "skia/ext/skia_utils_mac.h"
namespace remoting {
@@ -45,13 +47,18 @@ typedef CGLError (*CGLSetFullScreenFunc)(CGLContextObj);
// skia/ext/skia_utils_mac.h only defines CGRectToSkRect().
SkIRect CGRectToSkIRect(const CGRect& rect) {
- SkIRect sk_rect = {
- SkScalarRound(rect.origin.x),
- SkScalarRound(rect.origin.y),
- SkScalarRound(rect.origin.x + rect.size.width),
- SkScalarRound(rect.origin.y + rect.size.height)
+ SkIRect result;
+ gfx::CGRectToSkRect(rect).round(&result);
+ return result;
+}
+
+// Scales all coordinates of an SkRect by a specified factor.
+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
+ SkRect result = {
+ rect.left() * scale, rect.top() * scale,
+ rect.right() * scale, rect.bottom() * scale
};
- return sk_rect;
+ return result;
}
// Copy pixels in the |rect| from |src_place| to |dest_plane|.
@@ -84,7 +91,7 @@ const int64 kDisplayConfigurationEventTimeoutInSeconds = 10;
// A class representing a full-frame pixel buffer.
class VideoFrameMac : public VideoFrame {
public:
- explicit VideoFrameMac(const SkISize& size);
+ explicit VideoFrameMac(const MacDesktopConfiguration& desktop_config);
virtual ~VideoFrameMac();
const SkIPoint& dpi() const { return dpi_; }
@@ -152,8 +159,7 @@ class VideoFrameCapturerMac : public VideoFrameCapturer {
VideoFrameQueue queue_;
// Current display configuration.
- std::vector<CGDirectDisplayID> display_ids_;
- SkIRect desktop_bounds_;
+ MacDesktopConfiguration desktop_config_;
// A thread-safe list of invalid rectangles, and the size of the most
// recently captured screen.
@@ -190,7 +196,9 @@ class VideoFrameCapturerMac : public VideoFrameCapturer {
DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac);
};
-VideoFrameMac::VideoFrameMac(const SkISize& size) {
+VideoFrameMac::VideoFrameMac(const MacDesktopConfiguration& desktop_config) {
+ SkISize size = SkISize::Make(desktop_config.pixel_bounds.width(),
+ desktop_config.pixel_bounds.height());
set_bytes_per_row(size.width() * sizeof(uint32_t));
set_dimensions(size);
@@ -198,11 +206,7 @@ VideoFrameMac::VideoFrameMac(const SkISize& size) {
data_.reset(new uint8[buffer_size]);
set_pixels(data_.get());
- // TODO(wez): Move the ugly DPI code into a helper.
- NSScreen* screen = [NSScreen mainScreen];
- NSDictionary* attr = [screen deviceDescription];
- NSSize resolution = [[attr objectForKey: NSDeviceResolution] sizeValue];
- dpi_.set(resolution.width, resolution.height);
+ dpi_ = desktop_config.dpi;
}
VideoFrameMac::~VideoFrameMac() {
@@ -328,8 +332,7 @@ void VideoFrameCapturerMac::CaptureFrame() {
// Note that we can't reallocate other buffers at this point, since the caller
// may still be reading from them.
if (queue_.current_frame_needs_update()) {
- scoped_ptr<VideoFrameMac> buffer(new VideoFrameMac(
- SkISize::Make(desktop_bounds_.width(), desktop_bounds_.height())));
+ scoped_ptr<VideoFrameMac> buffer(new VideoFrameMac(desktop_config_));
queue_.ReplaceCurrentFrame(buffer.PassAs<VideoFrame>());
}
@@ -552,20 +555,23 @@ void VideoFrameCapturerMac::CgBlitPreLion(const VideoFrame& buffer,
buffer.bytes_per_row() * buffer_height);
}
- for (unsigned int d = 0; d < display_ids_.size(); ++d) {
+ for (size_t i = 0; i < desktop_config_.displays.size(); ++i) {
+ const MacDisplayConfiguration& display_config = desktop_config_.displays[i];
+
// Use deprecated APIs to determine the display buffer layout.
DCHECK(cg_display_base_address_ && cg_display_bytes_per_row_ &&
cg_display_bits_per_pixel_);
uint8* display_base_address =
- reinterpret_cast<uint8*>((*cg_display_base_address_)(display_ids_[d]));
+ reinterpret_cast<uint8*>((*cg_display_base_address_)(display_config.id));
CHECK(display_base_address);
- int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_ids_[d]);
+ int src_bytes_per_row = (*cg_display_bytes_per_row_)(display_config.id);
int src_bytes_per_pixel =
- (*cg_display_bits_per_pixel_)(display_ids_[d]) / 8;
+ (*cg_display_bits_per_pixel_)(display_config.id) / 8;
- // Determine the position of the display in the buffer.
- SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d]));
- display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top());
+ // Determine the display's position relative to the desktop, in pixels.
+ SkIRect display_bounds = display_config.pixel_bounds;
+ display_bounds.offset(-desktop_config_.pixel_bounds.left(),
+ -desktop_config_.pixel_bounds.top());
// Determine which parts of the blit region, if any, lay within the monitor.
SkRegion copy_region;
@@ -573,7 +579,8 @@ void VideoFrameCapturerMac::CgBlitPreLion(const VideoFrame& buffer,
continue;
// Translate the region to be copied into display-relative coordinates.
- copy_region.translate(-display_bounds.left(), -display_bounds.top());
+ copy_region.translate(-desktop_config_.pixel_bounds.left(),
+ -desktop_config_.pixel_bounds.top());
// Calculate where in the output buffer the display's origin is.
uint8* out_ptr = buffer.pixels() +
@@ -605,10 +612,13 @@ void VideoFrameCapturerMac::CgBlitPostLion(const VideoFrame& buffer,
buffer.bytes_per_row() * buffer_height);
}
- for (unsigned int d = 0; d < display_ids_.size(); ++d) {
- // Determine the position of the display in the buffer.
- SkIRect display_bounds = CGRectToSkIRect(CGDisplayBounds(display_ids_[d]));
- display_bounds.offset(-desktop_bounds_.left(), -desktop_bounds_.top());
+ for (size_t i = 0; i < desktop_config_.displays.size(); ++i) {
+ const MacDisplayConfiguration& display_config = desktop_config_.displays[i];
+
+ // Determine the display's position relative to the desktop, in pixels.
+ SkIRect display_bounds = display_config.pixel_bounds;
+ display_bounds.offset(-desktop_config_.pixel_bounds.left(),
+ -desktop_config_.pixel_bounds.top());
// Determine which parts of the blit region, if any, lay within the monitor.
SkRegion copy_region;
@@ -616,11 +626,12 @@ void VideoFrameCapturerMac::CgBlitPostLion(const VideoFrame& buffer,
continue;
// Translate the region to be copied into display-relative coordinates.
- copy_region.translate(-display_bounds.left(), -display_bounds.top());
+ copy_region.translate(-desktop_config_.pixel_bounds.left(),
+ -desktop_config_.pixel_bounds.top());
// Create an image containing a snapshot of the display.
base::mac::ScopedCFTypeRef<CGImageRef> image(
- CGDisplayCreateImage(display_ids_[d]));
+ CGDisplayCreateImage(display_config.id));
if (image.get() == NULL)
continue;
@@ -659,26 +670,13 @@ void VideoFrameCapturerMac::ScreenConfigurationChanged() {
// Clear the dirty region, in case the display is down-sizing.
helper_.ClearInvalidRegion();
- // Fetch the list if active displays and calculate their bounds.
- CGDisplayCount display_count;
- CGError error = CGGetActiveDisplayList(0, NULL, &display_count);
- CHECK_EQ(error, CGDisplayNoErr);
-
- display_ids_.resize(display_count);
- error = CGGetActiveDisplayList(display_count, &display_ids_[0],
- &display_count);
- CHECK_EQ(error, CGDisplayNoErr);
- CHECK_EQ(display_count, display_ids_.size());
-
- desktop_bounds_ = SkIRect::MakeEmpty();
- for (unsigned int d = 0; d < display_count; ++d) {
- CGRect display_bounds = CGDisplayBounds(display_ids_[d]);
- desktop_bounds_.join(CGRectToSkIRect(display_bounds));
- }
+ // Refresh the cached desktop configuration.
+ desktop_config_ = MacDesktopConfiguration::GetCurrent();
// Re-mark the entire desktop as dirty.
- helper_.InvalidateScreen(SkISize::Make(desktop_bounds_.width(),
- desktop_bounds_.height()));
+ helper_.InvalidateScreen(
+ SkISize::Make(desktop_config_.pixel_bounds.width(),
+ desktop_config_.pixel_bounds.height()));
// Make sure the frame buffers will be reallocated.
queue_.SetAllFramesNeedUpdate();
@@ -717,7 +715,7 @@ void VideoFrameCapturerMac::ScreenConfigurationChanged() {
CHECK(cg_display_base_address_ && cg_display_bytes_per_row_ &&
cg_display_bits_per_pixel_ && cgl_set_full_screen_);
- if (display_ids_.size() > 1) {
+ if (desktop_config_.displays.size() > 1) {
LOG(INFO) << "Using CgBlitPreLion (Multi-monitor).";
return;
}
@@ -748,21 +746,31 @@ void VideoFrameCapturerMac::ScreenConfigurationChanged() {
(*cgl_set_full_screen_)(cgl_context_);
CGLSetCurrentContext(cgl_context_);
- size_t buffer_size = desktop_bounds_.width() * desktop_bounds_.height() *
+ size_t buffer_size = desktop_config_.pixel_bounds.width() *
+ desktop_config_.pixel_bounds.height() *
sizeof(uint32_t);
pixel_buffer_object_.Init(cgl_context_, buffer_size);
}
void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count,
const CGRect* rect_array) {
- if (desktop_bounds_.isEmpty()) {
+ if (desktop_config_.pixel_bounds.isEmpty()) {
return;
}
SkIRect skirect_array[count];
+
for (CGRectCount i = 0; i < count; ++i) {
- skirect_array[i] = CGRectToSkIRect(rect_array[i]);
- skirect_array[i].offset(-desktop_bounds_.left(), -desktop_bounds_.top());
+ SkRect sk_rect = gfx::CGRectToSkRect(rect_array[i]);
+
+ // Convert from logical to pixel (device-scale) coordinates.
+ sk_rect = ScaleSkRect(sk_rect, desktop_config_.logical_to_pixel_scale);
+ sk_rect.round(&skirect_array[i]);
+
+ // Translate from local desktop to capturer framebuffer coordinates.
+ skirect_array[i].offset(-desktop_config_.pixel_bounds.left(),
+ -desktop_config_.pixel_bounds.top());
}
+
SkRegion region;
region.setRects(skirect_array, count);
InvalidateRegion(region);
@@ -771,16 +779,14 @@ void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count,
void VideoFrameCapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
size_t count,
const CGRect* rect_array) {
- SkIRect skirect_array[count];
+ // Translate |rect_array| to identify the move's destination.
+ CGRect refresh_rects[count];
for (CGRectCount i = 0; i < count; ++i) {
- CGRect rect = rect_array[i];
- rect = CGRectOffset(rect, delta.dX, delta.dY);
- skirect_array[i] = CGRectToSkIRect(rect);
- skirect_array[i].offset(-desktop_bounds_.left(), -desktop_bounds_.top());
+ refresh_rects[i] = CGRectOffset(rect_array[i], delta.dX, delta.dY);
}
- SkRegion region;
- region.setRects(skirect_array, count);
- InvalidateRegion(region);
+
+ // Currently we just treat move events the same as refreshes.
+ ScreenRefresh(count, refresh_rects);
}
void VideoFrameCapturerMac::DisplaysReconfigured(
@@ -814,7 +820,7 @@ void VideoFrameCapturerMac::ScreenRefreshCallback(CGRectCount count,
void* user_parameter) {
VideoFrameCapturerMac* capturer = reinterpret_cast<VideoFrameCapturerMac*>(
user_parameter);
- if (capturer->desktop_bounds_.isEmpty()) {
+ if (capturer->desktop_config_.pixel_bounds.isEmpty()) {
capturer->ScreenConfigurationChanged();
}
capturer->ScreenRefresh(count, rect_array);

Powered by Google App Engine
This is Rietveld 408576698