diff options
author | aelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-09 00:21:26 +0000 |
---|---|---|
committer | aelias@chromium.org <aelias@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-09 00:21:26 +0000 |
commit | 251699bdcff5063ceafe1442072f756085e2643b (patch) | |
tree | 1e9046aaccc1aa732f11323855a0a053d8a6b33e /cc | |
parent | 77439eb431f1a1152c9ba6a7de0fd874a67ff946 (diff) | |
download | chromium_src-251699bdcff5063ceafe1442072f756085e2643b.zip chromium_src-251699bdcff5063ceafe1442072f756085e2643b.tar.gz chromium_src-251699bdcff5063ceafe1442072f756085e2643b.tar.bz2 |
Make Android WebView filtering depend on scrolling status.
This patch makes bilinear filtering of software images enabled only when
there is no scrolling or CSS animation active, which matches the
policy of classic WebView. In the long run, we'll likely want to support
software tiling to avoid this kind of hack, but for now this maintains
bugwards compatibility.
Most of this patch is to solve the problem that CC was not aware whether
or not WebView-handled fling is active. I added a new getter
ScrollOffsetDelegate::IsExternalFlingActive for this. This also
enables prefer-smoothness mode for these flings.
New test RendererPixelTest.PictureDrawQuadDisableImageFiltering
NOTRY=true
BUG= internal b/10706494
Review URL: https://codereview.chromium.org/25233002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@227629 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
24 files changed, 194 insertions, 53 deletions
diff --git a/cc/input/layer_scroll_offset_delegate.h b/cc/input/layer_scroll_offset_delegate.h index 66f9ad4..805bbfb 100644 --- a/cc/input/layer_scroll_offset_delegate.h +++ b/cc/input/layer_scroll_offset_delegate.h @@ -34,6 +34,10 @@ class LayerScrollOffsetDelegate { // more than the value passed to the most recent SetMaxScrollOffset call. virtual gfx::Vector2dF GetTotalScrollOffset() = 0; + // This is called by the compositor to check whether a delegate-managed fling + // is active or not. + virtual bool IsExternalFlingActive() const = 0; + // This is called by the compositor to notify the delegate what is the current // page scale factor is. virtual void SetPageScaleFactor(float page_scale_factor) = 0; diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index dde14e2..c1fb321 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -980,6 +980,11 @@ void LayerImpl::SetScrollOffsetDelegate( } } +bool LayerImpl::IsExternalFlingActive() const { + return scroll_offset_delegate_ && + scroll_offset_delegate_->IsExternalFlingActive(); +} + void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) { SetScrollOffsetAndDelta(scroll_offset, ScrollDelta()); } diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index c97afc7..6513b32 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -345,6 +345,8 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver { void SetScrollOffsetDelegate( LayerScrollOffsetDelegate* scroll_offset_delegate); + bool IsExternalFlingActive() const; + void SetScrollOffset(gfx::Vector2d scroll_offset); void SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset, gfx::Vector2dF scroll_delta); diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index 5e36e81..3a0b1ce 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc @@ -376,6 +376,7 @@ class ScrollDelegateIgnore : public LayerScrollOffsetDelegate { virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE { return fixed_offset_; } + virtual bool IsExternalFlingActive() const OVERRIDE { return false; } void set_fixed_offset(gfx::Vector2dF fixed_offset) { fixed_offset_ = fixed_offset; @@ -432,6 +433,7 @@ class ScrollDelegateAccept : public LayerScrollOffsetDelegate { virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE { return current_offset_; } + virtual bool IsExternalFlingActive() const OVERRIDE { return false; } virtual void SetPageScaleFactor(float page_scale_factor) OVERRIDE {} virtual void SetScrollableSize(gfx::SizeF scrollable_size) OVERRIDE {} diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc index e3413a5..772a16a 100644 --- a/cc/output/delegating_renderer.cc +++ b/cc/output/delegating_renderer.cc @@ -100,7 +100,8 @@ static ResourceProvider::ResourceId AppendToArray( void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, ContextProvider* offscreen_context_provider, float device_scale_factor, - bool allow_partial_swap) { + bool allow_partial_swap, + bool disable_picture_quad_image_filtering) { TRACE_EVENT0("cc", "DelegatingRenderer::DrawFrame"); DCHECK(!frame_for_swap_buffers_.delegated_frame_data); diff --git a/cc/output/delegating_renderer.h b/cc/output/delegating_renderer.h index 57a2418..0ca685f 100644 --- a/cc/output/delegating_renderer.h +++ b/cc/output/delegating_renderer.h @@ -31,7 +31,8 @@ class CC_EXPORT DelegatingRenderer : public Renderer { virtual void DrawFrame(RenderPassList* render_passes_in_draw_order, ContextProvider* offscreen_context_provider, float device_scale_factor, - bool allow_partial_swap) OVERRIDE; + bool allow_partial_swap, + bool disable_picture_quad_image_filtering) OVERRIDE; virtual void Finish() OVERRIDE {} diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index d46f46d..c02200d 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc @@ -198,7 +198,8 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame( void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, ContextProvider* offscreen_context_provider, float device_scale_factor, - bool allow_partial_swap) { + bool allow_partial_swap, + bool disable_picture_quad_image_filtering) { TRACE_EVENT0("cc", "DirectRenderer::DrawFrame"); UMA_HISTOGRAM_COUNTS("Renderer4.renderPassCount", render_passes_in_draw_order->size()); @@ -214,6 +215,8 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, : root_render_pass->output_rect; frame.root_damage_rect.Intersect(gfx::Rect(client_->DeviceViewport().size())); frame.offscreen_context_provider = offscreen_context_provider; + frame.disable_picture_quad_image_filtering = + disable_picture_quad_image_filtering; EnsureBackbuffer(); diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h index a73c62d..f55cc59 100644 --- a/cc/output/direct_renderer.h +++ b/cc/output/direct_renderer.h @@ -34,7 +34,8 @@ class CC_EXPORT DirectRenderer : public Renderer { virtual void DrawFrame(RenderPassList* render_passes_in_draw_order, ContextProvider* offscreen_context_provider, float device_scale_factor, - bool allow_partial_swap) OVERRIDE; + bool allow_partial_swap, + bool disable_picture_quad_image_filtering) OVERRIDE; struct CC_EXPORT DrawingFrame { DrawingFrame(); @@ -50,6 +51,8 @@ class CC_EXPORT DirectRenderer : public Renderer { gfx::Transform window_matrix; ContextProvider* offscreen_context_provider; + + bool disable_picture_quad_image_filtering; }; void SetEnlargePassTextureAmountForTesting(gfx::Vector2d amount); diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index e30f0ceb..c8aab57 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc @@ -445,7 +445,7 @@ TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration) { renderer_->SetVisible(true); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_FALSE(renderer_->IsBackbufferDiscarded()); SwapBuffers(); @@ -460,7 +460,7 @@ TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible) { char pixels[4]; renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_FALSE(renderer_->IsBackbufferDiscarded()); renderer_->GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1)); @@ -475,7 +475,7 @@ TEST_F(GLRendererTest, ExternalStencil) { renderer_client_.root_render_pass()->has_transparent_background = false; renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_TRUE(renderer_->stencil_enabled()); } @@ -738,7 +738,7 @@ TEST(GLRendererTest2, OpaqueBackground) { EXPECT_CALL(*context, clear(_)).Times(1); #endif renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); Mock::VerifyAndClearExpectations(context); } @@ -769,7 +769,7 @@ TEST(GLRendererTest2, TransparentBackground) { .Times(1); EXPECT_CALL(*context, clear(_)).Times(1); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); Mock::VerifyAndClearExpectations(context); } @@ -800,7 +800,7 @@ TEST(GLRendererTest2, OffscreenOutputSurface) { .Times(1); EXPECT_CALL(*context, clear(_)).Times(AnyNumber()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); Mock::VerifyAndClearExpectations(context); } @@ -878,7 +878,7 @@ TEST(GLRendererTest2, VisibilityChangeIsLastCall) { // the stack. renderer.SetVisible(true); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); renderer.SetVisible(false); EXPECT_TRUE(context->last_call_was_set_visibility()); } @@ -1058,7 +1058,7 @@ TEST(GLRendererTest2, ShouldClearRootRenderPass) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); // In multiple render passes all but the root pass should clear the // framebuffer. @@ -1134,7 +1134,7 @@ TEST(GLRendererTest2, ScissorTestWhenClearing) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); } class DiscardCheckingContext : public TestWebGraphicsContext3D { @@ -1211,7 +1211,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_EQ(0, context->discarded()); context->reset(); } @@ -1226,7 +1226,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_EQ(1, context->discarded()); context->reset(); } @@ -1241,7 +1241,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, false); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, false, false); EXPECT_EQ(1, context->discarded()); context->reset(); } @@ -1258,7 +1258,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_EQ(0, context->discarded()); context->reset(); output_surface->set_has_external_stencil_test(false); @@ -1275,7 +1275,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_EQ(0, context->discarded()); context->reset(); } @@ -1292,7 +1292,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_EQ(0, context->discarded()); context->reset(); } @@ -1310,7 +1310,7 @@ TEST(GLRendererTest2, NoDiscardOnPartialUpdates) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); EXPECT_EQ(0, context->discarded()); context->reset(); } @@ -1387,7 +1387,7 @@ TEST(GLRendererTest2, ScissorAndViewportWithinNonreshapableSurface) { renderer.DecideRenderPassAllocationsForFrame( *renderer_client.render_passes_in_draw_order()); renderer.DrawFrame( - renderer_client.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client.render_passes_in_draw_order(), NULL, 1.f, true, false); } TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { @@ -1453,7 +1453,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassProgram(); // RenderPassColorMatrixProgram @@ -1470,7 +1470,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassColorMatrixProgram(); // RenderPassMaskProgram @@ -1491,7 +1491,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassMaskProgram(); // RenderPassMaskColorMatrixProgram @@ -1508,7 +1508,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassMaskColorMatrixProgram(); // RenderPassProgramAA @@ -1529,7 +1529,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassProgramAA(); // RenderPassColorMatrixProgramAA @@ -1546,7 +1546,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassColorMatrixProgramAA(); // RenderPassMaskProgramAA @@ -1564,7 +1564,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassMaskProgramAA(); // RenderPassMaskColorMatrixProgramAA @@ -1581,7 +1581,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestRenderPassMaskColorMatrixProgramAA(); } @@ -1630,7 +1630,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); // If use_aa incorrectly ignores clipping, it will use the // RenderPassProgramAA shader instead of the RenderPassProgram. @@ -1661,7 +1661,7 @@ TEST_F(GLRendererShaderTest, DrawSolidColorShader) { renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); renderer_->DrawFrame( - renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true); + renderer_client_.render_passes_in_draw_order(), NULL, 1.f, true, false); TestSolidColorProgramAA(); } @@ -1745,7 +1745,7 @@ class MockOutputSurfaceTest : public testing::Test, public FakeRendererClient { renderer_->DecideRenderPassAllocationsForFrame( *render_passes_in_draw_order()); renderer_->DrawFrame( - render_passes_in_draw_order(), NULL, device_scale_factor, true); + render_passes_in_draw_order(), NULL, device_scale_factor, true, false); } OutputSurfaceMockContext* Context() { diff --git a/cc/output/renderer.h b/cc/output/renderer.h index b3ff65b..b6fd74d 100644 --- a/cc/output/renderer.h +++ b/cc/output/renderer.h @@ -50,7 +50,8 @@ class CC_EXPORT Renderer { virtual void DrawFrame(RenderPassList* render_passes_in_draw_order, ContextProvider* offscreen_context_provider, float device_scale_factor, - bool allow_partial_swap) = 0; + bool allow_partial_swap, + bool disable_picture_quad_image_filtering) = 0; // Waits for rendering to finish. virtual void Finish() = 0; diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index 7165a93..278b30a 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -1520,6 +1520,86 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) { FuzzyPixelOffByOneComparator(true))); } +template<typename TypeParam> bool IsSoftwareRenderer() { + return false; +} + +template<> +bool IsSoftwareRenderer<SoftwareRenderer>() { + return true; +} + +template<> +bool IsSoftwareRenderer<SoftwareRendererWithExpandedViewport>() { + return true; +} + +// If we disable image filtering, then a 2x2 bitmap should appear as four +// huge sharp squares. +TYPED_TEST(RendererPixelTest, PictureDrawQuadDisableImageFiltering) { + // We only care about this in software mode since bilinear filtering is + // cheap in hardware. + if (!IsSoftwareRenderer<TypeParam>()) + return; + + gfx::Size pile_tile_size(1000, 1000); + gfx::Rect viewport(this->device_viewport_size_); + bool use_skia_gpu_backend = this->UseSkiaGPUBackend(); + ResourceFormat texture_format = RGBA_8888; + + RenderPass::Id id(1, 1); + gfx::Transform transform_to_root; + scoped_ptr<RenderPass> pass = + CreateTestRenderPass(id, viewport, transform_to_root); + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); + bitmap.allocPixels(); + { + SkAutoLockPixels lock(bitmap); + SkCanvas canvas(bitmap); + canvas.drawPoint(0, 0, SK_ColorGREEN); + canvas.drawPoint(0, 1, SK_ColorBLUE); + canvas.drawPoint(1, 0, SK_ColorBLUE); + canvas.drawPoint(1, 1, SK_ColorGREEN); + } + + scoped_refptr<FakePicturePileImpl> pile = + FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size()); + SkPaint paint; + paint.setFilterLevel(SkPaint::kLow_FilterLevel); + pile->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint); + pile->RerecordPile(); + + gfx::Transform content_to_target_transform; + scoped_ptr<SharedQuadState> shared_state = + CreateTestSharedQuadState(content_to_target_transform, viewport); + + scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create(); + quad->SetNew(shared_state.get(), + viewport, + gfx::Rect(), + gfx::RectF(0, 0, 2, 2), + viewport.size(), + texture_format, + viewport, + 1.f, + use_skia_gpu_backend, + pile); + pass->quad_list.push_back(quad.PassAs<DrawQuad>()); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + this->disable_picture_quad_image_filtering_ = true; + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + PixelTest::NoOffscreenContext, + base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")), + ExactPixelComparator(true))); +} + TYPED_TEST(RendererPixelTestWithSkiaGPUBackend, PictureDrawQuadNonIdentityScale) { gfx::Size pile_tile_size(1000, 1000); diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index 86d35c6..4457607 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc @@ -324,7 +324,8 @@ void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame, // cases and fall back to a persistent bitmap backing // (http://crbug.com/280374). skia::RefPtr<SkDrawFilter> opacity_filter = - skia::AdoptRef(new skia::OpacityDrawFilter(quad->opacity(), true)); + skia::AdoptRef(new skia::OpacityDrawFilter( + quad->opacity(), frame->disable_picture_quad_image_filtering)); DCHECK(!current_canvas_->getDrawFilter()); current_canvas_->setDrawFilter(opacity_filter.get()); diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc index 03f1635..f88a9ee 100644 --- a/cc/output/software_renderer_unittest.cc +++ b/cc/output/software_renderer_unittest.cc @@ -98,7 +98,7 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) { list.push_back(root_render_pass.PassAs<RenderPass>()); float device_scale_factor = 1.f; - renderer()->DrawFrame(&list, NULL, device_scale_factor, true); + renderer()->DrawFrame(&list, NULL, device_scale_factor, true, false); SkBitmap output; output.setConfig(SkBitmap::kARGB_8888_Config, @@ -191,7 +191,7 @@ TEST_F(SoftwareRendererTest, TileQuad) { list.push_back(root_render_pass.PassAs<RenderPass>()); float device_scale_factor = 1.f; - renderer()->DrawFrame(&list, NULL, device_scale_factor, true); + renderer()->DrawFrame(&list, NULL, device_scale_factor, true, false); SkBitmap output; output.setConfig(SkBitmap::kARGB_8888_Config, @@ -262,7 +262,7 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) { list.push_back(root_render_pass.PassAs<RenderPass>()); float device_scale_factor = 1.f; - renderer()->DrawFrame(&list, NULL, device_scale_factor, true); + renderer()->DrawFrame(&list, NULL, device_scale_factor, true, false); SkBitmap output; output.setConfig(SkBitmap::kARGB_8888_Config, @@ -314,7 +314,7 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) { AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN); renderer()->DecideRenderPassAllocationsForFrame(list); - renderer()->DrawFrame(&list, NULL, device_scale_factor, true); + renderer()->DrawFrame(&list, NULL, device_scale_factor, true, false); renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect); EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0)); @@ -333,7 +333,7 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) { AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA); renderer()->DecideRenderPassAllocationsForFrame(list); - renderer()->DrawFrame(&list, NULL, device_scale_factor, true); + renderer()->DrawFrame(&list, NULL, device_scale_factor, true, false); renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect); // If we didn't clear, the borders should still be green. @@ -380,7 +380,7 @@ TEST_F(SoftwareRendererTest, RenderPassVisibleRect) { root_clear_pass->quad_list[0]->visible_rect = interior_visible_rect; renderer()->DecideRenderPassAllocationsForFrame(list); - renderer()->DrawFrame(&list, NULL, device_scale_factor, true); + renderer()->DrawFrame(&list, NULL, device_scale_factor, true, false); renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect); EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0)); diff --git a/cc/resources/picture_pile_impl_unittest.cc b/cc/resources/picture_pile_impl_unittest.cc index ed3307e..53b2068 100644 --- a/cc/resources/picture_pile_impl_unittest.cc +++ b/cc/resources/picture_pile_impl_unittest.cc @@ -671,9 +671,10 @@ TEST(PicturePileImplTest, PixelRefIteratorMultiplePictures) { for (int x = 0; x < 2; ++x) { if (x == 0 && y == 1) continue; + SkPaint paint; content_layer_clients[y][x].add_draw_bitmap( lazy_bitmap[y][x], - gfx::Point(x * 128 + 10, y * 128 + 10)); + gfx::Point(x * 128 + 10, y * 128 + 10), paint); pictures[y][x] = Picture::Create( gfx::Rect(x * 128 + 10, y * 128 + 10, 64, 64)); pictures[y][x]->Record( diff --git a/cc/resources/picture_unittest.cc b/cc/resources/picture_unittest.cc index e7f632f..e07b0a8 100644 --- a/cc/resources/picture_unittest.cc +++ b/cc/resources/picture_unittest.cc @@ -127,9 +127,10 @@ TEST(PictureTest, PixelRefIterator) { for (int x = 0; x < 4; ++x) { if ((x + y) & 1) { CreateBitmap(gfx::Size(500, 500), "lazy", &lazy_bitmap[y][x]); + SkPaint paint; content_layer_client.add_draw_bitmap( lazy_bitmap[y][x], - gfx::Point(x * 512 + 6, y * 512 + 6)); + gfx::Point(x * 512 + 6, y * 512 + 6), paint); } } } @@ -224,9 +225,10 @@ TEST(PictureTest, PixelRefIteratorNonZeroLayer) { for (int x = 0; x < 4; ++x) { if ((x + y) & 1) { CreateBitmap(gfx::Size(500, 500), "lazy", &lazy_bitmap[y][x]); + SkPaint paint; content_layer_client.add_draw_bitmap( lazy_bitmap[y][x], - gfx::Point(1024 + x * 512 + 6, y * 512 + 6)); + gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint); } } } @@ -345,9 +347,10 @@ TEST(PictureTest, PixelRefIteratorOnePixelQuery) { for (int x = 0; x < 4; ++x) { if ((x + y) & 1) { CreateBitmap(gfx::Size(500, 500), "lazy", &lazy_bitmap[y][x]); + SkPaint paint; content_layer_client.add_draw_bitmap( lazy_bitmap[y][x], - gfx::Point(x * 512 + 6, y * 512 + 6)); + gfx::Point(x * 512 + 6, y * 512 + 6), paint); } } } diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc index 16033b7..af70c0c 100644 --- a/cc/test/fake_content_layer_client.cc +++ b/cc/test/fake_content_layer_client.cc @@ -35,7 +35,7 @@ void FakeContentLayerClient::PaintContents(SkCanvas* canvas, for (BitmapVector::const_iterator it = draw_bitmaps_.begin(); it != draw_bitmaps_.end(); ++it) { - canvas->drawBitmap(it->first, it->second.x(), it->second.y()); + canvas->drawBitmap(it->bitmap, it->point.x(), it->point.y(), &it->paint); } } diff --git a/cc/test/fake_content_layer_client.h b/cc/test/fake_content_layer_client.h index ff42855..6afa5b6 100644 --- a/cc/test/fake_content_layer_client.h +++ b/cc/test/fake_content_layer_client.h @@ -18,6 +18,12 @@ namespace cc { class FakeContentLayerClient : public cc::ContentLayerClient { public: + struct BitmapData { + SkBitmap bitmap; + gfx::Point point; + SkPaint paint; + }; + FakeContentLayerClient(); virtual ~FakeContentLayerClient(); @@ -32,13 +38,19 @@ class FakeContentLayerClient : public cc::ContentLayerClient { draw_rects_.push_back(std::make_pair(rect, paint)); } - void add_draw_bitmap(const SkBitmap& bitmap, gfx::Point point) { - draw_bitmaps_.push_back(std::make_pair(bitmap, point)); + void add_draw_bitmap(const SkBitmap& bitmap, + gfx::Point point, + const SkPaint& paint) { + BitmapData data; + data.bitmap = bitmap; + data.point = point; + data.paint = paint; + draw_bitmaps_.push_back(data); } private: typedef std::vector<std::pair<gfx::RectF, SkPaint> > RectPaintVector; - typedef std::vector<std::pair<SkBitmap, gfx::Point> > BitmapVector; + typedef std::vector<BitmapData> BitmapVector; bool paint_all_opaque_; RectPaintVector draw_rects_; diff --git a/cc/test/fake_picture_pile_impl.h b/cc/test/fake_picture_pile_impl.h index 1b35ecfc..770dffe4e 100644 --- a/cc/test/fake_picture_pile_impl.h +++ b/cc/test/fake_picture_pile_impl.h @@ -39,13 +39,19 @@ class FakePicturePileImpl : public PicturePileImpl { } void add_draw_bitmap(const SkBitmap& bitmap, gfx::Point point) { - client_.add_draw_bitmap(bitmap, point); + client_.add_draw_bitmap(bitmap, point, default_paint_); } void add_draw_rect_with_paint(const gfx::RectF& rect, const SkPaint& paint) { client_.add_draw_rect(rect, paint); } + void add_draw_bitmap_with_paint(const SkBitmap& bitmap, + gfx::Point point, + const SkPaint& paint) { + client_.add_draw_bitmap(bitmap, point, paint); + } + void set_default_paint(const SkPaint& paint) { default_paint_ = paint; } diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index 864af4e..05688b1 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc @@ -72,6 +72,7 @@ class PixelTest::PixelTestRendererClient PixelTest::PixelTest() : device_viewport_size_(gfx::Size(200, 200)), + disable_picture_quad_image_filtering_(false), fake_client_( new PixelTestRendererClient(gfx::Rect(device_viewport_size_))) {} @@ -119,7 +120,8 @@ bool PixelTest::RunPixelTestWithReadbackTarget( renderer_->DrawFrame(pass_list, offscreen_contexts.get(), device_scale_factor, - allow_partial_swap); + allow_partial_swap, + disable_picture_quad_image_filtering_); // Wait for the readback to complete. resource_provider_->Finish(); diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h index 6ff1762..7b5829d 100644 --- a/cc/test/pixel_test.h +++ b/cc/test/pixel_test.h @@ -44,6 +44,7 @@ class PixelTest : public testing::Test { LayerTreeSettings settings_; gfx::Size device_viewport_size_; + bool disable_picture_quad_image_filtering_; class PixelTestRendererClient; scoped_ptr<OutputSurface> output_surface_; scoped_ptr<ResourceProvider> resource_provider_; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index c2cb28d..fc8c75f 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -1329,11 +1329,14 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame, if (output_surface_->ForcedDrawToSoftwareDevice()) { bool allow_partial_swap = false; + bool disable_picture_quad_image_filtering = + IsCurrentlyScrolling() || needs_animate_layers(); scoped_ptr<SoftwareRenderer> temp_software_renderer = SoftwareRenderer::Create(this, &settings_, output_surface_.get(), NULL); temp_software_renderer->DrawFrame( - &frame->render_passes, NULL, device_scale_factor_, allow_partial_swap); + &frame->render_passes, NULL, device_scale_factor_, allow_partial_swap, + disable_picture_quad_image_filtering); } else { // We don't track damage on the HUD layer (it interacts with damage tracking // visualizations), so disable partial swaps to make the HUD layer display @@ -1343,7 +1346,8 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame, renderer_->DrawFrame(&frame->render_passes, offscreen_context_provider_.get(), device_scale_factor_, - allow_partial_swap); + allow_partial_swap, + false); } // The render passes should be consumed by the renderer. DCHECK(frame->render_passes.empty()); @@ -1448,6 +1452,11 @@ LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const { return active_tree_->CurrentlyScrollingLayer(); } +bool LayerTreeHostImpl::IsCurrentlyScrolling() const { + return CurrentlyScrollingLayer() || + (RootScrollLayer() && RootScrollLayer()->IsExternalFlingActive()); +} + // Content layers can be either directly scrollable or contained in an outer // scrolling layer which applies the scroll transform. Given a content layer, // this function returns the associated scroll layer if any. diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index b725ef4..4868774 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -282,6 +282,8 @@ class CC_EXPORT LayerTreeHostImpl return scroll_layer_id_when_mouse_over_scrollbar_; } + bool IsCurrentlyScrolling() const; + virtual void SetVisible(bool visible); bool visible() const { return visible_; } diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index ae2dfe8..23a0378 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -2449,6 +2449,8 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { return getter_return_value_; } + virtual bool IsExternalFlingActive() const OVERRIDE { return false; } + virtual void SetPageScaleFactor(float page_scale_factor) OVERRIDE { page_scale_factor_ = page_scale_factor; } diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index f409762..e184564 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -1494,7 +1494,7 @@ void ThreadProxy::RenewTreePriority() { DCHECK(IsImplThread()); bool smoothness_takes_priority = layer_tree_host_impl_->pinch_gesture_active() || - layer_tree_host_impl_->CurrentlyScrollingLayer() || + layer_tree_host_impl_->IsCurrentlyScrolling() || layer_tree_host_impl_->page_scale_animation_active(); base::TimeTicks now = layer_tree_host_impl_->CurrentPhysicalTimeTicks(); |