summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-21 03:21:07 +0000
committerccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-21 03:21:07 +0000
commit7b4bff53c5278de18e6e565743aabee1e1a5bcbe (patch)
treeb28981432f1df0a97dad2e055c64abea92705837
parentd5801aea4ece5a63b3ed83365f957a6d38556293 (diff)
downloadchromium_src-7b4bff53c5278de18e6e565743aabee1e1a5bcbe.zip
chromium_src-7b4bff53c5278de18e6e565743aabee1e1a5bcbe.tar.gz
chromium_src-7b4bff53c5278de18e6e565743aabee1e1a5bcbe.tar.bz2
Make delegated software renderer work on Mac
Add a device scale factor parameter to SoftwareOutputDevice::Resize and plumb that parameter through to the contentsScale property of the CALayer that is used to draw the software frame. Change the way that RWHVMac draws software frames (both delegated and non-delegated) so that the CALayer for the software frame has setContents called on it with a CGImageRef of the software frame, instead of drawing the CGImageRef to the inside the CALayer's displayInContext function. This is the way that things should have been done to begin with (it involves a lot less copying and a lot more idle time in the browser main thread), but wasn't compatible with the (now-defunct) legacy software path. Change the software rendering path to set the contentsScale of the software CALayer at the time that the software frame is received, when the contents are updated, instead of in RWHVMac::LayoutLayers. BUG=314190 Review URL: https://codereview.chromium.org/297573003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271839 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/output/output_surface.cc2
-rw-r--r--cc/output/software_output_device.cc19
-rw-r--r--cc/output/software_output_device.h5
-rw-r--r--cc/test/pixel_test_software_output_device.cc10
-rw-r--r--cc/test/pixel_test_software_output_device.h2
-rw-r--r--content/browser/android/in_process/synchronous_compositor_output_surface.cc3
-rw-r--r--content/browser/compositor/gpu_process_transport_factory.cc5
-rw-r--r--content/browser/compositor/software_output_device_mac.h35
-rw-r--r--content/browser/compositor/software_output_device_mac.mm43
-rw-r--r--content/browser/compositor/software_output_device_ozone.cc13
-rw-r--r--content/browser/compositor/software_output_device_ozone.h3
-rw-r--r--content/browser/compositor/software_output_device_ozone_unittest.cc8
-rw-r--r--content/browser/compositor/software_output_device_win.cc16
-rw-r--r--content/browser/compositor/software_output_device_win.h5
-rw-r--r--content/browser/compositor/software_output_device_x11.cc10
-rw-r--r--content/browser/compositor/software_output_device_x11.h2
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.h19
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.mm132
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/renderer/gpu/compositor_software_output_device.cc28
-rw-r--r--content/renderer/gpu/compositor_software_output_device.h2
21 files changed, 264 insertions, 100 deletions
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index 0f68b5b..80def54 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -226,7 +226,7 @@ void OutputSurface::Reshape(const gfx::Size& size, float scale_factor) {
size.width(), size.height(), scale_factor);
}
if (software_device_)
- software_device_->Resize(size);
+ software_device_->Resize(size, scale_factor);
}
gfx::Size OutputSurface::SurfaceSize() const {
diff --git a/cc/output/software_output_device.cc b/cc/output/software_output_device.cc
index 93860f1..9e13cf3 100644
--- a/cc/output/software_output_device.cc
+++ b/cc/output/software_output_device.cc
@@ -12,17 +12,22 @@
namespace cc {
-SoftwareOutputDevice::SoftwareOutputDevice() {}
+SoftwareOutputDevice::SoftwareOutputDevice() : scale_factor_(1.f) {
+}
SoftwareOutputDevice::~SoftwareOutputDevice() {}
-void SoftwareOutputDevice::Resize(const gfx::Size& viewport_size) {
- if (viewport_size_ == viewport_size)
+void SoftwareOutputDevice::Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) {
+ scale_factor_ = scale_factor;
+
+ if (viewport_pixel_size_ == viewport_pixel_size)
return;
- SkImageInfo info = SkImageInfo::MakeN32(
- viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType);
- viewport_size_ = viewport_size;
+ SkImageInfo info = SkImageInfo::MakeN32(viewport_pixel_size.width(),
+ viewport_pixel_size.height(),
+ kOpaque_SkAlphaType);
+ viewport_pixel_size_ = viewport_pixel_size;
canvas_ = skia::AdoptRef(SkCanvas::NewRaster(info));
}
@@ -35,7 +40,7 @@ SkCanvas* SoftwareOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
void SoftwareOutputDevice::EndPaint(SoftwareFrameData* frame_data) {
DCHECK(frame_data);
frame_data->id = 0;
- frame_data->size = viewport_size_;
+ frame_data->size = viewport_pixel_size_;
frame_data->damage_rect = damage_rect_;
}
diff --git a/cc/output/software_output_device.h b/cc/output/software_output_device.h
index e371654..e8de5b9 100644
--- a/cc/output/software_output_device.h
+++ b/cc/output/software_output_device.h
@@ -36,7 +36,7 @@ class CC_EXPORT SoftwareOutputDevice {
// Discards any pre-existing backing buffers and allocates memory for a
// software device of |size|. This must be called before the
// |SoftwareOutputDevice| can be used in other ways.
- virtual void Resize(const gfx::Size& size);
+ virtual void Resize(const gfx::Size& pixel_size, float scale_factor);
// Called on BeginDrawingFrame. The compositor will draw into the returned
// SkCanvas. The |SoftwareOutputDevice| implementation needs to provide a
@@ -74,7 +74,8 @@ class CC_EXPORT SoftwareOutputDevice {
virtual gfx::VSyncProvider* GetVSyncProvider();
protected:
- gfx::Size viewport_size_;
+ gfx::Size viewport_pixel_size_;
+ float scale_factor_;
gfx::Rect damage_rect_;
skia::RefPtr<SkCanvas> canvas_;
scoped_ptr<gfx::VSyncProvider> vsync_provider_;
diff --git a/cc/test/pixel_test_software_output_device.cc b/cc/test/pixel_test_software_output_device.cc
index a8d986c..6d049ac 100644
--- a/cc/test/pixel_test_software_output_device.cc
+++ b/cc/test/pixel_test_software_output_device.cc
@@ -6,10 +6,12 @@
namespace cc {
-void PixelTestSoftwareOutputDevice::Resize(const gfx::Size& size) {
- gfx::Size expanded_size(size.width() + surface_expansion_size_.width(),
- size.height() + surface_expansion_size_.height());
- SoftwareOutputDevice::Resize(expanded_size);
+void PixelTestSoftwareOutputDevice::Resize(const gfx::Size& pixel_size,
+ float scale_factor) {
+ gfx::Size expanded_size(
+ pixel_size.width() + surface_expansion_size_.width(),
+ pixel_size.height() + surface_expansion_size_.height());
+ SoftwareOutputDevice::Resize(expanded_size, scale_factor);
}
} // namespace cc
diff --git a/cc/test/pixel_test_software_output_device.h b/cc/test/pixel_test_software_output_device.h
index 7c1dae6..fd8f4b0 100644
--- a/cc/test/pixel_test_software_output_device.h
+++ b/cc/test/pixel_test_software_output_device.h
@@ -11,7 +11,7 @@ namespace cc {
class PixelTestSoftwareOutputDevice : public SoftwareOutputDevice {
public:
- virtual void Resize(const gfx::Size& size) OVERRIDE;
+ virtual void Resize(const gfx::Size& pixel_size, float scale_factor) OVERRIDE;
void set_surface_expansion_size(const gfx::Size& surface_expansion_size) {
surface_expansion_size_ = surface_expansion_size;
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index de609c3..04abdc0 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -39,7 +39,8 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
SoftwareDevice(SynchronousCompositorOutputSurface* surface)
: surface_(surface) {
}
- virtual void Resize(const gfx::Size& size) OVERRIDE {
+ virtual void Resize(const gfx::Size& pixel_size,
+ float scale_factor) OVERRIDE {
// Intentional no-op: canvas size is controlled by the embedder.
}
virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index b8e115c..0123efe 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -47,6 +47,8 @@
#include "ui/gfx/ozone/surface_factory_ozone.h"
#elif defined(USE_X11)
#include "content/browser/compositor/software_output_device_x11.h"
+#elif defined(OS_MACOSX)
+#include "content/browser/compositor/software_output_device_mac.h"
#endif
using cc::ContextProvider;
@@ -98,6 +100,9 @@ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
#elif defined(USE_X11)
return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceX11(
compositor));
+#elif defined(OS_MACOSX)
+ return scoped_ptr<cc::SoftwareOutputDevice>(
+ new SoftwareOutputDeviceMac(compositor));
#else
NOTREACHED();
return scoped_ptr<cc::SoftwareOutputDevice>();
diff --git a/content/browser/compositor/software_output_device_mac.h b/content/browser/compositor/software_output_device_mac.h
new file mode 100644
index 0000000..8220a3b
--- /dev/null
+++ b/content/browser/compositor/software_output_device_mac.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_MAC_H_
+#define CONTENT_BROWSER_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_MAC_H_
+
+#include "cc/output/software_output_device.h"
+
+namespace gfx {
+class Canvas;
+}
+
+namespace ui {
+class Compositor;
+}
+
+namespace content {
+
+class SoftwareOutputDeviceMac : public cc::SoftwareOutputDevice {
+ public:
+ explicit SoftwareOutputDeviceMac(ui::Compositor* compositor);
+ virtual ~SoftwareOutputDeviceMac();
+
+ virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+
+ private:
+ ui::Compositor* compositor_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_MAC_H_
diff --git a/content/browser/compositor/software_output_device_mac.mm b/content/browser/compositor/software_output_device_mac.mm
new file mode 100644
index 0000000..84670bd
--- /dev/null
+++ b/content/browser/compositor/software_output_device_mac.mm
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "content/browser/compositor/software_output_device_mac.h"
+
+#include "ui/compositor/compositor.h"
+
+// Declare methods used to present swaps to this view.
+@interface NSView (SoftwareDelegatedFrame)
+- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
+ withScaleFactor:(float)scale_factor
+ withCanvas:(SkCanvas*)canvas;
+@end
+
+@implementation NSView (SoftwareDelegatedFrame)
+- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
+ withScaleFactor:(float)scale_factor
+ withCanvas:(SkCanvas*)canvas {
+}
+@end
+
+namespace content {
+
+SoftwareOutputDeviceMac::SoftwareOutputDeviceMac(ui::Compositor* compositor)
+ : compositor_(compositor) {
+}
+
+SoftwareOutputDeviceMac::~SoftwareOutputDeviceMac() {
+}
+
+void SoftwareOutputDeviceMac::EndPaint(cc::SoftwareFrameData* frame_data) {
+ SoftwareOutputDevice::EndPaint(frame_data);
+
+ NSView* view = compositor_->widget();
+ [view gotSoftwareFrame:frame_data
+ withScaleFactor:scale_factor_
+ withCanvas:canvas_.get()];
+}
+
+} // namespace content
diff --git a/content/browser/compositor/software_output_device_ozone.cc b/content/browser/compositor/software_output_device_ozone.cc
index 4beb0f6..e5514a8 100644
--- a/content/browser/compositor/software_output_device_ozone.cc
+++ b/content/browser/compositor/software_output_device_ozone.cc
@@ -30,17 +30,20 @@ SoftwareOutputDeviceOzone::SoftwareOutputDeviceOzone(ui::Compositor* compositor)
SoftwareOutputDeviceOzone::~SoftwareOutputDeviceOzone() {
}
-void SoftwareOutputDeviceOzone::Resize(const gfx::Size& viewport_size) {
- if (viewport_size_ == viewport_size)
+void SoftwareOutputDeviceOzone::Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) {
+ scale_factor_ = scale_factor;
+
+ if (viewport_pixel_size_ == viewport_pixel_size)
return;
- viewport_size_ = viewport_size;
+ viewport_pixel_size_ = viewport_pixel_size;
- surface_ozone_->ResizeCanvas(viewport_size_);
+ surface_ozone_->ResizeCanvas(viewport_pixel_size_);
}
SkCanvas* SoftwareOutputDeviceOzone::BeginPaint(const gfx::Rect& damage_rect) {
- DCHECK(gfx::Rect(viewport_size_).Contains(damage_rect));
+ DCHECK(gfx::Rect(viewport_pixel_size_).Contains(damage_rect));
// Get canvas for next frame.
canvas_ = surface_ozone_->GetCanvas();
diff --git a/content/browser/compositor/software_output_device_ozone.h b/content/browser/compositor/software_output_device_ozone.h
index 07a617009..74ef6fd 100644
--- a/content/browser/compositor/software_output_device_ozone.h
+++ b/content/browser/compositor/software_output_device_ozone.h
@@ -28,7 +28,8 @@ class CONTENT_EXPORT SoftwareOutputDeviceOzone
explicit SoftwareOutputDeviceOzone(ui::Compositor* compositor);
virtual ~SoftwareOutputDeviceOzone();
- virtual void Resize(const gfx::Size& viewport_size) OVERRIDE;
+ virtual void Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) OVERRIDE;
virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
diff --git a/content/browser/compositor/software_output_device_ozone_unittest.cc b/content/browser/compositor/software_output_device_ozone_unittest.cc
index 158e932..dcacbd0 100644
--- a/content/browser/compositor/software_output_device_ozone_unittest.cc
+++ b/content/browser/compositor/software_output_device_ozone_unittest.cc
@@ -110,7 +110,7 @@ void SoftwareOutputDeviceOzoneTest::SetUp() {
output_device_.reset(new content::SoftwareOutputDeviceOzone(
compositor_.get()));
- output_device_->Resize(size);
+ output_device_->Resize(size, 1.f);
}
void SoftwareOutputDeviceOzoneTest::TearDown() {
@@ -135,7 +135,7 @@ TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) {
gfx::Rect damage(0, 0, 100, 100);
gfx::Size size(200, 100);
// Reduce size.
- output_device_->Resize(size);
+ output_device_->Resize(size, 1.f);
SkCanvas* canvas = output_device_->BeginPaint(damage);
gfx::Size canvas_size(canvas->getDeviceSize().width(),
@@ -144,7 +144,7 @@ TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) {
size.SetSize(1000, 500);
// Increase size.
- output_device_->Resize(size);
+ output_device_->Resize(size, 1.f);
canvas = output_device_->BeginPaint(damage);
canvas_size.SetSize(canvas->getDeviceSize().width(),
@@ -157,7 +157,7 @@ TEST_F(SoftwareOutputDeviceOzonePixelTest, CheckCopyToBitmap) {
const int width = 6;
const int height = 4;
const gfx::Rect area(width, height);
- output_device_->Resize(area.size());
+ output_device_->Resize(area.size(), 1.f);
SkCanvas* canvas = output_device_->BeginPaint(area);
// Clear the background to black.
diff --git a/content/browser/compositor/software_output_device_win.cc b/content/browser/compositor/software_output_device_win.cc
index 3c938bf..1a6b5f6 100644
--- a/content/browser/compositor/software_output_device_win.cc
+++ b/content/browser/compositor/software_output_device_win.cc
@@ -29,16 +29,20 @@ SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
-void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_size) {
+void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (viewport_size_ == viewport_size)
+ scale_factor_ = scale_factor;
+
+ if (viewport_pixel_size_ == viewport_pixel_size)
return;
- viewport_size_ = viewport_size;
- contents_.reset(new gfx::Canvas(viewport_size, 1.0f, true));
+ viewport_pixel_size_ = viewport_pixel_size;
+ contents_.reset(new gfx::Canvas(viewport_pixel_size, 1.0f, true));
memset(&bitmap_info_, 0, sizeof(bitmap_info_));
- gfx::CreateBitmapHeader(viewport_size_.width(), viewport_size_.height(),
+ gfx::CreateBitmapHeader(viewport_pixel_size_.width(),
+ viewport_pixel_size_.height(),
&bitmap_info_.bmiHeader);
}
@@ -61,7 +65,7 @@ void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) {
SoftwareOutputDevice::EndPaint(frame_data);
gfx::Rect rect = damage_rect_;
- rect.Intersect(gfx::Rect(viewport_size_));
+ rect.Intersect(gfx::Rect(viewport_pixel_size_));
if (rect.IsEmpty())
return;
diff --git a/content/browser/compositor/software_output_device_win.h b/content/browser/compositor/software_output_device_win.h
index 30addbc..3724f02 100644
--- a/content/browser/compositor/software_output_device_win.h
+++ b/content/browser/compositor/software_output_device_win.h
@@ -25,7 +25,8 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
explicit SoftwareOutputDeviceWin(ui::Compositor* compositor);
virtual ~SoftwareOutputDeviceWin();
- virtual void Resize(const gfx::Size& viewport_size) OVERRIDE;
+ virtual void Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) OVERRIDE;
virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE;
@@ -35,6 +36,8 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
BITMAPINFO bitmap_info_;
scoped_ptr<gfx::Canvas> contents_;
bool is_hwnd_composited_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWin);
};
} // namespace content
diff --git a/content/browser/compositor/software_output_device_x11.cc b/content/browser/compositor/software_output_device_x11.cc
index 44267d4..ebaefd7 100644
--- a/content/browser/compositor/software_output_device_x11.cc
+++ b/content/browser/compositor/software_output_device_x11.cc
@@ -47,7 +47,7 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
SoftwareOutputDevice::EndPaint(frame_data);
gfx::Rect rect = damage_rect_;
- rect.Intersect(gfx::Rect(viewport_size_));
+ rect.Intersect(gfx::Rect(viewport_pixel_size_));
if (rect.IsEmpty())
return;
@@ -65,8 +65,8 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
SkImageInfo info;
size_t rowBytes;
const void* addr = canvas_->peekPixels(&info, &rowBytes);
- image.width = viewport_size_.width();
- image.height = viewport_size_.height();
+ image.width = viewport_pixel_size_.width();
+ image.height = viewport_pixel_size_.height();
image.depth = 32;
image.bits_per_pixel = 32;
image.format = ZPixmap;
@@ -125,8 +125,8 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
compositor_->widget(),
gc_,
static_cast<const uint8*>(addr),
- viewport_size_.width(),
- viewport_size_.height(),
+ viewport_pixel_size_.width(),
+ viewport_pixel_size_.height(),
rect.x(),
rect.y(),
rect.x(),
diff --git a/content/browser/compositor/software_output_device_x11.h b/content/browser/compositor/software_output_device_x11.h
index 0bd07c3..20ae642 100644
--- a/content/browser/compositor/software_output_device_x11.h
+++ b/content/browser/compositor/software_output_device_x11.h
@@ -29,6 +29,8 @@ class SoftwareOutputDeviceX11 : public cc::SoftwareOutputDevice {
XDisplay* display_;
GC gc_;
XWindowAttributes attributes_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceX11);
};
} // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 49ef5a0..c8fa95c 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -186,15 +186,16 @@ class Layer;
actualRange:(NSRangePointer)actualRange;
@end
-@interface SoftwareLayer : CALayer {
- @private
- content::RenderWidgetHostViewMac* renderWidgetHostView_;
-}
+@interface SoftwareLayer : CALayer
-- (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r;
+- (id)init;
-// Invalidate the RenderWidgetHostViewMac because it may be going away. If
-// displayed again, it will draw white.
+- (void)setContentsToData:(const void *)data
+ withRowBytes:(size_t)rowBytes
+ withPixelSize:(gfx::Size)pixelSize
+ withScaleFactor:(float)scaleFactor;
+
+// Remove the layer from the layer hierarchy.
- (void)disableRendering;
@end
@@ -371,6 +372,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
float scale_factor,
const std::vector<ui::LatencyInfo>& latency_info);
+ void GotBrowserCompositorSoftwareFrame(cc::SoftwareFrameData* frame_data,
+ float scale_factor,
+ SkCanvas* canvas);
+
// Draw the IOSurface by making its context current to this view.
void DrawIOSurfaceWithoutCoreAnimation();
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index df7b921..709e60e 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -607,8 +607,7 @@ void RenderWidgetHostViewMac::EnsureSoftwareLayer() {
if (software_layer_ || !use_core_animation_)
return;
- software_layer_.reset([[SoftwareLayer alloc]
- initWithRenderWidgetHostViewMac:this]);
+ software_layer_.reset([[SoftwareLayer alloc] init]);
DCHECK(software_layer_);
// Disable the fade-in animation as the layer is added.
@@ -868,7 +867,6 @@ void RenderWidgetHostViewMac::WasShown() {
// Call setNeedsDisplay before pausing for new frames to come in -- if any
// do, and are drawn, then the needsDisplay bit will be cleared.
- [software_layer_ setNeedsDisplay];
[compositing_iosurface_layer_ setNeedsDisplay];
PauseForPendingResizeOrRepaintsAndDraw();
@@ -1570,6 +1568,27 @@ void RenderWidgetHostViewMac::CompositorSwapBuffers(
LayoutLayers();
}
+void RenderWidgetHostViewMac::GotBrowserCompositorSoftwareFrame(
+ cc::SoftwareFrameData* frame_data,
+ float scale_factor,
+ SkCanvas* canvas) {
+ if (!frame_data || !canvas)
+ return;
+
+ SkImageInfo info;
+ size_t row_bytes;
+ const void* pixels = canvas->peekPixels(&info, &row_bytes);
+
+ EnsureSoftwareLayer();
+ [software_layer_ setContentsToData:pixels
+ withRowBytes:row_bytes
+ withPixelSize:gfx::Size(info.fWidth, info.fHeight)
+ withScaleFactor:scale_factor];
+
+ LayoutLayers();
+ DestroyCompositedIOSurfaceAndLayer(kDestroyContext);
+}
+
void RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() {
CHECK(!use_core_animation_);
CHECK(compositing_iosurface_);
@@ -1893,6 +1912,8 @@ bool RenderWidgetHostViewMac::HasAcceleratedSurface(
void RenderWidgetHostViewMac::OnSwapCompositorFrame(
uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) {
+ TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame");
+
if (frame->delegated_frame_data) {
if (!compositor_) {
compositor_.reset(new ui::Compositor(cocoa_view_));
@@ -1930,6 +1951,23 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame(
// Add latency info to report when the frame finishes drawing.
AddPendingLatencyInfo(frame->metadata.latency_info);
+
+ if (use_core_animation_) {
+ const void* pixels = software_frame_manager_->GetCurrentFramePixels();
+ gfx::Size size_in_pixels =
+ software_frame_manager_->GetCurrentFrameSizeInPixels();
+
+ EnsureSoftwareLayer();
+ [software_layer_ setContentsToData:pixels
+ withRowBytes:4 * size_in_pixels.width()
+ withPixelSize:size_in_pixels
+ withScaleFactor:frame->metadata.device_scale_factor];
+
+ // Send latency information to the host immediately, as there will be no
+ // subsequent draw call in which to do so.
+ SendPendingLatencyInfoToHost();
+ }
+
GotSoftwareFrame();
cc::CompositorFrameAck ack;
@@ -2073,6 +2111,8 @@ void RenderWidgetHostViewMac::GotAcceleratedFrame() {
}
void RenderWidgetHostViewMac::GotSoftwareFrame() {
+ TRACE_EVENT0("browser", "RenderWidgetHostViewMac::GotSoftwareFrame");
+
if (!render_widget_host_)
return;
@@ -2084,7 +2124,6 @@ void RenderWidgetHostViewMac::GotSoftwareFrame() {
// happen before the frame be acked, otherwise the new frame will likely be
// ready before the drawing is complete, thrashing the browser main thread.
if (use_core_animation_) {
- [software_layer_ setNeedsDisplay];
[software_layer_ displayIfNeeded];
} else {
[cocoa_view_ setNeedsDisplay:YES];
@@ -2329,15 +2368,14 @@ void RenderWidgetHostViewMac::TickPendingLatencyInfoDelay() {
[compositing_iosurface_layer_ gotNewFrame];
}
if (software_layer_) {
- // In software mode, setNeedsDisplay will almost immediately result in the
- // layer's draw function being called, so manually insert a pretend-vsync
- // at 60 Hz.
+ // In software mode there is not an explicit setNeedsDisplay/display loop,
+ // so just wait a pretend-vsync at 60 Hz.
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&RenderWidgetHostViewMac::TickPendingLatencyInfoDelay,
pending_latency_info_delay_weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(1000/60));
- [software_layer_ setNeedsDisplay];
+ SendPendingLatencyInfoToHost();
}
}
@@ -2443,17 +2481,6 @@ void RenderWidgetHostViewMac::LayoutLayers() {
}
}
- // Dynamically update the software layer's contents scale to match the
- // software frame.
- if (software_frame_manager_->HasCurrentFrame() &&
- [software_layer_ respondsToSelector:(@selector(contentsScale))] &&
- [software_layer_ respondsToSelector:(@selector(setContentsScale:))]) {
- if (software_frame_manager_->GetCurrentFrameDeviceScaleFactor() !=
- [software_layer_ contentsScale]) {
- [software_layer_ setContentsScale:
- software_frame_manager_->GetCurrentFrameDeviceScaleFactor()];
- }
- }
// Changing the software layer's bounds and position doesn't always result
// in the layer being anchored to the top-left. Set the layer's frame
// explicitly, since this is more reliable in practice.
@@ -2462,7 +2489,6 @@ void RenderWidgetHostViewMac::LayoutLayers() {
new_background_frame, [software_layer_ frame]);
if (frame_changed) {
[software_layer_ setFrame:new_background_frame];
- [software_layer_ setNeedsDisplay];
}
}
}
@@ -3315,6 +3341,13 @@ SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() {
params.latency_info);
}
+- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
+ withScaleFactor:(float)scale_factor
+ withCanvas:(SkCanvas*)canvas {
+ renderWidgetHostView_->GotBrowserCompositorSoftwareFrame(
+ frame_data, scale_factor, canvas);
+}
+
- (void)drawRect:(NSRect)dirtyRect {
TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::drawRect");
DCHECK(!renderWidgetHostView_->use_core_animation_);
@@ -4385,38 +4418,54 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
@implementation SoftwareLayer
-- (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r {
+- (id)init {
if (self = [super init]) {
- renderWidgetHostView_ = r;
-
[self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
[self setAnchorPoint:CGPointMake(0, 0)];
// Setting contents gravity is necessary to prevent the layer from being
// scaled during dyanmic resizes (especially with devtools open).
[self setContentsGravity:kCAGravityTopLeft];
- if (renderWidgetHostView_->software_frame_manager_->HasCurrentFrame() &&
- [self respondsToSelector:(@selector(setContentsScale:))]) {
- [self setContentsScale:renderWidgetHostView_->software_frame_manager_->
- GetCurrentFrameDeviceScaleFactor()];
- }
-
- // Ensure that the transition between frames not be animated.
- [self setActions:@{ @"contents" : [NSNull null] }];
}
return self;
}
-- (void)drawInContext:(CGContextRef)context {
- TRACE_EVENT0("browser", "SoftwareLayer::drawInContext");
+- (void)setContentsToData:(const void *)data
+ withRowBytes:(size_t)rowBytes
+ withPixelSize:(gfx::Size)pixelSize
+ withScaleFactor:(float)scaleFactor {
+ TRACE_EVENT0("browser", "-[SoftwareLayer setContentsToData]");
- CGRect clipRect = CGContextGetClipBoundingBox(context);
- if (renderWidgetHostView_) {
- [renderWidgetHostView_->cocoa_view() drawWithDirtyRect:clipRect
- inContext:context];
- } else {
- CGContextSetFillColorWithColor(context,
- CGColorGetConstantColor(kCGColorWhite));
- CGContextFillRect(context, clipRect);
+ // Disable animating the contents change or the scale factor change.
+ ScopedCAActionDisabler disabler;
+
+ // Set the contents of the software CALayer to be a CGImage with the provided
+ // pixel data. Make a copy of the data before backing the image with them,
+ // because the same buffer will be reused for the next frame.
+ base::ScopedCFTypeRef<CFDataRef> dataCopy(
+ CFDataCreate(NULL,
+ static_cast<const UInt8 *>(data),
+ rowBytes * pixelSize.height()));
+ base::ScopedCFTypeRef<CGDataProviderRef> dataProvider(
+ CGDataProviderCreateWithCFData(dataCopy));
+ base::ScopedCFTypeRef<CGImageRef> image(
+ CGImageCreate(pixelSize.width(),
+ pixelSize.height(),
+ 8,
+ 32,
+ rowBytes,
+ base::mac::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ dataProvider,
+ NULL,
+ false,
+ kCGRenderingIntentDefault));
+ [self setContents:(id)image.get()];
+
+ // Set the contents scale of the software CALayer.
+ if ([self respondsToSelector:(@selector(contentsScale))] &&
+ [self respondsToSelector:(@selector(setContentsScale:))] &&
+ [self contentsScale] != scaleFactor) {
+ [self setContentsScale:scaleFactor];
}
}
@@ -4424,7 +4473,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// Disable the fade-out animation as the layer is removed.
ScopedCAActionDisabler disabler;
[self removeFromSuperlayer];
- renderWidgetHostView_ = nil;
}
@end // implementation SoftwareLayer
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index ad1a5e3..e83a8d6 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -378,6 +378,8 @@
'browser/compositor/gpu_browser_compositor_output_surface.h',
'browser/compositor/software_browser_compositor_output_surface.cc',
'browser/compositor/software_browser_compositor_output_surface.h',
+ 'browser/compositor/software_output_device_mac.mm',
+ 'browser/compositor/software_output_device_mac.h',
'browser/compositor/software_output_device_ozone.cc',
'browser/compositor/software_output_device_ozone.h',
'browser/compositor/software_output_device_win.cc',
diff --git a/content/renderer/gpu/compositor_software_output_device.cc b/content/renderer/gpu/compositor_software_output_device.cc
index a8c893b..c656d45 100644
--- a/content/renderer/gpu/compositor_software_output_device.cc
+++ b/content/renderer/gpu/compositor_software_output_device.cc
@@ -78,7 +78,7 @@ unsigned CompositorSoftwareOutputDevice::GetNextId() {
CompositorSoftwareOutputDevice::Buffer*
CompositorSoftwareOutputDevice::CreateBuffer() {
scoped_ptr<cc::SharedBitmap> shared_bitmap =
- shared_bitmap_manager_->AllocateSharedBitmap(viewport_size_);
+ shared_bitmap_manager_->AllocateSharedBitmap(viewport_pixel_size_);
CHECK(shared_bitmap);
return new Buffer(GetNextId(), shared_bitmap.Pass());
}
@@ -94,10 +94,14 @@ size_t CompositorSoftwareOutputDevice::FindFreeBuffer(size_t hint) {
return buffers_.size() - 1;
}
-void CompositorSoftwareOutputDevice::Resize(const gfx::Size& viewport_size) {
+void CompositorSoftwareOutputDevice::Resize(
+ const gfx::Size& viewport_pixel_size,
+ float scale_factor) {
DCHECK(CalledOnValidThread());
- if (viewport_size_ == viewport_size)
+ scale_factor_ = scale_factor;
+
+ if (viewport_pixel_size_ == viewport_pixel_size)
return;
// Keep non-ACKed buffers in awaiting_ack_ until they get acknowledged.
@@ -110,7 +114,7 @@ void CompositorSoftwareOutputDevice::Resize(const gfx::Size& viewport_size) {
buffers_.clear();
current_index_ = -1;
- viewport_size_ = viewport_size;
+ viewport_pixel_size_ = viewport_pixel_size;
}
void CompositorSoftwareOutputDevice::DiscardBackbuffer() {
@@ -141,14 +145,14 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
current->SetFree(false);
// Set up a canvas for the current front buffer.
- SkImageInfo info = SkImageInfo::MakeN32Premul(viewport_size_.width(),
- viewport_size_.height());
+ SkImageInfo info = SkImageInfo::MakeN32Premul(viewport_pixel_size_.width(),
+ viewport_pixel_size_.height());
SkBitmap bitmap;
bitmap.installPixels(info, current->memory(), info.minRowBytes());
canvas_ = skia::AdoptRef(new SkCanvas(bitmap));
if (!previous) {
- DCHECK(damage_rect == gfx::Rect(viewport_size_));
+ DCHECK(damage_rect == gfx::Rect(viewport_pixel_size_));
} else {
// Find the smallest damage region that needs
// to be copied from the |previous| buffer.
@@ -157,15 +161,15 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
current->FindDamageDifferenceFrom(previous, &region) ||
previous->FindDamageDifferenceFrom(current, &region);
if (!found)
- region = SkRegion(RectToSkIRect(gfx::Rect(viewport_size_)));
+ region = SkRegion(RectToSkIRect(gfx::Rect(viewport_pixel_size_)));
region.op(RectToSkIRect(damage_rect), SkRegion::kDifference_Op);
// Copy over the damage region.
if (!region.isEmpty()) {
SkBitmap back_bitmap;
back_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- viewport_size_.width(),
- viewport_size_.height());
+ viewport_pixel_size_.width(),
+ viewport_pixel_size_.height());
back_bitmap.setPixels(previous->memory());
for (SkRegion::Iterator it(region); !it.done(); it.next()) {
@@ -181,7 +185,7 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
for (size_t i = 0; i < buffers_.size(); ++i) {
Buffer* buffer = buffers_[i];
if (buffer->parent() == current)
- buffer->SetParent(NULL, gfx::Rect(viewport_size_));
+ buffer->SetParent(NULL, gfx::Rect(viewport_pixel_size_));
}
damage_rect_ = damage_rect;
@@ -195,7 +199,7 @@ void CompositorSoftwareOutputDevice::EndPaint(
Buffer* buffer = buffers_[current_index_];
frame_data->id = buffer->id();
- frame_data->size = viewport_size_;
+ frame_data->size = viewport_pixel_size_;
frame_data->damage_rect = damage_rect_;
frame_data->bitmap_id = buffer->shared_bitmap_id();
}
diff --git a/content/renderer/gpu/compositor_software_output_device.h b/content/renderer/gpu/compositor_software_output_device.h
index 646349a..75bda0c 100644
--- a/content/renderer/gpu/compositor_software_output_device.h
+++ b/content/renderer/gpu/compositor_software_output_device.h
@@ -31,7 +31,7 @@ public:
CompositorSoftwareOutputDevice();
virtual ~CompositorSoftwareOutputDevice();
- virtual void Resize(const gfx::Size& size) OVERRIDE;
+ virtual void Resize(const gfx::Size& pixel_size, float scale_factor) OVERRIDE;
virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;