diff options
author | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-21 21:31:44 +0000 |
---|---|---|
committer | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-21 21:31:44 +0000 |
commit | bec08429286ff70c2ce5514ba44c8058fc058a27 (patch) | |
tree | d3f04253d5ba58348f533386fa352203e1650b41 | |
parent | 2fccd420c7523d8379367cc1c8a3fc962b4babe1 (diff) | |
download | chromium_src-bec08429286ff70c2ce5514ba44c8058fc058a27.zip chromium_src-bec08429286ff70c2ce5514ba44c8058fc058a27.tar.gz chromium_src-bec08429286ff70c2ce5514ba44c8058fc058a27.tar.bz2 |
Add flag for drawing layers to screen with Ganesh
The --force-direct-layer-drawing flag causes any layer that could be
drawn direct to the backbuffer to be drawn to the backbuffer using
Ganesh. This flag also requires both the --enable-threaded-compositing
flag and the --enable-impl-side-painting flag to have any effect.
This patch also turns on testing for PictureDrawQuad using Ganesh in the
cc pixeltests.
BUG=none
Review URL: https://chromiumcodereview.appspot.com/13863015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@201362 0039d316-1c4b-4281-b951-d872f2087c98
35 files changed, 453 insertions, 124 deletions
diff --git a/cc/base/switches.cc b/cc/base/switches.cc index bc502e1..e24c72a 100644 --- a/cc/base/switches.cc +++ b/cc/base/switches.cc @@ -35,6 +35,11 @@ const char kEnableRightAlignedScheduling[] = "enable-right-aligned-scheduling"; const char kEnableTopControlsPositionCalculation[] = "enable-top-controls-position-calculation"; +// For any layers that can get drawn directly to screen, draw them with the Skia +// GPU backend. Only valid with gl rendering + threaded compositing + impl-side +// painting. +const char kForceDirectLayerDrawing[] = "force-direct-layer-drawing"; + // The height of the movable top controls. const char kTopControlsHeight[] = "top-controls-height"; diff --git a/cc/base/switches.h b/cc/base/switches.h index 28eaf1d..7b06597 100644 --- a/cc/base/switches.h +++ b/cc/base/switches.h @@ -24,6 +24,7 @@ CC_EXPORT extern const char kEnableCompositorFrameMessage[]; CC_EXPORT extern const char kEnableImplSidePainting[]; CC_EXPORT extern const char kEnableRightAlignedScheduling[]; CC_EXPORT extern const char kEnableTopControlsPositionCalculation[]; +CC_EXPORT extern const char kForceDirectLayerDrawing[]; CC_EXPORT extern const char kJankInsteadOfCheckerboard[]; CC_EXPORT extern const char kNumRasterThreads[]; CC_EXPORT extern const char kTopControlsHeight[]; diff --git a/cc/debug/debug_colors.cc b/cc/debug/debug_colors.cc index cc22297..bb0514c 100644 --- a/cc/debug/debug_colors.cc +++ b/cc/debug/debug_colors.cc @@ -136,6 +136,14 @@ int DebugColors::PictureTileBorderWidth(const LayerTreeImpl* tree_impl) { return Scale(1, tree_impl); } +// Direct picture borders are chartreuse. +SkColor DebugColors::DirectPictureBorderColor() { + return SkColorSetARGB(255, 127, 255, 0); +} +int DebugColors::DirectPictureBorderWidth(const LayerTreeImpl* tree_impl) { + return Scale(1, tree_impl); +} + // ======= Checkerboard colors ======= // Non-debug checkerboards are grey. diff --git a/cc/debug/debug_colors.h b/cc/debug/debug_colors.h index 51be76f..407aa65 100644 --- a/cc/debug/debug_colors.h +++ b/cc/debug/debug_colors.h @@ -59,6 +59,9 @@ class DebugColors { static SkColor PictureTileBorderColor(); static int PictureTileBorderWidth(const LayerTreeImpl* tree_impl); + static SkColor DirectPictureBorderColor(); + static int DirectPictureBorderWidth(const LayerTreeImpl* tree_impl); + static SkColor DefaultCheckerboardColor(); static SkColor EvictedTileCheckerboardColor(); static SkColor InvalidatedTileCheckerboardColor(); diff --git a/cc/layers/draw_properties.h b/cc/layers/draw_properties.h index ad598bc..c9bd90c 100644 --- a/cc/layers/draw_properties.h +++ b/cc/layers/draw_properties.h @@ -27,7 +27,8 @@ struct CC_EXPORT DrawProperties { contents_scale_x(1.f), contents_scale_y(1.f), num_descendants_that_draw_content(0), - descendants_can_clip_selves(false) {} + descendants_can_clip_selves(false), + can_draw_directly_to_backbuffer(false) {} // Transforms objects from content space to target surface space, where // this layer would be drawn. @@ -89,6 +90,8 @@ struct CC_EXPORT DrawProperties { // If true, every descendant in the sub-tree can clip itself without the // need to use hardware sissoring or a new render target. bool descendants_can_clip_selves; + + bool can_draw_directly_to_backbuffer; }; } // namespace cc diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 6ad5a68..916124a 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -194,12 +194,20 @@ void LayerImpl::AppendDebugBorderQuad( QuadSink* quad_sink, const SharedQuadState* shared_quad_state, AppendQuadsData* append_quads_data) const { - if (!ShowDebugBorders()) - return; - SkColor color; float width; GetDebugBorderProperties(&color, &width); + AppendDebugBorderQuad( + quad_sink, shared_quad_state, append_quads_data, color, width); +} + +void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink, + const SharedQuadState* shared_quad_state, + AppendQuadsData* append_quads_data, + SkColor color, + float width) const { + if (!ShowDebugBorders()) + return; gfx::Rect content_rect(content_bounds()); scoped_ptr<DebugBorderDrawQuad> debug_border_quad = diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index a8f7f1b..6e64b3f 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -424,6 +424,11 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver { void AppendDebugBorderQuad(QuadSink* quad_sink, const SharedQuadState* shared_quad_state, AppendQuadsData* append_quads_data) const; + void AppendDebugBorderQuad(QuadSink* quad_sink, + const SharedQuadState* shared_quad_state, + AppendQuadsData* append_quads_data, + SkColor color, + float width) const; virtual void DumpLayerProperties(std::string* str, int indent) const; static std::string IndentString(int indent); diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index f2b5e54..c1d5ee4 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc @@ -112,9 +112,19 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, SharedQuadState* shared_quad_state = quad_sink->UseSharedQuadState(CreateSharedQuadState()); - AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); - if (!append_quads_data->allow_tile_draw_quads) { + bool draw_direct_to_backbuffer = + draw_properties().can_draw_directly_to_backbuffer && + layer_tree_impl()->settings().force_direct_layer_drawing; + + if (draw_direct_to_backbuffer || !append_quads_data->allow_tile_draw_quads) { + AppendDebugBorderQuad( + quad_sink, + shared_quad_state, + append_quads_data, + DebugColors::DirectPictureBorderColor(), + DebugColors::DirectPictureBorderWidth(layer_tree_impl())); + gfx::Rect geometry_rect = rect; gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); gfx::Size texture_size = rect.size(); @@ -131,12 +141,15 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, false, quad_content_rect, contents_scale, + draw_direct_to_backbuffer, pile_); if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data)) append_quads_data->num_missing_tiles++; return; } + AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); + bool clipped = false; gfx::QuadF target_quad = MathUtil::MapQuad( draw_transform(), @@ -264,6 +277,7 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, tile_version.contents_swizzled(), iter->content_rect(), iter->contents_scale(), + draw_direct_to_backbuffer, pile_); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); break; @@ -370,8 +384,17 @@ void PictureLayerImpl::CalculateContentsScale( float* contents_scale_x, float* contents_scale_y, gfx::Size* content_bounds) { - if (!DrawsContent()) { - DCHECK(!tilings_->num_tilings()); + if (!CanHaveTilings()) { + ideal_page_scale_ = page_scale_factor; + ideal_device_scale_ = device_scale_factor; + ideal_contents_scale_ = ideal_contents_scale; + ideal_source_scale_ = + ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_; + *contents_scale_x = ideal_contents_scale_; + *contents_scale_y = ideal_contents_scale_; + *content_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), + ideal_contents_scale_, + ideal_contents_scale_)); return; } @@ -714,9 +737,7 @@ void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) { DCHECK(ideal_page_scale_); DCHECK(ideal_device_scale_); DCHECK(ideal_source_scale_); - - if (!CanHaveTilings()) - return; + DCHECK(CanHaveTilings()); bool change_target_tiling = raster_page_scale_ == 0.f || @@ -942,6 +963,9 @@ bool PictureLayerImpl::CanHaveTilings() const { return false; if (!layer_tree_impl()->tile_manager()) return false; + if (draw_properties().can_draw_directly_to_backbuffer && + layer_tree_impl()->settings().force_direct_layer_drawing) + return false; return true; } diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index e6cb0f5..d67ea46 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -168,19 +168,15 @@ class PictureLayerImplTest : public testing::Test { std::vector<SkRect>::const_iterator rect_iter = rects.begin(); for (tile_iter = tiles.begin(); tile_iter < tiles.end(); tile_iter++) { MockCanvas mock_canvas(&device); - active_pile->Raster(&mock_canvas, - (*tile_iter)->content_rect(), - 1.0f, - NULL); + active_pile->RasterDirect( + &mock_canvas, (*tile_iter)->content_rect(), 1.0f, NULL); // This test verifies that when drawing the contents of a specific tile // at content scale 1.0, the playback canvas never receives content from // neighboring tiles which indicates that the tile grid embedded in // SkPicture is perfectly aligned with the compositor's tiles. - // Note: There are two rects: the initial clear and the explicitly - // recorded rect. We only care about the second one. - EXPECT_EQ(2u, mock_canvas.rects_.size()); - EXPECT_RECT_EQ(*rect_iter, mock_canvas.rects_[1]); + EXPECT_EQ(1u, mock_canvas.rects_.size()); + EXPECT_RECT_EQ(*rect_iter, mock_canvas.rects_[0]); rect_iter++; } } diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index b3d51ee..b151e36 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -42,10 +42,12 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColorFilter.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/GrTexture.h" #include "third_party/skia/include/gpu/SkGpuDevice.h" #include "third_party/skia/include/gpu/SkGrTexturePixelRef.h" +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" #include "ui/gfx/quad_f.h" #include "ui/gfx/rect_conversions.h" @@ -103,11 +105,17 @@ struct GLRenderer::PendingAsyncReadPixels { scoped_ptr<GLRenderer> GLRenderer::Create(RendererClient* client, OutputSurface* output_surface, ResourceProvider* resource_provider, - int highp_threshold_min) { + int highp_threshold_min, + bool use_skia_gpu_backend) { scoped_ptr<GLRenderer> renderer(new GLRenderer( client, output_surface, resource_provider, highp_threshold_min)); if (!renderer->Initialize()) return scoped_ptr<GLRenderer>(); + if (use_skia_gpu_backend) { + renderer->InitializeGrContext(); + DCHECK(renderer->CanUseSkiaGPUBackend()) + << "Requested Skia GPU backend, but can't use it."; + } return renderer.Pass(); } @@ -193,10 +201,6 @@ bool GLRenderer::Initialize() { is_using_bind_uniform_ = extensions.count("GL_CHROMIUM_bind_uniform_location") > 0; - // Make sure scissoring starts as disabled. - GLC(context_, context_->disable(GL_SCISSOR_TEST)); - DCHECK(!is_scissor_enabled_); - if (!InitializeSharedObjects()) return false; @@ -205,6 +209,18 @@ bool GLRenderer::Initialize() { return true; } +void GLRenderer::InitializeGrContext() { + skia::RefPtr<GrGLInterface> interface = skia::AdoptRef( + context_->createGrGLInterface()); + if (!interface) + return; + + gr_context_ = skia::AdoptRef(GrContext::Create( + kOpenGL_GrBackend, + reinterpret_cast<GrBackendContext>(interface.get()))); + ReinitializeGrCanvas(); +} + GLRenderer::~GLRenderer() { while (!pending_async_read_pixels_.empty()) { pending_async_read_pixels_.back()->finished_read_pixels_callback.Cancel(); @@ -261,7 +277,10 @@ void GLRenderer::SendManagedMemoryStats(size_t bytes_visible, void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); } -void GLRenderer::ViewportChanged() { is_viewport_changed_ = true; } +void GLRenderer::ViewportChanged() { + is_viewport_changed_ = true; + ReinitializeGrCanvas(); +} void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { // On DEBUG builds, opaque render passes are cleared to blue to easily see @@ -271,10 +290,18 @@ void GLRenderer::ClearFramebuffer(DrawingFrame* frame) { else GLC(context_, context_->clearColor(0, 0, 1, 1)); -#ifdef NDEBUG - if (frame->current_render_pass->has_transparent_background) + bool always_clear = false; +#ifndef NDEBUG + always_clear = true; #endif - context_->clear(GL_COLOR_BUFFER_BIT); + if (always_clear || frame->current_render_pass->has_transparent_background) { + GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; + // Only the Skia GPU backend uses the stencil buffer. No need to clear it + // otherwise. + if (CanUseSkiaGPUBackend()) + clear_bits |= GL_STENCIL_BUFFER_BIT; + context_->clear(clear_bits); + } } void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { @@ -294,17 +321,8 @@ void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { } MakeContextCurrent(); - // Bind the common vertex attributes used for drawing all the layers. - shared_geometry_->PrepareForDraw(); - GLC(context_, context_->disable(GL_DEPTH_TEST)); - GLC(context_, context_->disable(GL_CULL_FACE)); - GLC(context_, context_->colorMask(true, true, true, true)); - GLC(context_, context_->enable(GL_BLEND)); - blend_shadow_ = true; - GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); - GLC(Context(), Context()->activeTexture(GL_TEXTURE0)); - program_shadow_ = 0; + ReinitializeGLState(); } void GLRenderer::DoNoOp() { @@ -1467,8 +1485,57 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame, program->vertex_shader().matrix_location()); } +void GLRenderer::DrawPictureQuadDirectToBackbuffer( + const DrawingFrame* frame, + const PictureDrawQuad* quad) { + DCHECK(CanUseSkiaGPUBackend()); + DCHECK_EQ(quad->opacity(), 1.f) << "Need to composite to a bitmap or a " + "render surface for non-1 opacity quads"; + + // TODO(enne): This should be done more lazily / efficiently. + gr_context_->resetContext(); + + // Reset the canvas matrix to identity because the clip rect is in target + // space. + SkMatrix sk_identity; + sk_identity.setIdentity(); + sk_canvas_->setMatrix(sk_identity); + + if (is_scissor_enabled_) { + sk_canvas_->clipRect(gfx::RectToSkRect(scissor_rect_), + SkRegion::kReplace_Op); + } else { + sk_canvas_->clipRect(gfx::RectToSkRect(gfx::Rect(ViewportSize())), + SkRegion::kReplace_Op); + } + + gfx::Transform contents_device_transform = frame->window_matrix * + frame->projection_matrix * quad->quadTransform(); + contents_device_transform.Translate(quad->rect.x(), + quad->rect.y()); + contents_device_transform.FlattenTo2d(); + SkMatrix sk_device_matrix; + gfx::TransformToFlattenedSkMatrix(contents_device_transform, + &sk_device_matrix); + sk_canvas_->setMatrix(sk_device_matrix); + + quad->picture_pile->RasterDirect( + sk_canvas_.get(), quad->content_rect, quad->contents_scale, NULL); + + // Flush any drawing buffers that have been deferred. + sk_canvas_->flush(); + + // TODO(enne): This should be done more lazily / efficiently. + ReinitializeGLState(); +} + void GLRenderer::DrawPictureQuad(const DrawingFrame* frame, const PictureDrawQuad* quad) { + if (quad->can_draw_direct_to_backbuffer && CanUseSkiaGPUBackend()) { + DrawPictureQuadDirectToBackbuffer(frame, quad); + return; + } + if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() || on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) { on_demand_tile_raster_bitmap_.setConfig( @@ -1490,8 +1557,8 @@ void GLRenderer::DrawPictureQuad(const DrawingFrame* frame, SkDevice device(on_demand_tile_raster_bitmap_); SkCanvas canvas(&device); - quad->picture_pile->Raster(&canvas, quad->content_rect, quad->contents_scale, - NULL); + quad->picture_pile->RasterToBitmap(&canvas, quad->content_rect, + quad->contents_scale, NULL); resource_provider_->SetPixels( on_demand_tile_raster_resource_id_, @@ -2798,6 +2865,51 @@ void GLRenderer::CleanupSharedObjects() { ReleaseRenderPassTextures(); } +void GLRenderer::ReinitializeGrCanvas() { + if (!CanUseSkiaGPUBackend()) + return; + + GrBackendRenderTargetDesc desc; + desc.fWidth = ViewportWidth(); + desc.fHeight = ViewportHeight(); + desc.fConfig = kRGBA_8888_GrPixelConfig; + desc.fOrigin = kTopLeft_GrSurfaceOrigin; + desc.fSampleCnt = 1; + desc.fStencilBits = 8; + desc.fRenderTargetHandle = 0; + + skia::RefPtr<GrSurface> surface( + skia::AdoptRef(gr_context_->wrapBackendRenderTarget(desc))); + skia::RefPtr<SkDevice> device( + skia::AdoptRef(SkGpuDevice::Create(surface.get()))); + sk_canvas_ = skia::AdoptRef(new SkCanvas(device.get())); +} + +void GLRenderer::ReinitializeGLState() { + // Bind the common vertex attributes used for drawing all the layers. + shared_geometry_->PrepareForDraw(); + + GLC(context_, context_->disable(GL_STENCIL_TEST)); + GLC(context_, context_->disable(GL_DEPTH_TEST)); + GLC(context_, context_->disable(GL_CULL_FACE)); + GLC(context_, context_->colorMask(true, true, true, true)); + GLC(context_, context_->enable(GL_BLEND)); + blend_shadow_ = true; + GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); + GLC(context_, context_->activeTexture(GL_TEXTURE0)); + program_shadow_ = 0; + + // Make sure scissoring starts as disabled. + is_scissor_enabled_ = false; + GLC(context_, context_->disable(GL_SCISSOR_TEST)); +} + +bool GLRenderer::CanUseSkiaGPUBackend() const { + // The Skia GPU backend requires a stencil buffer. See ReinitializeGrCanvas + // implementation. + return gr_context_ && context_->getContextAttributes().stencil; +} + bool GLRenderer::IsContextLost() { return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR); } diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h index c83169d..b81ae04 100644 --- a/cc/output/gl_renderer.h +++ b/cc/output/gl_renderer.h @@ -45,7 +45,8 @@ class CC_EXPORT GLRenderer static scoped_ptr<GLRenderer> Create(RendererClient* client, OutputSurface* output_surface, ResourceProvider* resource_provider, - int highp_threshold_min); + int highp_threshold_min, + bool use_skia_gpu_backend); virtual ~GLRenderer(); @@ -77,6 +78,8 @@ class CC_EXPORT GLRenderer const char* file, int line); + bool CanUseSkiaGPUBackend() const; + protected: GLRenderer(RendererClient* client, OutputSurface* output_surface, @@ -85,6 +88,7 @@ class CC_EXPORT GLRenderer bool IsBackbufferDiscarded() const { return is_backbuffer_discarded_; } bool Initialize(); + void InitializeGrContext(); const gfx::QuadF& SharedGeometryQuad() const { return shared_geometry_quad_; } const GeometryBinding* SharedGeometry() const { @@ -151,6 +155,8 @@ class CC_EXPORT GLRenderer const YUVVideoDrawQuad* quad); void DrawPictureQuad(const DrawingFrame* frame, const PictureDrawQuad* quad); + void DrawPictureQuadDirectToBackbuffer(const DrawingFrame* frame, + const PictureDrawQuad* quad); void SetShaderOpacity(float opacity, int alpha_location); void SetShaderQuadF(const gfx::QuadF& quad, int quad_location); @@ -206,6 +212,9 @@ class CC_EXPORT GLRenderer const CopyRenderPassCallback& callback, bool success); + void ReinitializeGrCanvas(); + void ReinitializeGLState(); + // WebKit:: // WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM // implementation. @@ -392,6 +401,9 @@ class CC_EXPORT GLRenderer OutputSurface* output_surface_; WebKit::WebGraphicsContext3D* context_; + skia::RefPtr<GrContext> gr_context_; + skia::RefPtr<SkCanvas> sk_canvas_; + gfx::Rect swap_buffer_rect_; gfx::Rect scissor_rect_; bool is_viewport_changed_; diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index 060a284..d479e5f 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -97,6 +97,16 @@ scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad( typedef ::testing::Types<GLRenderer, SoftwareRenderer> RendererTypes; TYPED_TEST_CASE(RendererPixelTest, RendererTypes); +typedef ::testing::Types<GLRenderer, + GLRendererWithSkiaGPUBackend, + SoftwareRenderer> RendererTypesWithSkiaGPUBackend; +template <typename RendererType> +class RendererPixelTestWithSkiaGPUBackend + : public RendererPixelTest<RendererType> { +}; +TYPED_TEST_CASE(RendererPixelTestWithSkiaGPUBackend, + RendererTypesWithSkiaGPUBackend); + // All pixels can be off by one, but any more than that is an error. class FuzzyPixelOffByOneComparator : public FuzzyPixelComparator { public: @@ -119,17 +129,17 @@ class FuzzyForSoftwareOnlyPixelComparator : public PixelComparator { }; template<> -bool FuzzyForSoftwareOnlyPixelComparator<GLRenderer>::Compare( +bool FuzzyForSoftwareOnlyPixelComparator<SoftwareRenderer>::Compare( const SkBitmap& actual_bmp, const SkBitmap& expected_bmp) const { - return exact_.Compare(actual_bmp, expected_bmp); + return fuzzy_.Compare(actual_bmp, expected_bmp); } -template<> -bool FuzzyForSoftwareOnlyPixelComparator<SoftwareRenderer>::Compare( +template<typename RendererType> +bool FuzzyForSoftwareOnlyPixelComparator<RendererType>::Compare( const SkBitmap& actual_bmp, const SkBitmap& expected_bmp) const { - return fuzzy_.Compare(actual_bmp, expected_bmp); + return exact_.Compare(actual_bmp, expected_bmp); } #if !defined(OS_ANDROID) @@ -570,8 +580,10 @@ class RendererPixelTestWithBackgroundFilter gfx::Rect filter_pass_content_rect_; }; -typedef ::testing::Types<GLRenderer, SoftwareRenderer> RendererTypes; -TYPED_TEST_CASE(RendererPixelTestWithBackgroundFilter, RendererTypes); +typedef ::testing::Types<GLRenderer, SoftwareRenderer> + BackgroundFilterRendererTypes; +TYPED_TEST_CASE(RendererPixelTestWithBackgroundFilter, + BackgroundFilterRendererTypes); typedef RendererPixelTestWithBackgroundFilter<GLRenderer> GLRendererPixelTestWithBackgroundFilter; @@ -729,9 +741,10 @@ TEST_F(GLRendererPixelTest, ForceAntiAliasingOff) { ExactPixelComparator(false))); } -TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) { +TYPED_TEST(RendererPixelTestWithSkiaGPUBackend, PictureDrawQuadIdentityScale) { gfx::Size pile_tile_size(1000, 1000); gfx::Rect viewport(this->device_viewport_size_); + bool use_skia_gpu_backend = this->UseSkiaGPUBackend(); // TODO(enne): the renderer should figure this out on its own. bool contents_swizzled = !PlatformColor::SameComponentOrder(GL_RGBA); @@ -774,6 +787,7 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) { contents_swizzled, viewport, 1.f, + use_skia_gpu_backend, blue_pile); pass->quad_list.push_back(blue_quad.PassAs<DrawQuad>()); @@ -798,6 +812,7 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) { contents_swizzled, viewport, 1.f, + use_skia_gpu_backend, green_pile); pass->quad_list.push_back(green_quad.PassAs<DrawQuad>()); @@ -810,9 +825,11 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) { ExactPixelComparator(true))); } -TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) { +TYPED_TEST(RendererPixelTestWithSkiaGPUBackend, + PictureDrawQuadNonIdentityScale) { gfx::Size pile_tile_size(1000, 1000); gfx::Rect viewport(this->device_viewport_size_); + bool use_skia_gpu_backend = this->UseSkiaGPUBackend(); // TODO(enne): the renderer should figure this out on its own. bool contents_swizzled = !PlatformColor::SameComponentOrder(GL_RGBA); @@ -851,6 +868,7 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) { contents_swizzled, green_rect1, 1.f, + use_skia_gpu_backend, green_pile); pass->quad_list.push_back(green_quad1.PassAs<DrawQuad>()); @@ -863,6 +881,7 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) { contents_swizzled, green_rect2, 1.f, + use_skia_gpu_backend, green_pile); pass->quad_list.push_back(green_quad2.PassAs<DrawQuad>()); @@ -899,10 +918,13 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) { scoped_refptr<FakePicturePileImpl> pile = FakePicturePileImpl::CreateFilledPile(pile_tile_size, layer_rect.size()); - pile->add_draw_rect_with_paint(layer_rect, red_paint); - SkPaint transparent_paint; - transparent_paint.setXfermodeMode(SkXfermode::kClear_Mode); - pile->add_draw_rect_with_paint(union_layer_rect, transparent_paint); + + Region outside(layer_rect); + outside.Subtract(gfx::ToEnclosingRect(union_layer_rect)); + for (Region::Iterator iter(outside); iter.has_rect(); iter.next()) { + pile->add_draw_rect_with_paint(iter.rect(), red_paint); + } + SkPaint blue_paint; blue_paint.setColor(SK_ColorBLUE); pile->add_draw_rect_with_paint(blue_layer_rect1, blue_paint); @@ -931,6 +953,7 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) { contents_swizzled, content_union_rect, contents_scale, + use_skia_gpu_backend, pile); pass->quad_list.push_back(blue_quad.PassAs<DrawQuad>()); diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index 7dd4a71..3906ea8 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc @@ -31,19 +31,6 @@ namespace cc { namespace { -void ToSkMatrix(SkMatrix* flattened, const gfx::Transform& m) { - // Convert from 4x4 to 3x3 by dropping the third row and column. - flattened->set(0, SkDoubleToScalar(m.matrix().getDouble(0, 0))); - flattened->set(1, SkDoubleToScalar(m.matrix().getDouble(0, 1))); - flattened->set(2, SkDoubleToScalar(m.matrix().getDouble(0, 3))); - flattened->set(3, SkDoubleToScalar(m.matrix().getDouble(1, 0))); - flattened->set(4, SkDoubleToScalar(m.matrix().getDouble(1, 1))); - flattened->set(5, SkDoubleToScalar(m.matrix().getDouble(1, 3))); - flattened->set(6, SkDoubleToScalar(m.matrix().getDouble(3, 0))); - flattened->set(7, SkDoubleToScalar(m.matrix().getDouble(3, 1))); - flattened->set(8, SkDoubleToScalar(m.matrix().getDouble(3, 3))); -} - bool IsScaleAndTranslate(const SkMatrix& matrix) { return SkScalarNearlyZero(matrix[SkMatrix::kMSkewX]) && SkScalarNearlyZero(matrix[SkMatrix::kMSkewY]) && @@ -228,7 +215,8 @@ void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { frame->window_matrix * frame->projection_matrix * quad_rect_matrix; contents_device_transform.FlattenTo2d(); SkMatrix sk_device_matrix; - ToSkMatrix(&sk_device_matrix, contents_device_transform); + gfx::TransformToFlattenedSkMatrix(contents_device_transform, + &sk_device_matrix); current_canvas_->setMatrix(sk_device_matrix); current_paint_.reset(); @@ -309,7 +297,7 @@ void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame, SkDevice temp_device(temp_bitmap); SkCanvas temp_canvas(&temp_device); - quad->picture_pile->Raster( + quad->picture_pile->RasterToBitmap( &temp_canvas, quad->content_rect, quad->contents_scale, NULL); current_paint_.setFilterBitmap(true); @@ -317,7 +305,7 @@ void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame, } else { TRACE_EVENT0("cc", "SoftwareRenderer::DrawPictureQuad direct from PicturePile"); - quad->picture_pile->Raster( + quad->picture_pile->RasterDirect( current_canvas_, quad->content_rect, quad->contents_scale, NULL); } } diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc index 6c02b1a..68873b2 100644 --- a/cc/quads/draw_quad_unittest.cc +++ b/cc/quads/draw_quad_unittest.cc @@ -657,16 +657,18 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) { bool swizzle_contents = true; gfx::Rect content_rect(30, 40, 20, 30); float contents_scale = 3.141592f; + bool can_draw_direct_to_backbuffer = true; scoped_refptr<PicturePileImpl> picture_pile = PicturePileImpl::Create(false); CREATE_SHARED_STATE(); - CREATE_QUAD_7_NEW(PictureDrawQuad, + CREATE_QUAD_8_NEW(PictureDrawQuad, opaque_rect, tex_coord_rect, texture_size, swizzle_contents, content_rect, contents_scale, + can_draw_direct_to_backbuffer, picture_pile); EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material); EXPECT_RECT_EQ(opaque_rect, copy_quad->opaque_rect); @@ -675,14 +677,17 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) { EXPECT_EQ(swizzle_contents, copy_quad->swizzle_contents); EXPECT_RECT_EQ(content_rect, copy_quad->content_rect); EXPECT_EQ(contents_scale, copy_quad->contents_scale); + EXPECT_EQ(can_draw_direct_to_backbuffer, + copy_quad->can_draw_direct_to_backbuffer); EXPECT_EQ(picture_pile, copy_quad->picture_pile); - CREATE_QUAD_6_ALL(PictureDrawQuad, + CREATE_QUAD_7_ALL(PictureDrawQuad, tex_coord_rect, texture_size, swizzle_contents, content_rect, contents_scale, + can_draw_direct_to_backbuffer, picture_pile); EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material); EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect); @@ -690,6 +695,8 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) { EXPECT_EQ(swizzle_contents, copy_quad->swizzle_contents); EXPECT_RECT_EQ(content_rect, copy_quad->content_rect); EXPECT_EQ(contents_scale, copy_quad->contents_scale); + EXPECT_EQ(can_draw_direct_to_backbuffer, + copy_quad->can_draw_direct_to_backbuffer); EXPECT_EQ(picture_pile, copy_quad->picture_pile); } @@ -873,16 +880,18 @@ TEST_F(DrawQuadIteratorTest, DISABLED_PictureDrawQuad) { bool swizzle_contents = true; gfx::Rect content_rect(30, 40, 20, 30); float contents_scale = 3.141592f; + bool can_draw_direct_to_backbuffer = true; scoped_refptr<PicturePileImpl> picture_pile = PicturePileImpl::Create(false); CREATE_SHARED_STATE(); - CREATE_QUAD_7_NEW(PictureDrawQuad, + CREATE_QUAD_8_NEW(PictureDrawQuad, opaque_rect, tex_coord_rect, texture_size, swizzle_contents, content_rect, contents_scale, + can_draw_direct_to_backbuffer, picture_pile); EXPECT_EQ(0, IterateAndCount(quad_new.get())); } diff --git a/cc/quads/picture_draw_quad.cc b/cc/quads/picture_draw_quad.cc index 8fda699..81f7913 100644 --- a/cc/quads/picture_draw_quad.cc +++ b/cc/quads/picture_draw_quad.cc @@ -24,12 +24,14 @@ void PictureDrawQuad::SetNew(const SharedQuadState* shared_quad_state, bool swizzle_contents, gfx::Rect content_rect, float contents_scale, + bool can_draw_direct_to_backbuffer, scoped_refptr<PicturePileImpl> picture_pile) { ContentDrawQuadBase::SetNew(shared_quad_state, DrawQuad::PICTURE_CONTENT, rect, opaque_rect, tex_coord_rect, texture_size, swizzle_contents); this->content_rect = content_rect; this->contents_scale = contents_scale; + this->can_draw_direct_to_backbuffer = can_draw_direct_to_backbuffer; this->picture_pile = picture_pile; } @@ -43,6 +45,7 @@ void PictureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, bool swizzle_contents, gfx::Rect content_rect, float contents_scale, + bool can_draw_direct_to_backbuffer, scoped_refptr<PicturePileImpl> picture_pile) { ContentDrawQuadBase::SetAll(shared_quad_state, DrawQuad::PICTURE_CONTENT, rect, opaque_rect, @@ -50,6 +53,7 @@ void PictureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, texture_size, swizzle_contents); this->content_rect = content_rect; this->contents_scale = contents_scale; + this->can_draw_direct_to_backbuffer = can_draw_direct_to_backbuffer; this->picture_pile = picture_pile; } diff --git a/cc/quads/picture_draw_quad.h b/cc/quads/picture_draw_quad.h index 40e8487..29af6d5 100644 --- a/cc/quads/picture_draw_quad.h +++ b/cc/quads/picture_draw_quad.h @@ -30,6 +30,7 @@ class CC_EXPORT PictureDrawQuad : public ContentDrawQuadBase { bool swizzle_contents, gfx::Rect content_rect, float contents_scale, + bool can_draw_direct_to_backbuffer, scoped_refptr<PicturePileImpl> picture_pile); void SetAll(const SharedQuadState* shared_quad_state, @@ -42,10 +43,12 @@ class CC_EXPORT PictureDrawQuad : public ContentDrawQuadBase { bool swizzle_contents, gfx::Rect content_rect, float contents_scale, + bool can_draw_direct_to_backbuffer, scoped_refptr<PicturePileImpl> picture_pile); gfx::Rect content_rect; float contents_scale; + bool can_draw_direct_to_backbuffer; scoped_refptr<PicturePileImpl> picture_pile; virtual void IterateResources(const ResourceIteratorCallback& callback) diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc index 3794605..748e404 100644 --- a/cc/resources/picture.cc +++ b/cc/resources/picture.cc @@ -253,15 +253,11 @@ void Picture::Record(ContentLayerClient* painter, canvas->translate(SkFloatToScalar(-layer_rect_.x()), SkFloatToScalar(-layer_rect_.y())); - SkPaint paint; - paint.setAntiAlias(false); - paint.setXfermodeMode(SkXfermode::kClear_Mode); SkRect layer_skrect = SkRect::MakeXYWH(layer_rect_.x(), layer_rect_.y(), layer_rect_.width(), layer_rect_.height()); canvas->clipRect(layer_skrect); - canvas->drawRect(layer_skrect, paint); gfx::RectF opaque_layer_rect; base::TimeTicks begin_record_time; diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc index 052e075..ffa0740 100644 --- a/cc/resources/picture_pile_impl.cc +++ b/cc/resources/picture_pile_impl.cc @@ -74,15 +74,13 @@ PicturePileImpl* PicturePileImpl::GetCloneForDrawingOnThread( return clones_for_drawing_.clones_[thread_index]; } -void PicturePileImpl::Raster( +void PicturePileImpl::RasterDirect( SkCanvas* canvas, gfx::Rect canvas_rect, float contents_scale, RasterStats* raster_stats) { - DCHECK(contents_scale >= min_contents_scale_); - canvas->save(); canvas->translate(-canvas_rect.x(), -canvas_rect.y()); gfx::SizeF total_content_size = gfx::ScaleSize(tiling_.total_size(), @@ -91,32 +89,12 @@ void PicturePileImpl::Raster( gfx::Rect content_rect = total_content_rect; content_rect.Intersect(canvas_rect); - // Clear one texel inside the right/bottom edge of the content rect, - // as it may only be partially covered by the picture playback. - // Also clear one texel outside the right/bottom edge of the content rect, - // as it may get blended in by linear filtering when zoomed in. - gfx::Rect deflated_content_rect = total_content_rect; - deflated_content_rect.Inset(0, 0, 1, 1); - - gfx::Rect canvas_outside_content_rect = canvas_rect; - canvas_outside_content_rect.Subtract(deflated_content_rect); - - if (!canvas_outside_content_rect.IsEmpty()) { - gfx::Rect inflated_content_rect = total_content_rect; - inflated_content_rect.Inset(0, 0, -1, -1); - canvas->clipRect(gfx::RectToSkRect(inflated_content_rect), - SkRegion::kReplace_Op); - canvas->clipRect(gfx::RectToSkRect(deflated_content_rect), - SkRegion::kDifference_Op); - canvas->drawColor(background_color_, SkXfermode::kSrc_Mode); - } - // Rasterize the collection of relevant picture piles. gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( content_rect, 1.f / contents_scale); canvas->clipRect(gfx::RectToSkRect(content_rect), - SkRegion::kReplace_Op); + SkRegion::kIntersect_Op); Region unclipped(content_rect); if (raster_stats) { @@ -217,8 +195,57 @@ void PicturePileImpl::Raster( // We should always paint some part of |content_rect|. DCHECK(!unclipped.Contains(content_rect)); +} + +void PicturePileImpl::RasterToBitmap( + SkCanvas* canvas, + gfx::Rect canvas_rect, + float contents_scale, + RasterStats* raster_stats) { + + canvas->save(); + canvas->translate(-canvas_rect.x(), -canvas_rect.y()); + + gfx::SizeF total_content_size = gfx::ScaleSize(tiling_.total_size(), + contents_scale); + gfx::Rect total_content_rect(gfx::ToCeiledSize(total_content_size)); + gfx::Rect content_rect = total_content_rect; + content_rect.Intersect(canvas_rect); + +#ifndef NDEBUG + // Any non-painted areas will be left in this color. + canvas->clear(DebugColors::NonPaintedFillColor()); +#endif // NDEBUG + + // TODO(enne): this needs to be rolled together with the border clear + SkPaint paint; + paint.setAntiAlias(false); + paint.setXfermodeMode(SkXfermode::kClear_Mode); + canvas->drawRect(gfx::RectToSkRect(content_rect), paint); + + // Clear one texel inside the right/bottom edge of the content rect, + // as it may only be partially covered by the picture playback. + // Also clear one texel outside the right/bottom edge of the content rect, + // as it may get blended in by linear filtering when zoomed in. + gfx::Rect deflated_content_rect = total_content_rect; + deflated_content_rect.Inset(0, 0, 1, 1); + + gfx::Rect canvas_outside_content_rect = canvas_rect; + canvas_outside_content_rect.Subtract(deflated_content_rect); + + if (!canvas_outside_content_rect.IsEmpty()) { + gfx::Rect inflated_content_rect = total_content_rect; + inflated_content_rect.Inset(0, 0, -1, -1); + canvas->clipRect(gfx::RectToSkRect(inflated_content_rect), + SkRegion::kReplace_Op); + canvas->clipRect(gfx::RectToSkRect(deflated_content_rect), + SkRegion::kDifference_Op); + canvas->drawColor(background_color_, SkXfermode::kSrc_Mode); + } canvas->restore(); + + RasterDirect(canvas, canvas_rect, contents_scale, raster_stats); } skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() { @@ -234,7 +261,7 @@ skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() { layer_rect.height(), SkPicture::kUsePathBoundsForClip_RecordingFlag); - Raster(canvas, layer_rect, 1.0, NULL); + RasterToBitmap(canvas, layer_rect, 1.0, NULL); picture->endRecording(); return picture; @@ -258,7 +285,7 @@ void PicturePileImpl::AnalyzeInRect(gfx::Rect content_rect, skia::AnalysisDevice device(empty_bitmap); skia::AnalysisCanvas canvas(&device); - Raster(&canvas, layer_rect, 1.0f, NULL); + RasterDirect(&canvas, layer_rect, 1.0f, NULL); analysis->is_solid_color = canvas.getColorIfSolid(&analysis->solid_color); analysis->has_text = canvas.hasText(); diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h index f3bc98c..92c0fb3f 100644 --- a/cc/resources/picture_pile_impl.h +++ b/cc/resources/picture_pile_impl.h @@ -47,7 +47,16 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase { // NULL. When slow-down-raster-scale-factor is set to a value // greater than 1, the reported rasterize time is the minimum // measured value over all runs. - void Raster( + void RasterDirect( + SkCanvas* canvas, + gfx::Rect canvas_rect, + float contents_scale, + RasterStats* raster_stats); + + // Similar to the above RasterDirect method, but this is a convenience method + // for when it is known that the raster is going to an intermediate bitmap + // that itself will then be blended and thus that a canvas clear is required. + void RasterToBitmap( SkCanvas* canvas, gfx::Rect canvas_rect, float contents_scale, diff --git a/cc/resources/picture_pile_impl_unittest.cc b/cc/resources/picture_pile_impl_unittest.cc index 10c859e..5fe7b2f 100644 --- a/cc/resources/picture_pile_impl_unittest.cc +++ b/cc/resources/picture_pile_impl_unittest.cc @@ -131,6 +131,21 @@ TEST(PicturePileImplTest, AnalyzeIsSolidScaled) { EXPECT_EQ(analysis.solid_color, solid_color); } +TEST(PicturePileImplTest, AnalyzeIsSolidEmpty) { + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(400, 400); + + scoped_refptr<FakePicturePileImpl> pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + PicturePileImpl::Analysis analysis; + EXPECT_FALSE(analysis.is_solid_color); + + pile->AnalyzeInRect(gfx::Rect(0, 0, 400, 400), 1.f, &analysis); + + EXPECT_TRUE(analysis.is_solid_color); + EXPECT_EQ(analysis.solid_color, SkColorSetARGB(0, 0, 0, 0)); +} + TEST(PicturePileImplTest, PixelRefIteratorEmpty) { gfx::Size tile_size(128, 128); gfx::Size layer_bounds(256, 256); diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc index efa914f..aabde77 100644 --- a/cc/resources/tile_manager.cc +++ b/cc/resources/tile_manager.cc @@ -11,7 +11,6 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/metrics/histogram.h" -#include "cc/debug/debug_colors.h" #include "cc/debug/devtools_instrumentation.h" #include "cc/debug/traced_value.h" #include "cc/resources/raster_worker_pool.h" @@ -908,14 +907,9 @@ void TileManager::RunRasterTask( SkDevice device(bitmap); SkCanvas canvas(&device); -#ifndef NDEBUG - // Any non-painted areas will be left in this color. - canvas.clear(DebugColors::NonPaintedFillColor()); -#endif // NDEBUG - if (stats_instrumentation->record_rendering_stats()) { PicturePileImpl::RasterStats raster_stats; - picture_pile->Raster(&canvas, rect, contents_scale, &raster_stats); + picture_pile->RasterToBitmap(&canvas, rect, contents_scale, &raster_stats); stats_instrumentation->AddRaster( raster_stats.total_rasterize_time, raster_stats.best_rasterize_time, @@ -929,7 +923,7 @@ void TileManager::RunRasterTask( 100000, 100); } else { - picture_pile->Raster(&canvas, rect, contents_scale, NULL); + picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL); } } diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index 7d4c8f8..a191401 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc @@ -113,7 +113,7 @@ bool PixelTest::PixelsMatchReference(const base::FilePath& ref_file, comparator); } -void PixelTest::SetUpGLRenderer() { +void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend) { CHECK(fake_client_); CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL)); @@ -127,7 +127,8 @@ void PixelTest::SetUpGLRenderer() { renderer_ = GLRenderer::Create(fake_client_.get(), output_surface_.get(), resource_provider_.get(), - 0).PassAs<DirectRenderer>(); + 0, + use_skia_gpu_backend).PassAs<DirectRenderer>(); scoped_refptr<webkit::gpu::ContextProviderInProcess> offscreen_contexts = webkit::gpu::ContextProviderInProcess::Create(); diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h index 148ecf9..c7dd7aa 100644 --- a/cc/test/pixel_test.h +++ b/cc/test/pixel_test.h @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/file_util.h" +#include "cc/output/gl_renderer.h" #include "cc/quads/render_pass.h" #include "cc/test/pixel_comparator.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,7 +14,6 @@ namespace cc { class DirectRenderer; -class GLRenderer; class SoftwareRenderer; class OutputSurface; class ResourceProvider; @@ -40,7 +40,7 @@ class PixelTest : public testing::Test { scoped_ptr<DirectRenderer> renderer_; scoped_ptr<SkBitmap> result_bitmap_; - void SetUpGLRenderer(); + void SetUpGLRenderer(bool use_skia_gpu_backend); void SetUpSoftwareRenderer(); private: @@ -57,13 +57,47 @@ class RendererPixelTest : public PixelTest { return static_cast<RendererType*>(renderer_.get()); } + bool UseSkiaGPUBackend() const; + protected: virtual void SetUp() OVERRIDE; }; +// A simple wrapper to differentiate a renderer that should use ganesh +// and one that shouldn't in templates. +class GLRendererWithSkiaGPUBackend : public GLRenderer { + public: + GLRendererWithSkiaGPUBackend(RendererClient* client, + OutputSurface* output_surface, + ResourceProvider* resource_provider, + int highp_threshold_min) + : GLRenderer(client, + output_surface, + resource_provider, + highp_threshold_min) {} +}; + template<> inline void RendererPixelTest<GLRenderer>::SetUp() { - SetUpGLRenderer(); + SetUpGLRenderer(false); + DCHECK(!renderer()->CanUseSkiaGPUBackend()); +} + +template<> +inline bool RendererPixelTest<GLRenderer>::UseSkiaGPUBackend() const { + return false; +} + +template<> +inline void RendererPixelTest<GLRendererWithSkiaGPUBackend>::SetUp() { + SetUpGLRenderer(true); + DCHECK(renderer()->CanUseSkiaGPUBackend()); +} + +template <> +inline bool +RendererPixelTest<GLRendererWithSkiaGPUBackend>::UseSkiaGPUBackend() const { + return true; } template<> @@ -71,7 +105,14 @@ inline void RendererPixelTest<SoftwareRenderer>::SetUp() { SetUpSoftwareRenderer(); } +template<> +inline bool RendererPixelTest<SoftwareRenderer>::UseSkiaGPUBackend() const { + return false; +} + typedef RendererPixelTest<GLRenderer> GLRendererPixelTest; +typedef RendererPixelTest<GLRendererWithSkiaGPUBackend> + GLRendererSkiaGPUBackendPixelTest; typedef RendererPixelTest<SoftwareRenderer> SoftwareRendererPixelTest; } // namespace cc diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index f0e5b8f..b8ab367 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc @@ -1267,6 +1267,21 @@ static void CalculateDrawPropertiesInternal( layer_draw_properties.render_target = layer->parent()->render_target(); } + // Mark whether a layer could be drawn directly to the back buffer, for + // example when it could use LCD text even though it's in a non-contents + // opaque layer. This means that it can't be drawn to an intermediate + // render target and also that no blending is applied to the layer as a whole + // (meaning that its contents don't have to be pre-composited into a bitmap or + // a render target). + // + // Ignoring animations is an optimization, + // as it means that we're going to need some retained resources for this + // layer in the near future even if its opacity is 1 now. + layer_draw_properties.can_draw_directly_to_backbuffer = + IsRootLayer(layer_draw_properties.render_target) && + layer->draw_properties().opacity == 1.f && + !animating_opacity_to_screen; + if (adjust_text_aa) layer_draw_properties.can_use_lcd_text = layer_can_use_lcd_text; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 0b87836..8faf970 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -1436,7 +1436,8 @@ bool LayerTreeHostImpl::InitializeRenderer( renderer_ = GLRenderer::Create(this, output_surface.get(), resource_provider.get(), - settings_.highp_threshold_min); + settings_.highp_threshold_min, + settings_.force_direct_layer_drawing); } else if (output_surface->software_device()) { renderer_ = SoftwareRenderer::Create(this, output_surface.get(), diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index 03a126d..74b03d2 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc @@ -54,6 +54,7 @@ LayerTreeSettings::LayerTreeSettings() max_tiles_for_interest_area(128), max_unused_resource_memory_percentage(100), highp_threshold_min(0), + force_direct_layer_drawing(false), strict_layer_property_change_checking(false) { // TODO(danakj): Renable surface caching when we can do it more realiably. // crbug.com/170713 diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index 66d6f20..5295e3f 100644 --- a/cc/trees/layer_tree_settings.h +++ b/cc/trees/layer_tree_settings.h @@ -58,6 +58,7 @@ class CC_EXPORT LayerTreeSettings { size_t max_tiles_for_interest_area; size_t max_unused_resource_memory_percentage; int highp_threshold_min; + bool force_direct_layer_drawing; // With Skia GPU backend. bool strict_layer_property_change_checking; LayerTreeDebugState initial_debug_state; diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index b6aa00e..5508a5d 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc @@ -142,6 +142,7 @@ std::string DeriveCommandLine(const GURL& start_url, cc::switches::kEnablePerTilePainting, cc::switches::kEnableRightAlignedScheduling, cc::switches::kEnableTopControlsPositionCalculation, + cc::switches::kForceDirectLayerDrawing, cc::switches::kLowResolutionContentsScaleFactor, cc::switches::kMaxTilesForInterestArea, cc::switches::kMaxUnusedResourceMemoryUsagePercentage, diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 1399cfa..9e73ac9 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -953,10 +953,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( cc::switches::kEnablePerTilePainting, cc::switches::kEnableRightAlignedScheduling, cc::switches::kEnableTopControlsPositionCalculation, + cc::switches::kForceDirectLayerDrawing, cc::switches::kLowResolutionContentsScaleFactor, + cc::switches::kMaxTilesForInterestArea, cc::switches::kMaxUnusedResourceMemoryUsagePercentage, cc::switches::kNumRasterThreads, - cc::switches::kMaxTilesForInterestArea, cc::switches::kShowCompositedLayerBorders, cc::switches::kShowCompositedLayerTree, cc::switches::kShowFPSCounter, diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index b6a1e53..55a7b49 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc @@ -102,6 +102,8 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( cmd->HasSwitch(cc::switches::kEnablePerTilePainting); settings.accelerated_animation_enabled = !cmd->HasSwitch(cc::switches::kDisableThreadedAnimation); + settings.force_direct_layer_drawing = + cmd->HasSwitch(cc::switches::kForceDirectLayerDrawing); int default_tile_width = settings.default_tile_size.width(); if (cmd->HasSwitch(switches::kDefaultTileWidth)) { diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 227761d..489c1ef 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc @@ -612,6 +612,8 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface() { attributes.noAutomaticFlushes = true; attributes.depth = false; attributes.stencil = false; + if (command_line.HasSwitch(cc::switches::kForceDirectLayerDrawing)) + attributes.stencil = true; WebGraphicsContext3DCommandBufferImpl* context = CreateGraphicsContext3D(attributes); if (!context) diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc index cf13127..d494ad7 100644 --- a/skia/ext/analysis_canvas.cc +++ b/skia/ext/analysis_canvas.cc @@ -71,13 +71,12 @@ AnalysisDevice::AnalysisDevice(const SkBitmap& bm) : INHERITED(bm) , isForcedNotSolid_(false) , isForcedNotTransparent_(false) - , isSolidColor_(false) - , isTransparent_(false) + , isSolidColor_(true) + , isTransparent_(true) , hasText_(false) { } AnalysisDevice::~AnalysisDevice() { - } bool AnalysisDevice::getColorIfSolid(SkColor* color) const { diff --git a/skia/ext/analysis_canvas_unittest.cc b/skia/ext/analysis_canvas_unittest.cc index d271a9e..3efcafc 100644 --- a/skia/ext/analysis_canvas_unittest.cc +++ b/skia/ext/analysis_canvas_unittest.cc @@ -25,9 +25,10 @@ TEST(AnalysisCanvasTest, EmptyCanvas) { emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); skia::AnalysisDevice device(emptyBitmap); skia::AnalysisCanvas canvas(&device); - + SkColor color; - EXPECT_FALSE(canvas.getColorIfSolid(&color)); + EXPECT_TRUE(canvas.getColorIfSolid(&color)); + EXPECT_EQ(color, SkColorSetARGB(0, 0, 0, 0)); } TEST(AnalysisCanvasTest, ClearCanvas) { diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc index 162a5ba..50092ab 100644 --- a/ui/gfx/skia_util.cc +++ b/ui/gfx/skia_util.cc @@ -15,6 +15,7 @@ #include "ui/gfx/rect.h" #include "ui/gfx/rect_f.h" #include "ui/gfx/shadow_value.h" +#include "ui/gfx/transform.h" namespace gfx { @@ -46,6 +47,19 @@ RectF SkRectToRectF(const SkRect& rect) { SkScalarToFloat(rect.height())); } +void TransformToFlattenedSkMatrix(const gfx::Transform& transform, + SkMatrix* flattened) { + // Convert from 4x4 to 3x3 by dropping the third row and column. + flattened->set(0, SkDoubleToScalar(transform.matrix().getDouble(0, 0))); + flattened->set(1, SkDoubleToScalar(transform.matrix().getDouble(0, 1))); + flattened->set(2, SkDoubleToScalar(transform.matrix().getDouble(0, 3))); + flattened->set(3, SkDoubleToScalar(transform.matrix().getDouble(1, 0))); + flattened->set(4, SkDoubleToScalar(transform.matrix().getDouble(1, 1))); + flattened->set(5, SkDoubleToScalar(transform.matrix().getDouble(1, 3))); + flattened->set(6, SkDoubleToScalar(transform.matrix().getDouble(3, 0))); + flattened->set(7, SkDoubleToScalar(transform.matrix().getDouble(3, 1))); + flattened->set(8, SkDoubleToScalar(transform.matrix().getDouble(3, 3))); +} skia::RefPtr<SkShader> CreateImageRepShader(const gfx::ImageSkiaRep& image_rep, SkShader::TileMode tile_mode, diff --git a/ui/gfx/skia_util.h b/ui/gfx/skia_util.h index bd9478f..4a2cfcf 100644 --- a/ui/gfx/skia_util.h +++ b/ui/gfx/skia_util.h @@ -23,6 +23,7 @@ class ImageSkiaRep; class Rect; class RectF; class ShadowValue; +class Transform; // Convert between Skia and gfx rect types. UI_EXPORT SkRect RectToSkRect(const Rect& rect); @@ -31,6 +32,9 @@ UI_EXPORT Rect SkIRectToRect(const SkIRect& rect); UI_EXPORT SkRect RectFToSkRect(const RectF& rect); UI_EXPORT RectF SkRectToRectF(const SkRect& rect); +UI_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform, + SkMatrix* flattened); + // Creates a bitmap shader for the image rep with the image rep's scale factor. // Sets the created shader's local matrix such that it displays the image rep at // the correct scale factor. |