summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-21 21:31:44 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-21 21:31:44 +0000
commitbec08429286ff70c2ce5514ba44c8058fc058a27 (patch)
treed3f04253d5ba58348f533386fa352203e1650b41
parent2fccd420c7523d8379367cc1c8a3fc962b4babe1 (diff)
downloadchromium_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
-rw-r--r--cc/base/switches.cc5
-rw-r--r--cc/base/switches.h1
-rw-r--r--cc/debug/debug_colors.cc8
-rw-r--r--cc/debug/debug_colors.h3
-rw-r--r--cc/layers/draw_properties.h5
-rw-r--r--cc/layers/layer_impl.cc14
-rw-r--r--cc/layers/layer_impl.h5
-rw-r--r--cc/layers/picture_layer_impl.cc38
-rw-r--r--cc/layers/picture_layer_impl_unittest.cc12
-rw-r--r--cc/output/gl_renderer.cc154
-rw-r--r--cc/output/gl_renderer.h14
-rw-r--r--cc/output/renderer_pixeltest.cc49
-rw-r--r--cc/output/software_renderer.cc20
-rw-r--r--cc/quads/draw_quad_unittest.cc15
-rw-r--r--cc/quads/picture_draw_quad.cc4
-rw-r--r--cc/quads/picture_draw_quad.h3
-rw-r--r--cc/resources/picture.cc4
-rw-r--r--cc/resources/picture_pile_impl.cc79
-rw-r--r--cc/resources/picture_pile_impl.h11
-rw-r--r--cc/resources/picture_pile_impl_unittest.cc15
-rw-r--r--cc/resources/tile_manager.cc10
-rw-r--r--cc/test/pixel_test.cc5
-rw-r--r--cc/test/pixel_test.h47
-rw-r--r--cc/trees/layer_tree_host_common.cc15
-rw-r--r--cc/trees/layer_tree_host_impl.cc3
-rw-r--r--cc/trees/layer_tree_settings.cc1
-rw-r--r--cc/trees/layer_tree_settings.h1
-rw-r--r--chrome/browser/chromeos/login/chrome_restart_request.cc1
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc3
-rw-r--r--content/renderer/gpu/render_widget_compositor.cc2
-rw-r--r--content/renderer/render_widget.cc2
-rw-r--r--skia/ext/analysis_canvas.cc5
-rw-r--r--skia/ext/analysis_canvas_unittest.cc5
-rw-r--r--ui/gfx/skia_util.cc14
-rw-r--r--ui/gfx/skia_util.h4
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.