Commit 7b4bff53 authored by ccameron@chromium.org's avatar ccameron@chromium.org

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
parent d5801aea
...@@ -226,7 +226,7 @@ void OutputSurface::Reshape(const gfx::Size& size, float scale_factor) { ...@@ -226,7 +226,7 @@ void OutputSurface::Reshape(const gfx::Size& size, float scale_factor) {
size.width(), size.height(), scale_factor); size.width(), size.height(), scale_factor);
} }
if (software_device_) if (software_device_)
software_device_->Resize(size); software_device_->Resize(size, scale_factor);
} }
gfx::Size OutputSurface::SurfaceSize() const { gfx::Size OutputSurface::SurfaceSize() const {
......
...@@ -12,17 +12,22 @@ ...@@ -12,17 +12,22 @@
namespace cc { namespace cc {
SoftwareOutputDevice::SoftwareOutputDevice() {} SoftwareOutputDevice::SoftwareOutputDevice() : scale_factor_(1.f) {
}
SoftwareOutputDevice::~SoftwareOutputDevice() {} SoftwareOutputDevice::~SoftwareOutputDevice() {}
void SoftwareOutputDevice::Resize(const gfx::Size& viewport_size) { void SoftwareOutputDevice::Resize(const gfx::Size& viewport_pixel_size,
if (viewport_size_ == viewport_size) float scale_factor) {
scale_factor_ = scale_factor;
if (viewport_pixel_size_ == viewport_pixel_size)
return; return;
SkImageInfo info = SkImageInfo::MakeN32( SkImageInfo info = SkImageInfo::MakeN32(viewport_pixel_size.width(),
viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType); viewport_pixel_size.height(),
viewport_size_ = viewport_size; kOpaque_SkAlphaType);
viewport_pixel_size_ = viewport_pixel_size;
canvas_ = skia::AdoptRef(SkCanvas::NewRaster(info)); canvas_ = skia::AdoptRef(SkCanvas::NewRaster(info));
} }
...@@ -35,7 +40,7 @@ SkCanvas* SoftwareOutputDevice::BeginPaint(const gfx::Rect& damage_rect) { ...@@ -35,7 +40,7 @@ SkCanvas* SoftwareOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
void SoftwareOutputDevice::EndPaint(SoftwareFrameData* frame_data) { void SoftwareOutputDevice::EndPaint(SoftwareFrameData* frame_data) {
DCHECK(frame_data); DCHECK(frame_data);
frame_data->id = 0; frame_data->id = 0;
frame_data->size = viewport_size_; frame_data->size = viewport_pixel_size_;
frame_data->damage_rect = damage_rect_; frame_data->damage_rect = damage_rect_;
} }
......
...@@ -36,7 +36,7 @@ class CC_EXPORT SoftwareOutputDevice { ...@@ -36,7 +36,7 @@ class CC_EXPORT SoftwareOutputDevice {
// Discards any pre-existing backing buffers and allocates memory for a // Discards any pre-existing backing buffers and allocates memory for a
// software device of |size|. This must be called before the // software device of |size|. This must be called before the
// |SoftwareOutputDevice| can be used in other ways. // |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 // Called on BeginDrawingFrame. The compositor will draw into the returned
// SkCanvas. The |SoftwareOutputDevice| implementation needs to provide a // SkCanvas. The |SoftwareOutputDevice| implementation needs to provide a
...@@ -74,7 +74,8 @@ class CC_EXPORT SoftwareOutputDevice { ...@@ -74,7 +74,8 @@ class CC_EXPORT SoftwareOutputDevice {
virtual gfx::VSyncProvider* GetVSyncProvider(); virtual gfx::VSyncProvider* GetVSyncProvider();
protected: protected:
gfx::Size viewport_size_; gfx::Size viewport_pixel_size_;
float scale_factor_;
gfx::Rect damage_rect_; gfx::Rect damage_rect_;
skia::RefPtr<SkCanvas> canvas_; skia::RefPtr<SkCanvas> canvas_;
scoped_ptr<gfx::VSyncProvider> vsync_provider_; scoped_ptr<gfx::VSyncProvider> vsync_provider_;
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
namespace cc { namespace cc {
void PixelTestSoftwareOutputDevice::Resize(const gfx::Size& size) { void PixelTestSoftwareOutputDevice::Resize(const gfx::Size& pixel_size,
gfx::Size expanded_size(size.width() + surface_expansion_size_.width(), float scale_factor) {
size.height() + surface_expansion_size_.height()); gfx::Size expanded_size(
SoftwareOutputDevice::Resize(expanded_size); pixel_size.width() + surface_expansion_size_.width(),
pixel_size.height() + surface_expansion_size_.height());
SoftwareOutputDevice::Resize(expanded_size, scale_factor);
} }
} // namespace cc } // namespace cc
...@@ -11,7 +11,7 @@ namespace cc { ...@@ -11,7 +11,7 @@ namespace cc {
class PixelTestSoftwareOutputDevice : public SoftwareOutputDevice { class PixelTestSoftwareOutputDevice : public SoftwareOutputDevice {
public: 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) { void set_surface_expansion_size(const gfx::Size& surface_expansion_size) {
surface_expansion_size_ = surface_expansion_size; surface_expansion_size_ = surface_expansion_size;
......
...@@ -39,7 +39,8 @@ class SynchronousCompositorOutputSurface::SoftwareDevice ...@@ -39,7 +39,8 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
SoftwareDevice(SynchronousCompositorOutputSurface* surface) SoftwareDevice(SynchronousCompositorOutputSurface* surface)
: surface_(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. // Intentional no-op: canvas size is controlled by the embedder.
} }
virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE { virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#include "ui/gfx/ozone/surface_factory_ozone.h" #include "ui/gfx/ozone/surface_factory_ozone.h"
#elif defined(USE_X11) #elif defined(USE_X11)
#include "content/browser/compositor/software_output_device_x11.h" #include "content/browser/compositor/software_output_device_x11.h"
#elif defined(OS_MACOSX)
#include "content/browser/compositor/software_output_device_mac.h"
#endif #endif
using cc::ContextProvider; using cc::ContextProvider;
...@@ -98,6 +100,9 @@ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice( ...@@ -98,6 +100,9 @@ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
#elif defined(USE_X11) #elif defined(USE_X11)
return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceX11( return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceX11(
compositor)); compositor));
#elif defined(OS_MACOSX)
return scoped_ptr<cc::SoftwareOutputDevice>(
new SoftwareOutputDeviceMac(compositor));
#else #else
NOTREACHED(); NOTREACHED();
return scoped_ptr<cc::SoftwareOutputDevice>(); return scoped_ptr<cc::SoftwareOutputDevice>();
......
// 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_
// 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
...@@ -30,17 +30,20 @@ SoftwareOutputDeviceOzone::SoftwareOutputDeviceOzone(ui::Compositor* compositor) ...@@ -30,17 +30,20 @@ SoftwareOutputDeviceOzone::SoftwareOutputDeviceOzone(ui::Compositor* compositor)
SoftwareOutputDeviceOzone::~SoftwareOutputDeviceOzone() { SoftwareOutputDeviceOzone::~SoftwareOutputDeviceOzone() {
} }
void SoftwareOutputDeviceOzone::Resize(const gfx::Size& viewport_size) { void SoftwareOutputDeviceOzone::Resize(const gfx::Size& viewport_pixel_size,
if (viewport_size_ == viewport_size) float scale_factor) {
scale_factor_ = scale_factor;
if (viewport_pixel_size_ == viewport_pixel_size)
return; 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) { 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. // Get canvas for next frame.
canvas_ = surface_ozone_->GetCanvas(); canvas_ = surface_ozone_->GetCanvas();
......
...@@ -28,7 +28,8 @@ class CONTENT_EXPORT SoftwareOutputDeviceOzone ...@@ -28,7 +28,8 @@ class CONTENT_EXPORT SoftwareOutputDeviceOzone
explicit SoftwareOutputDeviceOzone(ui::Compositor* compositor); explicit SoftwareOutputDeviceOzone(ui::Compositor* compositor);
virtual ~SoftwareOutputDeviceOzone(); 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 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE; virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
......
...@@ -110,7 +110,7 @@ void SoftwareOutputDeviceOzoneTest::SetUp() { ...@@ -110,7 +110,7 @@ void SoftwareOutputDeviceOzoneTest::SetUp() {
output_device_.reset(new content::SoftwareOutputDeviceOzone( output_device_.reset(new content::SoftwareOutputDeviceOzone(
compositor_.get())); compositor_.get()));
output_device_->Resize(size); output_device_->Resize(size, 1.f);
} }
void SoftwareOutputDeviceOzoneTest::TearDown() { void SoftwareOutputDeviceOzoneTest::TearDown() {
...@@ -135,7 +135,7 @@ TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) { ...@@ -135,7 +135,7 @@ TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) {
gfx::Rect damage(0, 0, 100, 100); gfx::Rect damage(0, 0, 100, 100);
gfx::Size size(200, 100); gfx::Size size(200, 100);
// Reduce size. // Reduce size.
output_device_->Resize(size); output_device_->Resize(size, 1.f);
SkCanvas* canvas = output_device_->BeginPaint(damage); SkCanvas* canvas = output_device_->BeginPaint(damage);
gfx::Size canvas_size(canvas->getDeviceSize().width(), gfx::Size canvas_size(canvas->getDeviceSize().width(),
...@@ -144,7 +144,7 @@ TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) { ...@@ -144,7 +144,7 @@ TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) {
size.SetSize(1000, 500); size.SetSize(1000, 500);
// Increase size. // Increase size.
output_device_->Resize(size); output_device_->Resize(size, 1.f);
canvas = output_device_->BeginPaint(damage); canvas = output_device_->BeginPaint(damage);
canvas_size.SetSize(canvas->getDeviceSize().width(), canvas_size.SetSize(canvas->getDeviceSize().width(),
...@@ -157,7 +157,7 @@ TEST_F(SoftwareOutputDeviceOzonePixelTest, CheckCopyToBitmap) { ...@@ -157,7 +157,7 @@ TEST_F(SoftwareOutputDeviceOzonePixelTest, CheckCopyToBitmap) {
const int width = 6; const int width = 6;
const int height = 4; const int height = 4;
const gfx::Rect area(width, height); const gfx::Rect area(width, height);
output_device_->Resize(area.size()); output_device_->Resize(area.size(), 1.f);
SkCanvas* canvas = output_device_->BeginPaint(area); SkCanvas* canvas = output_device_->BeginPaint(area);
// Clear the background to black. // Clear the background to black.
......
...@@ -29,16 +29,20 @@ SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() { ...@@ -29,16 +29,20 @@ SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 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)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (viewport_size_ == viewport_size) scale_factor_ = scale_factor;
if (viewport_pixel_size_ == viewport_pixel_size)
return; return;
viewport_size_ = viewport_size; viewport_pixel_size_ = viewport_pixel_size;
contents_.reset(new gfx::Canvas(viewport_size, 1.0f, true)); contents_.reset(new gfx::Canvas(viewport_pixel_size, 1.0f, true));
memset(&bitmap_info_, 0, sizeof(bitmap_info_)); 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); &bitmap_info_.bmiHeader);
} }
...@@ -61,7 +65,7 @@ void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) { ...@@ -61,7 +65,7 @@ void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) {
SoftwareOutputDevice::EndPaint(frame_data); SoftwareOutputDevice::EndPaint(frame_data);
gfx::Rect rect = damage_rect_; gfx::Rect rect = damage_rect_;
rect.Intersect(gfx::Rect(viewport_size_)); rect.Intersect(gfx::Rect(viewport_pixel_size_));
if (rect.IsEmpty()) if (rect.IsEmpty())
return; return;
......
...@@ -25,7 +25,8 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice { ...@@ -25,7 +25,8 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
explicit SoftwareOutputDeviceWin(ui::Compositor* compositor); explicit SoftwareOutputDeviceWin(ui::Compositor* compositor);
virtual ~SoftwareOutputDeviceWin(); 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 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE; virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE; virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE;
...@@ -35,6 +36,8 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice { ...@@ -35,6 +36,8 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
BITMAPINFO bitmap_info_; BITMAPINFO bitmap_info_;
scoped_ptr<gfx::Canvas> contents_; scoped_ptr<gfx::Canvas> contents_;
bool is_hwnd_composited_; bool is_hwnd_composited_;
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWin);
}; };
} // namespace content } // namespace content
......
...@@ -47,7 +47,7 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) { ...@@ -47,7 +47,7 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
SoftwareOutputDevice::EndPaint(frame_data); SoftwareOutputDevice::EndPaint(frame_data);
gfx::Rect rect = damage_rect_; gfx::Rect rect = damage_rect_;
rect.Intersect(gfx::Rect(viewport_size_)); rect.Intersect(gfx::Rect(viewport_pixel_size_));
if (rect.IsEmpty()) if (rect.IsEmpty())
return; return;
...@@ -65,8 +65,8 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) { ...@@ -65,8 +65,8 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
SkImageInfo info; SkImageInfo info;
size_t rowBytes; size_t rowBytes;
const void* addr = canvas_->peekPixels(&info, &rowBytes); const void* addr = canvas_->peekPixels(&info, &rowBytes);
image.width = viewport_size_.width(); image.width = viewport_pixel_size_.width();
image.height = viewport_size_.height(); image.height = viewport_pixel_size_.height();
image.depth = 32; image.depth = 32;
image.bits_per_pixel = 32; image.bits_per_pixel = 32;
image.format = ZPixmap; image.format = ZPixmap;
...@@ -125,8 +125,8 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) { ...@@ -125,8 +125,8 @@ void SoftwareOutputDeviceX11::EndPaint(cc::SoftwareFrameData* frame_data) {
compositor_->widget(), compositor_->widget(),
gc_, gc_,
static_cast<const uint8*>(addr), static_cast<const uint8*>(addr),
viewport_size_.width(), viewport_pixel_size_.width(),
viewport_size_.height(), viewport_pixel_size_.height(),
rect.x(), rect.x(),
rect.y(), rect.y(),
rect.x(), rect.x(),
......
...@@ -29,6 +29,8 @@ class SoftwareOutputDeviceX11 : public cc::SoftwareOutputDevice { ...@@ -29,6 +29,8 @@ class SoftwareOutputDeviceX11 : public cc::SoftwareOutputDevice {
XDisplay* display_; XDisplay* display_;
GC gc_; GC gc_;
XWindowAttributes attributes_; XWindowAttributes attributes_;
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceX11);
}; };
} // namespace content } // namespace content
......
...@@ -186,15 +186,16 @@ class Layer; ...@@ -186,15 +186,16 @@ class Layer;
actualRange:(NSRangePointer)actualRange; actualRange:(NSRangePointer)actualRange;
@end @end
@interface SoftwareLayer : CALayer { @interface SoftwareLayer : CALayer
@private
content::RenderWidgetHostViewMac* renderWidgetHostView_;
}
- (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r; - (id)init;
// Invalidate the RenderWidgetHostViewMac because it may be going away. If - (void)setContentsToData:(const void *)data
// displayed again, it will draw white. withRowBytes:(size_t)rowBytes
withPixelSize:(gfx::Size)pixelSize
withScaleFactor:(float)scaleFactor;
// Remove the layer from the layer hierarchy.
- (void)disableRendering; - (void)disableRendering;
@end @end
...@@ -371,6 +372,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac ...@@ -371,6 +372,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
float scale_factor, float scale_factor,
const std::vector<ui::LatencyInfo>& latency_info); 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. // Draw the IOSurface by making its context current to this view.
void DrawIOSurfaceWithoutCoreAnimation(); void DrawIOSurfaceWithoutCoreAnimation();
......
...@@ -607,8 +607,7 @@ void RenderWidgetHostViewMac::EnsureSoftwareLayer() { ...@@ -607,8 +607,7 @@ void RenderWidgetHostViewMac::EnsureSoftwareLayer() {
if (software_layer_ || !use_core_animation_) if (software_layer_ || !use_core_animation_)
return; return;
software_layer_.reset([[SoftwareLayer alloc] software_layer_.reset([[SoftwareLayer alloc] init]);
initWithRenderWidgetHostViewMac:this]);
DCHECK(software_layer_); DCHECK(software_layer_);
// Disable the fade-in animation as the layer is added. // Disable the fade-in animation as the layer is added.
...@@ -868,7 +867,6 @@ void RenderWidgetHostViewMac::WasShown() { ...@@ -868,7 +867,6 @@ void RenderWidgetHostViewMac::WasShown() {
// Call setNeedsDisplay before pausing for new frames to come in -- if any // Call setNeedsDisplay before pausing for new frames to come in -- if any
// do, and are drawn, then the needsDisplay bit will be cleared. // do, and are drawn, then the needsDisplay bit will be cleared.
[software_layer_ setNeedsDisplay];
[compositing_iosurface_layer_ setNeedsDisplay]; [compositing_iosurface_layer_ setNeedsDisplay];
PauseForPendingResizeOrRepaintsAndDraw(); PauseForPendingResizeOrRepaintsAndDraw();
...@@ -1570,6 +1568,27 @@ void RenderWidgetHostViewMac::CompositorSwapBuffers( ...@@ -1570,6 +1568,27 @@ void RenderWidgetHostViewMac::CompositorSwapBuffers(
LayoutLayers(); 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() { void RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() {
CHECK(!use_core_animation_); CHECK(!use_core_animation_);
CHECK(compositing_iosurface_); CHECK(compositing_iosurface_);
...@@ -1893,6 +1912,8 @@ bool RenderWidgetHostViewMac::HasAcceleratedSurface( ...@@ -1893,6 +1912,8 @@ bool RenderWidgetHostViewMac::HasAcceleratedSurface(
void RenderWidgetHostViewMac::OnSwapCompositorFrame( void RenderWidgetHostViewMac::OnSwapCompositorFrame(
uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) {
TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame");
if (frame->delegated_frame_data) { if (frame->delegated_frame_data) {
if (!compositor_) { if (!compositor_) {
compositor_.reset(new ui::Compositor(cocoa_view_)); compositor_.reset(new ui::Compositor(cocoa_view_));
...@@ -1930,6 +1951,23 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame( ...@@ -1930,6 +1951,23 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame(
// Add latency info to report when the frame finishes drawing. // Add latency info to report when the frame finishes drawing.
AddPendingLatencyInfo(frame->metadata.latency_info); 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(); GotSoftwareFrame();
cc::CompositorFrameAck ack; cc::CompositorFrameAck ack;
...@@ -2073,6 +2111,8 @@ void RenderWidgetHostViewMac::GotAcceleratedFrame() { ...@@ -2073,6 +2111,8 @@ void RenderWidgetHostViewMac::GotAcceleratedFrame() {
} }
void RenderWidgetHostViewMac::GotSoftwareFrame() { void RenderWidgetHostViewMac::GotSoftwareFrame() {
TRACE_EVENT0("browser", "RenderWidgetHostViewMac::GotSoftwareFrame");
if (!render_widget_host_) if (!render_widget_host_)
return; return;
...@@ -2084,7 +2124,6 @@ void RenderWidgetHostViewMac::GotSoftwareFrame() { ...@@ -2084,7 +2124,6 @@ void RenderWidgetHostViewMac::GotSoftwareFrame() {
// happen before the frame be acked, otherwise the new frame will likely be // happen before the frame be acked, otherwise the new frame will likely be
// ready before the drawing is complete, thrashing the browser main thread. // ready before the drawing is complete, thrashing the browser main thread.
if (use_core_animation_) { if (use_core_animation_) {
[software_layer_ setNeedsDisplay];
[software_layer_ displayIfNeeded]; [software_layer_ displayIfNeeded];
} else { } else {
[cocoa_view_ setNeedsDisplay:YES]; [cocoa_view_ setNeedsDisplay:YES];
...@@ -2329,15 +2368,14 @@ void RenderWidgetHostViewMac::TickPendingLatencyInfoDelay() { ...@@ -2329,15 +2368,14 @@ void RenderWidgetHostViewMac::TickPendingLatencyInfoDelay() {
[compositing_iosurface_layer_ gotNewFrame]; [compositing_iosurface_layer_ gotNewFrame];
} }
if (software_layer_) { if (software_layer_) {
// In software mode, setNeedsDisplay will almost immediately result in the // In software mode there is not an explicit setNeedsDisplay/display loop,
// layer's draw function being called, so manually insert a pretend-vsync // so just wait a pretend-vsync at 60 Hz.
// at 60 Hz.
base::MessageLoop::current()->PostDelayedTask( base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, FROM_HERE,
base::Bind(&RenderWidgetHostViewMac::TickPendingLatencyInfoDelay, base::Bind(&RenderWidgetHostViewMac::TickPendingLatencyInfoDelay,
pending_latency_info_delay_weak_ptr_factory_.GetWeakPtr()), pending_latency_info_delay_weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(1000/60)); base::TimeDelta::FromMilliseconds(1000/60));
[software_layer_ setNeedsDisplay]; SendPendingLatencyInfoToHost();
} }
} }
...@@ -2443,17 +2481,6 @@ void RenderWidgetHostViewMac::LayoutLayers() { ...@@ -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 // 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 // in the layer being anchored to the top-left. Set the layer's frame
// explicitly, since this is more reliable in practice. // explicitly, since this is more reliable in practice.
...@@ -2462,7 +2489,6 @@ void RenderWidgetHostViewMac::LayoutLayers() { ...@@ -2462,7 +2489,6 @@ void RenderWidgetHostViewMac::LayoutLayers() {
new_background_frame, [software_layer_ frame]); new_background_frame, [software_layer_ frame]);
if (frame_changed) { if (frame_changed) {
[software_layer_ setFrame:new_background_frame]; [software_layer_ setFrame:new_background_frame];
[software_layer_ setNeedsDisplay];
} }
} }
} }
...@@ -3315,6 +3341,13 @@ SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() { ...@@ -3315,6 +3341,13 @@ SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() {
params.latency_info); 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 { - (void)drawRect:(NSRect)dirtyRect {
TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::drawRect"); TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::drawRect");
DCHECK(!renderWidgetHostView_->use_core_animation_); DCHECK(!renderWidgetHostView_->use_core_animation_);
...@@ -4385,38 +4418,54 @@ extern NSString *NSTextInputReplacementRangeAttributeName; ...@@ -4385,38 +4418,54 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
@implementation SoftwareLayer @implementation SoftwareLayer
- (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r { - (id)init {
if (self = [super init]) { if (self = [super init]) {
renderWidgetHostView_ = r;
[self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
[self setAnchorPoint:CGPointMake(0, 0)]; [self setAnchorPoint:CGPointMake(0, 0)];
// Setting contents gravity is necessary to prevent the layer from being // Setting contents gravity is necessary to prevent the layer from being
// scaled during dyanmic resizes (especially with devtools open). // scaled during dyanmic resizes (especially with devtools open).
[self setContentsGravity:kCAGravityTopLeft]; [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; return self;
} }
- (void)drawInContext:(CGContextRef)context { - (void)setContentsToData:(const void *)data
TRACE_EVENT0("browser", "SoftwareLayer::drawInContext"); withRowBytes:(size_t)rowBytes
withPixelSize:(gfx::Size)pixelSize
withScaleFactor:(float)scaleFactor {
TRACE_EVENT0("browser", "-[SoftwareLayer setContentsToData]");
CGRect clipRect = CGContextGetClipBoundingBox(context); // Disable animating the contents change or the scale factor change.
if (renderWidgetHostView_) { ScopedCAActionDisabler disabler;
[renderWidgetHostView_->cocoa_view() drawWithDirtyRect:clipRect
inContext:context]; // Set the contents of the software CALayer to be a CGImage with the provided
} else { // pixel data. Make a copy of the data before backing the image with them,
CGContextSetFillColorWithColor(context, // because the same buffer will be reused for the next frame.
CGColorGetConstantColor(kCGColorWhite)); base::ScopedCFTypeRef<CFDataRef> dataCopy(
CGContextFillRect(context, clipRect); 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; ...@@ -4424,7 +4473,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// Disable the fade-out animation as the layer is removed. // Disable the fade-out animation as the layer is removed.
ScopedCAActionDisabler disabler; ScopedCAActionDisabler disabler;
[self removeFromSuperlayer]; [self removeFromSuperlayer];
renderWidgetHostView_ = nil;
} }
@end // implementation SoftwareLayer @end // implementation SoftwareLayer
...@@ -378,6 +378,8 @@ ...@@ -378,6 +378,8 @@
'browser/compositor/gpu_browser_compositor_output_surface.h', 'browser/compositor/gpu_browser_compositor_output_surface.h',
'browser/compositor/software_browser_compositor_output_surface.cc', 'browser/compositor/software_browser_compositor_output_surface.cc',
'browser/compositor/software_browser_compositor_output_surface.h', '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.cc',
'browser/compositor/software_output_device_ozone.h', 'browser/compositor/software_output_device_ozone.h',
'browser/compositor/software_output_device_win.cc', 'browser/compositor/software_output_device_win.cc',
......
...@@ -78,7 +78,7 @@ unsigned CompositorSoftwareOutputDevice::GetNextId() { ...@@ -78,7 +78,7 @@ unsigned CompositorSoftwareOutputDevice::GetNextId() {
CompositorSoftwareOutputDevice::Buffer* CompositorSoftwareOutputDevice::Buffer*
CompositorSoftwareOutputDevice::CreateBuffer() { CompositorSoftwareOutputDevice::CreateBuffer() {
scoped_ptr<cc::SharedBitmap> shared_bitmap = scoped_ptr<cc::SharedBitmap> shared_bitmap =
shared_bitmap_manager_->AllocateSharedBitmap(viewport_size_); shared_bitmap_manager_->AllocateSharedBitmap(viewport_pixel_size_);
CHECK(shared_bitmap); CHECK(shared_bitmap);
return new Buffer(GetNextId(), shared_bitmap.Pass()); return new Buffer(GetNextId(), shared_bitmap.Pass());
} }
...@@ -94,10 +94,14 @@ size_t CompositorSoftwareOutputDevice::FindFreeBuffer(size_t hint) { ...@@ -94,10 +94,14 @@ size_t CompositorSoftwareOutputDevice::FindFreeBuffer(size_t hint) {
return buffers_.size() - 1; 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()); DCHECK(CalledOnValidThread());
if (viewport_size_ == viewport_size) scale_factor_ = scale_factor;
if (viewport_pixel_size_ == viewport_pixel_size)
return; return;
// Keep non-ACKed buffers in awaiting_ack_ until they get acknowledged. // Keep non-ACKed buffers in awaiting_ack_ until they get acknowledged.
...@@ -110,7 +114,7 @@ void CompositorSoftwareOutputDevice::Resize(const gfx::Size& viewport_size) { ...@@ -110,7 +114,7 @@ void CompositorSoftwareOutputDevice::Resize(const gfx::Size& viewport_size) {
buffers_.clear(); buffers_.clear();
current_index_ = -1; current_index_ = -1;
viewport_size_ = viewport_size; viewport_pixel_size_ = viewport_pixel_size;
} }
void CompositorSoftwareOutputDevice::DiscardBackbuffer() { void CompositorSoftwareOutputDevice::DiscardBackbuffer() {
...@@ -141,14 +145,14 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint( ...@@ -141,14 +145,14 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
current->SetFree(false); current->SetFree(false);
// Set up a canvas for the current front buffer. // Set up a canvas for the current front buffer.
SkImageInfo info = SkImageInfo::MakeN32Premul(viewport_size_.width(), SkImageInfo info = SkImageInfo::MakeN32Premul(viewport_pixel_size_.width(),
viewport_size_.height()); viewport_pixel_size_.height());
SkBitmap bitmap; SkBitmap bitmap;
bitmap.installPixels(info, current->memory(), info.minRowBytes()); bitmap.installPixels(info, current->memory(), info.minRowBytes());
canvas_ = skia::AdoptRef(new SkCanvas(bitmap)); canvas_ = skia::AdoptRef(new SkCanvas(bitmap));
if (!previous) { if (!previous) {
DCHECK(damage_rect == gfx::Rect(viewport_size_)); DCHECK(damage_rect == gfx::Rect(viewport_pixel_size_));
} else { } else {
// Find the smallest damage region that needs // Find the smallest damage region that needs
// to be copied from the |previous| buffer. // to be copied from the |previous| buffer.
...@@ -157,15 +161,15 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint( ...@@ -157,15 +161,15 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
current->FindDamageDifferenceFrom(previous, &region) || current->FindDamageDifferenceFrom(previous, &region) ||
previous->FindDamageDifferenceFrom(current, &region); previous->FindDamageDifferenceFrom(current, &region);
if (!found) 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); region.op(RectToSkIRect(damage_rect), SkRegion::kDifference_Op);
// Copy over the damage region. // Copy over the damage region.
if (!region.isEmpty()) { if (!region.isEmpty()) {
SkBitmap back_bitmap; SkBitmap back_bitmap;
back_bitmap.setConfig(SkBitmap::kARGB_8888_Config, back_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
viewport_size_.width(), viewport_pixel_size_.width(),
viewport_size_.height()); viewport_pixel_size_.height());
back_bitmap.setPixels(previous->memory()); back_bitmap.setPixels(previous->memory());
for (SkRegion::Iterator it(region); !it.done(); it.next()) { for (SkRegion::Iterator it(region); !it.done(); it.next()) {
...@@ -181,7 +185,7 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint( ...@@ -181,7 +185,7 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
for (size_t i = 0; i < buffers_.size(); ++i) { for (size_t i = 0; i < buffers_.size(); ++i) {
Buffer* buffer = buffers_[i]; Buffer* buffer = buffers_[i];
if (buffer->parent() == current) if (buffer->parent() == current)
buffer->SetParent(NULL, gfx::Rect(viewport_size_)); buffer->SetParent(NULL, gfx::Rect(viewport_pixel_size_));
} }
damage_rect_ = damage_rect; damage_rect_ = damage_rect;
...@@ -195,7 +199,7 @@ void CompositorSoftwareOutputDevice::EndPaint( ...@@ -195,7 +199,7 @@ void CompositorSoftwareOutputDevice::EndPaint(
Buffer* buffer = buffers_[current_index_]; Buffer* buffer = buffers_[current_index_];
frame_data->id = buffer->id(); frame_data->id = buffer->id();
frame_data->size = viewport_size_; frame_data->size = viewport_pixel_size_;
frame_data->damage_rect = damage_rect_; frame_data->damage_rect = damage_rect_;
frame_data->bitmap_id = buffer->shared_bitmap_id(); frame_data->bitmap_id = buffer->shared_bitmap_id();
} }
......
...@@ -31,7 +31,7 @@ public: ...@@ -31,7 +31,7 @@ public:
CompositorSoftwareOutputDevice(); CompositorSoftwareOutputDevice();
virtual ~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 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE; virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment