Port flutter.mojo to Mozart

Everything should work except the keyboard.
This commit is contained in:
Adam Barth 2016-01-27 22:10:37 -08:00
parent 4d246f47d2
commit 411c6bfa4b
22 changed files with 785 additions and 406 deletions

View File

@ -13,6 +13,7 @@ mojom("interfaces") {
deps = [
"//mojo/public/interfaces/application",
"//mojo/services/asset_bundle/interfaces",
"//mojo/services/gfx/composition/interfaces",
"//mojo/services/service_registry/interfaces",
"//sky/services/pointer:interfaces",
]

View File

@ -7,6 +7,7 @@ module sky;
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/gfx/composition/interfaces/scheduling.mojom";
import "mojo/services/service_registry/interfaces/service_registry.mojom";
import "sky/services/engine/input_event.mojom";
import "sky/services/pointer/pointer.mojom";
@ -31,6 +32,7 @@ struct ServicesData {
mojo.ServiceRegistry? service_registry;
mojo.ServiceProvider? services_provided_by_embedder;
mojo.ServiceProvider&? services_provided_to_embedder;
mojo.gfx.composition.SceneScheduler? scene_scheduler;
};
[ServiceName="sky::SkyEngine"]

View File

@ -44,6 +44,7 @@ source_set("common") {
"//mojo/public/cpp/application",
"//mojo/public/interfaces/application",
"//mojo/services/asset_bundle/interfaces",
"//mojo/services/gfx/composition/interfaces",
"//mojo/services/keyboard/interfaces",
"//mojo/services/navigation/interfaces",
"//mojo/services/vsync/interfaces",
@ -76,17 +77,17 @@ source_set("gpu_direct") {
source_set("gpu_mojo") {
sources = [
"gpu/mojo/gl_texture_recycler.cc",
"gpu/mojo/gl_texture_recycler.h",
"gpu/mojo/rasterizer_mojo.cc",
"gpu/mojo/rasterizer_mojo.h",
]
deps = [
":common",
"//mojo/gpu",
"//mojo/public/c/gpu",
"//mojo/public/c/gpu:gpu_onscreen",
"//mojo/services/gpu/interfaces",
"//mojo/services/native_viewport/interfaces",
"//mojo/skia:skia_bindings",
"//mojo/skia",
":common",
]
}

View File

@ -0,0 +1,126 @@
// 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 "sky/shell/gpu/mojo/gl_texture_recycler.h"
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif
#include <GLES2/gl2.h>
#include <GLES2/gl2extmojo.h>
#include "mojo/gpu/gl_context.h"
#include "mojo/gpu/gl_texture.h"
namespace sky {
namespace shell {
GLTextureRecycler::GLTextureRecycler(base::WeakPtr<mojo::GLContext> gl_context,
uint32_t max_recycled_textures)
: gl_context_(gl_context),
max_recycled_textures_(max_recycled_textures),
weak_factory_(this) {}
GLTextureRecycler::~GLTextureRecycler() {}
std::unique_ptr<mojo::GLTexture> GLTextureRecycler::GetTexture(
const mojo::Size& requested_size) {
if (!gl_context_) {
recycled_textures_.clear();
return nullptr;
}
while (!recycled_textures_.empty()) {
GLRecycledTextureInfo texture_info(std::move(recycled_textures_.front()));
recycled_textures_.pop_front();
if (texture_info.first->size().Equals(requested_size)) {
gl_context_->MakeCurrent();
glWaitSyncPointCHROMIUM(texture_info.second);
return std::move(texture_info.first);
}
}
return std::unique_ptr<mojo::GLTexture>(
new mojo::GLTexture(gl_context_, requested_size));
}
mojo::gfx::composition::ResourcePtr GLTextureRecycler::BindTextureResource(
std::unique_ptr<mojo::GLTexture> texture) {
if (!gl_context_)
return nullptr;
// Produce the texture.
gl_context_->MakeCurrent();
glBindTexture(GL_TEXTURE_2D, texture->texture_id());
GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
glGenMailboxCHROMIUM(mailbox);
glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox);
glBindTexture(GL_TEXTURE_2D, 0);
GLuint sync_point = glInsertSyncPointCHROMIUM();
// Populate the resource description.
auto resource = mojo::gfx::composition::Resource::New();
resource->set_mailbox_texture(
mojo::gfx::composition::MailboxTextureResource::New());
resource->get_mailbox_texture()->mailbox_name.resize(sizeof(mailbox));
memcpy(resource->get_mailbox_texture()->mailbox_name.data(), mailbox,
sizeof(mailbox));
resource->get_mailbox_texture()->sync_point = sync_point;
resource->get_mailbox_texture()->size = texture->size().Clone();
resource->get_mailbox_texture()->callback =
(new GLTextureReleaser(
weak_factory_.GetWeakPtr(),
GLRecycledTextureInfo(std::move(texture), sync_point)))
->StrongBind()
.Pass();
bound_textures_++;
DVLOG(2) << "bind: bound_textures=" << bound_textures_;
return resource;
}
void GLTextureRecycler::ReleaseTexture(GLRecycledTextureInfo texture_info,
bool recyclable) {
DCHECK(bound_textures_);
bound_textures_--;
if (recyclable && recycled_textures_.size() < max_recycled_textures_) {
recycled_textures_.emplace_back(std::move(texture_info));
}
DVLOG(2) << "release: bound_textures=" << bound_textures_
<< ", recycled_textures=" << recycled_textures_.size();
}
GLTextureRecycler::GLTextureReleaser::GLTextureReleaser(
const base::WeakPtr<GLTextureRecycler>& provider,
GLRecycledTextureInfo info)
: provider_(provider), texture_info_(std::move(info)), binding_(this) {}
GLTextureRecycler::GLTextureReleaser::~GLTextureReleaser() {
// It's possible for the object to be destroyed due to a connection
// error on the callback pipe. When this happens we don't want to
// recycle the texture since we have too little knowledge about its
// state to confirm that it will be safe to do so.
Release(false /*recyclable*/);
}
mojo::gfx::composition::MailboxTextureCallbackPtr
GLTextureRecycler::GLTextureReleaser::StrongBind() {
mojo::gfx::composition::MailboxTextureCallbackPtr callback;
binding_.Bind(mojo::GetProxy(&callback));
return callback;
}
void GLTextureRecycler::GLTextureReleaser::OnMailboxTextureReleased() {
Release(true /*recyclable*/);
}
void GLTextureRecycler::GLTextureReleaser::Release(bool recyclable) {
if (provider_) {
provider_->ReleaseTexture(std::move(texture_info_), recyclable);
provider_.reset();
}
}
} // namespace shell
} // namespace sky

View File

@ -0,0 +1,86 @@
// 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 SKY_SHELL_GPU_GL_RENDERER_H_
#define SKY_SHELL_GPU_GL_RENDERER_H_
#include <deque>
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/services/gfx/composition/interfaces/resources.mojom.h"
namespace mojo {
class GLContext;
class GLTexture;
class Size;
} // namespace mojo
namespace sky {
namespace shell {
// Provides support for rendering GL commands into a pool of textures
// and producing scene resources for them.
// TODO(abarth): Move to //mojo/gpu and reconcile with mojo::ui::GLRenderer.
class GLTextureRecycler {
public:
GLTextureRecycler(base::WeakPtr<mojo::GLContext> gl_context,
uint32_t max_recycled_textures = 3u);
~GLTextureRecycler();
// Obtains a texture of the specified size.
// Returns a nullptr if the GLContext was destroyed.
std::unique_ptr<mojo::GLTexture> GetTexture(const mojo::Size& requested_size);
// Takes ownership of the specified texture, issues GL commands to
// produce a mailbox texture, and returns its resource pointer.
// The caller should add the resource to its scene.
// Returns a nullptr if the GLContext was destroyed.
mojo::gfx::composition::ResourcePtr BindTextureResource(
std::unique_ptr<mojo::GLTexture> texture);
private:
using GLRecycledTextureInfo =
std::pair<std::unique_ptr<mojo::GLTexture>, uint32_t>;
// TODO(jeffbrown): Avoid creating new callbacks each time, perhaps by
// migrating to image pipes.
class GLTextureReleaser : mojo::gfx::composition::MailboxTextureCallback {
public:
GLTextureReleaser(const base::WeakPtr<GLTextureRecycler>& provider,
GLRecycledTextureInfo info);
~GLTextureReleaser() override;
mojo::gfx::composition::MailboxTextureCallbackPtr StrongBind();
private:
void OnMailboxTextureReleased() override;
void Release(bool recyclable);
base::WeakPtr<GLTextureRecycler> provider_;
GLRecycledTextureInfo texture_info_;
mojo::StrongBinding<mojo::gfx::composition::MailboxTextureCallback>
binding_;
};
void ReleaseTexture(GLRecycledTextureInfo texture_info, bool recyclable);
const base::WeakPtr<mojo::GLContext> gl_context_;
const uint32_t max_recycled_textures_;
std::deque<GLRecycledTextureInfo> recycled_textures_;
uint32_t bound_textures_ = 0u;
base::WeakPtrFactory<GLTextureRecycler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(GLTextureRecycler);
};
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_GPU_GL_RENDERER_H_

View File

@ -1,24 +1,19 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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 "sky/shell/gpu/mojo/rasterizer_mojo.h"
#include "base/trace_event/trace_event.h"
#include "mojo/public/c/gpu/MGL/mgl.h"
#include "mojo/public/c/gpu/MGL/mgl_onscreen.h"
#include "mojo/skia/gl_bindings_skia.h"
#include "mojo/gpu/gl_texture.h"
#include "mojo/skia/ganesh_texture_surface.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace sky {
namespace shell {
namespace {
void ContextLostThunk(void* closure) {
static_cast<RasterizerMojo*>(closure)->OnContextLost();
}
} // namespace
const uint32_t kContentImageResourceId = 1;
const uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId;
std::unique_ptr<Rasterizer> Rasterizer::Create() {
return std::unique_ptr<Rasterizer>(new RasterizerMojo());
@ -43,6 +38,12 @@ void RasterizerMojo::ConnectToRasterizer (
binding_.Bind(request.Pass());
}
void RasterizerMojo::Init(mojo::ApplicationConnectorPtr connector,
mojo::gfx::composition::ScenePtr scene) {
gl_state_.reset(new GLState(connector.get()));
scene_ = scene.Pass();
}
void RasterizerMojo::Draw(uint64_t layer_tree_ptr,
const DrawCallback& callback) {
TRACE_EVENT0("flutter", "RasterizerMojo::Draw");
@ -50,53 +51,61 @@ void RasterizerMojo::Draw(uint64_t layer_tree_ptr,
std::unique_ptr<flow::LayerTree> layer_tree(
reinterpret_cast<flow::LayerTree*>(layer_tree_ptr));
if (!MGLGetCurrentContext()) {
if (!scene_ || !gl_state_ || !gl_state_->gl_context_owner.context()) {
callback.Run();
return;
}
if (layer_tree->frame_size().isEmpty()) {
callback.Run();
return;
mojo::Size size;
size.width = layer_tree->frame_size().width();
size.height = layer_tree->frame_size().height();
// TODO(abarth): Handle size == 0x0.
std::unique_ptr<mojo::GLTexture> texture =
gl_state_->gl_texture_recycler.GetTexture(size);
DCHECK(texture);
{
mojo::skia::GaneshContext::Scope scope(&gl_state_->ganesh_context);
mojo::skia::GaneshTextureSurface texture_surface(scope, std::move(texture));
SkCanvas* canvas = texture_surface.canvas();
flow::PaintContext::ScopedFrame frame =
paint_context_.AcquireFrame(scope.gr_context(), *canvas);
canvas->clear(SK_ColorBLACK);
layer_tree->Raster(frame);
texture = texture_surface.TakeTexture();
}
MGLResizeSurface(layer_tree->frame_size().width(),
layer_tree->frame_size().height());
SkCanvas* canvas = ganesh_canvas_.GetCanvas(0, layer_tree->frame_size());
flow::PaintContext::ScopedFrame frame =
paint_context_.AcquireFrame(ganesh_canvas_.gr_context(), *canvas);
canvas->clear(SK_ColorBLACK);
layer_tree->Raster(frame);
canvas->flush();
MGLSwapBuffers();
mojo::gfx::composition::ResourcePtr resource =
gl_state_->gl_texture_recycler.BindTextureResource(std::move(texture));
DCHECK(resource);
auto update = mojo::gfx::composition::SceneUpdate::New();
update->resources.insert(kContentImageResourceId, resource.Pass());
auto root_node = mojo::gfx::composition::Node::New();
root_node->op = mojo::gfx::composition::NodeOp::New();
root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New());
root_node->op->get_image()->content_rect = mojo::Rect::New();
root_node->op->get_image()->content_rect->width = size.width;
root_node->op->get_image()->content_rect->height = size.height;
root_node->op->get_image()->image_resource_id = kContentImageResourceId;
update->nodes.insert(kRootNodeId, root_node.Pass());
scene_->Update(update.Pass());
scene_->Publish(nullptr);
callback.Run();
}
void RasterizerMojo::OnContextProviderAvailable(
mojo::InterfacePtrInfo<mojo::ContextProvider> context_provider) {
context_provider_ = mojo::MakeProxy(context_provider.Pass());
context_provider_->Create(nullptr,
base::Bind(&RasterizerMojo::OnContextCreated, base::Unretained(this)));
RasterizerMojo::GLState::GLState(mojo::ApplicationConnector* connector)
: gl_context_owner(connector),
gl_texture_recycler(gl_context_owner.context()),
ganesh_context(gl_context_owner.context()) {
}
void RasterizerMojo::OnContextCreated(mojo::CommandBufferPtr command_buffer) {
context_ = MGLCreateContext(
MGL_API_VERSION_GLES2,
command_buffer.PassInterface().PassHandle().release().value(),
MGL_NO_CONTEXT, &ContextLostThunk, this,
mojo::Environment::GetDefaultAsyncWaiter());
MGLMakeCurrent(context_);
if (!gr_gl_interface_)
gr_gl_interface_ = skia::AdoptRef(skia_bindings::CreateMojoSkiaGLBinding());
ganesh_canvas_.SetGrGLInterface(gr_gl_interface_.get());
}
void RasterizerMojo::OnContextLost() {
ganesh_canvas_.SetGrGLInterface(nullptr);
MGLDestroyContext(context_);
context_ = nullptr;
context_provider_->Create(nullptr,
base::Bind(&RasterizerMojo::OnContextCreated, base::Unretained(this)));
RasterizerMojo::GLState::~GLState() {
}
} // namespace shell

View File

@ -1,4 +1,4 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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.
@ -6,46 +6,48 @@
#define SKY_SHELL_GPU_MOJO_RASTERIZER_MOJO_H_
#include "base/memory/weak_ptr.h"
#include "mojo/public/c/gpu/MGL/mgl.h"
#include "mojo/services/native_viewport/interfaces/native_viewport.mojom.h"
#include "skia/ext/refptr.h"
#include "flow/paint_context.h"
#include "sky/shell/gpu/ganesh_canvas.h"
#include "mojo/gpu/gl_context_owner.h"
#include "mojo/public/interfaces/application/application_connector.mojom.h"
#include "mojo/services/gfx/composition/interfaces/scenes.mojom.h"
#include "mojo/skia/ganesh_context.h"
#include "sky/shell/gpu/mojo/gl_texture_recycler.h"
#include "sky/shell/rasterizer.h"
namespace sky {
namespace shell {
class RasterizerMojo : public ::sky::shell::Rasterizer {
class RasterizerMojo : public Rasterizer {
public:
explicit RasterizerMojo();
~RasterizerMojo() override;
base::WeakPtr<RasterizerMojo> GetWeakPtr();
base::WeakPtr<::sky::shell::Rasterizer> GetWeakRasterizerPtr() override;
base::WeakPtr<Rasterizer> GetWeakRasterizerPtr() override;
void ConnectToRasterizer(
mojo::InterfaceRequest<rasterizer::Rasterizer> request) override;
void OnContextProviderAvailable(
mojo::InterfacePtrInfo<mojo::ContextProvider> context_provder);
void OnContextLost();
void Init(mojo::ApplicationConnectorPtr connector,
mojo::gfx::composition::ScenePtr scene);
private:
void OnContextCreated(mojo::CommandBufferPtr command_buffer);
void Draw(uint64_t layer_tree_ptr, const DrawCallback& callback) override;
mojo::ContextProviderPtr context_provider_;
skia::RefPtr<GrGLInterface> gr_gl_interface_;
MGLContext context_;
GaneshCanvas ganesh_canvas_;
struct GLState {
explicit GLState(mojo::ApplicationConnector* connector);
~GLState();
flow::PaintContext paint_context_;
mojo::GLContextOwner gl_context_owner;
GLTextureRecycler gl_texture_recycler;
mojo::skia::GaneshContext ganesh_context;
};
mojo::Binding<rasterizer::Rasterizer> binding_;
mojo::gfx::composition::ScenePtr scene_;
std::unique_ptr<GLState> gl_state_;
flow::PaintContext paint_context_;
base::WeakPtrFactory<RasterizerMojo> weak_factory_;

View File

@ -9,13 +9,17 @@ mojo_native_application("mojo") {
output_name = "flutter"
sources = [
"application_impl.cc",
"application_impl.h",
"content_handler_impl.cc",
"content_handler_impl.h",
"main_mojo.cc",
"platform_view_mojo.cc",
"platform_view_mojo.h",
"sky_application_impl.cc",
"sky_application_impl.h",
"pointer_converter_mojo.cc",
"pointer_converter_mojo.h",
"view_impl.cc",
"view_impl.h",
]
deps = [
@ -30,10 +34,11 @@ mojo_native_application("mojo") {
"//mojo/public/interfaces/application",
"//mojo/services/asset_bundle/interfaces",
"//mojo/services/content_handler/interfaces",
"//mojo/services/gpu/interfaces",
"//mojo/services/keyboard/interfaces",
"//mojo/services/native_viewport/interfaces",
"//mojo/services/gfx/composition/interfaces",
"//mojo/services/input_events/interfaces",
"//mojo/services/service_registry/interfaces",
"//mojo/services/ui/input/interfaces",
"//mojo/services/ui/views/interfaces",
"//services/asset_bundle:lib",
"//skia",
"//sky/engine/public/sky",

View File

@ -0,0 +1,84 @@
// 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 "sky/shell/platform/mojo/application_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "sky/shell/platform/mojo/view_impl.h"
namespace sky {
namespace shell {
ApplicationImpl::ApplicationImpl(
mojo::InterfaceRequest<mojo::Application> application,
mojo::URLResponsePtr response)
: binding_(this, application.Pass()),
initial_response_(response.Pass()) {
}
ApplicationImpl::~ApplicationImpl() {
}
void ApplicationImpl::Initialize(mojo::ShellPtr shell,
mojo::Array<mojo::String> args,
const mojo::String& url) {
DCHECK(initial_response_);
shell_ = shell.Pass();
url_ = url;
UnpackInitialResponse(shell_.get());
}
void ApplicationImpl::AcceptConnection(
const mojo::String& requestor_url,
mojo::InterfaceRequest<mojo::ServiceProvider> outgoing_services,
mojo::ServiceProviderPtr incoming_services,
const mojo::String& resolved_url) {
service_provider_bindings_.AddBinding(this, outgoing_services.Pass());
}
void ApplicationImpl::RequestQuit() {
}
void ApplicationImpl::ConnectToService(const mojo::String& service_name,
mojo::ScopedMessagePipeHandle handle) {
if (service_name == mojo::ui::ViewProvider::Name_) {
view_provider_bindings_.AddBinding(
this, mojo::MakeRequest<mojo::ui::ViewProvider>(handle.Pass()));
}
}
void ApplicationImpl::CreateView(
mojo::InterfaceRequest<mojo::ServiceProvider> outgoing_services,
mojo::ServiceProviderPtr incoming_services,
const mojo::ui::ViewProvider::CreateViewCallback& callback) {
if (!bundle_) {
LOG(ERROR) << "We only support creating one view.";
return;
}
mojo::ServiceRegistryPtr service_registry;
if (incoming_services)
mojo::ConnectToService(incoming_services.get(), &service_registry);
ServicesDataPtr services = ServicesData::New();
services->shell = shell_.Pass();
services->service_registry = service_registry.Pass();
services->services_provided_by_embedder = incoming_services.Pass();
services->services_provided_to_embedder = outgoing_services.Pass();
ViewImpl* view = new ViewImpl(services.Pass(), url_, callback);
view->Run(bundle_.Pass());
}
void ApplicationImpl::UnpackInitialResponse(mojo::Shell* shell) {
DCHECK(initial_response_);
DCHECK(!bundle_);
mojo::asset_bundle::AssetUnpackerPtr unpacker;
mojo::ConnectToService(shell, "mojo:asset_bundle", &unpacker);
unpacker->UnpackZipStream(initial_response_->body.Pass(),
mojo::GetProxy(&bundle_));
initial_response_ = nullptr;
}
} // namespace shell
} // namespace sky

View File

@ -1,11 +1,10 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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 SKY_SHELL_PLATFORM_MOJO_SKY_APPLICATION_IMPL_H_
#define SKY_SHELL_PLATFORM_MOJO_SKY_APPLICATION_IMPL_H_
#ifndef SKY_SHELL_PLATFORM_MOJO_APPLICATION_IMPL_H_
#define SKY_SHELL_PLATFORM_MOJO_APPLICATION_IMPL_H_
#include "base/message_loop/message_loop.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/interfaces/application/application.mojom.h"
#include "mojo/public/interfaces/application/shell.mojom.h"
@ -14,14 +13,19 @@
#include "sky/shell/platform/mojo/platform_view_mojo.h"
#include "sky/shell/shell_view.h"
#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
#include "mojo/common/binding_set.h"
namespace sky {
namespace shell {
class SkyApplicationImpl : public mojo::Application {
class ApplicationImpl : public mojo::Application,
public mojo::ServiceProvider,
public mojo::ui::ViewProvider {
public:
SkyApplicationImpl(mojo::InterfaceRequest<mojo::Application> application,
mojo::URLResponsePtr response);
~SkyApplicationImpl() override;
ApplicationImpl(mojo::InterfaceRequest<mojo::Application> application,
mojo::URLResponsePtr response);
~ApplicationImpl() override;
private:
// mojo::Application
@ -35,20 +39,28 @@ class SkyApplicationImpl : public mojo::Application {
const mojo::String& resolved_url) override;
void RequestQuit() override;
PlatformViewMojo* platform_view() {
return static_cast<PlatformViewMojo*>(shell_view_->view());
}
// mojo::ServiceProvider
void ConnectToService(const mojo::String& service_name,
mojo::ScopedMessagePipeHandle client_handle) override;
// mojo::ui::ViewProvider
void CreateView(
mojo::InterfaceRequest<mojo::ServiceProvider> services,
mojo::ServiceProviderPtr exposed_services,
const mojo::ui::ViewProvider::CreateViewCallback& callback) override;
void UnpackInitialResponse(mojo::Shell* shell);
mojo::StrongBinding<mojo::Application> binding_;
mojo::URLResponsePtr initial_response_;
mojo::BindingSet<mojo::ServiceProvider> service_provider_bindings_;
mojo::BindingSet<mojo::ui::ViewProvider> view_provider_bindings_;
std::string url_;
mojo::ShellPtr shell_;
mojo::asset_bundle::AssetBundlePtr bundle_;
std::unique_ptr<ShellView> shell_view_;
};
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_PLATFORM_MOJO_SKY_APPLICATION_IMPL_H_
#endif // SKY_SHELL_PLATFORM_MOJO_APPLICATION_IMPL_H_

View File

@ -4,7 +4,7 @@
#include "sky/shell/platform/mojo/content_handler_impl.h"
#include "sky/shell/platform/mojo/sky_application_impl.h"
#include "sky/shell/platform/mojo/application_impl.h"
namespace sky {
namespace shell {
@ -20,7 +20,7 @@ ContentHandlerImpl::~ContentHandlerImpl() {
void ContentHandlerImpl::StartApplication(
mojo::InterfaceRequest<mojo::Application> application,
mojo::URLResponsePtr response) {
new SkyApplicationImpl(application.Pass(), response.Pass());
new ApplicationImpl(application.Pass(), response.Pass());
}
} // namespace shell

View File

@ -5,9 +5,8 @@
#ifndef SKY_SHELL_PLATFORM_MOJO_CONTENT_HANDLER_IMPL_H_
#define SKY_SHELL_PLATFORM_MOJO_CONTENT_HANDLER_IMPL_H_
#include "base/message_loop/message_loop.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/interfaces/application/shell.mojom.h"
#include "mojo/services/content_handler/interfaces/content_handler.mojom.h"
namespace sky {

View File

@ -1,4 +1,4 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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.
@ -7,211 +7,32 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/application/connect.h"
#include "sky/shell/gpu/mojo/rasterizer_mojo.h"
namespace sky {
namespace shell {
namespace {
pointer::PointerType GetTypeFromAction(mojo::EventType type) {
switch (type) {
case mojo::EventType::POINTER_CANCEL:
return pointer::PointerType::CANCEL;
case mojo::EventType::POINTER_DOWN:
return pointer::PointerType::DOWN;
case mojo::EventType::POINTER_MOVE:
return pointer::PointerType::MOVE;
case mojo::EventType::POINTER_UP:
return pointer::PointerType::UP;
default:
DCHECK(false);
return pointer::PointerType::CANCEL;
}
}
pointer::PointerKind GetKindFromKind(mojo::PointerKind kind) {
switch (kind) {
case mojo::PointerKind::TOUCH:
return pointer::PointerKind::TOUCH;
case mojo::PointerKind::MOUSE:
return pointer::PointerKind::MOUSE;
}
DCHECK(false);
return pointer::PointerKind::TOUCH;
}
} // namespace
PlatformView* PlatformView::Create(const Config& config) {
return new PlatformViewMojo(config);
}
PlatformViewMojo::PlatformViewMojo(const Config& config)
: PlatformView(config), dispatcher_binding_(this) {
: PlatformView(config) {
}
PlatformViewMojo::~PlatformViewMojo() {
}
void PlatformViewMojo::Init(mojo::Shell* shell) {
mojo::ConnectToService(shell, "mojo:native_viewport_service", &viewport_);
// Grab the application connector so that we can connect to services later
shell->CreateApplicationConnector(GetProxy(&connector_));
mojo::NativeViewportEventDispatcherPtr ptr;
dispatcher_binding_.Bind(GetProxy(&ptr));
viewport_->SetEventDispatcher(ptr.Pass());
mojo::SizePtr size = mojo::Size::New();
size->width = 320;
size->height = 640;
viewport_->Create(
size.Clone(),
mojo::SurfaceConfiguration::New(),
[this](mojo::ViewportMetricsPtr metrics) {
OnMetricsChanged(metrics.Pass());
});
viewport_->Show();
mojo::ContextProviderPtr context_provider;
viewport_->GetContextProvider(GetProxy(&context_provider));
mojo::InterfacePtrInfo<mojo::ContextProvider> context_provider_info = context_provider.PassInterface();
void PlatformViewMojo::InitRasterizer(mojo::ApplicationConnectorPtr connector,
mojo::gfx::composition::ScenePtr scene) {
RasterizerMojo* rasterizer = static_cast<RasterizerMojo*>(config_.rasterizer);
config_.ui_task_runner->PostTask(
FROM_HERE, base::Bind(&UIDelegate::OnOutputSurfaceCreated,
config_.ui_delegate,
base::Bind(&RasterizerMojo::OnContextProviderAvailable,
rasterizer->GetWeakPtr(), base::Passed(&context_provider_info))));
ConnectToEngine(GetProxy(&sky_engine_));
}
void PlatformViewMojo::Run(const mojo::String& url,
ServicesDataPtr services,
mojo::asset_bundle::AssetBundlePtr bundle) {
mojo::ServiceProviderPtr services_provided_by_embedder;
service_provider_.Bind(GetProxy(&services_provided_by_embedder));
service_provider_.AddService<keyboard::KeyboardService>(this);
services->services_provided_by_embedder = services_provided_by_embedder.Pass();
sky_engine_->SetServices(services.Pass());
sky_engine_->RunFromAssetBundle(url, bundle.Pass());
}
void PlatformViewMojo::OnMetricsChanged(mojo::ViewportMetricsPtr metrics) {
DCHECK(metrics);
viewport_->RequestMetrics(
[this](mojo::ViewportMetricsPtr metrics) {
OnMetricsChanged(metrics.Pass());
});
sky::ViewportMetricsPtr sky_metrics = sky::ViewportMetrics::New();
sky_metrics->physical_width = metrics->size->width;
sky_metrics->physical_height = metrics->size->height;
sky_metrics->device_pixel_ratio = metrics->device_pixel_ratio;
sky_engine_->OnViewportMetricsChanged(sky_metrics.Pass());
}
void PlatformViewMojo::OnEvent(mojo::EventPtr event,
const mojo::Callback<void()>& callback) {
DCHECK(event);
switch (event->action) {
case mojo::EventType::POINTER_CANCEL:
case mojo::EventType::POINTER_DOWN:
case mojo::EventType::POINTER_MOVE:
case mojo::EventType::POINTER_UP: {
mojo::PointerDataPtr data = event->pointer_data.Pass();
if (!data)
break;
pointer::PointerPacketPtr packet;
int packetIndex = 0;
if (pointer_positions_.count(data->pointer_id) > 0) {
if (event->action == mojo::EventType::POINTER_UP ||
event->action == mojo::EventType::POINTER_CANCEL) {
std::pair<float, float> last_position = pointer_positions_[data->pointer_id];
if (last_position.first != data->x || last_position.second != data->y) {
packet = pointer::PointerPacket::New();
packet->pointers = mojo::Array<pointer::PointerPtr>::New(2);
packet->pointers[packetIndex] = CreateEvent(pointer::PointerType::MOVE, event.get(), data.get());
packetIndex += 1;
}
pointer_positions_.erase(data->pointer_id);
}
} else {
// We don't currently support hover moves.
// If we want to support those, we have to first implement
// added/removed events for pointers.
// See: https://github.com/flutter/flutter/issues/720
if (event->action != mojo::EventType::POINTER_DOWN)
break;
}
if (packetIndex == 0) {
packet = pointer::PointerPacket::New();
packet->pointers = mojo::Array<pointer::PointerPtr>::New(1);
}
packet->pointers[packetIndex] = CreateEvent(GetTypeFromAction(event->action), event.get(), data.get());
sky_engine_->OnPointerPacket(packet.Pass());
break;
}
case mojo::EventType::KEY_PRESSED:
case mojo::EventType::KEY_RELEASED:
if (key_event_dispatcher_) {
key_event_dispatcher_->OnEvent(event.Pass(), callback);
return; // key_event_dispatcher_ will invoke callback
}
default:
break;
}
callback.Run();
}
pointer::PointerPtr PlatformViewMojo::CreateEvent(pointer::PointerType type, mojo::Event* event, mojo::PointerData* data) {
DCHECK(data);
pointer::PointerPtr pointer = pointer::Pointer::New();
pointer->time_stamp = event->time_stamp;
pointer->pointer = data->pointer_id;
pointer->type = type;
pointer->kind = GetKindFromKind(data->kind);
pointer->x = data->x;
pointer->y = data->y;
pointer->buttons = static_cast<int32_t>(event->flags);
pointer->pressure = data->pressure;
pointer->radius_major = data->radius_major;
pointer->radius_minor = data->radius_minor;
pointer->orientation = data->orientation;
if (event->action != mojo::EventType::POINTER_UP &&
event->action != mojo::EventType::POINTER_CANCEL)
pointer_positions_[data->pointer_id] = { data->x, data->y };
return pointer.Pass();
}
void PlatformViewMojo::Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<keyboard::KeyboardService> request) {
mojo::ServiceProviderPtr keyboard_service_provider;
connector_->ConnectToApplication(
"mojo:keyboard",
GetProxy(&keyboard_service_provider),
nullptr);
#if defined(OS_LINUX)
keyboard::KeyboardServiceFactoryPtr factory;
mojo::ConnectToService(keyboard_service_provider.get(), &factory);
factory->CreateKeyboardService(GetProxy(&key_event_dispatcher_), request.Pass());
#else
keyboard_service_provider->ConnectToService(
keyboard::KeyboardService::Name_,
request.PassMessagePipe());
#endif
config_.ui_task_runner->PostTask(FROM_HERE, base::Bind(
&UIDelegate::OnOutputSurfaceCreated,
config_.ui_delegate,
base::Bind(&RasterizerMojo::Init,
rasterizer->GetWeakPtr(),
base::Passed(&connector),
base::Passed(&scene))));
}
} // namespace shell

View File

@ -1,62 +1,26 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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 SKY_SHELL_PLATFORM_MOJO_PLATFORM_VIEW_MOJO_H_
#define SKY_SHELL_PLATFORM_MOJO_PLATFORM_VIEW_MOJO_H_
#include "mojo/public/cpp/application/service_provider_impl.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/interfaces/application/service_provider.mojom.h"
#include "mojo/public/interfaces/application/shell.mojom.h"
#include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h"
#include "mojo/services/keyboard/interfaces/keyboard.mojom.h"
#include "mojo/services/native_viewport/interfaces/native_viewport.mojom.h"
#include "mojo/public/interfaces/application/application_connector.mojom.h"
#include "mojo/services/gfx/composition/interfaces/scenes.mojom.h"
#include "sky/shell/platform_view.h"
namespace sky {
namespace shell {
class PlatformViewMojo : public PlatformView,
public mojo::NativeViewportEventDispatcher,
public mojo::InterfaceFactory<::keyboard::KeyboardService> {
class PlatformViewMojo : public PlatformView {
public:
explicit PlatformViewMojo(const Config& config);
~PlatformViewMojo() override;
void Init(mojo::Shell* shell);
void Run(const mojo::String& url,
ServicesDataPtr services,
mojo::asset_bundle::AssetBundlePtr bundle);
void InitRasterizer(mojo::ApplicationConnectorPtr connector,
mojo::gfx::composition::ScenePtr scene);
private:
void OnMetricsChanged(mojo::ViewportMetricsPtr metrics);
// mojo::NativeViewportEventDispatcher
void OnEvent(mojo::EventPtr event,
const mojo::Callback<void()>& callback) override;
pointer::PointerPtr CreateEvent(pointer::PointerType type, mojo::Event* event, mojo::PointerData* data);
// |mojo::InterfaceFactory<mojo::asset_bundle::AssetUnpacker>| implementation:
void Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<::keyboard::KeyboardService>) override;
mojo::ApplicationConnectorPtr connector_;
mojo::NativeViewportPtr viewport_;
mojo::Binding<NativeViewportEventDispatcher> dispatcher_binding_;
sky::SkyEnginePtr sky_engine_;
mojo::ServiceProviderImpl service_provider_;
mojo::NativeViewportEventDispatcherPtr key_event_dispatcher_;
std::map<int, std::pair<float, float>> pointer_positions_;
DISALLOW_COPY_AND_ASSIGN(PlatformViewMojo);
};

View File

@ -0,0 +1,111 @@
// 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 "sky/shell/platform/mojo/pointer_converter_mojo.h"
#include "base/logging.h"
namespace sky {
namespace shell {
namespace {
pointer::PointerType GetTypeFromAction(mojo::EventType type) {
switch (type) {
case mojo::EventType::POINTER_CANCEL:
return pointer::PointerType::CANCEL;
case mojo::EventType::POINTER_DOWN:
return pointer::PointerType::DOWN;
case mojo::EventType::POINTER_MOVE:
return pointer::PointerType::MOVE;
case mojo::EventType::POINTER_UP:
return pointer::PointerType::UP;
default:
DCHECK(false);
return pointer::PointerType::CANCEL;
}
}
pointer::PointerKind GetKindFromKind(mojo::PointerKind kind) {
switch (kind) {
case mojo::PointerKind::TOUCH:
return pointer::PointerKind::TOUCH;
case mojo::PointerKind::MOUSE:
return pointer::PointerKind::MOUSE;
}
DCHECK(false);
return pointer::PointerKind::TOUCH;
}
} // namespace
PointerConverterMojo::PointerConverterMojo() {
}
PointerConverterMojo::~PointerConverterMojo() {
}
pointer::PointerPacketPtr PointerConverterMojo::ConvertEvent(
mojo::EventPtr event) {
DCHECK(event->action == mojo::EventType::POINTER_CANCEL
|| event->action == mojo::EventType::POINTER_DOWN
|| event->action == mojo::EventType::POINTER_MOVE
|| event->action == mojo::EventType::POINTER_UP);
mojo::PointerDataPtr data = event->pointer_data.Pass();
if (!data)
return nullptr;
pointer::PointerPacketPtr packet;
int packetIndex = 0;
if (pointer_positions_.count(data->pointer_id) > 0) {
if (event->action == mojo::EventType::POINTER_UP ||
event->action == mojo::EventType::POINTER_CANCEL) {
auto last_position = pointer_positions_[data->pointer_id];
if (last_position.first != data->x || last_position.second != data->y) {
packet = pointer::PointerPacket::New();
packet->pointers = mojo::Array<pointer::PointerPtr>::New(2);
packet->pointers[packetIndex] = CreatePointer(
pointer::PointerType::MOVE, event.get(), data.get());
packetIndex += 1;
}
pointer_positions_.erase(data->pointer_id);
}
} else {
// We don't currently support hover moves.
// If we want to support those, we have to first implement
// added/removed events for pointers.
// See: https://github.com/flutter/flutter/issues/720
if (event->action != mojo::EventType::POINTER_DOWN)
return nullptr;
}
if (packetIndex == 0) {
packet = pointer::PointerPacket::New();
packet->pointers = mojo::Array<pointer::PointerPtr>::New(1);
}
packet->pointers[packetIndex] = CreatePointer(
GetTypeFromAction(event->action), event.get(), data.get());
return packet.Pass();
}
pointer::PointerPtr PointerConverterMojo::CreatePointer(
pointer::PointerType type, mojo::Event* event, mojo::PointerData* data) {
DCHECK(data);
pointer::PointerPtr pointer = pointer::Pointer::New();
pointer->time_stamp = event->time_stamp;
pointer->pointer = data->pointer_id;
pointer->type = type;
pointer->kind = GetKindFromKind(data->kind);
pointer->x = data->x;
pointer->y = data->y;
pointer->buttons = static_cast<int32_t>(event->flags);
pointer->pressure = data->pressure;
pointer->radius_major = data->radius_major;
pointer->radius_minor = data->radius_minor;
pointer->orientation = data->orientation;
if (event->action != mojo::EventType::POINTER_UP &&
event->action != mojo::EventType::POINTER_CANCEL)
pointer_positions_[data->pointer_id] = { data->x, data->y };
return pointer.Pass();
}
} // namespace shell
} // namespace sky

View File

@ -0,0 +1,37 @@
// 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 SKY_SHELL_PLATFORM_MOJO_POINTER_CONVERTER_MOJO_H_
#define SKY_SHELL_PLATFORM_MOJO_POINTER_CONVERTER_MOJO_H_
#include <map>
#include "base/macros.h"
#include "mojo/services/input_events/interfaces/input_events.mojom.h"
#include "sky/services/pointer/pointer.mojom.h"
namespace sky {
namespace shell {
class PointerConverterMojo {
public:
PointerConverterMojo();
~PointerConverterMojo();
pointer::PointerPacketPtr ConvertEvent(mojo::EventPtr event);
private:
pointer::PointerPtr CreatePointer(pointer::PointerType type,
mojo::Event* event,
mojo::PointerData* data);
std::map<int, std::pair<float, float>> pointer_positions_;
DISALLOW_COPY_AND_ASSIGN(PointerConverterMojo);
};
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_PLATFORM_MOJO_POINTER_CONVERTER_MOJO_H_

View File

@ -1,69 +0,0 @@
// 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/shell/platform/mojo/sky_application_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/cpp/utility/run_loop.h"
#include "sky/shell/shell.h"
namespace sky {
namespace shell {
SkyApplicationImpl::SkyApplicationImpl(
mojo::InterfaceRequest<mojo::Application> application,
mojo::URLResponsePtr response)
: binding_(this, application.Pass()),
initial_response_(response.Pass()) {
}
SkyApplicationImpl::~SkyApplicationImpl() {
}
void SkyApplicationImpl::Initialize(mojo::ShellPtr shell,
mojo::Array<mojo::String> args,
const mojo::String& url) {
DCHECK(initial_response_);
UnpackInitialResponse(shell.get());
shell_view_.reset(new ShellView(Shell::Shared()));
platform_view()->Init(shell.get());
shell_ = shell.Pass();
}
void SkyApplicationImpl::AcceptConnection(
const mojo::String& requestor_url,
mojo::InterfaceRequest<mojo::ServiceProvider> outgoing_services,
mojo::ServiceProviderPtr incoming_services,
const mojo::String& resolved_url) {
if (!bundle_) {
LOG(INFO) << "Cannot handle multiple connections yet.";
return;
}
mojo::ServiceRegistryPtr service_registry;
if (incoming_services)
mojo::ConnectToService(incoming_services.get(), &service_registry);
ServicesDataPtr services = ServicesData::New();
services->shell = shell_.Pass();
services->service_registry = service_registry.Pass();
platform_view()->Run(resolved_url, services.Pass(), bundle_.Pass());
}
void SkyApplicationImpl::RequestQuit() {
}
void SkyApplicationImpl::UnpackInitialResponse(mojo::Shell* shell) {
DCHECK(initial_response_);
DCHECK(!bundle_);
mojo::asset_bundle::AssetUnpackerPtr unpacker;
mojo::ConnectToService(shell, "mojo:asset_bundle", &unpacker);
unpacker->UnpackZipStream(initial_response_->body.Pass(),
mojo::GetProxy(&bundle_));
initial_response_ = nullptr;
}
} // namespace shell
} // namespace sky

View File

@ -0,0 +1,98 @@
// 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 "sky/shell/platform/mojo/view_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/services/gfx/composition/interfaces/scheduling.mojom.h"
#include "sky/shell/shell.h"
namespace sky {
namespace shell {
ViewImpl::ViewImpl(ServicesDataPtr services,
const std::string& url,
const mojo::ui::ViewProvider::CreateViewCallback& callback)
: binding_(this), url_(url), listener_binding_(this) {
DCHECK(services);
// Views
mojo::ConnectToService(
services->shell.get(), "mojo:view_manager_service", &view_manager_);
mojo::ui::ViewPtr view;
binding_.Bind(mojo::GetProxy(&view));
view_manager_->RegisterView(
view.Pass(), mojo::GetProxy(&view_host_), url_, callback);
view_host_->GetServiceProvider(mojo::GetProxy(&view_service_provider_));
// Input
mojo::ConnectToService(view_service_provider_.get(), &input_connection_);
mojo::ui::InputListenerPtr listener;
listener_binding_.Bind(mojo::GetProxy(&listener));
input_connection_->SetListener(listener.Pass());
// Compositing
mojo::gfx::composition::ScenePtr scene;
view_host_->CreateScene(mojo::GetProxy(&scene));
scene->GetScheduler(mojo::GetProxy(&services->scene_scheduler));
// Engine
shell_view_.reset(new ShellView(Shell::Shared()));
shell_view_->view()->ConnectToEngine(GetProxy(&engine_));
mojo::ApplicationConnectorPtr connector;
services->shell->CreateApplicationConnector(mojo::GetProxy(&connector));
platform_view()->InitRasterizer(connector.Pass(), scene.Pass());
engine_->SetServices(services.Pass());
}
ViewImpl::~ViewImpl() {
}
void ViewImpl::Run(mojo::asset_bundle::AssetBundlePtr bundle) {
engine_->RunFromAssetBundle(url_, bundle.Pass());
}
void ViewImpl::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
mojo::Array<uint32_t> children_needing_layout,
const OnLayoutCallback& callback) {
viewport_metrics_.device_pixel_ratio = layout_params->device_pixel_ratio;
viewport_metrics_.physical_width = layout_params->constraints->max_width;
viewport_metrics_.physical_height = layout_params->constraints->max_height;
engine_->OnViewportMetricsChanged(viewport_metrics_.Clone());
auto info = mojo::ui::ViewLayoutResult::New();
info->size = mojo::Size::New();
info->size->width = viewport_metrics_.physical_width;
info->size->height = viewport_metrics_.physical_height;
callback.Run(info.Pass());
}
void ViewImpl::OnChildUnavailable(uint32_t child_key,
const OnChildUnavailableCallback& callback) {
callback.Run();
}
void ViewImpl::OnEvent(mojo::EventPtr event, const OnEventCallback& callback) {
DCHECK(event);
bool consumed = false;
switch (event->action) {
case mojo::EventType::POINTER_CANCEL:
case mojo::EventType::POINTER_DOWN:
case mojo::EventType::POINTER_MOVE:
case mojo::EventType::POINTER_UP: {
auto packet = pointer_converter_.ConvertEvent(event.Pass());
if (packet) {
engine_->OnPointerPacket(packet.Pass());
consumed = true;
}
break;
}
default:
break;
}
callback.Run(consumed);
}
} // namespace shell
} // namespace sky

View File

@ -0,0 +1,69 @@
// 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 SKY_SHELL_PLATFORM_MOJO_VIEW_IMPL_H_
#define SKY_SHELL_PLATFORM_MOJO_VIEW_IMPL_H_
#include "base/macros.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/interfaces/application/application_connector.mojom.h"
#include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h"
#include "mojo/services/gfx/composition/interfaces/scenes.mojom.h"
#include "mojo/services/ui/input/interfaces/input_connection.mojom.h"
#include "mojo/services/ui/views/interfaces/view_manager.mojom.h"
#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
#include "mojo/services/ui/views/interfaces/views.mojom.h"
#include "sky/shell/platform/mojo/platform_view_mojo.h"
#include "sky/shell/platform/mojo/pointer_converter_mojo.h"
#include "sky/shell/shell_view.h"
namespace sky {
namespace shell {
class ViewImpl : public mojo::ui::View,
public mojo::ui::InputListener {
public:
ViewImpl(ServicesDataPtr services,
const std::string& url,
const mojo::ui::ViewProvider::CreateViewCallback& callback);
~ViewImpl() override;
void Run(mojo::asset_bundle::AssetBundlePtr bundle);
private:
// mojo::ui::View
void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
mojo::Array<uint32_t> children_needing_layout,
const OnLayoutCallback& callback) override;
void OnChildUnavailable(uint32_t child_key,
const OnChildUnavailableCallback& callback) override;
// mojo::ui::InputListener
void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override;
PlatformViewMojo* platform_view() {
return static_cast<PlatformViewMojo*>(shell_view_->view());
}
mojo::StrongBinding<mojo::ui::View> binding_;
std::string url_;
mojo::ui::ViewManagerPtr view_manager_;
mojo::ui::ViewHostPtr view_host_;
mojo::ServiceProviderPtr view_service_provider_;
mojo::ui::InputConnectionPtr input_connection_;
mojo::Binding<mojo::ui::InputListener> listener_binding_;
std::unique_ptr<ShellView> shell_view_;
SkyEnginePtr engine_;
ViewportMetrics viewport_metrics_;
PointerConverterMojo pointer_converter_;
DISALLOW_COPY_AND_ASSIGN(ViewImpl);
};
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_PLATFORM_MOJO_VIEW_IMPL_H_

View File

@ -67,6 +67,10 @@ void Animator::Start() {
RequestFrame();
}
void Animator::Animate(mojo::gfx::composition::FrameInfoPtr frame_info) {
BeginFrame(frame_info->frame_time);
}
void Animator::BeginFrame(int64_t time_stamp) {
TRACE_EVENT_ASYNC_END0("flutter", "Frame request pending", this);
DCHECK(engine_requested_frame_);
@ -110,11 +114,16 @@ void Animator::OnFrameComplete() {
}
bool Animator::AwaitVSync() {
if (!vsync_provider_)
return false;
vsync_provider_->AwaitVSync(
base::Bind(&Animator::BeginFrame, weak_factory_.GetWeakPtr()));
return true;
if (scene_scheduler_) {
scene_scheduler_->ScheduleFrame(
base::Bind(&Animator::Animate, weak_factory_.GetWeakPtr()));
return true;
} else if (vsync_provider_) {
vsync_provider_->AwaitVSync(
base::Bind(&Animator::BeginFrame, weak_factory_.GetWeakPtr()));
return true;
}
return false;
}
} // namespace shell

View File

@ -6,6 +6,7 @@
#define SKY_SHELL_UI_ANIMATOR_H_
#include "base/memory/weak_ptr.h"
#include "mojo/services/gfx/composition/interfaces/scheduling.mojom.h"
#include "mojo/services/vsync/interfaces/vsync.mojom.h"
#include "sky/shell/ui/engine.h"
@ -24,11 +25,17 @@ class Animator {
void Start();
void Stop();
void set_scene_scheduler(
mojo::gfx::composition::SceneSchedulerPtr scene_scheduler) {
scene_scheduler_ = scene_scheduler.Pass();
}
void set_vsync_provider(vsync::VSyncProviderPtr vsync_provider) {
vsync_provider_ = vsync_provider.Pass();
}
private:
void Animate(mojo::gfx::composition::FrameInfoPtr frame_info);
void BeginFrame(int64_t time_stamp);
void OnFrameComplete();
bool AwaitVSync();
@ -36,6 +43,7 @@ class Animator {
Engine::Config config_;
rasterizer::RasterizerPtr rasterizer_;
Engine* engine_;
mojo::gfx::composition::SceneSchedulerPtr scene_scheduler_;
vsync::VSyncProviderPtr vsync_provider_;
int outstanding_requests_;
bool did_defer_frame_request_;

View File

@ -118,17 +118,21 @@ void Engine::OnOutputSurfaceDestroyed(const base::Closure& gpu_continuation) {
void Engine::SetServices(ServicesDataPtr services) {
services_ = services.Pass();
#if defined(OS_ANDROID) || defined(OS_IOS)
vsync::VSyncProviderPtr vsync_provider;
if (services_->shell) {
mojo::ConnectToService(services_->shell.get(), "mojo:vsync",
&vsync_provider);
if (services_->scene_scheduler) {
animator_->set_scene_scheduler(services_->scene_scheduler.Pass());
} else {
mojo::ConnectToService(services_->services_provided_by_embedder.get(),
&vsync_provider);
}
animator_->set_vsync_provider(vsync_provider.Pass());
#if defined(OS_ANDROID) || defined(OS_IOS)
vsync::VSyncProviderPtr vsync_provider;
if (services_->shell) {
mojo::ConnectToService(services_->shell.get(), "mojo:vsync",
&vsync_provider);
} else {
mojo::ConnectToService(services_->services_provided_by_embedder.get(),
&vsync_provider);
}
animator_->set_vsync_provider(vsync_provider.Pass());
#endif
}
}
void Engine::OnViewportMetricsChanged(ViewportMetricsPtr metrics) {