diff --git a/content_handler/BUILD.gn b/content_handler/BUILD.gn index 08d26c34d..3fe63d5e4 100644 --- a/content_handler/BUILD.gn +++ b/content_handler/BUILD.gn @@ -12,16 +12,18 @@ executable("content_handler") { "application_impl.h", "content_handler_impl.cc", "content_handler_impl.h", - "framebuffer_skia.cc", - "framebuffer_skia.h", "main.cc", "rasterizer.cc", "rasterizer.h", "runtime_holder.cc", "runtime_holder.h", + "skia_surface_holder.cc", + "skia_surface_holder.h", ] deps = [ + "//apps/mozart/services/composition/interfaces", + "//apps/mozart/services/views/interfaces", "//dart/runtime:libdart", "//dart/runtime/vm:libdart_platform", "//flutter/assets", diff --git a/content_handler/application_impl.cc b/content_handler/application_impl.cc index c70ab762c..876a47cba 100644 --- a/content_handler/application_impl.cc +++ b/content_handler/application_impl.cc @@ -27,9 +27,6 @@ ApplicationImpl::ApplicationImpl( FTL_LOG(ERROR) << "Failed to receive bundle."; return; } - // TODO(abarth): In principle, we should call StartRuntimeIfReady() here but - // because we're draining the data pipe synchronously, we know that we can't - // possibly be ready yet because we haven't received the Initialize() message. } ApplicationImpl::~ApplicationImpl() {} @@ -42,24 +39,36 @@ void ApplicationImpl::Initialize(mojo::InterfaceHandle shell, mojo::ApplicationConnectorPtr connector; shell_->CreateApplicationConnector(mojo::GetProxy(&connector)); runtime_holder_.reset(new RuntimeHolder()); - runtime_holder_->Init(std::move(connector)); - StartRuntimeIfReady(); + runtime_holder_->Init(std::move(connector), std::move(bundle_)); } void ApplicationImpl::AcceptConnection( const mojo::String& requestor_url, const mojo::String& resolved_url, - mojo::InterfaceRequest services) {} + mojo::InterfaceRequest services) { + service_provider_bindings_.AddBinding(this, std::move(services)); +} void ApplicationImpl::RequestQuit() { binding_.Close(); delete this; } -void ApplicationImpl::StartRuntimeIfReady() { - if (!runtime_holder_ || bundle_.empty()) - return; - runtime_holder_->Run(url_, std::move(bundle_)); +void ApplicationImpl::ConnectToService( + const mojo::String& service_name, + mojo::ScopedMessagePipeHandle client_handle) { + if (service_name == mozart::ViewProvider::Name_) { + view_provider_bindings_.AddBinding( + this, + mojo::InterfaceRequest(std::move(client_handle))); + } +} + +void ApplicationImpl::CreateView( + mojo::InterfaceRequest view_owner_request, + mojo::InterfaceRequest services) { + runtime_holder_->CreateView(url_, std::move(view_owner_request), + std::move(services)); } } // namespace flutter_content_handler diff --git a/content_handler/application_impl.h b/content_handler/application_impl.h index 76f8a907d..142b2d53d 100644 --- a/content_handler/application_impl.h +++ b/content_handler/application_impl.h @@ -7,17 +7,22 @@ #include +#include "apps/mozart/services/views/interfaces/view_provider.mojom.h" #include "flutter/glue/drain_data_pipe_job.h" #include "lib/ftl/macros.h" +#include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/interfaces/application/application.mojom.h" +#include "mojo/public/interfaces/application/service_provider.mojom.h" #include "mojo/public/interfaces/application/shell.mojom.h" #include "mojo/services/content_handler/interfaces/content_handler.mojom.h" namespace flutter_content_handler { class RuntimeHolder; -class ApplicationImpl : public mojo::Application { +class ApplicationImpl : public mojo::Application, + public mojo::ServiceProvider, + public mozart::ViewProvider { public: ApplicationImpl(mojo::InterfaceRequest application, mojo::URLResponsePtr response); @@ -34,11 +39,23 @@ class ApplicationImpl : public mojo::Application { mojo::InterfaceRequest services) override; void RequestQuit() override; + // mojo::ServiceProvider + void ConnectToService(const mojo::String& service_name, + mojo::ScopedMessagePipeHandle client_handle) override; + + // mozart::ViewProvider + void CreateView( + mojo::InterfaceRequest view_owner_request, + mojo::InterfaceRequest services) override; + void StartRuntimeIfReady(); mojo::StrongBinding binding_; std::unique_ptr drainer_; + mojo::BindingSet service_provider_bindings_; + mojo::BindingSet view_provider_bindings_; + std::vector bundle_; mojo::ShellPtr shell_; std::string url_; diff --git a/content_handler/framebuffer_skia.cc b/content_handler/framebuffer_skia.cc deleted file mode 100644 index 402cb10ef..000000000 --- a/content_handler/framebuffer_skia.cc +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2016 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 "flutter/content_handler/framebuffer_skia.h" - -#include -#include - -#include - -#include "lib/ftl/logging.h" - -namespace flutter_content_handler { -namespace { - -struct BackingStoreInfo { - mx_handle_t vmo; - uintptr_t buffer; - size_t size; -}; - -void DidReleaseSurface(void* pixels, void* context) { - BackingStoreInfo* info = static_cast(context); - mx_process_unmap_vm(mx_process_self(), info->buffer, info->size); - mx_handle_close(info->vmo); - delete info; -} - -} // namespace - -FramebufferSkia::FramebufferSkia() {} - -FramebufferSkia::~FramebufferSkia() {} - -void FramebufferSkia::Bind(mojo::InterfaceHandle framebuffer, - mojo::FramebufferInfoPtr info) { - if (!framebuffer) { - FTL_LOG(ERROR) << "Failed to bind framebuffer"; - surface_ = nullptr; - return; - } - - framebuffer_.Bind(std::move(framebuffer)); - info_ = std::move(info); - - uintptr_t buffer = 0; - size_t row_bytes = info_->row_bytes; - size_t size = row_bytes * info_->size->height; - - mx_status_t status = - mx_process_map_vm(mx_process_self(), info_->vmo.get().value(), 0, size, - &buffer, MX_VM_FLAG_PERM_READ | MX_VM_FLAG_PERM_WRITE); - - if (status < 0) { - FTL_LOG(ERROR) << "Cannot map framebuffer (status=" << status << ")"; - return; - } - - SkColorType sk_color_type; - SkAlphaType sk_alpha_type; - switch (info_->format) { - case mojo::FramebufferFormat::RGB_565: - sk_color_type = kRGB_565_SkColorType; - sk_alpha_type = kOpaque_SkAlphaType; - break; - case mojo::FramebufferFormat::ARGB_8888: - sk_color_type = kBGRA_8888_SkColorType; - sk_alpha_type = kPremul_SkAlphaType; - break; - case mojo::FramebufferFormat::RGB_x888: - sk_color_type = kBGRA_8888_SkColorType; - sk_alpha_type = kOpaque_SkAlphaType; - break; - default: - FTL_LOG(ERROR) << "Unknown color type " << info_->format; - return; - } - - SkImageInfo image_info = SkImageInfo::Make( - info_->size->width, info_->size->height, sk_color_type, sk_alpha_type); - - BackingStoreInfo* backing_store_info = new BackingStoreInfo(); - backing_store_info->vmo = info_->vmo.release().value(); - backing_store_info->buffer = buffer; - backing_store_info->size = size; - - surface_ = SkSurface::MakeRasterDirectReleaseProc( - image_info, reinterpret_cast(buffer), row_bytes, DidReleaseSurface, - backing_store_info); -} - -void FramebufferSkia::Finish() { - framebuffer_->Flush([] {}); - framebuffer_.WaitForIncomingResponse(); -} - -} // namespace flutter_content_handler diff --git a/content_handler/framebuffer_skia.h b/content_handler/framebuffer_skia.h deleted file mode 100644 index 74cda8662..000000000 --- a/content_handler/framebuffer_skia.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 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 FLUTTER_CONTENT_HANDLER_FRAMEBUFFER_SKIA_H_ -#define FLUTTER_CONTENT_HANDLER_FRAMEBUFFER_SKIA_H_ - -#include "lib/ftl/macros.h" -#include "mojo/services/framebuffer/interfaces/framebuffer.mojom.h" -#include "third_party/skia/include/core/SkSurface.h" - -namespace flutter_content_handler { - -class FramebufferSkia { - public: - FramebufferSkia(); - ~FramebufferSkia(); - - void Bind(mojo::InterfaceHandle framebuffer, - mojo::FramebufferInfoPtr info); - - void Finish(); - const sk_sp& surface() { return surface_; } - - private: - mojo::FramebufferPtr framebuffer_; - mojo::FramebufferInfoPtr info_; - sk_sp surface_; - - FTL_DISALLOW_COPY_AND_ASSIGN(FramebufferSkia); -}; - -} // namespace flutter_content_handler - -#endif // FLUTTER_CONTENT_HANDLER_FRAMEBUFFER_SKIA_H_ diff --git a/content_handler/rasterizer.cc b/content_handler/rasterizer.cc index 517506519..52f8ebaa1 100644 --- a/content_handler/rasterizer.cc +++ b/content_handler/rasterizer.cc @@ -6,36 +6,76 @@ #include -#include "lib/ftl/functional/make_runnable.h" +#include "apps/mozart/services/composition/interfaces/image.mojom.h" +#include "flutter/content_handler/skia_surface_holder.h" +#include "lib/ftl/logging.h" #include "third_party/skia/include/core/SkCanvas.h" namespace flutter_content_handler { +namespace { +constexpr uint32_t kContentImageResourceId = 1; +constexpr uint32_t kRootNodeId = mozart::kSceneRootNodeId; +} // namespace + Rasterizer::Rasterizer() {} Rasterizer::~Rasterizer() {} -void Rasterizer::SetFramebuffer( - mojo::InterfaceHandle framebuffer, - mojo::FramebufferInfoPtr info) { - framebuffer_.Bind(std::move(framebuffer), std::move(info)); +void Rasterizer::SetScene(mojo::InterfaceHandle scene) { + scene_.Bind(std::move(scene)); } void Rasterizer::Draw(std::unique_ptr layer_tree, ftl::Closure callback) { - if (!framebuffer_.surface()) { + FTL_DCHECK(layer_tree); + if (!scene_) { callback(); return; } - SkCanvas* canvas = framebuffer_.surface()->getCanvas(); - flow::CompositorContext::ScopedFrame frame = - compositor_context_.AcquireFrame(nullptr, *canvas); - canvas->clear(SK_ColorBLACK); - layer_tree->Raster(frame); - canvas->flush(); + const SkISize& frame_size = layer_tree->frame_size(); + auto update = mozart::SceneUpdate::New(); + + if (!frame_size.isEmpty()) { + // TODO(jeffbrown): Maintain a pool of images and recycle them. + SkiaSurfaceHolder surface_holder(frame_size); + + SkCanvas* canvas = surface_holder.surface()->getCanvas(); + flow::CompositorContext::ScopedFrame frame = + compositor_context_.AcquireFrame(nullptr, *canvas); + canvas->clear(SK_ColorBLACK); + layer_tree->Raster(frame); + canvas->flush(); + + mojo::RectF bounds; + bounds.width = frame_size.width(); + bounds.height = frame_size.height(); + + auto content_resource = mozart::Resource::New(); + content_resource->set_image(mozart::ImageResource::New()); + content_resource->get_image()->image = surface_holder.TakeImage(); + update->resources.insert(kContentImageResourceId, content_resource.Pass()); + + auto root_node = mozart::Node::New(); + root_node->op = mozart::NodeOp::New(); + root_node->op->set_image(mozart::ImageNodeOp::New()); + root_node->op->get_image()->content_rect = bounds.Clone(); + root_node->op->get_image()->image_resource_id = kContentImageResourceId; + update->nodes.insert(kRootNodeId, root_node.Pass()); + + layer_tree->UpdateScene(update.get(), root_node.get()); + } else { + auto root_node = mozart::Node::New(); + update->nodes.insert(kRootNodeId, root_node.Pass()); + } + + scene_->Update(std::move(update)); + + auto metadata = mozart::SceneMetadata::New(); + metadata->version = layer_tree->scene_version(); + scene_->Publish(std::move(metadata)); - framebuffer_.Finish(); callback(); } diff --git a/content_handler/rasterizer.h b/content_handler/rasterizer.h index ee0bf2302..e15080d5c 100644 --- a/content_handler/rasterizer.h +++ b/content_handler/rasterizer.h @@ -5,13 +5,11 @@ #ifndef FLUTTER_CONTENT_HANDLER_RASTERIZER_H_ #define FLUTTER_CONTENT_HANDLER_RASTERIZER_H_ -#include "flutter/content_handler/framebuffer_skia.h" +#include "apps/mozart/services/composition/interfaces/scenes.mojom.h" #include "flutter/flow/compositor_context.h" #include "flutter/flow/layers/layer_tree.h" #include "lib/ftl/functional/closure.h" #include "lib/ftl/macros.h" -#include "mojo/services/framebuffer/interfaces/framebuffer.mojom.h" -#include "third_party/skia/include/core/SkSurface.h" namespace flutter_content_handler { @@ -20,14 +18,12 @@ class Rasterizer { Rasterizer(); ~Rasterizer(); - void SetFramebuffer(mojo::InterfaceHandle framebuffer, - mojo::FramebufferInfoPtr info); + void SetScene(mojo::InterfaceHandle scene); void Draw(std::unique_ptr layer_tree, ftl::Closure callback); private: - FramebufferSkia framebuffer_; - sk_sp surface_; + mozart::ScenePtr scene_; flow::CompositorContext compositor_context_; FTL_DISALLOW_COPY_AND_ASSIGN(Rasterizer); diff --git a/content_handler/runtime_holder.cc b/content_handler/runtime_holder.cc index 0d1c27d9a..c2692249e 100644 --- a/content_handler/runtime_holder.cc +++ b/content_handler/runtime_holder.cc @@ -24,14 +24,20 @@ namespace flutter_content_handler { namespace { constexpr char kSnapshotKey[] = "snapshot_blob.bin"; -constexpr int kPipelineDepth = 3; -constexpr ftl::TimeDelta kTargetFrameInterval = - ftl::TimeDelta::FromMilliseconds(16); + +// Maximum number of frames in flight. +constexpr int kMaxPipelineDepth = 3; + +// When the max pipeline depth is exceeded, drain to this number of frames +// to recover before acknowleding the invalidation and scheduling more frames. +constexpr int kRecoveryPipelineDepth = 1; } // namespace RuntimeHolder::RuntimeHolder() - : viewport_metrics_(sky::ViewportMetrics::New()), weak_factory_(this) {} + : viewport_metrics_(sky::ViewportMetrics::New()), + view_listener_binding_(this), + weak_factory_(this) {} RuntimeHolder::~RuntimeHolder() { blink::Threads::Gpu()->PostTask( @@ -40,22 +46,26 @@ RuntimeHolder::~RuntimeHolder() { })); } -void RuntimeHolder::Init(mojo::ApplicationConnectorPtr connector) { +void RuntimeHolder::Init(mojo::ApplicationConnectorPtr connector, + std::vector bundle) { FTL_DCHECK(!rasterizer_); rasterizer_.reset(new Rasterizer()); - mojo::ConnectToService(connector.get(), "mojo:framebuffer", - mojo::GetProxy(&framebuffer_provider_)); - framebuffer_provider_->Create(ftl::MakeRunnable([self = GetWeakPtr()]( - mojo::InterfaceHandle framebuffer, - mojo::FramebufferInfoPtr info) { - if (self) - self->DidCreateFramebuffer(std::move(framebuffer), std::move(info)); - })); + InitRootBundle(std::move(bundle)); + + mojo::ConnectToService(connector.get(), "mojo:view_manager_service", + mojo::GetProxy(&view_manager_)); } -void RuntimeHolder::Run(const std::string& script_uri, - std::vector bundle) { - InitRootBundle(std::move(bundle)); +void RuntimeHolder::CreateView( + const std::string& script_uri, + mojo::InterfaceRequest view_owner_request, + mojo::InterfaceRequest services) { + if (view_listener_binding_.is_bound()) { + // TODO(jeffbrown): Refactor this to support multiple view instances + // sharing the same underlying root bundle (but with different runtimes). + FTL_LOG(ERROR) << "The view has already been created."; + return; + } std::vector snapshot; if (!asset_store_->GetAsBuffer(kSnapshotKey, &snapshot)) { @@ -63,6 +73,18 @@ void RuntimeHolder::Run(const std::string& script_uri, return; } + mozart::ViewListenerPtr view_listener; + view_listener_binding_.Bind(mojo::GetProxy(&view_listener)); + view_manager_->CreateView(mojo::GetProxy(&view_), + std::move(view_owner_request), + std::move(view_listener), script_uri); + + mozart::ScenePtr scene; + view_->CreateScene(mojo::GetProxy(&scene)); + blink::Threads::Gpu()->PostTask(ftl::MakeCopyable([ + rasterizer = rasterizer_.get(), scene = std::move(scene) + ]() mutable { rasterizer->SetScene(std::move(scene)); })); + runtime_ = blink::RuntimeController::Create(this); runtime_->CreateDartController(script_uri); runtime_->SetViewportMetrics(viewport_metrics_); @@ -71,19 +93,10 @@ void RuntimeHolder::Run(const std::string& script_uri, } void RuntimeHolder::ScheduleFrame() { - if (runtime_requested_frame_) + if (pending_invalidation_ || !deferred_invalidation_callback_.is_null()) return; - runtime_requested_frame_ = true; - - FTL_DCHECK(!did_defer_frame_request_); - ++outstanding_requests_; - - if (outstanding_requests_ >= kPipelineDepth) { - did_defer_frame_request_ = true; - return; - } - - ScheduleDelayedFrame(); + pending_invalidation_ = true; + view_->Invalidate(); } void RuntimeHolder::Render(std::unique_ptr layer_tree) { @@ -91,6 +104,10 @@ void RuntimeHolder::Render(std::unique_ptr layer_tree) { return; // Only draw once per frame. is_ready_to_draw_ = false; + layer_tree->set_frame_size(SkISize::Make(viewport_metrics_->physical_width, + viewport_metrics_->physical_height)); + layer_tree->set_scene_version(scene_version_); + blink::Threads::Gpu()->PostTask(ftl::MakeCopyable([ rasterizer = rasterizer_.get(), layer_tree = std::move(layer_tree), self = GetWeakPtr() @@ -129,42 +146,51 @@ blink::UnzipperProvider RuntimeHolder::GetUnzipperProviderForRootBundle() { }; } -void RuntimeHolder::DidCreateFramebuffer( - mojo::InterfaceHandle framebuffer, - mojo::FramebufferInfoPtr info) { - viewport_metrics_->physical_width = info->size->width; - viewport_metrics_->physical_height = info->size->height; - if (runtime_) - runtime_->SetViewportMetrics(viewport_metrics_); +void RuntimeHolder::OnInvalidation(mozart::ViewInvalidationPtr invalidation, + const OnInvalidationCallback& callback) { + FTL_DCHECK(invalidation); + pending_invalidation_ = false; - blink::Threads::Gpu()->PostTask(ftl::MakeCopyable([ - rasterizer = rasterizer_.get(), framebuffer = std::move(framebuffer), - info = std::move(info) - ]() mutable { - rasterizer->SetFramebuffer(std::move(framebuffer), std::move(info)); - })); + // Apply view property changes. + if (invalidation->properties) { + view_properties_ = std::move(invalidation->properties); + viewport_metrics_->physical_width = + view_properties_->view_layout->size->width; + viewport_metrics_->physical_height = + view_properties_->view_layout->size->height; + viewport_metrics_->device_pixel_ratio = + view_properties_->display_metrics->device_pixel_ratio; + runtime_->SetViewportMetrics(viewport_metrics_); + } + + // Remember the scene version for rendering. + scene_version_ = invalidation->scene_version; + + // TODO(jeffbrown): Flow the frame time through the rendering pipeline. + if (outstanding_requests_ >= kMaxPipelineDepth) { + FTL_DCHECK(deferred_invalidation_callback_.is_null()); + deferred_invalidation_callback_ = callback; + return; + } + + ++outstanding_requests_; + BeginFrame(); + + // TODO(jeffbrown): Consider running the callback earlier. + // Note that this may result in the view processing stale view properties + // (such as size) if it prematurely acks the frame but takes too long + // to handle it. + callback.Run(); } ftl::WeakPtr RuntimeHolder::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } -void RuntimeHolder::ScheduleDelayedFrame() { - // TODO(abarth): We should align with vsync or with our own timer pulse. - blink::Threads::UI()->PostDelayedTask( - [self = GetWeakPtr()]() { - if (self) - self->BeginFrame(); - }, - kTargetFrameInterval); -} - void RuntimeHolder::BeginFrame() { FTL_DCHECK(outstanding_requests_ > 0); - FTL_DCHECK(outstanding_requests_ <= kPipelineDepth) << outstanding_requests_; - - FTL_DCHECK(runtime_requested_frame_); - runtime_requested_frame_ = false; + FTL_DCHECK(outstanding_requests_ <= kMaxPipelineDepth) + << outstanding_requests_; FTL_DCHECK(!is_ready_to_draw_); is_ready_to_draw_ = true; @@ -183,9 +209,15 @@ void RuntimeHolder::OnFrameComplete() { FTL_DCHECK(outstanding_requests_ > 0); --outstanding_requests_; - if (did_defer_frame_request_) { - did_defer_frame_request_ = false; - ScheduleDelayedFrame(); + if (!deferred_invalidation_callback_.is_null() && + outstanding_requests_ <= kRecoveryPipelineDepth) { + // Schedule frame first to avoid potentially generating a second + // invalidation in case the view manager already has one pending + // awaiting acknowledgement of the deferred invalidation. + OnInvalidationCallback callback = deferred_invalidation_callback_; + deferred_invalidation_callback_.reset(); + ScheduleFrame(); + callback.Run(); } } diff --git a/content_handler/runtime_holder.h b/content_handler/runtime_holder.h index afea41bf8..0aeddff42 100644 --- a/content_handler/runtime_holder.h +++ b/content_handler/runtime_holder.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_CONTENT_HANDLER_RUNTIME_HOLDER_H_ #define FLUTTER_CONTENT_HANDLER_RUNTIME_HOLDER_H_ +#include "apps/mozart/services/views/interfaces/view_manager.mojom.h" #include "flutter/assets/unzipper_provider.h" #include "flutter/assets/zip_asset_store.h" #include "flutter/flow/layers/layer_tree.h" @@ -14,20 +15,22 @@ #include "lib/ftl/functional/closure.h" #include "lib/ftl/macros.h" #include "lib/ftl/memory/weak_ptr.h" +#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/interfaces/application/application_connector.mojom.h" #include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h" -#include "mojo/services/framebuffer/interfaces/framebuffer.mojom.h" namespace flutter_content_handler { class Rasterizer; -class RuntimeHolder : public blink::RuntimeDelegate { +class RuntimeHolder : public blink::RuntimeDelegate, mozart::ViewListener { public: RuntimeHolder(); ~RuntimeHolder(); - void Init(mojo::ApplicationConnectorPtr connector); - void Run(const std::string& script_uri, std::vector bundle); + void Init(mojo::ApplicationConnectorPtr connector, std::vector bundle); + void CreateView(const std::string& script_uri, + mojo::InterfaceRequest view_owner_request, + mojo::InterfaceRequest services); private: // |blink::RuntimeDelegate| implementation: @@ -35,30 +38,35 @@ class RuntimeHolder : public blink::RuntimeDelegate { void Render(std::unique_ptr layer_tree) override; void DidCreateMainIsolate(Dart_Isolate isolate) override; + // |mozart::ViewListener| implementation: + void OnInvalidation(mozart::ViewInvalidationPtr invalidation, + const OnInvalidationCallback& callback) override; + ftl::WeakPtr GetWeakPtr(); void InitRootBundle(std::vector bundle); blink::UnzipperProvider GetUnzipperProviderForRootBundle(); - void DidCreateFramebuffer( - mojo::InterfaceHandle framebuffer, - mojo::FramebufferInfoPtr info); - - void ScheduleDelayedFrame(); void BeginFrame(); void OnFrameComplete(); + void Invalidate(); std::vector root_bundle_data_; ftl::RefPtr asset_store_; mojo::asset_bundle::AssetBundlePtr root_bundle_; - mojo::FramebufferProviderPtr framebuffer_provider_; std::unique_ptr rasterizer_; std::unique_ptr runtime_; sky::ViewportMetricsPtr viewport_metrics_; - bool runtime_requested_frame_ = false; - bool did_defer_frame_request_ = false; + mozart::ViewManagerPtr view_manager_; + mojo::Binding view_listener_binding_; + mozart::ViewPtr view_; + mozart::ViewPropertiesPtr view_properties_; + uint32_t scene_version_ = mozart::kSceneVersionNone; + + bool pending_invalidation_ = false; + OnInvalidationCallback deferred_invalidation_callback_; bool is_ready_to_draw_ = false; int outstanding_requests_ = 0; diff --git a/content_handler/skia_surface_holder.cc b/content_handler/skia_surface_holder.cc new file mode 100644 index 000000000..807bec99c --- /dev/null +++ b/content_handler/skia_surface_holder.cc @@ -0,0 +1,48 @@ +// Copyright 2016 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 "flutter/content_handler/skia_surface_holder.h" + +#include "lib/ftl/logging.h" +#include "mojo/public/cpp/system/buffer.h" +#include "third_party/skia/include/core/SkCanvas.h" + +namespace flutter_content_handler { + +SkiaSurfaceHolder::SkiaSurfaceHolder(const SkISize& size) { + size_t row_bytes = size.width() * sizeof(uint32_t); + size_t total_bytes = size.height() * row_bytes; + + FTL_CHECK(MOJO_RESULT_OK == + mojo::CreateSharedBuffer(nullptr, total_bytes, &buffer_handle_)); + FTL_CHECK(MOJO_RESULT_OK == mojo::MapBuffer(buffer_handle_.get(), 0u, + total_bytes, &buffer_, + MOJO_MAP_BUFFER_FLAG_NONE)); + + surface_ = SkSurface::MakeRasterDirect( + SkImageInfo::Make(size.width(), size.height(), kBGRA_8888_SkColorType, + kPremul_SkAlphaType), + buffer_, row_bytes); + FTL_CHECK(surface_); +} + +SkiaSurfaceHolder::~SkiaSurfaceHolder() { + FTL_CHECK(MOJO_RESULT_OK == mojo::UnmapBuffer(buffer_)); +} + +mozart::ImagePtr SkiaSurfaceHolder::TakeImage() { + FTL_DCHECK(buffer_handle_.get().value()); + + auto image = mozart::Image::New(); + image->size = mojo::Size::New(); + image->size->width = surface_->width(); + image->size->height = surface_->height(); + image->stride = image->size->width * sizeof(uint32_t); + image->pixel_format = mozart::Image::PixelFormat::B8G8R8A8; + image->alpha_format = mozart::Image::AlphaFormat::PREMULTIPLIED; + image->buffer = std::move(buffer_handle_); + return image; +} + +} // namespace flutter_content_handler diff --git a/content_handler/skia_surface_holder.h b/content_handler/skia_surface_holder.h new file mode 100644 index 000000000..5e764d0d4 --- /dev/null +++ b/content_handler/skia_surface_holder.h @@ -0,0 +1,47 @@ +// Copyright 2016 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 FLUTTER_CONTENT_HANDLER_SKIA_SURFACE_HOLDER_H_ +#define FLUTTER_CONTENT_HANDLER_SKIA_SURFACE_HOLDER_H_ + +#include "apps/mozart/services/composition/interfaces/image.mojom.h" +#include "lib/ftl/macros.h" +#include "mojo/services/geometry/interfaces/geometry.mojom.h" +#include "third_party/skia/include/core/SkSize.h" +#include "third_party/skia/include/core/SkSurface.h" + +namespace flutter_content_handler { + +// Provides an |SkSurface| backed by a shared memory buffer for software +// rendering which can then be passed to the Mozart compositor in the form +// of an |Image|. +class SkiaSurfaceHolder { + public: + SkiaSurfaceHolder(const SkISize& size); + ~SkiaSurfaceHolder(); + + // Gets the |SkSurface| backed by this buffer. + const sk_sp& surface() const { return surface_; } + + // Gets an |Image| backed by this buffer, transferring ownership of the + // underlying shared memory buffer to the image. The image can then be + // sent to the Mozart compositor as an |ImageResource|. + // This method must be called at most once. + // + // Note: The underlying shared memory buffer remains mapped in this process + // (and the |SkSurface| remains usable) until the |SkiaSurfaceHolder| + // itself is destroyed. + mozart::ImagePtr TakeImage(); + + private: + mojo::ScopedSharedBufferHandle buffer_handle_; + void* buffer_; + sk_sp surface_; + + FTL_DISALLOW_COPY_AND_ASSIGN(SkiaSurfaceHolder); +}; + +} // namespace flutter_content_handler + +#endif // FLUTTER_CONTENT_HANDLER_SKIA_SURFACE_HOLDER_H_ diff --git a/flow/BUILD.gn b/flow/BUILD.gn index 3bcb43e2f..cf444faa3 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -10,8 +10,6 @@ source_set("flow") { "instrumentation.h", "layers/backdrop_filter_layer.cc", "layers/backdrop_filter_layer.h", - "layers/child_scene_layer.cc", - "layers/child_scene_layer.h", "layers/clip_path_layer.cc", "layers/clip_path_layer.h", "layers/clip_rect_layer.cc", @@ -48,13 +46,17 @@ source_set("flow") { "//flutter/skia", "//flutter/synchronization", "//lib/ftl", - "//mojo/services/gfx/composition/interfaces", ] if (is_fuchsia) { sources += [ + "layers/child_scene_layer.cc", + "layers/child_scene_layer.h", "texture_image_none.cc", ] + deps += [ + "//apps/mozart/services/composition/interfaces", + ] } else { sources += [ "gl_connection.cc", diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index de9cb3707..1ae7cbd3c 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -50,18 +50,19 @@ void ChildSceneLayer::Paint(PaintContext& context) { TRACE_EVENT0("flutter", "ChildSceneLayer::Paint"); } -void ChildSceneLayer::UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container) { +void ChildSceneLayer::UpdateScene(mozart::SceneUpdate* update, + mozart::Node* container) { uint32_t id = next_id++; - auto child_resource = mojo::gfx::composition::Resource::New(); - child_resource->set_scene(mojo::gfx::composition::SceneResource::New()); - child_resource->get_scene()->scene_token = scene_token_.Clone(); + auto child_resource = mozart::Resource::New(); + child_resource->set_scene(mozart::SceneResource::New()); + child_resource->get_scene()->scene_token = mozart::SceneToken::New(); + child_resource->get_scene()->scene_token->value = scene_token_; update->resources.insert(id, child_resource.Pass()); - auto child_node = mojo::gfx::composition::Node::New(); - child_node->op = mojo::gfx::composition::NodeOp::New(); - child_node->op->set_scene(mojo::gfx::composition::SceneNodeOp::New()); + auto child_node = mozart::Node::New(); + child_node->op = mozart::NodeOp::New(); + child_node->op->set_scene(mozart::SceneNodeOp::New()); child_node->op->get_scene()->scene_resource_id = id; child_node->content_clip = mojo::RectF::New(); child_node->content_clip->width = physical_size_.width(); diff --git a/flow/layers/child_scene_layer.h b/flow/layers/child_scene_layer.h index c2461caa2..86262d9ef 100644 --- a/flow/layers/child_scene_layer.h +++ b/flow/layers/child_scene_layer.h @@ -6,7 +6,7 @@ #define FLUTTER_FLOW_LAYERS_CHILD_SCENE_LAYER_H_ #include "flutter/flow/layers/layer.h" -#include "mojo/services/gfx/composition/interfaces/scenes.mojom.h" +#include "apps/mozart/services/composition/interfaces/scenes.mojom.h" namespace flow { @@ -25,20 +25,18 @@ class ChildSceneLayer : public Layer { physical_size_ = physical_size; } - void set_scene_token(mojo::gfx::composition::SceneTokenPtr scene_token) { - scene_token_ = scene_token.Pass(); - } + void set_scene_token(uint32_t scene_token) { scene_token_ = scene_token; } void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) override; - void UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container) override; + void UpdateScene(mozart::SceneUpdate* update, + mozart::Node* container) override; private: SkPoint offset_; float device_pixel_ratio_; SkISize physical_size_; - mojo::gfx::composition::SceneTokenPtr scene_token_; + uint32_t scene_token_; SkMatrix transform_; FTL_DISALLOW_COPY_AND_ASSIGN(ChildSceneLayer); diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index 684e98815..d2da8a5de 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -39,10 +39,12 @@ void ContainerLayer::PaintChildren(PaintContext& context) const { layer->Paint(context); } -void ContainerLayer::UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container) { +#if defined(OS_FUCHSIA) +void ContainerLayer::UpdateScene(mozart::SceneUpdate* update, + mozart::Node* container) { for (auto& layer : layers_) layer->UpdateScene(update, container); } +#endif } // namespace flow diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index 1663b35fd..4eedf389e 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -22,8 +22,10 @@ class ContainerLayer : public Layer { void PaintChildren(PaintContext& context) const; - void UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container) override; +#if defined(OS_FUCHSIA) + void UpdateScene(mozart::SceneUpdate* update, + mozart::Node* container) override; +#endif const std::vector>& layers() const { return layers_; } diff --git a/flow/layers/layer.cc b/flow/layers/layer.cc index 3bbcec8ab..ef9ed6de3 100644 --- a/flow/layers/layer.cc +++ b/flow/layers/layer.cc @@ -14,7 +14,8 @@ Layer::~Layer() {} void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {} -void Layer::UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container) {} +#if defined(OS_FUCHSIA) +void Layer::UpdateScene(mozart::SceneUpdate* update, mozart::Node* container) {} +#endif } // namespace flow diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 31b02ae21..52515d26c 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -11,6 +11,7 @@ #include "flutter/flow/instrumentation.h" #include "flutter/flow/raster_cache.h" #include "flutter/glue/trace_event.h" +#include "lib/ftl/build_config.h" #include "lib/ftl/logging.h" #include "lib/ftl/macros.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -23,14 +24,12 @@ #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkXfermode.h" -namespace mojo { -namespace gfx { -namespace composition { +#if defined(OS_FUCHSIA) +namespace mozart { class SceneUpdate; class Node; -} // composition -} // namespace gfx -} // namespace mojo +} // namespace mozart +#endif namespace flow { @@ -55,8 +54,11 @@ class Layer { }; virtual void Paint(PaintContext& context) = 0; - virtual void UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container); + +#if defined(OS_FUCHSIA) + virtual void UpdateScene(mozart::SceneUpdate* update, + mozart::Node* container); +#endif ContainerLayer* parent() const { return parent_; } diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 72ff3255c..c0262f091 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -9,7 +9,8 @@ namespace flow { -LayerTree::LayerTree() : scene_version_(0), rasterizer_tracing_threshold_(0) {} +LayerTree::LayerTree() + : frame_size_{}, scene_version_(0), rasterizer_tracing_threshold_(0) {} LayerTree::~LayerTree() {} @@ -32,10 +33,12 @@ void LayerTree::Raster(CompositorContext::ScopedFrame& frame, } } -void LayerTree::UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container) { +#if defined(OS_FUCHSIA) +void LayerTree::UpdateScene(mozart::SceneUpdate* update, + mozart::Node* container) { TRACE_EVENT0("flutter", "LayerTree::UpdateScene"); root_layer_->UpdateScene(update, container); } +#endif } // namespace flow diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 34786a426..f1dfcdb36 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -26,11 +26,12 @@ class LayerTree { void Raster(CompositorContext::ScopedFrame& frame, bool ignore_raster_cache = false); +#if defined(OS_FUCHSIA) // TODO(abarth): Integrate scene updates with the rasterization pass so that // we can draw on top of child scenes (and so that we can apply clips and // blending operations to child scene). - void UpdateScene(mojo::gfx::composition::SceneUpdate* update, - mojo::gfx::composition::Node* container); + void UpdateScene(mozart::SceneUpdate* update, mozart::Node* container); +#endif Layer* root_layer() const { return root_layer_.get(); } diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index b12e38cf9..e48b886da 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -5,7 +5,6 @@ #include "flutter/lib/ui/compositing/scene_builder.h" #include "flutter/flow/layers/backdrop_filter_layer.h" -#include "flutter/flow/layers/child_scene_layer.h" #include "flutter/flow/layers/clip_path_layer.h" #include "flutter/flow/layers/clip_rect_layer.h" #include "flutter/flow/layers/clip_rrect_layer.h" @@ -18,12 +17,17 @@ #include "flutter/flow/layers/transform_layer.h" #include "flutter/lib/ui/painting/matrix.h" #include "flutter/lib/ui/painting/shader.h" +#include "lib/ftl/build_config.h" #include "lib/tonic/dart_args.h" #include "lib/tonic/dart_binding_macros.h" #include "lib/tonic/converter/dart_converter.h" #include "lib/tonic/dart_library_natives.h" #include "third_party/skia/include/core/SkColorFilter.h" +#if defined(OS_FUCHSIA) +#include "flutter/flow/layers/child_scene_layer.h" +#endif + namespace blink { static void SceneBuilder_constructor(Dart_NativeArguments args) { @@ -197,17 +201,16 @@ void SceneBuilder::addChildScene(double dx, int physicalWidth, int physicalHeight, uint32_t sceneToken) { +#if defined(OS_FUCHSIA) if (!m_currentLayer) return; std::unique_ptr layer(new flow::ChildSceneLayer()); layer->set_offset(SkPoint::Make(dx, dy)); layer->set_device_pixel_ratio(devicePixelRatio); layer->set_physical_size(SkISize::Make(physicalWidth, physicalHeight)); - mojo::gfx::composition::SceneTokenPtr token = - mojo::gfx::composition::SceneToken::New(); - token->value = sceneToken; - layer->set_scene_token(token.Pass()); + layer->set_scene_token(sceneToken); m_currentLayer->Add(std::move(layer)); +#endif } void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, diff --git a/lib/ui/mojo_services.cc b/lib/ui/mojo_services.cc index cf9307948..c771deecc 100644 --- a/lib/ui/mojo_services.cc +++ b/lib/ui/mojo_services.cc @@ -49,13 +49,6 @@ void DartTakeShell(Dart_NativeArguments args) { Dart_SetIntegerReturnValue(args, handle); } -void DartTakeView(Dart_NativeArguments args) { - int handle = MOJO_HANDLE_INVALID; - if (MojoServices* services = GetMojoServices()) - handle = services->TakeView(); - Dart_SetIntegerReturnValue(args, handle); -} - void DartTakeViewServices(Dart_NativeArguments args) { int handle = MOJO_HANDLE_INVALID; if (MojoServices* services = GetMojoServices()) @@ -71,7 +64,6 @@ void MojoServices::RegisterNatives(tonic::DartLibraryNatives* natives) { {"MojoServices_takeIncomingServices", DartTakeIncomingServices, 0, true}, {"MojoServices_takeOutgoingServices", DartTakeOutgoingServices, 0, true}, {"MojoServices_takeShell", DartTakeShell, 0, true}, - {"MojoServices_takeView", DartTakeView, 0, true}, {"MojoServices_takeViewServices", DartTakeViewServices, 0, true}, }); } @@ -122,12 +114,6 @@ int MojoServices::TakeShell() { return MOJO_HANDLE_INVALID; } -int MojoServices::TakeView() { - if (services_) - return services_->view.PassHandle().release().value(); - return MOJO_HANDLE_INVALID; -} - int MojoServices::TakeViewServices() { if (services_) return services_->view_services.PassHandle().release().value(); diff --git a/lib/ui/mojo_services.dart b/lib/ui/mojo_services.dart index ee76e6f95..a7d472119 100644 --- a/lib/ui/mojo_services.dart +++ b/lib/ui/mojo_services.dart @@ -16,6 +16,5 @@ class MojoServices { static int takeIncomingServices() native "MojoServices_takeIncomingServices"; static int takeOutgoingServices() native "MojoServices_takeOutgoingServices"; static int takeShell() native "MojoServices_takeShell"; - static int takeView() native "MojoServices_takeView"; static int takeViewServices() native "MojoServices_takeViewServices"; } diff --git a/services/engine/BUILD.gn b/services/engine/BUILD.gn index a0eb41565..ef44b7121 100644 --- a/services/engine/BUILD.gn +++ b/services/engine/BUILD.gn @@ -11,10 +11,8 @@ mojom("interfaces") { ] deps = [ + "//flutter/services/pointer:interfaces", "//mojo/public/interfaces/application", "//mojo/services/asset_bundle/interfaces", - "//mojo/services/gfx/composition/interfaces", - "//mojo/services/ui/views/interfaces", - "//flutter/services/pointer:interfaces", ] } diff --git a/services/engine/sky_engine.mojom b/services/engine/sky_engine.mojom index d75d7a590..3c054af79 100644 --- a/services/engine/sky_engine.mojom +++ b/services/engine/sky_engine.mojom @@ -4,12 +4,11 @@ module sky; +import "flutter/services/engine/input_event.mojom"; +import "flutter/services/pointer/pointer.mojom"; import "mojo/public/interfaces/application/service_provider.mojom"; import "mojo/public/interfaces/application/shell.mojom"; import "mojo/services/asset_bundle/interfaces/asset_bundle.mojom"; -import "mojo/services/ui/views/interfaces/views.mojom"; -import "flutter/services/engine/input_event.mojom"; -import "flutter/services/pointer/pointer.mojom"; enum AppLifecycleState { PAUSED, @@ -31,7 +30,6 @@ struct ServicesData { mojo.Shell? shell; mojo.ServiceProvider? incoming_services; mojo.ServiceProvider&? outgoing_services; - mojo.ui.View? view; mojo.ServiceProvider? view_services; }; diff --git a/sky/packages/flutter_services/lib/mojo/gfx/composition/scene_token.dart b/sky/packages/flutter_services/lib/mojo/gfx/composition/scene_token.dart deleted file mode 100644 index 7f01742ce..000000000 --- a/sky/packages/flutter_services/lib/mojo/gfx/composition/scene_token.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// Copyright 2016 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. - -import 'package:mojo_services/mojo/gfx/composition/scene_token.mojom.dart'; -export 'package:mojo_services/mojo/gfx/composition/scene_token.mojom.dart'; diff --git a/sky/packages/flutter_services/lib/mojo/ui/view_containers.dart b/sky/packages/flutter_services/lib/mojo/ui/view_containers.dart deleted file mode 100644 index fffde1acd..000000000 --- a/sky/packages/flutter_services/lib/mojo/ui/view_containers.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// Copyright 2016 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. - -import 'package:mojo_services/mojo/ui/view_containers.mojom.dart'; -export 'package:mojo_services/mojo/ui/view_containers.mojom.dart'; diff --git a/sky/packages/flutter_services/lib/mojo/ui/view_properties.dart b/sky/packages/flutter_services/lib/mojo/ui/view_properties.dart deleted file mode 100644 index 50f8ce978..000000000 --- a/sky/packages/flutter_services/lib/mojo/ui/view_properties.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// Copyright 2016 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. - -import 'package:mojo_services/mojo/ui/view_properties.mojom.dart'; -export 'package:mojo_services/mojo/ui/view_properties.mojom.dart'; diff --git a/sky/packages/flutter_services/lib/mojo/ui/view_provider.dart b/sky/packages/flutter_services/lib/mojo/ui/view_provider.dart deleted file mode 100644 index e1f08f37c..000000000 --- a/sky/packages/flutter_services/lib/mojo/ui/view_provider.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// Copyright 2016 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. - -import 'package:mojo_services/mojo/ui/view_provider.mojom.dart'; -export 'package:mojo_services/mojo/ui/view_provider.mojom.dart'; diff --git a/sky/packages/flutter_services/lib/mojo/ui/view_token.dart b/sky/packages/flutter_services/lib/mojo/ui/view_token.dart deleted file mode 100644 index a21de77d3..000000000 --- a/sky/packages/flutter_services/lib/mojo/ui/view_token.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// Copyright 2016 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. - -import 'package:mojo_services/mojo/ui/view_token.mojom.dart'; -export 'package:mojo_services/mojo/ui/view_token.mojom.dart'; diff --git a/sky/packages/flutter_services/lib/mojo/ui/views.dart b/sky/packages/flutter_services/lib/mojo/ui/views.dart deleted file mode 100644 index ed187b5a6..000000000 --- a/sky/packages/flutter_services/lib/mojo/ui/views.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// Copyright 2016 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. - -import 'package:mojo_services/mojo/ui/views.mojom.dart'; -export 'package:mojo_services/mojo/ui/views.mojom.dart';