summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authoraelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-06 23:23:32 +0000
committeraelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-06 23:23:32 +0000
commitf224cc9a660a41bf5115fb2db7564cd0c87d68b5 (patch)
tree367cecabdd2f47685b214c92833567a44140ba99 /cc
parent2ed80f0145fc03eb7eac6333b11eb27645bb37ea (diff)
downloadchromium_src-f224cc9a660a41bf5115fb2db7564cd0c87d68b5.zip
chromium_src-f224cc9a660a41bf5115fb2db7564cd0c87d68b5.tar.gz
chromium_src-f224cc9a660a41bf5115fb2db7564cd0c87d68b5.tar.bz2
Implement transform/clip support for Android WebView.
Transforms are applied above the root-layer. I fixed LTHCommon to forward root-layer transforms to sublayers, as the RenderSurface-based logic was previously clearing transforms and copying over only the scale portion. The clip rect is treated as the viewport for the purposes of DrawQuads and Renderer (this is required to avoid awful performance when the WebView is much larger than the screen). Because y-flipping the clip rect depends on knowledge of the true surface size, I also needed to add a new OutputSurface::SurfaceSize() getter and refactored viewport size throughout the Renderers to separate render-pass draw rect, glViewport rect, and surface size. Scale and translate transforms work with this patch, but rotation is still broken. New tests: LayerTreeHostCommonTest.TransformAboveRootLayer, GLRendererTest2.ScissorAndViewportWithinNonreshapableSurface, RendererPixelTest/2* and 3* NOTRY=true BUG=230463 Review URL: https://chromiumcodereview.appspot.com/15579002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@204650 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/layers/contents_scaling_layer_unittest.cc1
-rw-r--r--cc/layers/layer_iterator_unittest.cc3
-rw-r--r--cc/layers/layer_position_constraint_unittest.cc41
-rw-r--r--cc/layers/solid_color_layer_impl_unittest.cc1
-rw-r--r--cc/layers/tiled_layer_unittest.cc1
-rw-r--r--cc/output/direct_renderer.cc78
-rw-r--r--cc/output/direct_renderer.h31
-rw-r--r--cc/output/gl_renderer.cc62
-rw-r--r--cc/output/gl_renderer.h7
-rw-r--r--cc/output/gl_renderer_unittest.cc111
-rw-r--r--cc/output/output_surface.cc24
-rw-r--r--cc/output/output_surface.h3
-rw-r--r--cc/output/output_surface_client.h6
-rw-r--r--cc/output/output_surface_unittest.cc2
-rw-r--r--cc/output/renderer.h12
-rw-r--r--cc/output/renderer_pixeltest.cc13
-rw-r--r--cc/output/software_output_device.cc6
-rw-r--r--cc/output/software_renderer.cc27
-rw-r--r--cc/output/software_renderer.h7
-rw-r--r--cc/output/software_renderer_unittest.cc39
-rw-r--r--cc/test/fake_output_surface.h2
-rw-r--r--cc/test/pixel_test.cc76
-rw-r--r--cc/test/pixel_test.h85
-rw-r--r--cc/trees/damage_tracker_unittest.cc1
-rw-r--r--cc/trees/layer_tree_host.cc1
-rw-r--r--cc/trees/layer_tree_host_common.cc113
-rw-r--r--cc/trees/layer_tree_host_common.h2
-rw-r--r--cc/trees/layer_tree_host_common_unittest.cc168
-rw-r--r--cc/trees/layer_tree_host_impl.cc28
-rw-r--r--cc/trees/layer_tree_host_impl.h29
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc4
-rw-r--r--cc/trees/layer_tree_impl.cc3
-rw-r--r--cc/trees/occlusion_tracker_unittest.cc2
33 files changed, 736 insertions, 253 deletions
diff --git a/cc/layers/contents_scaling_layer_unittest.cc b/cc/layers/contents_scaling_layer_unittest.cc
index 08d9eb1..23f1376 100644
--- a/cc/layers/contents_scaling_layer_unittest.cc
+++ b/cc/layers/contents_scaling_layer_unittest.cc
@@ -41,6 +41,7 @@ void CalcDrawProps(Layer* root, float device_scale) {
LayerTreeHostCommon::CalculateDrawProperties(
root,
gfx::Size(500, 500),
+ gfx::Transform(),
device_scale,
1.f,
NULL,
diff --git a/cc/layers/layer_iterator_unittest.cc b/cc/layers/layer_iterator_unittest.cc
index e7cecfd..10526ba 100644
--- a/cc/layers/layer_iterator_unittest.cc
+++ b/cc/layers/layer_iterator_unittest.cc
@@ -141,6 +141,7 @@ TEST(LayerIteratorTest, SimpleTree) {
LayerList render_surface_layerList;
LayerTreeHostCommon::CalculateDrawProperties(root_layer.get(),
root_layer->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -189,6 +190,7 @@ TEST(LayerIteratorTest, ComplexTree) {
LayerList render_surface_layerList;
LayerTreeHostCommon::CalculateDrawProperties(root_layer.get(),
root_layer->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -252,6 +254,7 @@ TEST(LayerIteratorTest, ComplexTreeMultiSurface) {
LayerList render_surface_layerList;
LayerTreeHostCommon::CalculateDrawProperties(root_layer.get(),
root_layer->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
diff --git a/cc/layers/layer_position_constraint_unittest.cc b/cc/layers/layer_position_constraint_unittest.cc
index af1af4e..1e6084f 100644
--- a/cc/layers/layer_position_constraint_unittest.cc
+++ b/cc/layers/layer_position_constraint_unittest.cc
@@ -50,6 +50,7 @@ void ExecuteCalculateDrawProperties(LayerImpl* root_layer,
LayerTreeHostCommon::CalculateDrawProperties(
root_layer,
device_viewport_size,
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
page_scale_application_layer,
@@ -1034,8 +1035,7 @@ TEST_F(LayerPositionConstraintTest,
ScrollCompensationForFixedPositionLayerThatHasNoContainer) {
// This test checks scroll compensation when a fixed-position layer does not
// find any ancestor that is a "containerForFixedPositionLayers". In this
- // situation, the layer should be fixed to the viewport -- not the root_layer,
- // which may have transforms of its own.
+ // situation, the layer should be fixed to the root layer.
LayerImpl* child = root_->children()[0];
LayerImpl* grand_child = child->children()[0];
@@ -1051,46 +1051,43 @@ TEST_F(LayerPositionConstraintTest,
gfx::Transform identity_matrix;
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix,
+ EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z, child->draw_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z,
grand_child->draw_transform());
// Case 2: root scroll delta of 10, 10
root_->SetScrollDelta(gfx::Vector2d(10, 20));
ExecuteCalculateDrawProperties(root_.get());
- // The child is affected by scroll delta, but it is already implcitly
- // accounted for by the child's target surface (i.e. the root render surface).
- // The grand_child is not affected by the scroll delta, so its draw transform
- // needs to explicitly inverse-compensate for the scroll that's embedded in
- // the target surface.
- gfx::Transform expected_grand_child_transform;
- expected_grand_child_transform.PreconcatTransform(Inverse(rotation_by_z));
- // explicit cancelling out the scroll delta that gets embedded in the fixed
- // position layer's surface.
- expected_grand_child_transform.Translate(10.0, 20.0);
- expected_grand_child_transform.PreconcatTransform(rotation_by_z);
+ gfx::Transform expected_child_transform;
+ expected_child_transform.Translate(-10.0, -20.0);
+ expected_child_transform.PreconcatTransform(rotation_by_z);
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
+ child->draw_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z,
grand_child->draw_transform());
-
// Case 3: fixed-container size delta of 20, 20
root_->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
ExecuteCalculateDrawProperties(root_.get());
// Top-left fixed-position layer should not be affected by container size.
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, child->draw_transform());
- EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
+ child->draw_transform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z,
grand_child->draw_transform());
// Case 4: Bottom-right fixed-position layer.
grand_child->SetPositionConstraint(fixed_to_bottom_right_);
ExecuteCalculateDrawProperties(root_.get());
- // Root layer is not the fixed-container anyway.
- EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, child->draw_transform());
+ gfx::Transform expected_grand_child_transform;
+ expected_grand_child_transform.Translate(-20.0, 20.0);
+ expected_grand_child_transform.PreconcatTransform(rotation_by_z);
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
+ child->draw_transform());
EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
grand_child->draw_transform());
}
diff --git a/cc/layers/solid_color_layer_impl_unittest.cc b/cc/layers/solid_color_layer_impl_unittest.cc
index dcb4123..0ec7040 100644
--- a/cc/layers/solid_color_layer_impl_unittest.cc
+++ b/cc/layers/solid_color_layer_impl_unittest.cc
@@ -112,6 +112,7 @@ TEST(SolidColorLayerImplTest, VerifyOpaqueRect) {
LayerList render_surface_layer_list;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
gfx::Size(500, 500),
+ gfx::Transform(),
1.f,
1.f,
NULL,
diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc
index fe2ed5a..819a874 100644
--- a/cc/layers/tiled_layer_unittest.cc
+++ b/cc/layers/tiled_layer_unittest.cc
@@ -135,6 +135,7 @@ class TiledLayerTest : public testing::Test {
LayerTreeHostCommon::CalculateDrawProperties(
layer_tree_host_->root_layer(),
layer_tree_host_->device_viewport_size(),
+ gfx::Transform(),
layer_tree_host_->device_scale_factor(),
1.f, // page_scale_factor
NULL,
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index e2c17b8..76c5426 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -79,10 +79,15 @@ void DirectRenderer::QuadRectTransform(gfx::Transform* quad_rect_transform,
quad_rect_transform->Scale(quad_rect.width(), quad_rect.height());
}
-// static
-void DirectRenderer::InitializeMatrices(DrawingFrame* frame,
+void DirectRenderer::InitializeViewport(DrawingFrame* frame,
gfx::Rect draw_rect,
+ gfx::Rect viewport_rect,
+ gfx::Size surface_size,
bool flip_y) {
+ DCHECK_GE(viewport_rect.x(), 0);
+ DCHECK_GE(viewport_rect.y(), 0);
+ DCHECK_LE(viewport_rect.right(), surface_size.width());
+ DCHECK_LE(viewport_rect.bottom(), surface_size.height());
if (flip_y) {
frame->projection_matrix = OrthoProjectionMatrix(draw_rect.x(),
draw_rect.right(),
@@ -94,35 +99,38 @@ void DirectRenderer::InitializeMatrices(DrawingFrame* frame,
draw_rect.y(),
draw_rect.bottom());
}
- frame->window_matrix =
- window_matrix(0, 0, draw_rect.width(), draw_rect.height());
+
+ gfx::Rect window_rect = viewport_rect;
+ if (flip_y)
+ window_rect.set_y(surface_size.height() - viewport_rect.bottom());
+ frame->window_matrix = window_matrix(window_rect.x(),
+ window_rect.y(),
+ window_rect.width(),
+ window_rect.height());
+ SetDrawViewport(window_rect);
+
frame->flipped_y = flip_y;
+
+ current_draw_rect_ = draw_rect;
+ current_viewport_rect_ = viewport_rect;
+ current_surface_size_ = surface_size;
}
-// static
-gfx::Rect DirectRenderer::MoveScissorToWindowSpace(
- const DrawingFrame* frame, const gfx::RectF& scissor_rect) {
- gfx::Rect scissor_rect_in_canvas_space = gfx::ToEnclosingRect(scissor_rect);
- // The scissor coordinates must be supplied in viewport space so we need to
- // offset by the relative position of the top left corner of the current
- // render pass.
- gfx::Rect framebuffer_output_rect = frame->current_render_pass->output_rect;
- scissor_rect_in_canvas_space.set_x(
- scissor_rect_in_canvas_space.x() - framebuffer_output_rect.x());
- if (frame->flipped_y && !frame->current_texture) {
- scissor_rect_in_canvas_space.set_y(
- framebuffer_output_rect.height() -
- (scissor_rect_in_canvas_space.bottom() - framebuffer_output_rect.y()));
- } else {
- scissor_rect_in_canvas_space.set_y(
- scissor_rect_in_canvas_space.y() - framebuffer_output_rect.y());
- }
- return scissor_rect_in_canvas_space;
+gfx::Rect DirectRenderer::MoveFromDrawToWindowSpace(
+ const gfx::RectF& draw_rect, bool flip_y) const {
+ gfx::Rect window_rect = gfx::ToEnclosingRect(draw_rect);
+ window_rect -= current_draw_rect_.OffsetFromOrigin();
+ window_rect += current_viewport_rect_.OffsetFromOrigin();
+ if (flip_y)
+ window_rect.set_y(current_surface_size_.height() - window_rect.bottom());
+ return window_rect;
}
DirectRenderer::DirectRenderer(RendererClient* client,
+ OutputSurface* output_surface,
ResourceProvider* resource_provider)
: Renderer(client),
+ output_surface_(output_surface),
resource_provider_(resource_provider) {}
DirectRenderer::~DirectRenderer() {}
@@ -197,7 +205,13 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order) {
frame.root_damage_rect =
Capabilities().using_partial_swap && client_->AllowPartialSwap() ?
root_render_pass->damage_rect : root_render_pass->output_rect;
- frame.root_damage_rect.Intersect(gfx::Rect(ViewportSize()));
+ frame.root_damage_rect.Intersect(gfx::Rect(client_->DeviceViewport().size()));
+
+ // Only reshape when we know we are going to draw. Otherwise, the reshape
+ // can leave the window at the wrong size if we never draw and the proper
+ // viewport size is never set.
+ output_surface_->Reshape(client_->DeviceViewport().size(),
+ client_->DeviceScaleFactor());
BeginDrawingFrame(&frame);
for (size_t i = 0; i < render_passes_in_draw_order->size(); ++i) {
@@ -245,7 +259,8 @@ void DirectRenderer::SetScissorStateForQuad(const DrawingFrame* frame,
const DrawQuad& quad) {
if (quad.isClipped()) {
gfx::RectF quad_scissor_rect = quad.clipRect();
- SetScissorTestRect(MoveScissorToWindowSpace(frame, quad_scissor_rect));
+ SetScissorTestRect(
+ MoveFromDrawToWindowSpace(quad_scissor_rect, frame->flipped_y));
} else {
EnsureScissorTestDisabled();
}
@@ -267,7 +282,8 @@ void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor(
}
*should_skip_quad = false;
- SetScissorTestRect(MoveScissorToWindowSpace(frame, quad_scissor_rect));
+ SetScissorTestRect(
+ MoveFromDrawToWindowSpace(quad_scissor_rect, frame->flipped_y));
}
void DirectRenderer::FinishDrawingQuadList() {}
@@ -284,7 +300,8 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame,
if (using_scissor_as_optimization) {
render_pass_scissor = ComputeScissorRectForRenderPass(frame);
- SetScissorTestRect(MoveScissorToWindowSpace(frame, render_pass_scissor));
+ SetScissorTestRect(
+ MoveFromDrawToWindowSpace(render_pass_scissor, frame->flipped_y));
}
if (frame->current_render_pass != frame->root_render_pass ||
@@ -327,8 +344,11 @@ bool DirectRenderer::UseRenderPass(DrawingFrame* frame,
if (render_pass == frame->root_render_pass) {
BindFramebufferToOutputSurface(frame);
- InitializeMatrices(frame, render_pass->output_rect, FlippedFramebuffer());
- SetDrawViewportSize(render_pass->output_rect.size());
+ InitializeViewport(frame,
+ render_pass->output_rect,
+ client_->DeviceViewport(),
+ output_surface_->SurfaceSize(),
+ FlippedFramebuffer());
return true;
}
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h
index 4baadee..864ce91 100644
--- a/cc/output/direct_renderer.h
+++ b/cc/output/direct_renderer.h
@@ -50,7 +50,9 @@ class CC_EXPORT DirectRenderer : public Renderer {
void SetEnlargePassTextureAmountForTesting(gfx::Vector2d amount);
protected:
- DirectRenderer(RendererClient* client, ResourceProvider* resource_provider);
+ DirectRenderer(RendererClient* client,
+ OutputSurface* output_surface,
+ ResourceProvider* resource_provider);
class CachedResource : public ScopedResource {
public:
@@ -78,11 +80,14 @@ class CC_EXPORT DirectRenderer : public Renderer {
static void QuadRectTransform(gfx::Transform* quad_rect_transform,
const gfx::Transform& quad_transform,
const gfx::RectF& quad_rect);
- static void InitializeMatrices(DrawingFrame* frame,
- gfx::Rect draw_rect,
- bool flip_y);
- static gfx::Rect MoveScissorToWindowSpace(const DrawingFrame* frame,
- const gfx::RectF& scissor_rect);
+ void InitializeViewport(DrawingFrame* frame,
+ gfx::Rect draw_rect,
+ gfx::Rect viewport_rect,
+ gfx::Size surface_size,
+ bool flip_y);
+ gfx::Rect MoveFromDrawToWindowSpace(const gfx::RectF& draw_rect,
+ bool flip_y) const;
+
static gfx::RectF ComputeScissorRectForRenderPass(const DrawingFrame* frame);
void SetScissorStateForQuad(const DrawingFrame* frame, const DrawQuad& quad);
void SetScissorStateForQuadWithRenderPassScissor(
@@ -100,8 +105,8 @@ class CC_EXPORT DirectRenderer : public Renderer {
virtual void BindFramebufferToOutputSurface(DrawingFrame* frame) = 0;
virtual bool BindFramebufferToTexture(DrawingFrame* frame,
const ScopedResource* resource,
- gfx::Rect framebuffer_rect) = 0;
- virtual void SetDrawViewportSize(gfx::Size viewport_size) = 0;
+ gfx::Rect target_rect) = 0;
+ virtual void SetDrawViewport(gfx::Rect window_space_viewport) = 0;
virtual void SetScissorTestRect(gfx::Rect scissor_rect) = 0;
virtual void ClearFramebuffer(DrawingFrame* frame) = 0;
virtual void DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) = 0;
@@ -117,8 +122,18 @@ class CC_EXPORT DirectRenderer : public Renderer {
scoped_ptr<CopyOutputRequest> request) = 0;
ScopedPtrHashMap<RenderPass::Id, CachedResource> render_pass_textures_;
+ OutputSurface* output_surface_;
ResourceProvider* resource_provider_;
+ // For use in coordinate conversion, this stores the output rect, viewport
+ // rect (= unflipped version of glViewport rect), and the size of target
+ // framebuffer. During a draw, this stores the values for the current render
+ // pass; in between draws, they retain the values for the root render pass of
+ // the last draw.
+ gfx::Rect current_draw_rect_;
+ gfx::Rect current_viewport_rect_;
+ gfx::Size current_surface_size_;
+
private:
gfx::Vector2d enlarge_pass_texture_amount_;
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 4da3aab..4519af3 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -125,12 +125,10 @@ GLRenderer::GLRenderer(RendererClient* client,
OutputSurface* output_surface,
ResourceProvider* resource_provider,
int highp_threshold_min)
- : DirectRenderer(client, resource_provider),
+ : DirectRenderer(client, output_surface, resource_provider),
offscreen_framebuffer_id_(0),
shared_geometry_quad_(gfx::RectF(-0.5f, -0.5f, 1.0f, 1.0f)),
- output_surface_(output_surface),
context_(output_surface->context3d()),
- is_viewport_changed_(false),
is_backbuffer_discarded_(false),
discard_backbuffer_when_not_visible_(false),
is_using_bind_uniform_(false),
@@ -275,7 +273,6 @@ void GLRenderer::SendManagedMemoryStats(size_t bytes_visible,
void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); }
void GLRenderer::ViewportChanged() {
- is_viewport_changed_ = true;
ReinitializeGrCanvas();
}
@@ -305,18 +302,10 @@ void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) {
// FIXME: Remove this once backbuffer is automatically recreated on first use
EnsureBackbuffer();
- if (ViewportSize().IsEmpty())
+ if (client_->DeviceViewport().IsEmpty())
return;
TRACE_EVENT0("cc", "GLRenderer::DrawLayers");
- if (is_viewport_changed_) {
- // Only reshape when we know we are going to draw. Otherwise, the reshape
- // can leave the window at the wrong size if we never draw and the proper
- // viewport size is never set.
- is_viewport_changed_ = false;
- output_surface_->Reshape(gfx::Size(ViewportWidth(), ViewportHeight()),
- DeviceScaleFactor());
- }
MakeContextCurrent();
@@ -1503,7 +1492,7 @@ void GLRenderer::DrawPictureQuadDirectToBackbuffer(
sk_canvas_->clipRect(gfx::RectToSkRect(scissor_rect_),
SkRegion::kReplace_Op);
} else {
- sk_canvas_->clipRect(gfx::RectToSkRect(gfx::Rect(ViewportSize())),
+ sk_canvas_->clipRect(gfx::RectToSkRect(client_->DeviceViewport()),
SkRegion::kReplace_Op);
}
@@ -1970,9 +1959,10 @@ void GLRenderer::SwapBuffers(const ui::LatencyInfo& latency_info) {
if (capabilities_.using_partial_swap && client_->AllowPartialSwap()) {
// If supported, we can save significant bandwidth by only swapping the
// damaged/scissored region (clamped to the viewport)
- swap_buffer_rect_.Intersect(gfx::Rect(ViewportSize()));
+ swap_buffer_rect_.Intersect(client_->DeviceViewport());
int flipped_y_pos_of_rect_bottom =
- ViewportHeight() - swap_buffer_rect_.y() - swap_buffer_rect_.height();
+ client_->DeviceViewport().height() - swap_buffer_rect_.y() -
+ swap_buffer_rect_.height();
output_surface_->PostSubBuffer(gfx::Rect(swap_buffer_rect_.x(),
flipped_y_pos_of_rect_bottom,
swap_buffer_rect_.width(),
@@ -2126,8 +2116,9 @@ void GLRenderer::DoGetFramebufferPixels(
gfx::Rect rect,
bool flipped_y,
const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback) {
- DCHECK(rect.right() <= ViewportWidth());
- DCHECK(rect.bottom() <= ViewportHeight());
+ gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect, flipped_y);
+ DCHECK_LE(window_rect.right(), current_surface_size_.width());
+ DCHECK_LE(window_rect.bottom(), current_surface_size_.height());
bool is_async = !cleanup_callback.is_null();
@@ -2167,8 +2158,8 @@ void GLRenderer::DoGetFramebufferPixels(
GL_RGBA,
0,
0,
- current_framebuffer_size_.width(),
- current_framebuffer_size_.height(),
+ current_surface_size_.width(),
+ current_surface_size_.height(),
0));
temporary_fbo = context_->createFramebuffer();
// Attach this texture to an FBO, and perform the readback from that FBO.
@@ -2193,10 +2184,10 @@ void GLRenderer::DoGetFramebufferPixels(
GL_STREAM_READ));
GLC(context_,
- context_->readPixels(rect.x(),
- current_framebuffer_size_.height() - rect.bottom(),
- rect.width(),
- rect.height(),
+ context_->readPixels(window_rect.x(),
+ window_rect.y(),
+ window_rect.width(),
+ window_rect.height(),
GL_RGBA,
GL_UNSIGNED_BYTE,
NULL));
@@ -2348,7 +2339,7 @@ void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) {
bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame,
const ScopedResource* texture,
- gfx::Rect framebuffer_rect) {
+ gfx::Rect target_rect) {
DCHECK(texture->id());
current_framebuffer_lock_.reset();
@@ -2366,9 +2357,11 @@ bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame,
DCHECK(context_->checkFramebufferStatus(GL_FRAMEBUFFER) ==
GL_FRAMEBUFFER_COMPLETE || IsContextLost());
- InitializeMatrices(frame, framebuffer_rect, false);
- SetDrawViewportSize(framebuffer_rect.size());
-
+ InitializeViewport(frame,
+ target_rect,
+ gfx::Rect(target_rect.size()),
+ target_rect.size(),
+ false);
return true;
}
@@ -2389,10 +2382,11 @@ void GLRenderer::SetScissorTestRect(gfx::Rect scissor_rect) {
scissor_rect.height()));
}
-void GLRenderer::SetDrawViewportSize(gfx::Size viewport_size) {
- current_framebuffer_size_ = viewport_size;
- GLC(context_,
- context_->viewport(0, 0, viewport_size.width(), viewport_size.height()));
+void GLRenderer::SetDrawViewport(gfx::Rect window_space_viewport) {
+ GLC(context_, context_->viewport(window_space_viewport.x(),
+ window_space_viewport.y(),
+ window_space_viewport.width(),
+ window_space_viewport.height()));
}
bool GLRenderer::MakeContextCurrent() { return context_->makeContextCurrent(); }
@@ -2866,8 +2860,8 @@ void GLRenderer::ReinitializeGrCanvas() {
return;
GrBackendRenderTargetDesc desc;
- desc.fWidth = ViewportWidth();
- desc.fHeight = ViewportHeight();
+ desc.fWidth = client_->DeviceViewport().width();
+ desc.fHeight = client_->DeviceViewport().height();
desc.fConfig = kRGBA_8888_GrPixelConfig;
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
desc.fSampleCnt = 1;
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 1c30d34..a45af22 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -104,8 +104,8 @@ class CC_EXPORT GLRenderer
virtual void BindFramebufferToOutputSurface(DrawingFrame* frame) OVERRIDE;
virtual bool BindFramebufferToTexture(DrawingFrame* frame,
const ScopedResource* resource,
- gfx::Rect framebuffer_rect) OVERRIDE;
- virtual void SetDrawViewportSize(gfx::Size viewport_size) OVERRIDE;
+ gfx::Rect target_rect) OVERRIDE;
+ virtual void SetDrawViewport(gfx::Rect window_space_viewport) OVERRIDE;
virtual void SetScissorTestRect(gfx::Rect scissor_rect) OVERRIDE;
virtual void ClearFramebuffer(DrawingFrame* frame) OVERRIDE;
virtual void DoDrawQuad(DrawingFrame* frame, const class DrawQuad*) OVERRIDE;
@@ -399,7 +399,6 @@ class CC_EXPORT GLRenderer
scoped_ptr<SolidColorProgram> solid_color_program_;
scoped_ptr<SolidColorProgramAA> solid_color_program_aa_;
- OutputSurface* output_surface_;
WebKit::WebGraphicsContext3D* context_;
skia::RefPtr<GrContext> gr_context_;
@@ -407,7 +406,6 @@ class CC_EXPORT GLRenderer
gfx::Rect swap_buffer_rect_;
gfx::Rect scissor_rect_;
- bool is_viewport_changed_;
bool is_backbuffer_discarded_;
bool discard_backbuffer_when_not_visible_;
bool is_using_bind_uniform_;
@@ -423,7 +421,6 @@ class CC_EXPORT GLRenderer
ScopedPtrVector<PendingAsyncReadPixels> pending_async_read_pixels_;
scoped_ptr<ResourceProvider::ScopedWriteLockGL> current_framebuffer_lock_;
- gfx::Size current_framebuffer_size_;
scoped_refptr<ResourceProvider::Fence> last_swap_fence_;
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 48a5951..0f901c5 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -153,8 +153,7 @@ class FakeRendererClient : public RendererClient {
memory_allocation_limit_bytes_(
PrioritizedResourceManager::DefaultMemoryAllocationLimit()),
viewport_size_(gfx::Size(1, 1)),
- scale_factor_(1.f),
- is_viewport_changed_(true) {
+ scale_factor_(1.f) {
root_layer_->CreateRenderSurface();
RenderPass::Id render_pass_id =
root_layer_->render_surface()->RenderPassId();
@@ -165,9 +164,9 @@ class FakeRendererClient : public RendererClient {
}
// RendererClient methods.
- virtual gfx::Size DeviceViewportSize() const OVERRIDE {
+ virtual gfx::Rect DeviceViewport() const OVERRIDE {
static gfx::Size fake_size(1, 1);
- return fake_size;
+ return gfx::Rect(fake_size);
}
virtual float DeviceScaleFactor() const OVERRIDE {
return scale_factor_;
@@ -209,10 +208,7 @@ class FakeRendererClient : public RendererClient {
gfx::Size viewport_size, float scale_factor) {
viewport_size_ = viewport_size;
scale_factor_ = scale_factor;
- is_viewport_changed_ = true;
}
- bool is_viewport_changed() const { return is_viewport_changed_; }
- void clear_viewport_changed() { is_viewport_changed_ = false; }
RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
RenderPassList* render_passes_in_draw_order() {
@@ -233,7 +229,6 @@ class FakeRendererClient : public RendererClient {
size_t memory_allocation_limit_bytes_;
gfx::Size viewport_size_;
float scale_factor_;
- bool is_viewport_changed_;
};
class FakeRendererGL : public GLRenderer {
@@ -1004,7 +999,7 @@ TEST(GLRendererTest2, ShouldClearRootRenderPass) {
&mock_client, output_surface.get(), resource_provider.get());
EXPECT_TRUE(renderer.Initialize());
- gfx::Rect viewport_rect(mock_client.DeviceViewportSize());
+ gfx::Rect viewport_rect(mock_client.DeviceViewport());
ScopedPtrVector<RenderPass>& render_passes =
*mock_client.render_passes_in_draw_order();
render_passes.clear();
@@ -1075,7 +1070,7 @@ TEST(GLRendererTest2, ScissorTestWhenClearing) {
EXPECT_TRUE(renderer.Initialize());
EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
- gfx::Rect viewport_rect(mock_client.DeviceViewportSize());
+ gfx::Rect viewport_rect(mock_client.DeviceViewport());
ScopedPtrVector<RenderPass>& render_passes =
*mock_client.render_passes_in_draw_order();
render_passes.clear();
@@ -1105,12 +1100,89 @@ TEST(GLRendererTest2, ScissorTestWhenClearing) {
renderer.DrawFrame(mock_client.render_passes_in_draw_order());
}
+class NonReshapableOutputSurface : public FakeOutputSurface {
+ public:
+ explicit NonReshapableOutputSurface(
+ scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
+ : FakeOutputSurface(context3d.Pass(), false) {}
+ virtual gfx::Size SurfaceSize() const OVERRIDE { return gfx::Size(500, 500); }
+};
+
+class OffsetViewportRendererClient : public FakeRendererClient {
+ public:
+ virtual gfx::Rect DeviceViewport() const OVERRIDE {
+ return gfx::Rect(10, 10, 100, 100);
+ }
+};
+
+class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D {
+ public:
+ FlippedScissorAndViewportContext()
+ : did_call_viewport_(false), did_call_scissor_(false) {}
+ virtual ~FlippedScissorAndViewportContext() {
+ EXPECT_TRUE(did_call_viewport_);
+ EXPECT_TRUE(did_call_scissor_);
+ }
+
+ virtual void viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+ EXPECT_EQ(10, x);
+ EXPECT_EQ(390, y);
+ EXPECT_EQ(100, width);
+ EXPECT_EQ(100, height);
+ did_call_viewport_ = true;
+ }
+
+ virtual void scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+ EXPECT_EQ(30, x);
+ EXPECT_EQ(450, y);
+ EXPECT_EQ(20, width);
+ EXPECT_EQ(20, height);
+ did_call_scissor_ = true;
+ }
+
+ private:
+ bool did_call_viewport_;
+ bool did_call_scissor_;
+};
+
+TEST(GLRendererTest2, ScissorAndViewportWithinNonreshapableSurface) {
+ // In Android WebView, the OutputSurface is unable to respect reshape() calls
+ // and maintains a fixed size. This test verifies that glViewport and
+ // glScissor's Y coordinate is flipped correctly in this environment, and that
+ // the glViewport can be at a nonzero origin within the surface.
+ OffsetViewportRendererClient mock_client;
+ scoped_ptr<OutputSurface> output_surface(make_scoped_ptr(
+ new NonReshapableOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(
+ new FlippedScissorAndViewportContext))));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(), 0));
+ FakeRendererGL renderer(
+ &mock_client, output_surface.get(), resource_provider.get());
+ EXPECT_TRUE(renderer.Initialize());
+ EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
+
+ gfx::Rect viewport_rect(mock_client.DeviceViewport().size());
+ gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
+ ScopedPtrVector<RenderPass>& render_passes =
+ *mock_client.render_passes_in_draw_order();
+ render_passes.clear();
+
+ RenderPass::Id root_pass_id(1, 0);
+ TestRenderPass* root_pass = AddRenderPass(
+ &render_passes, root_pass_id, viewport_rect, gfx::Transform());
+ AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
+
+ renderer.DecideRenderPassAllocationsForFrame(
+ *mock_client.render_passes_in_draw_order());
+ renderer.DrawFrame(mock_client.render_passes_in_draw_order());
+}
+
// This test was never actually working as intended. Before adding
// ShaderCreatorMockGraphicsContext, all shader programs received the same
// program identifier from the TestWebGraphicsContext3D, so it always passed
// when checking which shader was used.
TEST_F(GLRendererShaderTest, DISABLED_DrawRenderPassQuadShaderPermutations) {
- gfx::Rect viewport_rect(mock_client_.DeviceViewportSize());
+ gfx::Rect viewport_rect(mock_client_.DeviceViewport());
ScopedPtrVector<RenderPass>* render_passes =
mock_client_.render_passes_in_draw_order();
@@ -1372,7 +1444,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
RenderPass::Id child_pass_id(2, 0);
TestRenderPass* child_pass;
- gfx::Rect viewport_rect(mock_client_.DeviceViewportSize());
+ gfx::Rect viewport_rect(mock_client_.DeviceViewport());
RenderPass::Id root_pass_id(1, 0);
TestRenderPass* root_pass;
@@ -1417,7 +1489,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
}
TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
- gfx::Rect viewport_rect(mock_client_.DeviceViewportSize());
+ gfx::Rect viewport_rect(mock_client_.DeviceViewport());
ScopedPtrVector<RenderPass>* render_passes =
mock_client_.render_passes_in_draw_order();
@@ -1474,7 +1546,9 @@ class MockOutputSurface : public OutputSurface {
public:
MockOutputSurface()
: OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(
- new StrictMock<OutputSurfaceMockContext>)) {}
+ new StrictMock<OutputSurfaceMockContext>)) {
+ surface_size_ = gfx::Size(100, 100);
+ }
virtual ~MockOutputSurface() {}
MOCK_METHOD1(SendFrameToParentCompositor, void(CompositorFrame* frame));
@@ -1497,7 +1571,7 @@ class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
void SwapBuffers() { renderer_.SwapBuffers(ui::LatencyInfo()); }
void DrawFrame() {
- gfx::Rect viewport_rect(DeviceViewportSize());
+ gfx::Rect viewport_rect(DeviceViewport());
ScopedPtrVector<RenderPass>* render_passes = render_passes_in_draw_order();
render_passes->clear();
@@ -1508,11 +1582,8 @@ class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient {
EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
- if (is_viewport_changed()) {
- EXPECT_CALL(output_surface_,
- Reshape(DeviceViewportSize(), DeviceScaleFactor())).Times(1);
- clear_viewport_changed();
- }
+ EXPECT_CALL(output_surface_,
+ Reshape(DeviceViewport().size(), DeviceScaleFactor())).Times(1);
EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index fe2b074..1be41892 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -46,14 +46,16 @@ OutputSurface::OutputSurface(
scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
: client_(NULL),
context3d_(context3d.Pass()),
- has_gl_discard_backbuffer_(false) {
+ has_gl_discard_backbuffer_(false),
+ device_scale_factor_(-1) {
}
OutputSurface::OutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device)
: client_(NULL),
software_device_(software_device.Pass()),
- has_gl_discard_backbuffer_(false) {
+ has_gl_discard_backbuffer_(false),
+ device_scale_factor_(-1) {
}
OutputSurface::OutputSurface(
@@ -62,7 +64,8 @@ OutputSurface::OutputSurface(
: client_(NULL),
context3d_(context3d.Pass()),
software_device_(software_device.Pass()),
- has_gl_discard_backbuffer_(false) {
+ has_gl_discard_backbuffer_(false),
+ device_scale_factor_(-1) {
}
OutputSurface::~OutputSurface() {
@@ -112,8 +115,19 @@ void OutputSurface::DiscardBackbuffer() {
}
void OutputSurface::Reshape(gfx::Size size, float scale_factor) {
- DCHECK(context3d_);
- context3d_->reshapeWithScaleFactor(size.width(), size.height(), scale_factor);
+ if (size == surface_size_ && scale_factor == device_scale_factor_)
+ return;
+
+ surface_size_ = size;
+ device_scale_factor_ = scale_factor;
+ if (context3d_) {
+ context3d_->reshapeWithScaleFactor(
+ size.width(), size.height(), scale_factor);
+ }
+}
+
+gfx::Size OutputSurface::SurfaceSize() const {
+ return surface_size_;
}
void OutputSurface::BindFramebuffer() {
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index d6f4b82..00877de 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -89,6 +89,7 @@ class CC_EXPORT OutputSurface {
virtual void DiscardBackbuffer();
virtual void Reshape(gfx::Size size, float scale_factor);
+ virtual gfx::Size SurfaceSize() const;
virtual void BindFramebuffer();
@@ -110,6 +111,8 @@ class CC_EXPORT OutputSurface {
scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
scoped_ptr<cc::SoftwareOutputDevice> software_device_;
bool has_gl_discard_backbuffer_;
+ gfx::Size surface_size_;
+ float device_scale_factor_;
scoped_ptr<OutputSurfaceCallbacks> callbacks_;
diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h
index cbb3b8c..26edec8 100644
--- a/cc/output/output_surface_client.h
+++ b/cc/output/output_surface_client.h
@@ -9,6 +9,10 @@
#include "cc/base/cc_export.h"
#include "ui/gfx/rect.h"
+namespace gfx {
+class Transform;
+}
+
namespace cc {
class CompositorFrameAck;
@@ -23,6 +27,8 @@ class CC_EXPORT OutputSurfaceClient {
const CompositorFrameAck& ack) = 0;
virtual void OnSwapBuffersComplete() = 0;
virtual void DidLoseOutputSurface() = 0;
+ virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
+ gfx::Rect viewport) = 0;
protected:
virtual ~OutputSurfaceClient() {}
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
index a23ba93..d54afe2 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -36,6 +36,8 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
OVERRIDE {}
virtual void OnSwapBuffersComplete() OVERRIDE {}
virtual void DidLoseOutputSurface() OVERRIDE {}
+ virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
+ gfx::Rect viewport) OVERRIDE {}
};
TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
diff --git a/cc/output/renderer.h b/cc/output/renderer.h
index aaf9fd7..a905d4c 100644
--- a/cc/output/renderer.h
+++ b/cc/output/renderer.h
@@ -20,7 +20,11 @@ class ScopedResource;
class CC_EXPORT RendererClient {
public:
- virtual gfx::Size DeviceViewportSize() const = 0;
+ // Draw viewport in non-y-flipped window space. Note that while a draw is in
+ // progress, this is guaranteed to be contained within the output surface
+ // size.
+ virtual gfx::Rect DeviceViewport() const = 0;
+
virtual float DeviceScaleFactor() const = 0;
virtual const LayerTreeSettings& Settings() const = 0;
virtual void SetFullRootLayerDamage() = 0;
@@ -44,12 +48,6 @@ class CC_EXPORT Renderer {
const LayerTreeSettings& Settings() const { return client_->Settings(); }
- gfx::Size ViewportSize() const { return client_->DeviceViewportSize(); }
- int ViewportWidth() const { return ViewportSize().width(); }
- int ViewportHeight() const { return ViewportSize().height(); }
-
- float DeviceScaleFactor() const { return client_->DeviceScaleFactor(); }
-
virtual void ViewportChanged() {}
virtual void ReceiveCompositorFrameAck(const CompositorFrameAck& ack) {}
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index d479e5f..2faa0d0 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -94,7 +94,10 @@ scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad(
return quad.PassAs<DrawQuad>();
}
-typedef ::testing::Types<GLRenderer, SoftwareRenderer> RendererTypes;
+typedef ::testing::Types<GLRenderer,
+ SoftwareRenderer,
+ GLRendererWithExpandedViewport,
+ SoftwareRendererWithExpandedViewport> RendererTypes;
TYPED_TEST_CASE(RendererPixelTest, RendererTypes);
typedef ::testing::Types<GLRenderer,
@@ -135,6 +138,14 @@ bool FuzzyForSoftwareOnlyPixelComparator<SoftwareRenderer>::Compare(
return fuzzy_.Compare(actual_bmp, expected_bmp);
}
+template <>
+bool FuzzyForSoftwareOnlyPixelComparator<
+ SoftwareRendererWithExpandedViewport>::Compare(
+ const SkBitmap& actual_bmp,
+ const SkBitmap& expected_bmp) const {
+ return fuzzy_.Compare(actual_bmp, expected_bmp);
+}
+
template<typename RendererType>
bool FuzzyForSoftwareOnlyPixelComparator<RendererType>::Compare(
const SkBitmap& actual_bmp,
diff --git a/cc/output/software_output_device.cc b/cc/output/software_output_device.cc
index 956ee6c..719eeed 100644
--- a/cc/output/software_output_device.cc
+++ b/cc/output/software_output_device.cc
@@ -8,6 +8,7 @@
#include "cc/output/software_frame_data.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/gfx/skia_util.h"
namespace cc {
@@ -43,11 +44,8 @@ void SoftwareOutputDevice::EndPaint(SoftwareFrameData* frame_data) {
void SoftwareOutputDevice::CopyToBitmap(
gfx::Rect rect, SkBitmap* output) {
DCHECK(device_);
- SkIRect invert_rect = SkIRect::MakeXYWH(
- rect.x(), viewport_size_.height() - rect.bottom(),
- rect.width(), rect.height());
const SkBitmap& bitmap = device_->accessBitmap(false);
- bitmap.extractSubset(output, invert_rect);
+ bitmap.extractSubset(output, gfx::RectToSkIRect(rect));
}
void SoftwareOutputDevice::Scroll(
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index b555b57..c53e0c7 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -53,11 +53,10 @@ scoped_ptr<SoftwareRenderer> SoftwareRenderer::Create(
SoftwareRenderer::SoftwareRenderer(RendererClient* client,
OutputSurface* output_surface,
ResourceProvider* resource_provider)
- : DirectRenderer(client, resource_provider),
+ : DirectRenderer(client, output_surface, resource_provider),
visible_(true),
is_scissor_enabled_(false),
is_viewport_changed_(true),
- output_surface_(output_surface),
output_device_(output_surface->software_device()),
current_canvas_(NULL) {
if (resource_provider_) {
@@ -88,7 +87,7 @@ void SoftwareRenderer::BeginDrawingFrame(DrawingFrame* frame) {
TRACE_EVENT0("cc", "SoftwareRenderer::BeginDrawingFrame");
if (is_viewport_changed_) {
is_viewport_changed_ = false;
- output_device_->Resize(ViewportSize());
+ output_device_->Resize(client_->DeviceViewport().size());
}
root_canvas_ = output_device_->BeginPaint(
gfx::ToEnclosingRect(frame->root_damage_rect));
@@ -146,15 +145,17 @@ void SoftwareRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) {
bool SoftwareRenderer::BindFramebufferToTexture(
DrawingFrame* frame,
const ScopedResource* texture,
- gfx::Rect framebuffer_rect) {
+ gfx::Rect target_rect) {
current_framebuffer_lock_.reset();
current_framebuffer_lock_ = make_scoped_ptr(
new ResourceProvider::ScopedWriteLockSoftware(
resource_provider_, texture->id()));
current_canvas_ = current_framebuffer_lock_->sk_canvas();
- InitializeMatrices(frame, framebuffer_rect, false);
- SetDrawViewportSize(framebuffer_rect.size());
-
+ InitializeViewport(frame,
+ target_rect,
+ gfx::Rect(target_rect.size()),
+ target_rect.size(),
+ false);
return true;
}
@@ -193,7 +194,7 @@ void SoftwareRenderer::ClearFramebuffer(DrawingFrame* frame) {
}
}
-void SoftwareRenderer::SetDrawViewportSize(gfx::Size viewport_size) {}
+void SoftwareRenderer::SetDrawViewport(gfx::Rect window_space_viewport) {}
bool SoftwareRenderer::IsSoftwareResource(
ResourceProvider::ResourceId resource_id) const {
@@ -437,13 +438,12 @@ void SoftwareRenderer::DrawUnsupportedQuad(const DrawingFrame* frame,
void SoftwareRenderer::CopyCurrentRenderPassToBitmap(
DrawingFrame* frame,
scoped_ptr<CopyOutputRequest> request) {
- gfx::Size render_pass_size = frame->current_render_pass->output_rect.size();
-
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
bitmap->setConfig(SkBitmap::kARGB_8888_Config,
- render_pass_size.width(),
- render_pass_size.height());
- current_canvas_->readPixels(bitmap.get(), 0, 0);
+ current_viewport_rect_.width(),
+ current_viewport_rect_.height());
+ current_canvas_->readPixels(
+ bitmap.get(), current_viewport_rect_.x(), current_viewport_rect_.y());
request->SendBitmapResult(bitmap.Pass());
}
@@ -451,6 +451,7 @@ void SoftwareRenderer::CopyCurrentRenderPassToBitmap(
void SoftwareRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) {
TRACE_EVENT0("cc", "SoftwareRenderer::GetFramebufferPixels");
SkBitmap subset_bitmap;
+ rect += current_viewport_rect_.OffsetFromOrigin();
output_device_->CopyToBitmap(rect, &subset_bitmap);
subset_bitmap.copyPixelsTo(pixels,
4 * rect.width() * rect.height(),
diff --git a/cc/output/software_renderer.h b/cc/output/software_renderer.h
index cbaf1d3..8eb9c0e 100644
--- a/cc/output/software_renderer.h
+++ b/cc/output/software_renderer.h
@@ -50,8 +50,8 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
virtual bool BindFramebufferToTexture(
DrawingFrame* frame,
const ScopedResource* texture,
- gfx::Rect framebuffer_rect) OVERRIDE;
- virtual void SetDrawViewportSize(gfx::Size viewport_size) OVERRIDE;
+ gfx::Rect target_rect) OVERRIDE;
+ virtual void SetDrawViewport(gfx::Rect window_space_viewport) OVERRIDE;
virtual void SetScissorTestRect(gfx::Rect scissor_rect) OVERRIDE;
virtual void ClearFramebuffer(DrawingFrame* frame) OVERRIDE;
virtual void DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) OVERRIDE;
@@ -64,12 +64,12 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
DrawingFrame* frame,
scoped_ptr<CopyOutputRequest> request) OVERRIDE;
- private:
SoftwareRenderer(
RendererClient* client,
OutputSurface* output_surface,
ResourceProvider* resource_provider);
+ private:
void ClearCanvas(SkColor color);
void SetClipRect(gfx::Rect rect);
bool IsSoftwareResource(ResourceProvider::ResourceId resource_id) const;
@@ -95,7 +95,6 @@ class CC_EXPORT SoftwareRenderer : public DirectRenderer {
bool is_viewport_changed_;
gfx::Rect scissor_rect_;
- OutputSurface* output_surface_;
SoftwareOutputDevice* output_device_;
SkCanvas* root_canvas_;
SkCanvas* current_canvas_;
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index af4d7d1..b4e91fc 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -18,6 +18,8 @@
#include "cc/test/render_pass_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkDevice.h"
namespace cc {
namespace {
@@ -26,9 +28,10 @@ class SoftwareRendererTest : public testing::Test, public RendererClient {
public:
SoftwareRendererTest() : should_clear_root_render_pass_(true) {}
- void InitializeRenderer() {
+ void InitializeRenderer(
+ scoped_ptr<SoftwareOutputDevice> software_output_device) {
output_surface_ = FakeOutputSurface::CreateSoftware(
- make_scoped_ptr(new SoftwareOutputDevice));
+ software_output_device.Pass());
resource_provider_ = ResourceProvider::Create(output_surface_.get(), 0);
renderer_ = SoftwareRenderer::Create(
this, output_surface_.get(), resource_provider());
@@ -40,8 +43,8 @@ class SoftwareRendererTest : public testing::Test, public RendererClient {
SoftwareRenderer* renderer() const { return renderer_.get(); }
- void set_viewport_size(gfx::Size viewport_size) {
- viewport_size_ = viewport_size;
+ void set_viewport(gfx::Rect viewport) {
+ viewport_ = viewport;
}
void set_should_clear_root_render_pass(bool clear_root_render_pass) {
@@ -49,8 +52,8 @@ class SoftwareRendererTest : public testing::Test, public RendererClient {
}
// RendererClient implementation.
- virtual gfx::Size DeviceViewportSize() const OVERRIDE {
- return viewport_size_;
+ virtual gfx::Rect DeviceViewport() const OVERRIDE {
+ return viewport_;
}
virtual float DeviceScaleFactor() const OVERRIDE {
return 1.f;
@@ -78,7 +81,7 @@ class SoftwareRendererTest : public testing::Test, public RendererClient {
scoped_ptr<FakeOutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
scoped_ptr<SoftwareRenderer> renderer_;
- gfx::Size viewport_size_;
+ gfx::Rect viewport_;
LayerTreeSettings settings_;
bool should_clear_root_render_pass_;
};
@@ -88,9 +91,9 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
gfx::Size inner_size(98, 98);
gfx::Rect outer_rect(outer_size);
gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
- set_viewport_size(outer_size);
+ set_viewport(gfx::Rect(outer_size));
- InitializeRenderer();
+ InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
shared_quad_state->SetAll(
@@ -113,8 +116,8 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
SkBitmap output;
output.setConfig(SkBitmap::kARGB_8888_Config,
- DeviceViewportSize().width(),
- DeviceViewportSize().height());
+ DeviceViewport().width(),
+ DeviceViewport().height());
output.allocPixels();
renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
@@ -131,8 +134,8 @@ TEST_F(SoftwareRendererTest, TileQuad) {
gfx::Size inner_size(98, 98);
gfx::Rect outer_rect(outer_size);
gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
- set_viewport_size(outer_size);
- InitializeRenderer();
+ set_viewport(gfx::Rect(outer_size));
+ InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
ResourceProvider::ResourceId resource_yellow =
resource_provider()->CreateResource(
@@ -165,7 +168,7 @@ TEST_F(SoftwareRendererTest, TileQuad) {
gfx::Rect(inner_size),
gfx::Vector2d());
- gfx::Rect root_rect = gfx::Rect(DeviceViewportSize());
+ gfx::Rect root_rect = DeviceViewport();
scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
shared_quad_state->SetAll(
@@ -199,8 +202,8 @@ TEST_F(SoftwareRendererTest, TileQuad) {
SkBitmap output;
output.setConfig(SkBitmap::kARGB_8888_Config,
- DeviceViewportSize().width(),
- DeviceViewportSize().height());
+ DeviceViewport().width(),
+ DeviceViewport().height());
output.allocPixels();
renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
@@ -214,9 +217,9 @@ TEST_F(SoftwareRendererTest, TileQuad) {
TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
gfx::Rect viewport_rect(0, 0, 100, 100);
- set_viewport_size(viewport_rect.size());
+ set_viewport(viewport_rect);
set_should_clear_root_render_pass(false);
- InitializeRenderer();
+ InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
RenderPassList list;
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h
index 090571f..6eff484 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -81,7 +81,7 @@ class FakeOutputSurface : public OutputSurface {
}
virtual bool ForcedDrawToSoftwareDevice() const OVERRIDE;
- private:
+ protected:
FakeOutputSurface(
scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
bool has_parent);
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 0885c76..1e75156 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -23,12 +23,12 @@ namespace cc {
class PixelTest::PixelTestRendererClient : public RendererClient {
public:
- explicit PixelTestRendererClient(gfx::Size device_viewport_size)
- : device_viewport_size_(device_viewport_size) {}
+ explicit PixelTestRendererClient(gfx::Rect device_viewport)
+ : device_viewport_(device_viewport) {}
// RendererClient implementation.
- virtual gfx::Size DeviceViewportSize() const OVERRIDE {
- return device_viewport_size_;
+ virtual gfx::Rect DeviceViewport() const OVERRIDE {
+ return device_viewport_ + test_expansion_offset_;
}
virtual float DeviceScaleFactor() const OVERRIDE {
return 1.f;
@@ -51,14 +51,60 @@ class PixelTest::PixelTestRendererClient : public RendererClient {
return true;
}
+ void SetTestExpansionOffset(gfx::Vector2d test_expansion_offset) {
+ test_expansion_offset_ = test_expansion_offset;
+ }
+
private:
- gfx::Size device_viewport_size_;
+ gfx::Rect device_viewport_;
+ gfx::Vector2d test_expansion_offset_;
LayerTreeSettings settings_;
};
+class PixelTest::PixelTestOutputSurface : public OutputSurface {
+ public:
+ explicit PixelTestOutputSurface(
+ scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
+ : OutputSurface(context3d.Pass()) {}
+ explicit PixelTestOutputSurface(
+ scoped_ptr<cc::SoftwareOutputDevice> software_device)
+ : OutputSurface(software_device.Pass()) {}
+ virtual void Reshape(gfx::Size size, float scale_factor) OVERRIDE {
+ OutputSurface::Reshape(
+ gfx::Size(size.width() + test_expansion_size_.width(),
+ size.height() + test_expansion_size_.height()),
+ scale_factor);
+ }
+
+ void SetTestExpansionSize(gfx::Size test_expansion_size) {
+ test_expansion_size_ = test_expansion_size;
+ }
+
+ private:
+ gfx::Size test_expansion_size_;
+};
+
+class PixelTestSoftwareOutputDevice : public SoftwareOutputDevice {
+ public:
+ PixelTestSoftwareOutputDevice() {}
+ virtual void Resize(gfx::Size size) OVERRIDE {
+ SoftwareOutputDevice::Resize(
+ gfx::Size(size.width() + test_expansion_size_.width(),
+ size.height() + test_expansion_size_.height()));
+ }
+
+ void SetTestExpansionSize(gfx::Size test_expansion_size) {
+ test_expansion_size_ = test_expansion_size;
+ }
+
+ private:
+ gfx::Size test_expansion_size_;
+};
+
PixelTest::PixelTest()
: device_viewport_size_(gfx::Size(200, 200)),
- fake_client_(new PixelTestRendererClient(device_viewport_size_)) {}
+ fake_client_(
+ new PixelTestRendererClient(gfx::Rect(device_viewport_size_))) {}
PixelTest::~PixelTest() {}
@@ -125,7 +171,7 @@ void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend) {
scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d(
WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext(
WebKit::WebGraphicsContext3D::Attributes()));
- output_surface_.reset(new OutputSurface(
+ output_surface_.reset(new PixelTestOutputSurface(
context3d.PassAs<WebKit::WebGraphicsContext3D>()));
resource_provider_ = ResourceProvider::Create(output_surface_.get(), 0);
renderer_ = GLRenderer::Create(fake_client_.get(),
@@ -140,11 +186,23 @@ void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend) {
resource_provider_->set_offscreen_context_provider(offscreen_contexts);
}
+void PixelTest::ForceExpandedViewport(gfx::Size surface_expansion,
+ gfx::Vector2d viewport_offset) {
+ static_cast<PixelTestOutputSurface*>(output_surface_.get())
+ ->SetTestExpansionSize(surface_expansion);
+ fake_client_->SetTestExpansionOffset(viewport_offset);
+ SoftwareOutputDevice* device = output_surface_->software_device();
+ if (device) {
+ static_cast<PixelTestSoftwareOutputDevice*>(device)
+ ->SetTestExpansionSize(surface_expansion);
+ }
+}
+
void PixelTest::SetUpSoftwareRenderer() {
CHECK(fake_client_);
- scoped_ptr<SoftwareOutputDevice> device(new SoftwareOutputDevice());
- output_surface_.reset(new OutputSurface(device.Pass()));
+ scoped_ptr<SoftwareOutputDevice> device(new PixelTestSoftwareOutputDevice());
+ output_surface_.reset(new PixelTestOutputSurface(device.Pass()));
resource_provider_ = ResourceProvider::Create(output_surface_.get(), 0);
renderer_ = SoftwareRenderer::Create(
fake_client_.get(),
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index c7dd7aa..eb53e07 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -4,6 +4,7 @@
#include "base/file_util.h"
#include "cc/output/gl_renderer.h"
+#include "cc/output/software_renderer.h"
#include "cc/quads/render_pass.h"
#include "cc/test/pixel_comparator.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,9 +34,10 @@ class PixelTest : public testing::Test {
const PixelComparator& comparator);
gfx::Size device_viewport_size_;
+ class PixelTestOutputSurface;
+ class PixelTestRendererClient;
scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
- class PixelTestRendererClient;
scoped_ptr<PixelTestRendererClient> fake_client_;
scoped_ptr<DirectRenderer> renderer_;
scoped_ptr<SkBitmap> result_bitmap_;
@@ -43,6 +45,9 @@ class PixelTest : public testing::Test {
void SetUpGLRenderer(bool use_skia_gpu_backend);
void SetUpSoftwareRenderer();
+ void ForceExpandedViewport(gfx::Size surface_expansion,
+ gfx::Vector2d viewport_offset);
+
private:
void ReadbackResult(base::Closure quit_run_loop, scoped_ptr<SkBitmap> bitmap);
@@ -58,6 +63,7 @@ class RendererPixelTest : public PixelTest {
}
bool UseSkiaGPUBackend() const;
+ bool ExpandedViewport() const;
protected:
virtual void SetUp() OVERRIDE;
@@ -77,6 +83,31 @@ class GLRendererWithSkiaGPUBackend : public GLRenderer {
highp_threshold_min) {}
};
+// Wrappers to differentiate renderers where the the output surface and viewport
+// have an externally determined size and offset.
+class GLRendererWithExpandedViewport : public GLRenderer {
+ public:
+ GLRendererWithExpandedViewport(RendererClient* client,
+ OutputSurface* output_surface,
+ ResourceProvider* resource_provider,
+ int highp_threshold_min)
+ : GLRenderer(client,
+ output_surface,
+ resource_provider,
+ highp_threshold_min) {}
+};
+
+class SoftwareRendererWithExpandedViewport : public SoftwareRenderer {
+ public:
+ SoftwareRendererWithExpandedViewport(RendererClient* client,
+ OutputSurface* output_surface,
+ ResourceProvider* resource_provider)
+ : SoftwareRenderer(client,
+ output_surface,
+ resource_provider) {}
+};
+
+
template<>
inline void RendererPixelTest<GLRenderer>::SetUp() {
SetUpGLRenderer(false);
@@ -89,6 +120,11 @@ inline bool RendererPixelTest<GLRenderer>::UseSkiaGPUBackend() const {
}
template<>
+inline bool RendererPixelTest<GLRenderer>::ExpandedViewport() const {
+ return false;
+}
+
+template<>
inline void RendererPixelTest<GLRendererWithSkiaGPUBackend>::SetUp() {
SetUpGLRenderer(true);
DCHECK(renderer()->CanUseSkiaGPUBackend());
@@ -100,6 +136,30 @@ RendererPixelTest<GLRendererWithSkiaGPUBackend>::UseSkiaGPUBackend() const {
return true;
}
+template <>
+inline bool RendererPixelTest<GLRendererWithSkiaGPUBackend>::ExpandedViewport()
+ const {
+ return false;
+}
+
+template<>
+inline void RendererPixelTest<GLRendererWithExpandedViewport>::SetUp() {
+ SetUpGLRenderer(false);
+ ForceExpandedViewport(gfx::Size(50, 50), gfx::Vector2d(10, 20));
+}
+
+template <>
+inline bool
+RendererPixelTest<GLRendererWithExpandedViewport>::UseSkiaGPUBackend() const {
+ return false;
+}
+
+template <>
+inline bool
+RendererPixelTest<GLRendererWithExpandedViewport>::ExpandedViewport() const {
+ return true;
+}
+
template<>
inline void RendererPixelTest<SoftwareRenderer>::SetUp() {
SetUpSoftwareRenderer();
@@ -110,6 +170,29 @@ inline bool RendererPixelTest<SoftwareRenderer>::UseSkiaGPUBackend() const {
return false;
}
+template <>
+inline bool RendererPixelTest<SoftwareRenderer>::ExpandedViewport() const {
+ return false;
+}
+
+template<>
+inline void RendererPixelTest<SoftwareRendererWithExpandedViewport>::SetUp() {
+ SetUpSoftwareRenderer();
+ ForceExpandedViewport(gfx::Size(50, 50), gfx::Vector2d(10, 20));
+}
+
+template <>
+inline bool RendererPixelTest<
+ SoftwareRendererWithExpandedViewport>::UseSkiaGPUBackend() const {
+ return false;
+}
+
+template <>
+inline bool RendererPixelTest<
+ SoftwareRendererWithExpandedViewport>::ExpandedViewport() const {
+ return true;
+}
+
typedef RendererPixelTest<GLRenderer> GLRendererPixelTest;
typedef RendererPixelTest<GLRendererWithSkiaGPUBackend>
GLRendererSkiaGPUBackendPixelTest;
diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc
index 724fd37..56bf80b 100644
--- a/cc/trees/damage_tracker_unittest.cc
+++ b/cc/trees/damage_tracker_unittest.cc
@@ -36,6 +36,7 @@ void ExecuteCalculateDrawProperties(
LayerTreeHostCommon::CalculateDrawProperties(root,
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 4ba7d59..a637f02 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -715,6 +715,7 @@ void LayerTreeHost::UpdateLayers(Layer* root_layer,
LayerTreeHostCommon::CalculateDrawProperties(
root_layer,
device_viewport_size(),
+ gfx::Transform(),
device_scale_factor_,
page_scale_factor_,
root_scroll,
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 6123e25..88609329 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -406,8 +406,7 @@ gfx::Transform ComputeSizeDeltaCompensation(
gfx::Transform target_surface_space_to_container_layer_space;
// Calculate step 1a
- LayerImpl* container_target_surface =
- container ? container->render_target() : 0;
+ LayerImpl* container_target_surface = container->render_target();
for (LayerImpl* current_target_surface = NextTargetSurface(layer);
current_target_surface &&
current_target_surface != container_target_surface;
@@ -418,20 +417,18 @@ gfx::Transform ComputeSizeDeltaCompensation(
current_target_surface->render_surface()->draw_transform());
}
// Calculate step 1b
- if (container) {
- gfx::Transform container_layer_space_to_container_target_surface_space =
- container->draw_transform();
- container_layer_space_to_container_target_surface_space.Scale(
- container->contents_scale_x(), container->contents_scale_y());
-
- gfx::Transform container_target_surface_space_to_container_layer_space;
- if (container_layer_space_to_container_target_surface_space.GetInverse(
- &container_target_surface_space_to_container_layer_space)) {
- // Note: Again, Concat is used to conver the result coordinate space from
- // the container render surface to the container layer.
- target_surface_space_to_container_layer_space.ConcatTransform(
- container_target_surface_space_to_container_layer_space);
- }
+ gfx::Transform container_layer_space_to_container_target_surface_space =
+ container->draw_transform();
+ container_layer_space_to_container_target_surface_space.Scale(
+ container->contents_scale_x(), container->contents_scale_y());
+
+ gfx::Transform container_target_surface_space_to_container_layer_space;
+ if (container_layer_space_to_container_target_surface_space.GetInverse(
+ &container_target_surface_space_to_container_layer_space)) {
+ // Note: Again, Concat is used to conver the result coordinate space from
+ // the container render surface to the container layer.
+ target_surface_space_to_container_layer_space.ConcatTransform(
+ container_target_surface_space_to_container_layer_space);
}
// Apply step 3
@@ -482,8 +479,7 @@ void ApplyPositionAdjustment(
layer->position_constraint().is_fixed_to_right_edge();
bool fixed_to_bottom_edge =
layer->position_constraint().is_fixed_to_bottom_edge();
- gfx::Vector2dF position_offset =
- container ? container->fixed_container_size_delta() : gfx::Vector2dF();
+ gfx::Vector2dF position_offset = container->fixed_container_size_delta();
position_offset.set_x(fixed_to_right_edge ? position_offset.x() : 0);
position_offset.set_y(fixed_to_bottom_edge ? position_offset.y() : 0);
if (position_offset.IsZero())
@@ -1115,41 +1111,39 @@ static void CalculateDrawPropertiesInternal(
RenderSurfaceType* render_surface = layer->render_surface();
render_surface->ClearLayerLists();
- // The owning layer's draw transform has a scale from content to layer
- // space which we do not want; so here we use the combined_transform
- // instead of the draw_transform. However, we do need to add a different
- // scale factor that accounts for the surface's pixel dimensions.
- combined_transform.Scale(1.0 / render_surface_sublayer_scale.x(),
- 1.0 / render_surface_sublayer_scale.y());
- render_surface->SetDrawTransform(combined_transform);
-
- // If this is the root layer, there should be no scale in the surface's draw
- // transform.
if (IsRootLayer(layer)) {
- DCHECK_EQ(render_surface_sublayer_scale.x(),
- combined_transform_scales.x());
- DCHECK_EQ(render_surface_sublayer_scale.y(),
- combined_transform_scales.y());
+ // The root layer's render surface size is predetermined and so the root
+ // layer can't directly support non-identity transforms. It should just
+ // forward top-level transforms to the rest of the tree.
+ sublayer_matrix = combined_transform;
+ } else {
+ // The owning layer's draw transform has a scale from content to layer
+ // space which we do not want; so here we use the combined_transform
+ // instead of the draw_transform. However, we do need to add a different
+ // scale factor that accounts for the surface's pixel dimensions.
+ combined_transform.Scale(1.0 / render_surface_sublayer_scale.x(),
+ 1.0 / render_surface_sublayer_scale.y());
+ render_surface->SetDrawTransform(combined_transform);
+
+ // The owning layer's transform was re-parented by the surface, so the
+ // layer's new draw_transform only needs to scale the layer to surface
+ // space.
+ layer_draw_properties.target_space_transform.MakeIdentity();
+ layer_draw_properties.target_space_transform.
+ Scale(render_surface_sublayer_scale.x() / layer->contents_scale_x(),
+ render_surface_sublayer_scale.y() / layer->contents_scale_y());
+
+ // Inside the surface's subtree, we scale everything to the owning layer's
+ // scale. The sublayer matrix transforms layer rects into target surface
+ // content space. Conceptually, all layers in the subtree inherit the
+ // scale at the point of the render surface in the transform hierarchy,
+ // but we apply it explicitly to the owning layer and the remainder of the
+ // subtree independently.
+ DCHECK(sublayer_matrix.IsIdentity());
+ sublayer_matrix.Scale(render_surface_sublayer_scale.x(),
+ render_surface_sublayer_scale.y());
}
- // The owning layer's transform was re-parented by the surface, so the
- // layer's new draw_transform only needs to scale the layer to surface
- // space.
- layer_draw_properties.target_space_transform.MakeIdentity();
- layer_draw_properties.target_space_transform.
- Scale(render_surface_sublayer_scale.x() / layer->contents_scale_x(),
- render_surface_sublayer_scale.y() / layer->contents_scale_y());
-
- // Inside the surface's subtree, we scale everything to the owning layer's
- // scale. The sublayer matrix transforms layer rects into target surface
- // content space. Conceptually, all layers in the subtree inherit the scale
- // at the point of the render surface in the transform hierarchy, but we
- // apply it explicitly to the owning layer and the remainder of the subtree
- // indenpendently.
- DCHECK(sublayer_matrix.IsIdentity());
- sublayer_matrix.Scale(render_surface_sublayer_scale.x(),
- render_surface_sublayer_scale.y());
-
// The opacity value is moved from the layer to its surface, so that the
// entire subtree properly inherits opacity.
render_surface->SetDrawOpacity(accumulated_draw_opacity);
@@ -1337,6 +1331,7 @@ static void CalculateDrawPropertiesInternal(
LayerType* child =
LayerTreeHostCommon::get_child_as_raw_ptr(layer->children(), i);
gfx::Rect drawable_content_rect_of_child_subtree;
+ gfx::Transform identity_matrix;
CalculateDrawPropertiesInternal<LayerType, LayerList, RenderSurfaceType>(
child,
sublayer_matrix,
@@ -1526,6 +1521,7 @@ static void CalculateDrawPropertiesInternal(
void LayerTreeHostCommon::CalculateDrawProperties(
Layer* root_layer,
gfx::Size device_viewport_size,
+ const gfx::Transform& device_transform,
float device_scale_factor,
float page_scale_factor,
Layer* page_scale_application_layer,
@@ -1535,8 +1531,8 @@ void LayerTreeHostCommon::CalculateDrawProperties(
LayerList* render_surface_layer_list) {
gfx::Rect total_drawable_content_rect;
gfx::Transform identity_matrix;
- gfx::Transform device_scale_transform;
- device_scale_transform.Scale(device_scale_factor, device_scale_factor);
+ gfx::Transform scaled_device_transform = device_transform;
+ scaled_device_transform.Scale(device_scale_factor, device_scale_factor);
LayerList dummy_layer_list;
// The root layer's render_surface should receive the device viewport as the
@@ -1551,10 +1547,10 @@ void LayerTreeHostCommon::CalculateDrawProperties(
PreCalculateMetaInformation<Layer>(root_layer);
CalculateDrawPropertiesInternal<Layer, LayerList, RenderSurface>(
root_layer,
- device_scale_transform,
+ scaled_device_transform,
identity_matrix,
identity_matrix,
- NULL,
+ root_layer,
device_viewport_rect,
device_viewport_rect,
subtree_should_be_clipped,
@@ -1581,6 +1577,7 @@ void LayerTreeHostCommon::CalculateDrawProperties(
void LayerTreeHostCommon::CalculateDrawProperties(
LayerImpl* root_layer,
gfx::Size device_viewport_size,
+ const gfx::Transform& device_transform,
float device_scale_factor,
float page_scale_factor,
LayerImpl* page_scale_application_layer,
@@ -1590,8 +1587,8 @@ void LayerTreeHostCommon::CalculateDrawProperties(
LayerImplList* render_surface_layer_list) {
gfx::Rect total_drawable_content_rect;
gfx::Transform identity_matrix;
- gfx::Transform device_scale_transform;
- device_scale_transform.Scale(device_scale_factor, device_scale_factor);
+ gfx::Transform scaled_device_transform = device_transform;
+ scaled_device_transform.Scale(device_scale_factor, device_scale_factor);
LayerImplList dummy_layer_list;
LayerSorter layer_sorter;
@@ -1609,10 +1606,10 @@ void LayerTreeHostCommon::CalculateDrawProperties(
LayerImplList,
RenderSurfaceImpl>(
root_layer,
- device_scale_transform,
+ scaled_device_transform,
identity_matrix,
identity_matrix,
- NULL,
+ root_layer,
device_viewport_rect,
device_viewport_rect,
subtree_should_be_clipped,
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h
index 165cd5e..b2b39c4 100644
--- a/cc/trees/layer_tree_host_common.h
+++ b/cc/trees/layer_tree_host_common.h
@@ -29,6 +29,7 @@ class CC_EXPORT LayerTreeHostCommon {
static void CalculateDrawProperties(
Layer* root_layer,
gfx::Size device_viewport_size,
+ const gfx::Transform& device_transform,
float device_scale_factor,
float page_scale_factor,
Layer* page_scale_application_layer,
@@ -39,6 +40,7 @@ class CC_EXPORT LayerTreeHostCommon {
static void CalculateDrawProperties(
LayerImpl* root_layer,
gfx::Size device_viewport_size,
+ const gfx::Transform& device_transform,
float device_scale_factor,
float page_scale_factor,
LayerImpl* page_scale_application_layer,
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index aa9c7f0..8fa91ce 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -99,6 +99,7 @@ void ExecuteCalculateDrawProperties(Layer* root_layer,
LayerTreeHostCommon::CalculateDrawProperties(
root_layer,
device_viewport_size,
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
page_scale_application_layer,
@@ -126,6 +127,7 @@ void ExecuteCalculateDrawProperties(LayerImpl* root_layer,
LayerTreeHostCommon::CalculateDrawProperties(
root_layer,
device_viewport_size,
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
page_scale_application_layer,
@@ -1484,6 +1486,121 @@ TEST(LayerTreeHostCommonTest, TransformsForDegenerateIntermediateLayer) {
grand_child->draw_transform());
}
+TEST(LayerTreeHostCommonTest, TransformAboveRootLayer) {
+ // Transformations applied at the root of the tree should be forwarded
+ // to child layers instead of applied to the root RenderSurface.
+ const gfx::Transform identity_matrix;
+ scoped_refptr<Layer> root = Layer::Create();
+ scoped_refptr<Layer> child = Layer::Create();
+
+ root->AddChild(child);
+
+ SetLayerPropertiesForTesting(root.get(),
+ identity_matrix,
+ identity_matrix,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(20, 20),
+ false);
+ SetLayerPropertiesForTesting(child.get(),
+ identity_matrix,
+ identity_matrix,
+ gfx::PointF(),
+ gfx::PointF(),
+ gfx::Size(20, 20),
+ false);
+
+ LayerList render_surface_layer_list;
+ int dummy_max_texture_size = 512;
+
+ gfx::Transform translate;
+ translate.Translate(50, 50);
+ LayerTreeHostCommon::CalculateDrawProperties(root.get(),
+ root->bounds(),
+ translate,
+ 1.f,
+ 1.f,
+ NULL,
+ dummy_max_texture_size,
+ false,
+ true, // can_adjust_raster_scale
+ &render_surface_layer_list);
+ EXPECT_EQ(translate, root->draw_properties().target_space_transform);
+ EXPECT_EQ(translate, child->draw_properties().target_space_transform);
+ EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform());
+
+ gfx::Transform scale;
+ scale.Scale(2, 2);
+ LayerTreeHostCommon::CalculateDrawProperties(root.get(),
+ root->bounds(),
+ scale,
+ 1.f,
+ 1.f,
+ NULL,
+ dummy_max_texture_size,
+ false,
+ true, // can_adjust_raster_scale
+ &render_surface_layer_list);
+ EXPECT_EQ(scale, root->draw_properties().target_space_transform);
+ EXPECT_EQ(scale, child->draw_properties().target_space_transform);
+ EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform());
+
+ gfx::Transform rotate;
+ rotate.Rotate(2);
+ LayerTreeHostCommon::CalculateDrawProperties(root.get(),
+ root->bounds(),
+ rotate,
+ 1.f,
+ 1.f,
+ NULL,
+ dummy_max_texture_size,
+ false,
+ true, // can_adjust_raster_scale
+ &render_surface_layer_list);
+ EXPECT_EQ(rotate, root->draw_properties().target_space_transform);
+ EXPECT_EQ(rotate, child->draw_properties().target_space_transform);
+ EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform());
+
+ gfx::Transform composite;
+ composite.ConcatTransform(translate);
+ composite.ConcatTransform(scale);
+ composite.ConcatTransform(rotate);
+ LayerTreeHostCommon::CalculateDrawProperties(root.get(),
+ root->bounds(),
+ composite,
+ 1.f,
+ 1.f,
+ NULL,
+ dummy_max_texture_size,
+ false,
+ true, // can_adjust_raster_scale
+ &render_surface_layer_list);
+ EXPECT_EQ(composite, root->draw_properties().target_space_transform);
+ EXPECT_EQ(composite, child->draw_properties().target_space_transform);
+ EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform());
+
+ // Verify that it composes correctly with transforms directly on root layer.
+ root->SetTransform(composite);
+ root->SetSublayerTransform(composite);
+ LayerTreeHostCommon::CalculateDrawProperties(root.get(),
+ root->bounds(),
+ composite,
+ 1.f,
+ 1.f,
+ NULL,
+ dummy_max_texture_size,
+ false,
+ true, // can_adjust_raster_scale
+ &render_surface_layer_list);
+ gfx::Transform compositeSquared = composite;
+ compositeSquared.ConcatTransform(composite);
+ gfx::Transform compositeCubed = compositeSquared;
+ compositeCubed.ConcatTransform(composite);
+ EXPECT_EQ(compositeSquared, root->draw_properties().target_space_transform);
+ EXPECT_EQ(compositeCubed, child->draw_properties().target_space_transform);
+ EXPECT_EQ(identity_matrix, root->render_surface()->draw_transform());
+}
+
TEST(LayerTreeHostCommonTest,
RenderSurfaceListForRenderSurfaceWithClippedLayer) {
scoped_refptr<Layer> parent = Layer::Create();
@@ -1523,6 +1640,7 @@ TEST(LayerTreeHostCommonTest,
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1572,6 +1690,7 @@ TEST(LayerTreeHostCommonTest, RenderSurfaceListForTransparentChild) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1631,6 +1750,7 @@ TEST(LayerTreeHostCommonTest, ForceRenderSurface) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1648,6 +1768,7 @@ TEST(LayerTreeHostCommonTest, ForceRenderSurface) {
render_surface1->SetForceRenderSurface(false);
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1749,6 +1870,7 @@ TEST(LayerTreeHostCommonTest, ClipRectCullsRenderSurfaces) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1830,6 +1952,7 @@ TEST(LayerTreeHostCommonTest, ClipRectCullsSurfaceWithoutVisibleContent) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1854,6 +1977,7 @@ TEST(LayerTreeHostCommonTest, ClipRectCullsSurfaceWithoutVisibleContent) {
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1958,6 +2082,7 @@ TEST(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -1987,6 +2112,7 @@ TEST(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
parent->SetMasksToBounds(true);
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -2015,6 +2141,7 @@ TEST(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
child2->SetMasksToBounds(true);
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -2123,6 +2250,7 @@ TEST(LayerTreeHostCommonTest, drawable_content_rectForLayers) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -2268,6 +2396,7 @@ TEST(LayerTreeHostCommonTest, ClipRectIsPropagatedCorrectlyToSurfaces) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -3598,6 +3727,7 @@ TEST(LayerTreeHostCommonTest, BackFaceCullingWithoutPreserves3d) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -3792,6 +3922,7 @@ TEST(LayerTreeHostCommonTest, BackFaceCullingWithPreserves3d) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -3932,6 +4063,7 @@ TEST(LayerTreeHostCommonTest, BackFaceCullingWithAnimatingTransforms) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4060,6 +4192,7 @@ TEST(LayerTreeHostCommonTest,
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4138,6 +4271,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForSingleLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4214,6 +4348,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForSingleLayerAndHud) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
hud_bounds,
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4282,6 +4417,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForUninvertibleTransform) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4359,6 +4495,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForSinglePositionedLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4425,6 +4562,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForSingleRotatedLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4504,6 +4642,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForSinglePerspectiveLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4594,6 +4733,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForSingleLayerWithScaledContents) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4695,6 +4835,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForSimpleClippedLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4829,6 +4970,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForMultiClippedRotatedLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -4956,6 +5098,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForNonClippingIntermediateLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -5074,6 +5217,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForMultipleLayers) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -5228,6 +5372,7 @@ TEST(LayerTreeHostCommonTest, HitTestingForMultipleLayerLists) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -5346,6 +5491,7 @@ TEST(LayerTreeHostCommonTest, HitCheckingTouchHandlerRegionsForSingleLayer) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -5444,6 +5590,7 @@ TEST(LayerTreeHostCommonTest,
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -5532,6 +5679,7 @@ TEST(LayerTreeHostCommonTest,
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -5638,6 +5786,7 @@ TEST(LayerTreeHostCommonTest,
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -5751,6 +5900,7 @@ TEST(LayerTreeHostCommonTest,
gfx::ScaleSize(root->bounds(), device_scale_factor * page_scale_factor));
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
scaled_bounds_for_root,
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
root.get(),
@@ -5891,6 +6041,7 @@ TEST(LayerTreeHostCommonTest,
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -6036,6 +6187,7 @@ TEST(LayerTreeHostCommonTest, LayerTransformsInHighDPI) {
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6173,6 +6325,7 @@ TEST(LayerTreeHostCommonTest, SurfaceLayerTransformsInHighDPI) {
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6273,6 +6426,7 @@ TEST(LayerTreeHostCommonTest,
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6412,6 +6566,7 @@ TEST(LayerTreeHostCommonTest, ContentsScale) {
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6454,6 +6609,7 @@ TEST(LayerTreeHostCommonTest, ContentsScale) {
render_surface_layer_list.clear();
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6482,6 +6638,7 @@ TEST(LayerTreeHostCommonTest, ContentsScale) {
render_surface_layer_list.clear();
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6507,6 +6664,7 @@ TEST(LayerTreeHostCommonTest, ContentsScale) {
render_surface_layer_list.clear();
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6595,6 +6753,7 @@ TEST(LayerTreeHostCommonTest,
LayerTreeHostCommon::CalculateDrawProperties(
root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6678,6 +6837,7 @@ TEST(LayerTreeHostCommonTest, SmallContentsScale) {
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6703,6 +6863,7 @@ TEST(LayerTreeHostCommonTest, SmallContentsScale) {
render_surface_layer_list.clear();
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -6824,6 +6985,7 @@ TEST(LayerTreeHostCommonTest, ContentsScaleForSurfaces) {
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -7039,6 +7201,7 @@ TEST(LayerTreeHostCommonTest,
LayerTreeHostCommon::CalculateDrawProperties(
root.get(),
root->bounds(),
+ gfx::Transform(),
device_scale_factor,
page_scale_factor,
parent.get(),
@@ -7192,6 +7355,7 @@ TEST(LayerTreeHostCommonTest, ContentsScaleForAnimatingLayer) {
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -7210,6 +7374,7 @@ TEST(LayerTreeHostCommonTest, ContentsScaleForAnimatingLayer) {
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -7280,6 +7445,7 @@ TEST(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) {
float device_scale_factor = 1.5f;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
device_scale_factor,
1.f,
NULL,
@@ -7417,6 +7583,7 @@ TEST(LayerTreeHostCommonTest,
float device_scale_factor = 1.7f;
LayerTreeHostCommon::CalculateDrawProperties(parent.get(),
parent->bounds(),
+ gfx::Transform(),
device_scale_factor,
1.f,
NULL,
@@ -7571,6 +7738,7 @@ TEST(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) {
int dummy_max_texture_size = 512;
LayerTreeHostCommon::CalculateDrawProperties(root.get(),
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 7d8bf91..5d84fcd 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -165,8 +165,6 @@ LayerTreeHostImpl::LayerTreeHostImpl(
wheel_scrolling_(false),
root_layer_scroll_offset_delegate_(NULL),
settings_(settings),
- overdraw_bottom_height_(0.f),
- device_scale_factor_(1.f),
visible_(true),
managed_memory_policy_(
PrioritizedResourceManager::DefaultMemoryAllocationLimit(),
@@ -182,6 +180,8 @@ LayerTreeHostImpl::LayerTreeHostImpl(
last_sent_memory_visible_bytes_(0),
last_sent_memory_visible_and_nearby_bytes_(0),
last_sent_memory_use_bytes_(0),
+ device_scale_factor_(1.f),
+ overdraw_bottom_height_(0.f),
animation_registrar_(AnimationRegistrar::Create()),
rendering_stats_instrumentation_(rendering_stats_instrumentation) {
DCHECK(proxy_->IsImplThread());
@@ -1040,6 +1040,13 @@ void LayerTreeHostImpl::SetManagedMemoryPolicy(
client_->SetNeedsCommitOnImplThread();
}
+void LayerTreeHostImpl::SetExternalDrawConstraints(
+ const gfx::Transform& transform,
+ gfx::Rect viewport) {
+ external_transform_ = transform;
+ external_viewport_ = viewport;
+}
+
void LayerTreeHostImpl::SetNeedsRedrawRect(gfx::Rect damage_rect) {
client_->SetNeedsRedrawRectOnImplThread(damage_rect);
}
@@ -1221,17 +1228,13 @@ void LayerTreeHostImpl::SetNeedsBeginFrame(bool enable) {
output_surface_->SetNeedsBeginFrame(enable);
}
-gfx::Size LayerTreeHostImpl::DeviceViewportSize() const {
- return device_viewport_size();
-}
-
float LayerTreeHostImpl::DeviceScaleFactor() const {
return device_scale_factor_;
}
gfx::SizeF LayerTreeHostImpl::VisibleViewportSize() const {
gfx::SizeF dip_size =
- gfx::ScaleSize(DeviceViewportSize(), 1.f / device_scale_factor());
+ gfx::ScaleSize(device_viewport_size(), 1.f / device_scale_factor());
// The clip layer should be used if non-overlay scrollbars may exist since
// it adjusts for them.
@@ -1553,6 +1556,17 @@ void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
SetFullRootLayerDamage();
}
+gfx::Rect LayerTreeHostImpl::DeviceViewport() const {
+ if (external_viewport_.IsEmpty())
+ return gfx::Rect(device_viewport_size_);
+
+ return external_viewport_;
+}
+
+const gfx::Transform& LayerTreeHostImpl::DeviceTransform() const {
+ return external_transform_;
+}
+
void LayerTreeHostImpl::UpdateMaxScrollOffset() {
active_tree_->UpdateMaxScrollOffset();
}
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index f65922a..e3671cf 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -176,8 +176,8 @@ class CC_EXPORT LayerTreeHostImpl
gfx::SizeF VisibleViewportSize() const;
// RendererClient implementation
+ virtual gfx::Rect DeviceViewport() const OVERRIDE;
private:
- virtual gfx::Size DeviceViewportSize() const OVERRIDE;
virtual float DeviceScaleFactor() const OVERRIDE;
virtual const LayerTreeSettings& Settings() const OVERRIDE;
public:
@@ -207,6 +207,8 @@ class CC_EXPORT LayerTreeHostImpl
OVERRIDE;
virtual void OnSendFrameToParentCompositorAck(const CompositorFrameAck& ack)
OVERRIDE;
+ virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
+ gfx::Rect viewport) OVERRIDE;
// Called from LayerTreeImpl.
void OnCanDrawStateChangedForTree();
@@ -267,6 +269,8 @@ class CC_EXPORT LayerTreeHostImpl
void SetDeviceScaleFactor(float device_scale_factor);
float device_scale_factor() const { return device_scale_factor_; }
+ const gfx::Transform& DeviceTransform() const;
+
scoped_ptr<ScrollAndScaleSet> ProcessScrollDeltas();
bool needs_animate_layers() const {
@@ -457,9 +461,6 @@ class CC_EXPORT LayerTreeHostImpl
LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate_;
LayerTreeSettings settings_;
LayerTreeDebugState debug_state_;
- gfx::Size device_viewport_size_;
- float overdraw_bottom_height_;
- float device_scale_factor_;
bool visible_;
ManagedMemoryPolicy managed_memory_policy_;
@@ -493,6 +494,26 @@ class CC_EXPORT LayerTreeHostImpl
size_t last_sent_memory_visible_and_nearby_bytes_;
size_t last_sent_memory_use_bytes_;
+ // Viewport size passed in from the main thread, in physical pixels.
+ gfx::Size device_viewport_size_;
+
+ // Conversion factor from CSS pixels to physical pixels when
+ // pageScaleFactor=1.
+ float device_scale_factor_;
+
+ // Vertical amount of the viewport size that's known to covered by a
+ // browser-side UI element, such as an on-screen-keyboard. This affects
+ // scrollable size since we want to still be able to scroll to the bottom of
+ // the page when the keyboard is up.
+ float overdraw_bottom_height_;
+
+ // Optional top-level constraints that can be set by the OutputSurface. The
+ // external_viewport_'s size takes precedence over device_viewport_size_ for
+ // DrawQuad generation and Renderer; however, device_viewport_size_ is still
+ // used for scrollable size.
+ gfx::Transform external_transform_;
+ gfx::Rect external_viewport_;
+
gfx::Rect viewport_damage_rect_;
base::TimeTicks current_frame_timeticks_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index ab97c86..95bc4fe 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -4602,8 +4602,8 @@ class TestRenderer : public GLRenderer, public RendererClient {
}
// RendererClient implementation.
- virtual gfx::Size DeviceViewportSize() const OVERRIDE {
- return viewport_size_;
+ virtual gfx::Rect DeviceViewport() const OVERRIDE {
+ return gfx::Rect(viewport_size_);
}
virtual float DeviceScaleFactor() const OVERRIDE {
return 1.f;
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 6bc370c..e8ae6f1 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -282,7 +282,8 @@ void LayerTreeImpl::UpdateDrawProperties() {
IsActiveTree());
LayerTreeHostCommon::CalculateDrawProperties(
root_layer(),
- device_viewport_size(),
+ layer_tree_host_impl_->DeviceViewport().size(),
+ layer_tree_host_impl_->DeviceTransform(),
device_scale_factor(),
total_page_scale_factor(),
root_scroll_layer_,
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index 09c64ef..7cf6aa7 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -316,6 +316,7 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test {
LayerTreeHostCommon::CalculateDrawProperties(
root,
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,
@@ -337,6 +338,7 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test {
LayerTreeHostCommon::CalculateDrawProperties(
root,
root->bounds(),
+ gfx::Transform(),
1.f,
1.f,
NULL,