diff --git a/sky/compositor/clip_path_layer.cc b/sky/compositor/clip_path_layer.cc index 3cf9079270e..be74e84ad11 100644 --- a/sky/compositor/clip_path_layer.cc +++ b/sky/compositor/clip_path_layer.cc @@ -14,11 +14,11 @@ ClipPathLayer::~ClipPathLayer() { } void ClipPathLayer::Paint(PaintContext& context) { - SkCanvas* canvas = context.canvas(); - canvas->saveLayer(&clip_path_.getBounds(), nullptr); - canvas->clipPath(clip_path_); + SkCanvas& canvas = context.canvas(); + canvas.saveLayer(&clip_path_.getBounds(), nullptr); + canvas.clipPath(clip_path_); PaintChildren(context); - canvas->restore(); + canvas.restore(); } } // namespace compositor diff --git a/sky/compositor/clip_path_layer.h b/sky/compositor/clip_path_layer.h index 67c09fa54e0..4e76798462d 100644 --- a/sky/compositor/clip_path_layer.h +++ b/sky/compositor/clip_path_layer.h @@ -17,6 +17,7 @@ class ClipPathLayer : public ContainerLayer { void set_clip_path(const SkPath& clip_path) { clip_path_ = clip_path; } + protected: void Paint(PaintContext& context) override; private: diff --git a/sky/compositor/clip_rect_layer.cc b/sky/compositor/clip_rect_layer.cc index e3ae0ee4eea..8e22da9b3d1 100644 --- a/sky/compositor/clip_rect_layer.cc +++ b/sky/compositor/clip_rect_layer.cc @@ -14,11 +14,11 @@ ClipRectLayer::~ClipRectLayer() { } void ClipRectLayer::Paint(PaintContext& context) { - SkCanvas* canvas = context.canvas(); - canvas->save(); - canvas->clipRect(clip_rect_); + SkCanvas& canvas = context.canvas(); + canvas.save(); + canvas.clipRect(clip_rect_); PaintChildren(context); - canvas->restore(); + canvas.restore(); } } // namespace compositor diff --git a/sky/compositor/clip_rect_layer.h b/sky/compositor/clip_rect_layer.h index 69d752301b3..4e0266160fe 100644 --- a/sky/compositor/clip_rect_layer.h +++ b/sky/compositor/clip_rect_layer.h @@ -17,6 +17,7 @@ class ClipRectLayer : public ContainerLayer { void set_clip_rect(const SkRect& clip_rect) { clip_rect_ = clip_rect; } + protected: void Paint(PaintContext& context) override; private: diff --git a/sky/compositor/clip_rrect_layer.cc b/sky/compositor/clip_rrect_layer.cc index 7ec0d5448c4..62ef9a56ff6 100644 --- a/sky/compositor/clip_rrect_layer.cc +++ b/sky/compositor/clip_rrect_layer.cc @@ -14,11 +14,11 @@ ClipRRectLayer::~ClipRRectLayer() { } void ClipRRectLayer::Paint(PaintContext& context) { - SkCanvas* canvas = context.canvas(); - canvas->saveLayer(&clip_rrect_.getBounds(), nullptr); - canvas->clipRRect(clip_rrect_); + SkCanvas& canvas = context.canvas(); + canvas.saveLayer(&clip_rrect_.getBounds(), nullptr); + canvas.clipRRect(clip_rrect_); PaintChildren(context); - canvas->restore(); + canvas.restore(); } } // namespace compositor diff --git a/sky/compositor/clip_rrect_layer.h b/sky/compositor/clip_rrect_layer.h index 817b3f26713..5304112ad53 100644 --- a/sky/compositor/clip_rrect_layer.h +++ b/sky/compositor/clip_rrect_layer.h @@ -17,6 +17,7 @@ class ClipRRectLayer : public ContainerLayer { void set_clip_rrect(const SkRRect& clip_rrect) { clip_rrect_ = clip_rrect; } + protected: void Paint(PaintContext& context) override; private: diff --git a/sky/compositor/color_filter_layer.cc b/sky/compositor/color_filter_layer.cc index 6235f6f9151..5fb272f704f 100644 --- a/sky/compositor/color_filter_layer.cc +++ b/sky/compositor/color_filter_layer.cc @@ -18,10 +18,10 @@ void ColorFilterLayer::Paint(PaintContext& context) { adoptRef(SkColorFilter::CreateModeFilter(color_, transfer_mode_)); SkPaint paint; paint.setColorFilter(color_filter.get()); - SkCanvas* canvas = context.canvas(); - canvas->saveLayer(&paint_bounds(), &paint); + SkCanvas& canvas = context.canvas(); + canvas.saveLayer(&paint_bounds(), &paint); PaintChildren(context); - canvas->restore(); + canvas.restore(); } } // namespace compositor diff --git a/sky/compositor/color_filter_layer.h b/sky/compositor/color_filter_layer.h index 9695896c75a..69337c7977e 100644 --- a/sky/compositor/color_filter_layer.h +++ b/sky/compositor/color_filter_layer.h @@ -21,6 +21,7 @@ class ColorFilterLayer : public ContainerLayer { transfer_mode_ = transfer_mode; } + protected: void Paint(PaintContext& context) override; private: diff --git a/sky/compositor/compositor_options.cc b/sky/compositor/compositor_options.cc index 102c23938a9..3f0111e5def 100644 --- a/sky/compositor/compositor_options.cc +++ b/sky/compositor/compositor_options.cc @@ -9,13 +9,6 @@ namespace sky { namespace compositor { -CompositorOptions& CompositorOptions::Shared() { - static std::once_flag once; - static CompositorOptions* options = nullptr; - std::call_once(once, []() { options = new CompositorOptions(); }); - return *options; -} - CompositorOptions::CompositorOptions() { static_assert(std::is_unsigned::value, "OptionType must be unsigned"); diff --git a/sky/compositor/compositor_options.h b/sky/compositor/compositor_options.h index f6cc8766e24..c20ce861233 100644 --- a/sky/compositor/compositor_options.h +++ b/sky/compositor/compositor_options.h @@ -23,7 +23,8 @@ class CompositorOptions { TerminationSentinel, }; - static CompositorOptions& Shared(); + CompositorOptions(); + ~CompositorOptions(); bool isEnabled(Option option) const; @@ -32,9 +33,6 @@ class CompositorOptions { private: std::vector options_; - CompositorOptions(); - ~CompositorOptions(); - DISALLOW_COPY_AND_ASSIGN(CompositorOptions); }; diff --git a/sky/compositor/layer.h b/sky/compositor/layer.h index d48c6cf802c..a601570befe 100644 --- a/sky/compositor/layer.h +++ b/sky/compositor/layer.h @@ -32,7 +32,7 @@ class Layer { Layer(); virtual ~Layer(); - virtual void Paint(PaintContext& context) = 0; + void Paint(PaintContext::ScopedFrame& frame) { Paint(frame.paint_context()); } virtual SkMatrix model_view_matrix(const SkMatrix& model_matrix) const; @@ -46,10 +46,15 @@ class Layer { paint_bounds_ = paint_bounds; } + protected: + virtual void Paint(PaintContext& context) = 0; + private: ContainerLayer* parent_; SkRect paint_bounds_; + friend class ContainerLayer; + DISALLOW_COPY_AND_ASSIGN(Layer); }; diff --git a/sky/compositor/opacity_layer.cc b/sky/compositor/opacity_layer.cc index 619a769d555..c8d30f97f8c 100644 --- a/sky/compositor/opacity_layer.cc +++ b/sky/compositor/opacity_layer.cc @@ -19,10 +19,10 @@ void OpacityLayer::Paint(PaintContext& context) { SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode)); SkPaint paint; paint.setColorFilter(colorFilter.get()); - SkCanvas* canvas = context.canvas(); - canvas->saveLayer(&paint_bounds(), &paint); + SkCanvas& canvas = context.canvas(); + canvas.saveLayer(&paint_bounds(), &paint); PaintChildren(context); - canvas->restore(); + canvas.restore(); } } // namespace compositor diff --git a/sky/compositor/opacity_layer.h b/sky/compositor/opacity_layer.h index e4d26116e66..37896aaf433 100644 --- a/sky/compositor/opacity_layer.h +++ b/sky/compositor/opacity_layer.h @@ -17,6 +17,7 @@ class OpacityLayer : public ContainerLayer { void set_alpha(int alpha) { alpha_ = alpha; } + protected: void Paint(PaintContext& context) override; private: diff --git a/sky/compositor/paint_context.cc b/sky/compositor/paint_context.cc index ab21b96b46d..daef046b70a 100644 --- a/sky/compositor/paint_context.cc +++ b/sky/compositor/paint_context.cc @@ -3,14 +3,33 @@ // found in the LICENSE file. #include "sky/compositor/paint_context.h" +#include "base/logging.h" namespace sky { namespace compositor { -PaintContext::PaintContext(PictureRasterzier& rasterizer, - GrContext* gr_context, - SkCanvas* canvas) - : rasterizer_(rasterizer), gr_context_(gr_context), canvas_(canvas) { +PaintContext::PaintContext() { +} + +void PaintContext::beginFrame(SkCanvas& canvas, GrContext* gr_context) { + canvas_ = &canvas; // required + gr_context_ = gr_context; // optional + + DCHECK(canvas_); +} + +void PaintContext::endFrame() { + DCHECK(canvas_); + + rasterizer_.PurgeCache(); + + canvas_ = nullptr; + gr_context_ = nullptr; +} + +PaintContext::ScopedFrame PaintContext::AcquireFrame(SkCanvas& canvas, + GrContext* gr_context) { + return ScopedFrame(*this, canvas, gr_context); } PaintContext::~PaintContext() { diff --git a/sky/compositor/paint_context.h b/sky/compositor/paint_context.h index d3af878f578..4b5455394fb 100644 --- a/sky/compositor/paint_context.h +++ b/sky/compositor/paint_context.h @@ -6,6 +6,8 @@ #define SKY_COMPOSITOR_PAINT_CONTEXT_CC_ #include "base/macros.h" +#include "base/logging.h" +#include "sky/compositor/compositor_options.h" #include "sky/compositor/picture_rasterizer.h" namespace sky { @@ -13,22 +15,57 @@ namespace compositor { class PaintContext { public: - PaintContext(PictureRasterzier& rasterizer, - GrContext* gr_context, - SkCanvas* canvas); + class ScopedFrame { + public: + PaintContext& paint_context() { return context_; }; + + ScopedFrame(ScopedFrame&& frame) = default; + + ~ScopedFrame() { context_.endFrame(); } + + private: + PaintContext& context_; + + ScopedFrame() = delete; + + ScopedFrame(PaintContext& context, SkCanvas& canvas, GrContext* gr_context) + : context_(context) { + context_.beginFrame(canvas, gr_context); + }; + + friend class PaintContext; + + DISALLOW_COPY_AND_ASSIGN(ScopedFrame); + }; + + PaintContext(); ~PaintContext(); PictureRasterzier& rasterizer() { return rasterizer_; } + CompositorOptions& options() { return options_; }; + GrContext* gr_context() { return gr_context_; } - SkCanvas* canvas() { return canvas_; } + SkCanvas& canvas() { + DCHECK(canvas_) << "Tried to access the canvas of a context whose frame " + "was not initialized. Did you forget to " + "`AcquireFrame`?"; + return *canvas_; + } + + ScopedFrame AcquireFrame(SkCanvas& canvas, GrContext* gr_context); private: - PictureRasterzier& rasterizer_; + PictureRasterzier rasterizer_; + CompositorOptions options_; GrContext* gr_context_; SkCanvas* canvas_; + void beginFrame(SkCanvas& canvas, GrContext* context); + + void endFrame(); + DISALLOW_COPY_AND_ASSIGN(PaintContext); }; diff --git a/sky/compositor/picture_layer.cc b/sky/compositor/picture_layer.cc index a04da168677..e38f0bf2764 100644 --- a/sky/compositor/picture_layer.cc +++ b/sky/compositor/picture_layer.cc @@ -27,16 +27,16 @@ void PictureLayer::Paint(PaintContext& context) { SkISize size = SkISize::Make(bounds.width(), bounds.height()); RefPtr image = context.rasterizer().GetCachedImageIfPresent( - context.gr_context(), picture_.get(), size); - SkCanvas* canvas = context.canvas(); + context, picture_.get(), size); + SkCanvas& canvas = context.canvas(); if (image) { - canvas->drawImage(image.get(), offset_.x(), offset_.y()); + canvas.drawImage(image.get(), offset_.x(), offset_.y()); } else { - canvas->save(); - canvas->translate(offset_.x(), offset_.y()); - canvas->drawPicture(picture_.get()); - canvas->restore(); + canvas.save(); + canvas.translate(offset_.x(), offset_.y()); + canvas.drawPicture(picture_.get()); + canvas.restore(); } } diff --git a/sky/compositor/picture_layer.h b/sky/compositor/picture_layer.h index 44a84601e4c..5bd620a77f9 100644 --- a/sky/compositor/picture_layer.h +++ b/sky/compositor/picture_layer.h @@ -21,10 +21,11 @@ class PictureLayer : public Layer { SkMatrix model_view_matrix(const SkMatrix& model_matrix) const override; - void Paint(PaintContext& context) override; - SkPicture* picture() const { return picture_.get(); } + protected: + void Paint(PaintContext& context) override; + private: SkPoint offset_; RefPtr picture_; diff --git a/sky/compositor/picture_rasterizer.cc b/sky/compositor/picture_rasterizer.cc index 77589b9b085..4930a9b8baa 100644 --- a/sky/compositor/picture_rasterizer.cc +++ b/sky/compositor/picture_rasterizer.cc @@ -5,6 +5,7 @@ #include "sky/compositor/compositor_options.h" #include "sky/compositor/checkerboard.h" #include "sky/compositor/picture_rasterizer.h" +#include "sky/compositor/paint_context.h" #include "base/logging.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/gpu/GrContext.h" @@ -37,7 +38,7 @@ PictureRasterzier::Value::Value() PictureRasterzier::Value::~Value() { } -static RefPtr ImageFromPicture(GrContext* context, +static RefPtr ImageFromPicture(PaintContext& context, SkPicture* picture, const SkISize& size) { // Step 1: Create a texture from the context's texture provider @@ -48,7 +49,8 @@ static RefPtr ImageFromPicture(GrContext* context, desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fConfig = kRGBA_8888_GrPixelConfig; - GrTexture* texture = context->textureProvider()->createTexture(desc, true); + GrTexture* texture = + context.gr_context()->textureProvider()->createTexture(desc, true); if (!texture) { // The texture provider could not allocate a texture backing. Render @@ -82,22 +84,24 @@ static RefPtr ImageFromPicture(GrContext* context, canvas->drawPicture(picture); - if (CompositorOptions::Shared().isEnabled( + if (context.options().isEnabled( CompositorOptions::Option::HightlightRasterizedImages)) { DrawCheckerboard(canvas, desc.fWidth, desc.fHeight); } // Step 4: Create an image representation from the texture - RefPtr image = adoptRef(SkImage::NewFromTexture( - context, backendDesc, kPremul_SkAlphaType, &ImageReleaseProc, texture)); + RefPtr image = adoptRef( + SkImage::NewFromTexture(context.gr_context(), backendDesc, + kPremul_SkAlphaType, &ImageReleaseProc, texture)); return image; } -RefPtr PictureRasterzier::GetCachedImageIfPresent(GrContext* context, - SkPicture* picture, - SkISize size) { - if (size.isEmpty() || picture == nullptr || context == nullptr) { +RefPtr PictureRasterzier::GetCachedImageIfPresent( + PaintContext& context, + SkPicture* picture, + SkISize size) { + if (size.isEmpty() || picture == nullptr || context.gr_context() == nullptr) { return nullptr; } diff --git a/sky/compositor/picture_rasterizer.h b/sky/compositor/picture_rasterizer.h index fbde8d40021..797af750d04 100644 --- a/sky/compositor/picture_rasterizer.h +++ b/sky/compositor/picture_rasterizer.h @@ -18,12 +18,13 @@ namespace sky { namespace compositor { +class PaintContext; class PictureRasterzier { public: PictureRasterzier(); ~PictureRasterzier(); - RefPtr GetCachedImageIfPresent(GrContext* context, + RefPtr GetCachedImageIfPresent(PaintContext& context, SkPicture* picture, SkISize size); diff --git a/sky/compositor/transform_layer.cc b/sky/compositor/transform_layer.cc index 2d9dfe1bcb2..2115e5e57da 100644 --- a/sky/compositor/transform_layer.cc +++ b/sky/compositor/transform_layer.cc @@ -20,11 +20,11 @@ SkMatrix TransformLayer::model_view_matrix(const SkMatrix& model_matrix) const { } void TransformLayer::Paint(PaintContext& context) { - SkCanvas* canvas = context.canvas(); - canvas->save(); - canvas->concat(transform_); + SkCanvas& canvas = context.canvas(); + canvas.save(); + canvas.concat(transform_); PaintChildren(context); - canvas->restore(); + canvas.restore(); } } // namespace compositor diff --git a/sky/compositor/transform_layer.h b/sky/compositor/transform_layer.h index b669efae3c3..cfeb82cbd18 100644 --- a/sky/compositor/transform_layer.h +++ b/sky/compositor/transform_layer.h @@ -19,6 +19,7 @@ class TransformLayer : public ContainerLayer { SkMatrix model_view_matrix(const SkMatrix& model_matrix) const override; + protected: void Paint(PaintContext& context) override; private: diff --git a/sky/shell/gpu/rasterizer.cc b/sky/shell/gpu/rasterizer.cc index 03a814d4f44..90c5d0861c9 100644 --- a/sky/shell/gpu/rasterizer.cc +++ b/sky/shell/gpu/rasterizer.cc @@ -78,8 +78,10 @@ void Rasterizer::Draw(scoped_ptr layer_tree) { SkCanvas* canvas = ganesh_surface_->canvas(); canvas->clear(SK_ColorBLACK); - compositor::PaintContext context(rasterizer_, ganesh_context_->gr(), canvas); - layer_tree->root_layer()->Paint(context); + { + auto frame = paint_context_.AcquireFrame(*canvas, ganesh_context_->gr()); + layer_tree->root_layer()->Paint(frame); + } canvas->flush(); surface_->SwapBuffers(); diff --git a/sky/shell/gpu/rasterizer.h b/sky/shell/gpu/rasterizer.h index cb766342ab1..8b56784fa6b 100644 --- a/sky/shell/gpu/rasterizer.h +++ b/sky/shell/gpu/rasterizer.h @@ -11,7 +11,7 @@ #include "sky/shell/gpu_delegate.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" -#include "sky/compositor/picture_rasterizer.h" +#include "sky/compositor/paint_context.h" class SkPicture; @@ -48,7 +48,7 @@ class Rasterizer : public GPUDelegate { scoped_ptr ganesh_context_; scoped_ptr ganesh_surface_; - compositor::PictureRasterzier rasterizer_; + compositor::PaintContext paint_context_; base::WeakPtrFactory weak_factory_;