blob: 7c63ffd5781ca7f37bde43faae8a313fb05adb27 [file] [log] [blame]
// 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 "flutter/sky/shell/platform_view.h"
#include <utility>
#include "flutter/lib/ui/painting/resource_context.h"
#include "flutter/glue/movable_wrapper.h"
#include "flutter/sky/shell/rasterizer.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
namespace sky {
namespace shell {
PlatformView::Config::Config() : rasterizer(nullptr) {}
PlatformView::Config::~Config() = default;
PlatformView::PlatformView()
: rasterizer_(Rasterizer::Create()), size_(SkISize::Make(0, 0)) {
Shell& shell = Shell::Shared();
// Create the engine for this platform view.
Engine::Config engine_config;
engine_config.gpu_task_runner =
ftl::RefPtr<ftl::TaskRunner>(shell.gpu_ftl_task_runner());
ftl::WeakPtr<Rasterizer> rasterizer_impl =
rasterizer_->GetWeakRasterizerPtr();
rasterizer::RasterizerPtr rasterizer;
auto request = glue::WrapMovable(mojo::GetProxy(&rasterizer));
shell.gpu_ftl_task_runner()->PostTask([rasterizer_impl, request]() mutable {
if (rasterizer_impl)
rasterizer_impl->ConnectToRasterizer(request.Unwrap());
});
engine_.reset(new Engine(engine_config, rasterizer.Pass()));
// Setup the platform config.
config_.ui_task_runner =
ftl::RefPtr<ftl::TaskRunner>(shell.ui_ftl_task_runner());
config_.ui_delegate = engine_->GetWeakPtr();
config_.rasterizer = rasterizer_.get();
}
PlatformView::~PlatformView() {
Shell& shell = Shell::Shared();
shell.ui_ftl_task_runner()->PostTask(
[]() { Shell::Shared().PurgePlatformViews(); });
Rasterizer* rasterizer = rasterizer_.release();
shell.gpu_ftl_task_runner()->PostTask([rasterizer]() { delete rasterizer; });
Engine* engine = engine_.release();
shell.ui_ftl_task_runner()->PostTask([engine]() { delete engine; });
}
void PlatformView::ConnectToEngine(mojo::InterfaceRequest<SkyEngine> request) {
ftl::WeakPtr<UIDelegate> ui_delegate = config_.ui_delegate;
auto wrapped_request = glue::WrapMovable(std::move(request));
config_.ui_task_runner->PostTask([ui_delegate, wrapped_request]() mutable {
if (ui_delegate)
ui_delegate->ConnectToEngine(wrapped_request.Unwrap());
});
ftl::WeakPtr<PlatformView> view = GetWeakViewPtr();
config_.ui_task_runner->PostTask(
[view]() { Shell::Shared().AddPlatformView(view); });
}
void PlatformView::NotifyCreated() {
PlatformView::NotifyCreated([]() {});
}
void PlatformView::NotifyCreated(ftl::Closure rasterizer_continuation) {
CHECK(config_.rasterizer != nullptr);
auto rasterizer = config_.rasterizer->GetWeakRasterizerPtr();
ftl::AutoResetWaitableEvent latch;
auto delegate_continuation = [rasterizer, this, rasterizer_continuation,
&latch]() {
if (rasterizer)
rasterizer->Setup(this, rasterizer_continuation, &latch);
// TODO(abarth): We should signal the latch if the rasterizer is gone.
};
auto delegate = config_.ui_delegate;
config_.ui_task_runner->PostTask([delegate, delegate_continuation]() {
if (delegate)
delegate->OnOutputSurfaceCreated(delegate_continuation);
// TODO(abarth): We should signal the latch if the delegate is gone.
});
latch.Wait();
}
void PlatformView::NotifyDestroyed() {
FTL_CHECK(config_.rasterizer != nullptr);
auto delegate = config_.ui_delegate;
auto rasterizer = config_.rasterizer->GetWeakRasterizerPtr();
ftl::AutoResetWaitableEvent latch;
auto delegate_continuation = [rasterizer, &latch]() {
if (rasterizer)
rasterizer->Teardown(&latch);
// TODO(abarth): We should signal the latch if the rasterizer is gone.
};
config_.ui_task_runner->PostTask([delegate, delegate_continuation]() {
if (delegate)
delegate->OnOutputSurfaceDestroyed(delegate_continuation);
// TODO(abarth): We should signal the latch if the delegate is gone.
});
latch.Wait();
}
SkISize PlatformView::GetSize() {
return size_;
}
void PlatformView::Resize(const SkISize& size) {
size_ = size;
}
void PlatformView::SetupResourceContextOnIOThread() {
ftl::AutoResetWaitableEvent latch;
Shell::Shared().io_ftl_task_runner()->PostTask(
[this, &latch]() { SetupResourceContextOnIOThreadPerform(&latch); });
latch.Wait();
}
void PlatformView::SetupResourceContextOnIOThreadPerform(
ftl::AutoResetWaitableEvent* latch) {
if (blink::ResourceContext::Get() != nullptr) {
// The resource context was already setup. This could happen if platforms
// try to setup a context multiple times, or, if there are multiple platform
// views. In any case, there is nothing else to do. So just signal the
// latch.
latch->Signal();
return;
}
bool current = ResourceContextMakeCurrent();
if (!current) {
LOG(WARNING)
<< "WARNING: Could not setup an OpenGL context on the resource loader.";
}
blink::ResourceContext::Set(GrContext::Create(
GrBackend::kOpenGL_GrBackend,
reinterpret_cast<GrBackendContext>(GrGLCreateNativeInterface())));
latch->Signal();
}
} // namespace shell
} // namespace sky