From f7d1856bd08ec9f24b74734bf147beacd0c2524f Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 8 Jan 2016 16:05:34 -0800 Subject: [PATCH] Compute paint bounds from cull rects Rather than relying upon the rects passed in from Dart, the compositor should compute the paint bounds of layers from the cull rects of the underlying SkPictures. This approach is better because it will handle effects like shadows that paint outside the incorrect paint bounds we use today (as well as shrinking around empty space). --- sky/compositor/color_filter_layer.cc | 7 ++++++- sky/compositor/color_filter_layer.h | 2 ++ sky/compositor/container_layer.cc | 16 ++++++++++------ sky/compositor/container_layer.h | 5 ++--- sky/compositor/layer.cc | 2 +- sky/compositor/layer.h | 8 ++++++-- sky/compositor/layer_tree.cc | 3 ++- sky/compositor/opacity_layer.cc | 7 ++++++- sky/compositor/opacity_layer.h | 1 + sky/compositor/picture_layer.cc | 14 +++++++------- sky/compositor/picture_layer.h | 3 +-- sky/compositor/transform_layer.cc | 6 +++--- sky/compositor/transform_layer.h | 3 +-- sky/engine/core/compositing/SceneBuilder.cpp | 10 +--------- sky/engine/core/compositing/SceneBuilder.h | 1 - 15 files changed, 49 insertions(+), 39 deletions(-) diff --git a/sky/compositor/color_filter_layer.cc b/sky/compositor/color_filter_layer.cc index e844db9f68..674022ec1e 100644 --- a/sky/compositor/color_filter_layer.cc +++ b/sky/compositor/color_filter_layer.cc @@ -13,13 +13,18 @@ ColorFilterLayer::ColorFilterLayer() { ColorFilterLayer::~ColorFilterLayer() { } +void ColorFilterLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + ContainerLayer::Preroll(context, matrix); + set_paint_bounds(context->child_paint_bounds); +} + void ColorFilterLayer::Paint(PaintContext::ScopedFrame& frame) { RefPtr color_filter = adoptRef(SkColorFilter::CreateModeFilter(color_, transfer_mode_)); SkPaint paint; paint.setColorFilter(color_filter.get()); SkCanvas& canvas = frame.canvas(); - canvas.saveLayer(has_paint_bounds() ? &paint_bounds() : nullptr, &paint); + canvas.saveLayer(&paint_bounds(), &paint); PaintChildren(frame); canvas.restore(); } diff --git a/sky/compositor/color_filter_layer.h b/sky/compositor/color_filter_layer.h index db08327562..7633842c0a 100644 --- a/sky/compositor/color_filter_layer.h +++ b/sky/compositor/color_filter_layer.h @@ -21,6 +21,8 @@ class ColorFilterLayer : public ContainerLayer { transfer_mode_ = transfer_mode; } + protected: + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/compositor/container_layer.cc b/sky/compositor/container_layer.cc index 28c71d945e..985baef35a 100644 --- a/sky/compositor/container_layer.cc +++ b/sky/compositor/container_layer.cc @@ -18,15 +18,19 @@ void ContainerLayer::Add(std::unique_ptr layer) { layers_.push_back(std::move(layer)); } -void ContainerLayer::Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) { - PrerollChildren(frame, matrix); +void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + PrerollChildren(context, matrix); } -void ContainerLayer::PrerollChildren(PaintContext::ScopedFrame& frame, +void ContainerLayer::PrerollChildren(PrerollContext* context, const SkMatrix& matrix) { - for (auto& layer : layers_) - layer->Preroll(frame, matrix); + SkRect child_paint_bounds; + for (auto& layer : layers_) { + PrerollContext child_context = *context; + layer->Preroll(&child_context, matrix); + child_paint_bounds.join(child_context.child_paint_bounds); + } + context->child_paint_bounds = child_paint_bounds; } void ContainerLayer::PaintChildren(PaintContext::ScopedFrame& frame) const { diff --git a/sky/compositor/container_layer.h b/sky/compositor/container_layer.h index 8c3aeabdf8..674ab704ef 100644 --- a/sky/compositor/container_layer.h +++ b/sky/compositor/container_layer.h @@ -18,10 +18,9 @@ class ContainerLayer : public Layer { void Add(std::unique_ptr layer); - void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) override; + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; + void PrerollChildren(PrerollContext* context, const SkMatrix& matrix); - void PrerollChildren(PaintContext::ScopedFrame& frame, const SkMatrix& matrix); void PaintChildren(PaintContext::ScopedFrame& frame) const; const std::vector>& layers() const { return layers_; } diff --git a/sky/compositor/layer.cc b/sky/compositor/layer.cc index 43b68a7566..70337b1df7 100644 --- a/sky/compositor/layer.cc +++ b/sky/compositor/layer.cc @@ -18,7 +18,7 @@ Layer::Layer() Layer::~Layer() { } -void Layer::Preroll(PaintContext::ScopedFrame& frame, const SkMatrix& matrix) { +void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) { } } // namespace compositor diff --git a/sky/compositor/layer.h b/sky/compositor/layer.h index 532c8fbd9e..8c91143c60 100644 --- a/sky/compositor/layer.h +++ b/sky/compositor/layer.h @@ -31,8 +31,12 @@ class Layer { Layer(); virtual ~Layer(); - virtual void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix); + struct PrerollContext { + PaintContext::ScopedFrame& frame; + SkRect child_paint_bounds; + }; + + virtual void Preroll(PrerollContext* context, const SkMatrix& matrix); virtual void Paint(PaintContext::ScopedFrame& frame) = 0; ContainerLayer* parent() const { return parent_; } diff --git a/sky/compositor/layer_tree.cc b/sky/compositor/layer_tree.cc index 5af12a6b71..39e742cf8c 100644 --- a/sky/compositor/layer_tree.cc +++ b/sky/compositor/layer_tree.cc @@ -16,7 +16,8 @@ LayerTree::~LayerTree() { } void LayerTree::Raster(PaintContext::ScopedFrame& frame) { - root_layer_->Preroll(frame, SkMatrix()); + Layer::PrerollContext context = { frame, SkRect::MakeEmpty() }; + root_layer_->Preroll(&context, SkMatrix()); root_layer_->Paint(frame); } diff --git a/sky/compositor/opacity_layer.cc b/sky/compositor/opacity_layer.cc index ff5a814312..ad77687a70 100644 --- a/sky/compositor/opacity_layer.cc +++ b/sky/compositor/opacity_layer.cc @@ -13,12 +13,17 @@ OpacityLayer::OpacityLayer() { OpacityLayer::~OpacityLayer() { } +void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + ContainerLayer::Preroll(context, matrix); + set_paint_bounds(context->child_paint_bounds); +} + void OpacityLayer::Paint(PaintContext::ScopedFrame& frame) { SkPaint paint; paint.setColor(SkColorSetARGB(alpha_, 0, 0, 0)); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); SkCanvas& canvas = frame.canvas(); - canvas.saveLayer(has_paint_bounds() ? &paint_bounds() : nullptr, &paint); + canvas.saveLayer(&paint_bounds(), &paint); PaintChildren(frame); canvas.restore(); } diff --git a/sky/compositor/opacity_layer.h b/sky/compositor/opacity_layer.h index 5d684f0bcd..9ed79a5e5b 100644 --- a/sky/compositor/opacity_layer.h +++ b/sky/compositor/opacity_layer.h @@ -18,6 +18,7 @@ class OpacityLayer : public ContainerLayer { void set_alpha(int alpha) { alpha_ = alpha; } protected: + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/compositor/picture_layer.cc b/sky/compositor/picture_layer.cc index be87a746c0..43bfa9d671 100644 --- a/sky/compositor/picture_layer.cc +++ b/sky/compositor/picture_layer.cc @@ -20,10 +20,11 @@ PictureLayer::PictureLayer() { PictureLayer::~PictureLayer() { } -void PictureLayer::Preroll(PaintContext::ScopedFrame& frame, +void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { - image_ = frame.context().raster_cache().GetPrerolledImage( - frame.gr_context(), picture_.get(), matrix); + image_ = context->frame.context().raster_cache().GetPrerolledImage( + context->frame.gr_context(), picture_.get(), matrix); + context->child_paint_bounds = picture_->cullRect(); } void PictureLayer::Paint(PaintContext::ScopedFrame& frame) { @@ -44,10 +45,9 @@ void PictureLayer::Paint(PaintContext::ScopedFrame& frame) { canvas.drawImage(image_.get(), dx, dy); canvas.restore(); - if (kDebugCheckerboardRasterizedLayers) { - SkRect rect = paint_bounds().makeOffset(offset_.x(), offset_.y()); - DrawCheckerboard(&canvas, rect); - } + if (kDebugCheckerboardRasterizedLayers) + DrawCheckerboard(&canvas, rect.makeOffset(offset_.x(), offset_.y())); + } else { canvas.save(); canvas.translate(offset_.x(), offset_.y()); diff --git a/sky/compositor/picture_layer.h b/sky/compositor/picture_layer.h index c7efba34d9..1fbb293262 100644 --- a/sky/compositor/picture_layer.h +++ b/sky/compositor/picture_layer.h @@ -21,8 +21,7 @@ class PictureLayer : public Layer { SkPicture* picture() const { return picture_.get(); } - void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) override; + void Preroll(PrerollContext* frame, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/compositor/transform_layer.cc b/sky/compositor/transform_layer.cc index 9fe8c896d7..2b94c84664 100644 --- a/sky/compositor/transform_layer.cc +++ b/sky/compositor/transform_layer.cc @@ -13,11 +13,11 @@ TransformLayer::TransformLayer() { TransformLayer::~TransformLayer() { } -void TransformLayer::Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) { +void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkMatrix childMatrix; childMatrix.setConcat(matrix, transform_); - PrerollChildren(frame, childMatrix); + PrerollChildren(context, childMatrix); + transform_.mapRect(&context->child_paint_bounds); } void TransformLayer::Paint(PaintContext::ScopedFrame& frame) { diff --git a/sky/compositor/transform_layer.h b/sky/compositor/transform_layer.h index 8f49d33b93..bd2c4e5b0f 100644 --- a/sky/compositor/transform_layer.h +++ b/sky/compositor/transform_layer.h @@ -17,8 +17,7 @@ class TransformLayer : public ContainerLayer { void set_transform(const SkMatrix& transform) { transform_ = transform; } - void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) override; + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/engine/core/compositing/SceneBuilder.cpp b/sky/engine/core/compositing/SceneBuilder.cpp index acdb2fabbb..e360936f71 100644 --- a/sky/engine/core/compositing/SceneBuilder.cpp +++ b/sky/engine/core/compositing/SceneBuilder.cpp @@ -62,8 +62,7 @@ FOR_EACH_BINDING(DART_REGISTER_NATIVE) } SceneBuilder::SceneBuilder(const Rect& bounds) - : m_rootPaintBounds(bounds.sk_rect) - , m_currentLayer(nullptr) + : m_currentLayer(nullptr) , m_currentRasterizerTracingThreshold(0) { } @@ -106,8 +105,6 @@ void SceneBuilder::pushClipPath(const CanvasPath* path, const Rect& bounds) void SceneBuilder::pushOpacity(int alpha, const Rect& bounds) { std::unique_ptr layer(new sky::compositor::OpacityLayer()); - if (!bounds.is_null) - layer->set_paint_bounds(bounds.sk_rect); layer->set_alpha(alpha); addLayer(std::move(layer)); } @@ -115,8 +112,6 @@ void SceneBuilder::pushOpacity(int alpha, const Rect& bounds) void SceneBuilder::pushColorFilter(CanvasColor color, TransferMode transferMode, const Rect& bounds) { std::unique_ptr layer(new sky::compositor::ColorFilterLayer()); - if (!bounds.is_null) - layer->set_paint_bounds(bounds.sk_rect); layer->set_color(color); layer->set_transfer_mode(transferMode); addLayer(std::move(layer)); @@ -128,7 +123,6 @@ void SceneBuilder::addLayer(std::unique_ptr lay if (!m_rootLayer) { DCHECK(!m_currentLayer); m_rootLayer = std::move(layer); - m_rootLayer->set_paint_bounds(m_rootPaintBounds); m_currentLayer = m_rootLayer.get(); return; } @@ -153,8 +147,6 @@ void SceneBuilder::addPicture(const Offset& offset, Picture* picture, const Rect std::unique_ptr layer(new sky::compositor::PictureLayer()); layer->set_offset(SkPoint::Make(offset.sk_size.width(), offset.sk_size.height())); layer->set_picture(picture->toSkia()); - if (!paintBounds.is_null) - layer->set_paint_bounds(paintBounds.sk_rect); m_currentLayer->Add(std::move(layer)); } diff --git a/sky/engine/core/compositing/SceneBuilder.h b/sky/engine/core/compositing/SceneBuilder.h index d8d06626d6..d09f8afcd6 100644 --- a/sky/engine/core/compositing/SceneBuilder.h +++ b/sky/engine/core/compositing/SceneBuilder.h @@ -57,7 +57,6 @@ private: void addLayer(std::unique_ptr layer); - SkRect m_rootPaintBounds; std::unique_ptr m_rootLayer; sky::compositor::ContainerLayer* m_currentLayer; int32_t m_currentRasterizerTracingThreshold; -- GitLab