diff options
38 files changed, 776 insertions, 280 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, diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc index d5876e4..b0e2d0e 100644 --- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc +++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc @@ -154,24 +154,33 @@ bool SynchronousCompositorOutputSurface::IsHwReady() { return context3d() != NULL; } +namespace { +void AdjustTransformForClip(gfx::Transform* transform, gfx::Rect clip) { + // The system-provided transform translates us from the screen origin to the + // origin of the clip rect, but CC's draw origin starts at the clip. + transform->matrix().postTranslate(-clip.x(), -clip.y(), 0); +} +} // namespace + bool SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) { DCHECK(CalledOnValidThread()); DCHECK(canvas); DCHECK(!current_sw_canvas_); current_sw_canvas_ = canvas; - SkRect canvas_clip; - gfx::Rect damage_area; - if (canvas->getClipBounds(&canvas_clip)) { - damage_area = gfx::ToEnclosedRect(gfx::SkRectToRectF(canvas_clip)); - } else { - damage_area = gfx::Rect(kint16max, kint16max); - } + SkIRect canvas_clip; + canvas->getClipDeviceBounds(&canvas_clip); + gfx::Rect clip = gfx::SkIRectToRect(canvas_clip); - gfx::Transform transform; + gfx::Transform transform(gfx::Transform::kSkipInitialization); transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4. + AdjustTransformForClip(&transform, clip); + + surface_size_ = gfx::Size(canvas->getDeviceSize().width(), + canvas->getDeviceSize().height()); + client_->SetExternalDrawConstraints(transform, clip); - InvokeComposite(transform, damage_area); + InvokeComposite(clip.size()); bool finished_draw = current_sw_canvas_ == NULL; current_sw_canvas_ = NULL; @@ -179,9 +188,9 @@ bool SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) { } bool SynchronousCompositorOutputSurface::DemandDrawHw( - gfx::Size view_size, + gfx::Size surface_size, const gfx::Transform& transform, - gfx::Rect damage_area) { + gfx::Rect clip) { DCHECK(CalledOnValidThread()); DCHECK(client_); DCHECK(context3d()); @@ -196,17 +205,18 @@ bool SynchronousCompositorOutputSurface::DemandDrawHw( did_swap_buffer_ = false; - InvokeComposite(transform, damage_area); + gfx::Transform adjusted_transform = transform; + AdjustTransformForClip(&adjusted_transform, clip); + surface_size_ = surface_size; + client_->SetExternalDrawConstraints(adjusted_transform, clip); + InvokeComposite(clip.size()); return did_swap_buffer_; } void SynchronousCompositorOutputSurface::InvokeComposite( - const gfx::Transform& transform, - gfx::Rect damage_area) { - // TODO(boliu): This assumes |transform| is identity and |damage_area| is the - // whole view. Tracking bug to implement this: crbug.com/230463. - client_->SetNeedsRedrawRect(damage_area); + gfx::Size damage_size) { + client_->SetNeedsRedrawRect(gfx::Rect(damage_size)); if (needs_begin_frame_) client_->BeginFrame(base::TimeTicks::Now()); } diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.h b/content/browser/android/in_process/synchronous_compositor_output_surface.h index d6af43b..78672fd 100644 --- a/content/browser/android/in_process/synchronous_compositor_output_surface.h +++ b/content/browser/android/in_process/synchronous_compositor_output_surface.h @@ -55,7 +55,7 @@ class SynchronousCompositorOutputSurface // Partial SynchronousCompositor API implementation. bool IsHwReady(); bool DemandDrawSw(SkCanvas* canvas); - bool DemandDrawHw(gfx::Size view_size, + bool DemandDrawHw(gfx::Size surface_size, const gfx::Transform& transform, gfx::Rect clip); @@ -63,7 +63,7 @@ class SynchronousCompositorOutputSurface class SoftwareDevice; friend class SoftwareDevice; - void InvokeComposite(const gfx::Transform& transform, gfx::Rect damage_area); + void InvokeComposite(gfx::Size damage_size); void UpdateCompositorClientSettings(); void NotifyCompositorSettingsChanged(); bool CalledOnValidThread() const; diff --git a/content/renderer/gpu/mailbox_output_surface.cc b/content/renderer/gpu/mailbox_output_surface.cc index aa9b4b0..d7b13ce 100644 --- a/content/renderer/gpu/mailbox_output_surface.cc +++ b/content/renderer/gpu/mailbox_output_surface.cc @@ -45,7 +45,7 @@ void MailboxOutputSurface::EnsureBackbuffer() { // Find a texture of matching size to recycle. while (!returned_textures_.empty()) { TransferableFrame& texture = returned_textures_.front(); - if (texture.size == size_) { + if (texture.size == surface_size_) { current_backing_ = texture; if (current_backing_.sync_point) context3d_->waitSyncPoint(current_backing_.sync_point); @@ -59,7 +59,7 @@ void MailboxOutputSurface::EnsureBackbuffer() { if (!current_backing_.texture_id) { current_backing_.texture_id = context3d_->createTexture(); - current_backing_.size = size_; + current_backing_.size = surface_size_; context3d_->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id); context3d_->texParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -70,7 +70,8 @@ void MailboxOutputSurface::EnsureBackbuffer() { context3d_->texParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); context3d_->texImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, size_.width(), size_.height(), 0, + GL_TEXTURE_2D, 0, GL_RGBA, + surface_size_.width(), surface_size_.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); context3d_->genMailboxCHROMIUM(current_backing_.mailbox.name); context3d_->produceTextureCHROMIUM( @@ -101,10 +102,11 @@ void MailboxOutputSurface::DiscardBackbuffer() { } void MailboxOutputSurface::Reshape(gfx::Size size, float scale_factor) { - if (size == size_) + if (size == surface_size_) return; - size_ = size; + surface_size_ = size; + device_scale_factor_ = scale_factor; DiscardBackbuffer(); EnsureBackbuffer(); } @@ -125,8 +127,8 @@ void MailboxOutputSurface::SendFrameToParentCompositor( cc::CompositorFrame* frame) { frame->gl_frame_data.reset(new GLFrameData()); - DCHECK(!size_.IsEmpty()); - DCHECK(size_ == current_backing_.size); + DCHECK(!surface_size_.IsEmpty()); + DCHECK(surface_size_ == current_backing_.size); DCHECK(!current_backing_.mailbox.IsZero()); frame->gl_frame_data->mailbox = current_backing_.mailbox; diff --git a/content/renderer/gpu/mailbox_output_surface.h b/content/renderer/gpu/mailbox_output_surface.h index 34c25fe..9133c9a 100644 --- a/content/renderer/gpu/mailbox_output_surface.h +++ b/content/renderer/gpu/mailbox_output_surface.h @@ -61,7 +61,6 @@ class MailboxOutputSurface : public CompositorOutputSurface { std::deque<TransferableFrame> pending_textures_; std::queue<TransferableFrame> returned_textures_; - gfx::Size size_; uint32 fbo_; bool is_backbuffer_discarded_; }; diff --git a/webkit/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc b/webkit/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc index f02afd2..7099d7f 100644 --- a/webkit/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc +++ b/webkit/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc @@ -131,6 +131,7 @@ void CompareFixedBoundsLayerAndNormalLayer( cc::LayerTreeHostCommon::CalculateDrawProperties( root_layer->layer(), kDeviceViewportSize, + gfx::Transform(), kDeviceScaleFactor, kPageScaleFactor, root_layer->layer(), @@ -149,6 +150,7 @@ void CompareFixedBoundsLayerAndNormalLayer( cc::LayerTreeHostCommon::CalculateDrawProperties( root_layer->layer(), kDeviceViewportSize, + gfx::Transform(), kDeviceScaleFactor, kPageScaleFactor, root_layer->layer(), |