From e5d7e6934611b3afa8691d86f82c72fb66230ab6 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 3 Sep 2015 13:32:44 -0700 Subject: [PATCH] Pass the sky::LayerTree to the GPU thread for drawing Instead of squashing the layers down into a single SkPicture, we now pass the tree to the GPU thread, which draws everything separately. --- services/sky/document_view.cc | 13 ++++----- services/sky/document_view.h | 2 ++ sky/compositor/BUILD.gn | 2 ++ sky/compositor/layer.h | 6 ++--- sky/compositor/layer_tree.cc | 17 ++++++++++++ sky/compositor/layer_tree.h | 38 +++++++++++++++++++++++++++ sky/engine/core/compositing/Scene.cpp | 13 +++------ sky/engine/core/compositing/Scene.h | 7 +++-- sky/engine/core/view/View.cpp | 5 ++-- sky/engine/core/view/View.h | 6 +---- sky/engine/core/view/View.idl | 1 - sky/engine/public/sky/BUILD.gn | 1 + sky/engine/public/sky/sky_view.cc | 12 ++------- sky/engine/public/sky/sky_view.h | 5 ++-- sky/shell/BUILD.gn | 1 + sky/shell/gpu/rasterizer.cc | 19 +++++++------- sky/shell/gpu/rasterizer.h | 3 +-- sky/shell/gpu_delegate.h | 7 +++-- sky/shell/ui/animator.cc | 13 ++++++--- sky/shell/ui/engine.cc | 27 ++++++------------- sky/shell/ui/engine.h | 4 +-- 21 files changed, 118 insertions(+), 84 deletions(-) create mode 100644 sky/compositor/layer_tree.cc create mode 100644 sky/compositor/layer_tree.h diff --git a/services/sky/document_view.cc b/services/sky/document_view.cc index 8ce55d3bf..8632184ee 100644 --- a/services/sky/document_view.cc +++ b/services/sky/document_view.cc @@ -209,7 +209,9 @@ mojo::Shell* DocumentView::GetShell() { void DocumentView::BeginFrame(base::TimeTicks frame_time) { if (sky_view_) { - sky_view_->BeginFrame(frame_time); + std::unique_ptr layer_tree = sky_view_->BeginFrame(frame_time); + if (layer_tree) + current_layer_tree_ = std::move(layer_tree); root_layer_->SetSize(sky_view_->display_metrics().physical_size); } } @@ -220,13 +222,8 @@ void DocumentView::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) { } void DocumentView::PaintContents(SkCanvas* canvas, const gfx::Rect& clip) { - blink::WebRect rect(clip.x(), clip.y(), clip.width(), clip.height()); - - if (sky_view_) { - RefPtr picture = sky_view_->Paint(); - if (picture) - canvas->drawPicture(picture.get()); - } + if (current_layer_tree_) + current_layer_tree_->root_layer()->Paint(canvas); } float DocumentView::GetDevicePixelRatio() const { diff --git a/services/sky/document_view.h b/services/sky/document_view.h index e67faa958..4d7e7e2ed 100644 --- a/services/sky/document_view.h +++ b/services/sky/document_view.h @@ -22,6 +22,7 @@ #include "mojo/services/view_manager/public/cpp/view_observer.h" #include "services/sky/compositor/layer_client.h" #include "services/sky/compositor/layer_host_client.h" +#include "sky/compositor/layer_tree.h" #include "sky/engine/public/platform/ServiceProvider.h" #include "sky/engine/public/sky/sky_view.h" #include "sky/engine/public/sky/sky_view_client.h" @@ -128,6 +129,7 @@ class DocumentView : public blink::ServiceProvider, scoped_ptr library_provider_; scoped_ptr layer_host_; scoped_refptr root_layer_; + std::unique_ptr current_layer_tree_; // TODO(abarth): Integrate //sky/compositor and //services/sky/compositor. RasterizerBitmap* bitmap_rasterizer_; // Used for pixel tests. mojo::ServiceRegistryPtr service_registry_; scoped_ptr> diff --git a/sky/compositor/BUILD.gn b/sky/compositor/BUILD.gn index ffce6c03f..c9aeb7296 100644 --- a/sky/compositor/BUILD.gn +++ b/sky/compositor/BUILD.gn @@ -4,6 +4,8 @@ source_set("compositor") { sources = [ + "layer_tree.cc", + "layer_tree.h", "layer.cc", "layer.h", ] diff --git a/sky/compositor/layer.h b/sky/compositor/layer.h index 6dcd36e2b..60b3ded65 100644 --- a/sky/compositor/layer.h +++ b/sky/compositor/layer.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SKY_COMPOSITOR_H_ -#define SKY_COMPOSITOR_H_ +#ifndef SKY_COMPOSITOR_LAYER_H_ +#define SKY_COMPOSITOR_LAYER_H_ #include #include @@ -170,4 +170,4 @@ class ColorFilterLayer : public ContainerLayer { } // namespace sky -#endif // SKY_COMPOSITOR_H_ +#endif // SKY_COMPOSITOR_LAYER_H_ diff --git a/sky/compositor/layer_tree.cc b/sky/compositor/layer_tree.cc new file mode 100644 index 000000000..4f1f57453 --- /dev/null +++ b/sky/compositor/layer_tree.cc @@ -0,0 +1,17 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/compositor/layer_tree.h" + +#include "sky/compositor/layer.h" + +namespace sky { + +LayerTree::LayerTree() { +} + +LayerTree::~LayerTree() { +} + +} // namespace sky diff --git a/sky/compositor/layer_tree.h b/sky/compositor/layer_tree.h new file mode 100644 index 000000000..f3bde5a3f --- /dev/null +++ b/sky/compositor/layer_tree.h @@ -0,0 +1,38 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_COMPOSITOR_LAYER_TREE_H_ +#define SKY_COMPOSITOR_LAYER_TREE_H_ + +#include + +#include "base/macros.h" +#include "sky/compositor/layer.h" +#include "third_party/skia/include/core/SkSize.h" + +namespace sky { + +class LayerTree { + public: + LayerTree(); + ~LayerTree(); + + Layer* root_layer() const { return root_layer_.get(); } + void set_root_layer(std::unique_ptr root_layer) { + root_layer_ = std::move(root_layer); + } + + const SkISize& frame_size() const { return frame_size_; } + void set_frame_size(const SkISize& frame_size) { frame_size_ = frame_size; } + + private: + SkISize frame_size_; // Physical pixels. + std::unique_ptr root_layer_; + + DISALLOW_COPY_AND_ASSIGN(LayerTree); +}; + +} // namespace sky + +#endif // SKY_COMPOSITOR_LAYER_TREE_H_ diff --git a/sky/engine/core/compositing/Scene.cpp b/sky/engine/core/compositing/Scene.cpp index d58883f98..f81cf261e 100644 --- a/sky/engine/core/compositing/Scene.cpp +++ b/sky/engine/core/compositing/Scene.cpp @@ -16,22 +16,17 @@ PassRefPtr Scene::create(std::unique_ptr rootLayer) } Scene::Scene(std::unique_ptr rootLayer) - : m_rootLayer(std::move(rootLayer)) + : m_layerTree(new sky::LayerTree()) { + m_layerTree->set_root_layer(std::move(rootLayer)); } Scene::~Scene() { } -PassRefPtr Scene::createPicture() const -{ - SkRTreeFactory rtreeFactory; - SkPictureRecorder pictureRecorder; - SkCanvas* canvas = pictureRecorder.beginRecording(m_rootLayer->paint_bounds(), - &rtreeFactory, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); - m_rootLayer->Paint(canvas); - return adoptRef(pictureRecorder.endRecording()); +std::unique_ptr Scene::takeLayerTree() { + return std::move(m_layerTree); } } // namespace blink diff --git a/sky/engine/core/compositing/Scene.h b/sky/engine/core/compositing/Scene.h index af2347f1a..94e4a5aa2 100644 --- a/sky/engine/core/compositing/Scene.h +++ b/sky/engine/core/compositing/Scene.h @@ -8,6 +8,7 @@ #include #include "sky/compositor/layer.h" +#include "sky/compositor/layer_tree.h" #include "sky/engine/tonic/dart_wrappable.h" #include "sky/engine/wtf/PassRefPtr.h" #include "sky/engine/wtf/RefCounted.h" @@ -21,14 +22,12 @@ public: ~Scene() override; static PassRefPtr create(std::unique_ptr rootLayer); - // While bootstraping the compositing system, we use an SkPicture instead - // of a layer tree to back the scene. - PassRefPtr createPicture() const; + std::unique_ptr takeLayerTree(); private: explicit Scene(std::unique_ptr rootLayer); - std::unique_ptr m_rootLayer; + std::unique_ptr m_layerTree; }; } // namespace blink diff --git a/sky/engine/core/view/View.cpp b/sky/engine/core/view/View.cpp index c9dbc07d6..dcb4b3940 100644 --- a/sky/engine/core/view/View.cpp +++ b/sky/engine/core/view/View.cpp @@ -65,12 +65,13 @@ void View::handleInputEvent(PassRefPtr event) m_eventCallback->handleEvent(event.get()); } -void View::beginFrame(base::TimeTicks frameTime) +std::unique_ptr View::beginFrame(base::TimeTicks frameTime) { if (!m_frameCallback) - return; + return nullptr; double frameTimeMS = (frameTime - base::TimeTicks()).InMillisecondsF(); m_frameCallback->handleEvent(frameTimeMS); + return m_scene ? m_scene->takeLayerTree() : nullptr; } } // namespace blink diff --git a/sky/engine/core/view/View.h b/sky/engine/core/view/View.h index d8e7757fc..aa89a147b 100644 --- a/sky/engine/core/view/View.h +++ b/sky/engine/core/view/View.h @@ -35,9 +35,6 @@ public: double width() const; double height() const; - Picture* picture() const { return m_picture.get(); } - void setPicture(Picture* picture) { m_picture = picture; } - Scene* scene() const { return m_scene.get(); } void setScene(Scene* scene) { m_scene = scene; } @@ -50,7 +47,7 @@ public: void setDisplayMetrics(const SkyDisplayMetrics& metrics); void handleInputEvent(PassRefPtr event); - void beginFrame(base::TimeTicks frameTime); + std::unique_ptr beginFrame(base::TimeTicks frameTime); private: explicit View(const base::Closure& scheduleFrameCallback); @@ -60,7 +57,6 @@ private: OwnPtr m_eventCallback; OwnPtr m_metricsChangedCallback; OwnPtr m_frameCallback; - RefPtr m_picture; RefPtr m_scene; }; diff --git a/sky/engine/core/view/View.idl b/sky/engine/core/view/View.idl index 569ed212e..3c5e02554 100644 --- a/sky/engine/core/view/View.idl +++ b/sky/engine/core/view/View.idl @@ -14,7 +14,6 @@ interface View { readonly attribute double width; readonly attribute double height; - attribute Picture picture; attribute Scene scene; void setEventCallback(EventCallback callback); diff --git a/sky/engine/public/sky/BUILD.gn b/sky/engine/public/sky/BUILD.gn index 19c32b2f2..9b7a274d1 100644 --- a/sky/engine/public/sky/BUILD.gn +++ b/sky/engine/public/sky/BUILD.gn @@ -8,6 +8,7 @@ source_set("sky") { "//mojo/public/cpp/system", "//mojo/services/network/public/interfaces", "//skia", + "//sky/compositor", "//sky/engine/core", "//sky/engine/platform", "//sky/engine/wtf", diff --git a/sky/engine/public/sky/sky_view.cc b/sky/engine/public/sky/sky_view.cc index de5cc2df1..54809acb9 100644 --- a/sky/engine/public/sky/sky_view.cc +++ b/sky/engine/public/sky/sky_view.cc @@ -66,16 +66,8 @@ void SkyView::RunFromSnapshot(const WebString& name, dart_controller_->RunFromSnapshot(snapshot.Pass()); } -void SkyView::BeginFrame(base::TimeTicks frame_time) { - view_->beginFrame(frame_time); -} - -PassRefPtr SkyView::Paint() { - if (Scene* scene = view_->scene()) - return scene->createPicture(); - if (Picture* picture = view_->picture()) - return picture->toSkia(); - return nullptr; +std::unique_ptr SkyView::BeginFrame(base::TimeTicks frame_time) { + return view_->beginFrame(frame_time); } void SkyView::HandleInputEvent(const WebInputEvent& inputEvent) { diff --git a/sky/engine/public/sky/sky_view.h b/sky/engine/public/sky/sky_view.h index 8eaae7911..a5b023102 100644 --- a/sky/engine/public/sky/sky_view.h +++ b/sky/engine/public/sky/sky_view.h @@ -11,6 +11,7 @@ #include "base/time/time.h" #include "mojo/public/cpp/system/data_pipe.h" #include "mojo/services/network/public/interfaces/url_loader.mojom.h" +#include "sky/compositor/layer_tree.h" #include "sky/engine/public/platform/WebCommon.h" #include "sky/engine/public/platform/WebURL.h" #include "sky/engine/public/platform/sky_display_metrics.h" @@ -33,7 +34,8 @@ class SkyView { const SkyDisplayMetrics& display_metrics() const { return display_metrics_; } void SetDisplayMetrics(const SkyDisplayMetrics& metrics); - void BeginFrame(base::TimeTicks frame_time); + + std::unique_ptr BeginFrame(base::TimeTicks frame_time); void CreateView(const String& name); @@ -42,7 +44,6 @@ class SkyView { void RunFromSnapshot(const WebString& name, mojo::ScopedDataPipeConsumerHandle snapshot); - PassRefPtr Paint(); void HandleInputEvent(const WebInputEvent& event); void StartDartTracing(); diff --git a/sky/shell/BUILD.gn b/sky/shell/BUILD.gn index 4b8c35050..aa417c94e 100644 --- a/sky/shell/BUILD.gn +++ b/sky/shell/BUILD.gn @@ -18,6 +18,7 @@ common_deps = [ "//mojo/services/network/public/interfaces", "//services/asset_bundle:lib", "//skia", + "//sky/compositor", "//sky/engine", "//sky/engine/tonic", "//sky/engine/wtf", diff --git a/sky/shell/gpu/rasterizer.cc b/sky/shell/gpu/rasterizer.cc index d2e930d6f..391b585f9 100644 --- a/sky/shell/gpu/rasterizer.cc +++ b/sky/shell/gpu/rasterizer.cc @@ -5,6 +5,7 @@ #include "sky/shell/gpu/rasterizer.h" #include "base/trace_event/trace_event.h" +#include "sky/compositor/layer.h" #include "sky/shell/gpu/ganesh_context.h" #include "sky/shell/gpu/ganesh_surface.h" #include "sky/shell/gpu/picture_serializer.h" @@ -35,33 +36,31 @@ void Rasterizer::OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) { CHECK(surface_) << "GLSurface required."; } -void Rasterizer::Draw(PassRefPtr picture, gfx::Size size) { +void Rasterizer::Draw(scoped_ptr layer_tree) { TRACE_EVENT0("sky", "Rasterizer::Draw"); if (!surface_) return; + gfx::Size size(layer_tree->frame_size().width(), + layer_tree->frame_size().height()); + if (surface_->GetSize() != size) surface_->Resize(size); EnsureGLContext(); CHECK(context_->MakeCurrent(surface_.get())); EnsureGaneshSurface(surface_->GetBackingFrameBufferObject(), size); + SkCanvas* canvas = ganesh_surface_->canvas(); - DrawPicture(picture.get()); + canvas->clear(SK_ColorBLACK); + layer_tree->root_layer()->Paint(canvas); + canvas->flush(); surface_->SwapBuffers(); // SerializePicture("/data/data/org.domokit.sky.shell/cache/layer0.skp", picture.get()); } -void Rasterizer::DrawPicture(SkPicture* picture) { - TRACE_EVENT0("sky", "Rasterizer::DrawPicture"); - SkCanvas* canvas = ganesh_surface_->canvas(); - canvas->clear(SK_ColorBLACK); - canvas->drawPicture(picture); - canvas->flush(); -} - void Rasterizer::OnOutputSurfaceDestroyed() { if (context_) { CHECK(context_->MakeCurrent(surface_.get())); diff --git a/sky/shell/gpu/rasterizer.h b/sky/shell/gpu/rasterizer.h index ff8b687ac..21dcd0da2 100644 --- a/sky/shell/gpu/rasterizer.h +++ b/sky/shell/gpu/rasterizer.h @@ -34,12 +34,11 @@ class Rasterizer : public GPUDelegate { void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override; void OnOutputSurfaceDestroyed() override; - void Draw(PassRefPtr picture, gfx::Size size) override; + void Draw(scoped_ptr layer_tree) override; private: void EnsureGLContext(); void EnsureGaneshSurface(intptr_t window_fbo, const gfx::Size& size); - void DrawPicture(SkPicture* picture); scoped_refptr share_group_; scoped_refptr surface_; diff --git a/sky/shell/gpu_delegate.h b/sky/shell/gpu_delegate.h index 43cca28cf..b3bbe549f 100644 --- a/sky/shell/gpu_delegate.h +++ b/sky/shell/gpu_delegate.h @@ -5,7 +5,10 @@ #ifndef SKY_SHELL_GPU_DELEGATE_H_ #define SKY_SHELL_GPU_DELEGATE_H_ -#include "sky/engine/wtf/PassRefPtr.h" +#include + +#include "base/memory/scoped_ptr.h" +#include "sky/compositor/layer_tree.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" @@ -18,7 +21,7 @@ class GPUDelegate { public: virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0; virtual void OnOutputSurfaceDestroyed() = 0; - virtual void Draw(PassRefPtr picture, gfx::Size size) = 0; + virtual void Draw(scoped_ptr layer_tree) = 0; protected: virtual ~GPUDelegate(); diff --git a/sky/shell/ui/animator.cc b/sky/shell/ui/animator.cc index 1fc37546f..9ee517dfd 100644 --- a/sky/shell/ui/animator.cc +++ b/sky/shell/ui/animator.cc @@ -71,13 +71,18 @@ void Animator::BeginFrame(int64_t time_stamp) { base::TimeTicks frame_time = time_stamp ? base::TimeTicks::FromInternalValue(time_stamp) : base::TimeTicks::Now(); - engine_->BeginFrame(frame_time); - RefPtr picture = engine_->Paint(); + scoped_ptr layer_tree = + make_scoped_ptr(engine_->BeginFrame(frame_time).release()); + + if (!layer_tree) { + OnFrameComplete(); + return; + } config_.gpu_task_runner->PostTaskAndReply( FROM_HERE, - base::Bind(&GPUDelegate::Draw, config_.gpu_delegate, picture, - engine_->physical_size()), + base::Bind(&GPUDelegate::Draw, config_.gpu_delegate, + base::Passed(&layer_tree)), base::Bind(&Animator::OnFrameComplete, weak_factory_.GetWeakPtr())); } diff --git a/sky/shell/ui/engine.cc b/sky/shell/ui/engine.cc index b9a3efd44..f3f425147 100644 --- a/sky/shell/ui/engine.cc +++ b/sky/shell/ui/engine.cc @@ -96,27 +96,18 @@ void Engine::Init() { blink::initialize(g_platform_impl); } -void Engine::BeginFrame(base::TimeTicks frame_time) { +std::unique_ptr Engine::BeginFrame(base::TimeTicks frame_time) { TRACE_EVENT0("sky", "Engine::BeginFrame"); - if (sky_view_) - sky_view_->BeginFrame(frame_time); -} + if (!sky_view_) + return nullptr; -PassRefPtr Engine::Paint() { - TRACE_EVENT0("sky", "Engine::Paint"); - - if (sky_view_) { - RefPtr picture = sky_view_->Paint(); - if (picture) - return picture.release(); + std::unique_ptr layer_tree = sky_view_->BeginFrame(frame_time); + if (layer_tree) { + layer_tree->set_frame_size(SkISize::Make(physical_size_.width(), + physical_size_.height())); } - - SkPictureRecorder recorder; - SkCanvas* canvas = recorder.beginRecording( - physical_size_.width(), physical_size_.height()); - canvas->clear(SK_ColorBLACK); - return adoptRef(recorder.endRecordingAsPicture()); + return layer_tree; } void Engine::ConnectToEngine(mojo::InterfaceRequest request) { @@ -272,8 +263,6 @@ void Engine::StopDartTracing(mojo::ScopedDataPipeProducerHandle producer) { } void Engine::SaveFrameToSkPicture(const base::FilePath& destination) { - PassRefPtr picture = Paint(); - SerializePicture(destination.AsUTF8Unsafe().c_str(), picture.get()); } } // namespace shell diff --git a/sky/shell/ui/engine.h b/sky/shell/ui/engine.h index 8b682307e..794089f7a 100644 --- a/sky/shell/ui/engine.h +++ b/sky/shell/ui/engine.h @@ -55,9 +55,7 @@ class Engine : public UIDelegate, static void Init(); - void BeginFrame(base::TimeTicks frame_time); - PassRefPtr Paint(); - const gfx::Size& physical_size() { return physical_size_; } + std::unique_ptr BeginFrame(base::TimeTicks frame_time); void StartDartTracing(); void StopDartTracing(mojo::ScopedDataPipeProducerHandle producer); -- GitLab