提交 fdf13d72 编写于 作者: C Chinmay Garde 提交者: GitHub

Make the PlatformView client rendering API agnostic. (#3099)

上级 e9807414
......@@ -6,3 +6,4 @@ BasedOnStyle: Chromium
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
# 'int>>' if the file already contains at least one such instance.)
Standard: Cpp11
SortIncludes: true
......@@ -8,9 +8,9 @@
namespace flow {
CompositorContext::CompositorContext() {}
CompositorContext::CompositorContext() = default;
CompositorContext::~CompositorContext() {}
CompositorContext::~CompositorContext() = default;
void CompositorContext::BeginFrame(ScopedFrame& frame,
bool enable_instrumentation) {
......
......@@ -21,10 +21,13 @@ class CompositorContext {
class ScopedFrame {
public:
SkCanvas& canvas() { return *canvas_; }
CompositorContext& context() const { return context_; }
GrContext* gr_context() const { return gr_context_; }
ScopedFrame(ScopedFrame&& frame);
~ScopedFrame();
private:
......@@ -44,6 +47,7 @@ class CompositorContext {
};
CompositorContext();
~CompositorContext();
ScopedFrame AcquireFrame(GrContext* gr_context,
......@@ -53,18 +57,21 @@ class CompositorContext {
void OnGrContextDestroyed();
RasterCache& raster_cache() { return raster_cache_; }
const Counter& frame_count() const { return frame_count_; }
const Stopwatch& frame_time() const { return frame_time_; }
Stopwatch& engine_time() { return engine_time_; };
private:
RasterCache raster_cache_;
Counter frame_count_;
Stopwatch frame_time_;
Stopwatch engine_time_;
void BeginFrame(ScopedFrame& frame, bool enable_instrumentation);
void EndFrame(ScopedFrame& frame, bool enable_instrumentation);
FTL_DISALLOW_COPY_AND_ASSIGN(CompositorContext);
......
......@@ -22,6 +22,8 @@ source_set("common") {
"diagnostic/diagnostic_server.h",
"engine.cc",
"engine.h",
"null_rasterizer.cc",
"null_rasterizer.h",
"picture_serializer.cc",
"picture_serializer.h",
"platform_view.cc",
......@@ -32,6 +34,8 @@ source_set("common") {
"rasterizer.h",
"shell.cc",
"shell.h",
"surface.cc",
"surface.h",
"switches.cc",
"switches.h",
"tracing_controller.cc",
......
// 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/shell/common/null_rasterizer.h"
namespace shell {
NullRasterizer::NullRasterizer() : weak_factory_(this) {}
void NullRasterizer::Setup(
std::unique_ptr<Surface> surface_or_null,
ftl::Closure rasterizer_continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) {
rasterizer_continuation();
setup_completion_event->Signal();
}
void NullRasterizer::Teardown(
ftl::AutoResetWaitableEvent* teardown_completion_event) {
teardown_completion_event->Signal();
}
ftl::WeakPtr<Rasterizer> NullRasterizer::GetWeakRasterizerPtr() {
return weak_factory_.GetWeakPtr();
}
flow::LayerTree* NullRasterizer::GetLastLayerTree() {
return nullptr;
}
void NullRasterizer::Clear(SkColor color, const SkISize& size) {
// Null rasterizer. Nothing to do.
}
void NullRasterizer::Draw(
ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) {
// Null rasterizer. Nothing to do.
}
} // namespace shell
// 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_SHELL_COMMON_NULL_RASTERIZER_H_
#define FLUTTER_SHELL_COMMON_NULL_RASTERIZER_H_
#include "flutter/shell/common/rasterizer.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/weak_ptr.h"
namespace shell {
class NullRasterizer : public Rasterizer {
public:
NullRasterizer();
void Setup(std::unique_ptr<Surface> surface_or_null,
ftl::Closure rasterizer_continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) override;
void Teardown(
ftl::AutoResetWaitableEvent* teardown_completion_event) override;
void Clear(SkColor color, const SkISize& size) override;
ftl::WeakPtr<Rasterizer> GetWeakRasterizerPtr() override;
flow::LayerTree* GetLastLayerTree() override;
void Draw(ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) override;
private:
ftl::WeakPtrFactory<NullRasterizer> weak_factory_;
FTL_DISALLOW_COPY_AND_ASSIGN(NullRasterizer);
};
} // namespace shell
#endif // FLUTTER_SHELL_COMMON_NULL_RASTERIZER_H_
......@@ -10,6 +10,7 @@
#include "flutter/glue/movable_wrapper.h"
#include "flutter/lib/ui/painting/resource_context.h"
#include "flutter/shell/common/rasterizer.h"
#include "lib/ftl/functional/wrap_lambda.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
namespace shell {
......@@ -18,8 +19,8 @@ PlatformView::Config::Config() : rasterizer(nullptr) {}
PlatformView::Config::~Config() = default;
PlatformView::PlatformView()
: rasterizer_(Rasterizer::Create()), size_(SkISize::Make(0, 0)) {
PlatformView::PlatformView(std::unique_ptr<Rasterizer> rasterizer)
: rasterizer_(std::move(rasterizer)), size_(SkISize::Make(0, 0)) {
engine_.reset(new Engine(rasterizer_.get()));
// Setup the platform config.
......@@ -51,24 +52,40 @@ void PlatformView::ConnectToEngine(
[view]() { Shell::Shared().AddPlatformView(view); });
}
void PlatformView::NotifyCreated() {
PlatformView::NotifyCreated([]() {});
void PlatformView::NotifyCreated(std::unique_ptr<Surface> surface) {
NotifyCreated(std::move(surface), []() {});
}
void PlatformView::NotifyCreated(ftl::Closure rasterizer_continuation) {
void PlatformView::NotifyCreated(std::unique_ptr<Surface> surface,
ftl::Closure caller_continuation) {
FTL_CHECK(config_.rasterizer);
ftl::AutoResetWaitableEvent latch;
auto delegate_continuation = [this, rasterizer_continuation, &latch]() {
config_.rasterizer->Setup(this, rasterizer_continuation, &latch);
};
auto delegate = config_.ui_delegate;
blink::Threads::UI()->PostTask([delegate, delegate_continuation]() {
delegate->OnOutputSurfaceCreated(delegate_continuation);
auto ui_continuation = ftl::WrapLambda([
delegate = config_.ui_delegate, //
rasterizer = config_.rasterizer, //
surface = std::move(surface), //
caller_continuation, //
&latch
]() mutable {
auto gpu_continuation = ftl::WrapLambda([
rasterizer, //
surface = std::move(surface), //
caller_continuation, //
&latch
]() mutable {
// Runs on the GPU Thread. So does the Caller Continuation.
surface->Setup();
rasterizer->Setup(std::move(surface), caller_continuation, &latch);
});
// Runs on the UI Thread.
delegate->OnOutputSurfaceCreated(std::move(gpu_continuation));
});
// Runs on the Platform Thread.
blink::Threads::UI()->PostTask(std::move(ui_continuation));
latch.Wait();
}
......
......@@ -9,6 +9,7 @@
#include "flutter/shell/common/engine.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/surface.h"
#include "flutter/shell/common/ui_delegate.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/weak_ptr.h"
......@@ -46,22 +47,17 @@ class PlatformView {
void ConnectToEngine(mojo::InterfaceRequest<sky::SkyEngine> request);
void NotifyCreated();
void NotifyCreated(std::unique_ptr<Surface> surface);
void NotifyCreated(ftl::Closure continuation);
void NotifyCreated(std::unique_ptr<Surface> surface,
ftl::Closure continuation);
void NotifyDestroyed();
virtual ftl::WeakPtr<PlatformView> GetWeakViewPtr() = 0;
virtual uint64_t DefaultFramebuffer() const = 0;
virtual bool ContextMakeCurrent() = 0;
virtual bool ResourceContextMakeCurrent() = 0;
virtual bool SwapBuffers() = 0;
virtual SkISize GetSize();
virtual void Resize(const SkISize& size);
......@@ -75,13 +71,11 @@ class PlatformView {
protected:
Config config_;
SurfaceConfig surface_config_;
std::unique_ptr<Rasterizer> rasterizer_;
std::unique_ptr<Engine> engine_;
SkISize size_;
explicit PlatformView();
explicit PlatformView(std::unique_ptr<Rasterizer> rasterizer);
void SetupResourceContextOnIOThreadPerform(
ftl::AutoResetWaitableEvent* event);
......
......@@ -6,6 +6,6 @@
namespace shell {
Rasterizer::~Rasterizer() {}
Rasterizer::~Rasterizer() = default;
} // namespace shell
......@@ -6,8 +6,8 @@
#define SHELL_COMMON_RASTERIZER_H_
#include <memory>
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/shell/common/surface.h"
#include "flutter/synchronization/pipeline.h"
#include "lib/ftl/functional/closure.h"
#include "lib/ftl/memory/weak_ptr.h"
......@@ -16,30 +16,25 @@
namespace shell {
class PlatformView;
class Rasterizer {
public:
virtual ~Rasterizer();
virtual void Setup(PlatformView* platform_view,
virtual void Setup(std::unique_ptr<Surface> surface_or_null,
ftl::Closure rasterizer_continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) = 0;
virtual void Clear(SkColor color) = 0;
virtual void Teardown(
ftl::AutoResetWaitableEvent* teardown_completion_event) = 0;
virtual void Clear(SkColor color, const SkISize& size) = 0;
virtual ftl::WeakPtr<Rasterizer> GetWeakRasterizerPtr() = 0;
virtual flow::LayerTree* GetLastLayerTree() = 0;
virtual void Draw(
ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) = 0;
// Implemented by each GPU backend.
static std::unique_ptr<Rasterizer> Create();
};
} // namespace shell
......
......@@ -2,24 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu_canvas.h"
#include "gpu_canvas_gl.h"
#include "gpu_canvas_vulkan.h"
#include "flutter/shell/common/surface.h"
namespace shell {
GPUCanvas::~GPUCanvas() = default;
SurfaceFrame::SurfaceFrame() : submitted_(false) {}
std::unique_ptr<GPUCanvas> GPUCanvas::CreatePlatformCanvas(
const PlatformView& platform_view) {
std::unique_ptr<GPUCanvas> canvas;
SurfaceFrame::~SurfaceFrame() = default;
// TODO: Vulkan capability detection will be added here to return a differnt
// canvas instance.
bool SurfaceFrame::Submit() {
if (submitted_) {
return false;
}
canvas.reset(new GPUCanvasGL(platform_view.DefaultFramebuffer()));
submitted_ = PerformSubmit();
return canvas;
return submitted_;
}
Surface::Surface() = default;
Surface::~Surface() = default;
} // namespace shell
......@@ -2,33 +2,53 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_GPU_GPU_CANVAS_H_
#define SHELL_GPU_GPU_CANVAS_H_
#ifndef FLUTTER_SHELL_COMMON_SURFACE_H_
#define FLUTTER_SHELL_COMMON_SURFACE_H_
#include <memory>
#include "flutter/shell/common/platform_view.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/compiler_specific.h"
#include "lib/ftl/macros.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace shell {
class GPUCanvas {
class SurfaceFrame {
public:
static std::unique_ptr<GPUCanvas> CreatePlatformCanvas(
const PlatformView& platform_view);
SurfaceFrame();
virtual ~SurfaceFrame();
bool Submit();
virtual SkCanvas* SkiaCanvas() = 0;
private:
bool submitted_;
virtual ~GPUCanvas();
virtual bool PerformSubmit() = 0;
FTL_DISALLOW_COPY_AND_ASSIGN(SurfaceFrame);
};
class Surface {
public:
Surface();
virtual ~Surface();
FTL_WARN_UNUSED_RESULT
virtual bool Setup() = 0;
virtual bool IsValid() = 0;
virtual SkCanvas* AcquireCanvas(const SkISize& size) = 0;
virtual std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) = 0;
virtual GrContext* GetContext() = 0;
private:
FTL_DISALLOW_COPY_AND_ASSIGN(Surface);
};
} // namespace shell
#endif // SHELL_GPU_GPU_CANVAS_H_
#endif // FLUTTER_SHELL_COMMON_SURFACE_H_
......@@ -4,23 +4,22 @@
source_set("gpu") {
sources = [
"gpu_canvas.cc",
"gpu_canvas.h",
"gpu_canvas_gl.cc",
"gpu_canvas_gl.h",
"gpu_canvas_vulkan.cc",
"gpu_canvas_vulkan.h",
"gpu_rasterizer.cc",
"gpu_rasterizer.h",
"gpu_surface_gl.cc",
"gpu_surface_gl.h",
"gpu_surface_vulkan.cc",
"gpu_surface_vulkan.h",
]
deps = [
"../common",
"//lib/ftl",
"//flutter/skia",
"//flutter/flow",
"//flutter/common",
"//flutter/flow",
"//flutter/glue",
"//flutter/skia",
"//flutter/synchronization",
"//lib/ftl",
"//mojo/public/cpp/system",
]
}
......@@ -9,16 +9,15 @@
#include "flutter/common/threads.h"
#include "flutter/glue/trace_event.h"
#include "flutter/shell/common/picture_serializer.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/picture_serializer.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPicture.h"
namespace shell {
GPURasterizer::GPURasterizer() : platform_view_(nullptr), weak_factory_(this) {
GPURasterizer::GPURasterizer() : weak_factory_(this) {
auto weak_ptr = weak_factory_.GetWeakPtr();
blink::Threads::Gpu()->PostTask(
[weak_ptr]() { Shell::Shared().AddRasterizer(weak_ptr); });
......@@ -29,70 +28,45 @@ GPURasterizer::~GPURasterizer() {
Shell::Shared().PurgeRasterizers();
}
std::unique_ptr<Rasterizer> Rasterizer::Create() {
return std::unique_ptr<GPURasterizer>(new GPURasterizer());
}
ftl::WeakPtr<Rasterizer> GPURasterizer::GetWeakRasterizerPtr() {
return weak_factory_.GetWeakPtr();
}
bool GPURasterizer::Setup(PlatformView* platform_view) {
if (platform_view == nullptr) {
return false;
}
if (!platform_view->ContextMakeCurrent()) {
return false;
}
auto gpu_canvas = GPUCanvas::CreatePlatformCanvas(*platform_view);
if (gpu_canvas == nullptr) {
return false;
}
if (!gpu_canvas->Setup()) {
return false;
}
gpu_canvas_ = std::move(gpu_canvas);
platform_view_ = platform_view;
return true;
}
void GPURasterizer::Setup(PlatformView* platform_view,
void GPURasterizer::Setup(std::unique_ptr<Surface> surface,
ftl::Closure continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) {
auto setup_result = Setup(platform_view);
FTL_CHECK(setup_result) << "Must be able to setup the GPU canvas.";
surface_ = std::move(surface);
continuation();
setup_completion_event->Signal();
}
void GPURasterizer::Clear(SkColor color) {
if (gpu_canvas_ == nullptr) {
void GPURasterizer::Clear(SkColor color, const SkISize& size) {
if (surface_ == nullptr) {
return;
}
auto frame = surface_->AcquireFrame(size);
if (frame == nullptr) {
return;
}
SkCanvas* canvas = gpu_canvas_->AcquireCanvas(platform_view_->GetSize());
SkCanvas* canvas = frame->SkiaCanvas();
if (canvas == nullptr) {
return;
}
canvas->clear(color);
canvas->flush();
platform_view_->SwapBuffers();
frame->Submit();
}
void GPURasterizer::Teardown(
ftl::AutoResetWaitableEvent* teardown_completion_event) {
platform_view_ = nullptr;
surface_.reset();
last_layer_tree_.reset();
compositor_context_.OnGrContextDestroyed();
teardown_completion_event->Signal();
......@@ -106,9 +80,6 @@ void GPURasterizer::Draw(
ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) {
TRACE_EVENT0("flutter", "GPURasterizer::Draw");
if (!platform_view_)
return;
flutter::Pipeline<flow::LayerTree>::Consumer consumer =
std::bind(&GPURasterizer::DoDraw, this, std::placeholders::_1);
......@@ -130,7 +101,7 @@ void GPURasterizer::Draw(
}
void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
if (!layer_tree || !gpu_canvas_) {
if (!layer_tree || !surface_) {
return;
}
......@@ -139,62 +110,76 @@ void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
// for instrumentation.
compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());
SkISize size = layer_tree->frame_size();
if (platform_view_->GetSize() != size) {
platform_view_->Resize(size);
DrawToSurface(*layer_tree);
DrawToTraceIfNecessary(*layer_tree);
last_layer_tree_ = std::move(layer_tree);
}
void GPURasterizer::DrawToSurface(flow::LayerTree& layer_tree) {
auto frame = surface_->AcquireFrame(layer_tree.frame_size());
if (frame == nullptr) {
return;
}
if (!platform_view_->ContextMakeCurrent() || !layer_tree->root_layer()) {
auto canvas = frame->SkiaCanvas();
if (canvas == nullptr) {
return;
}
{
SkCanvas* canvas = gpu_canvas_->AcquireCanvas(layer_tree->frame_size());
flow::CompositorContext::ScopedFrame frame =
compositor_context_.AcquireFrame(gpu_canvas_->GetContext(), *canvas);
canvas->clear(SK_ColorBLACK);
layer_tree->Raster(frame);
auto compositor_frame =
compositor_context_.AcquireFrame(surface_->GetContext(), *canvas);
{
TRACE_EVENT0("flutter", "SkCanvas::Flush");
canvas->flush();
}
canvas->clear(SK_ColorBLACK);
layer_tree.Raster(compositor_frame);
platform_view_->SwapBuffers();
frame->Submit();
}
bool GPURasterizer::ShouldDrawToTrace(flow::LayerTree& layer_tree) {
if (Shell::Shared().tracing_controller().picture_tracing_enabled()) {
// Picture tracing is unconditionally enabled for all frames by the tracing
// controller.
return true;
}
const uint32_t threshold_interval = layer_tree.rasterizer_tracing_threshold();
if (threshold_interval == 0) {
// An interval of zero means tracing is disabled.
return false;
}
// Trace to a file if necessary
static const double kOneFrameDuration = 1e3 / 60.0;
bool frameExceededThreshold = false;
uint32_t thresholdInterval = layer_tree->rasterizer_tracing_threshold();
if (thresholdInterval != 0 &&
compositor_context_.frame_time().LastLap().ToMillisecondsF() >
thresholdInterval * kOneFrameDuration) {
// While rendering the last frame, if we exceeded the tracing threshold
// specified in the layer tree, we force a trace to disk.
frameExceededThreshold = true;
return compositor_context_.frame_time().LastLap().ToMillisecondsF() >
threshold_interval * 1e3 / 60.0;
}
void GPURasterizer::DrawToTraceIfNecessary(flow::LayerTree& layer_tree) {
if (!ShouldDrawToTrace(layer_tree)) {
return;
}
const auto& tracingController = Shell::Shared().tracing_controller();
auto& tracing_controller = Shell::Shared().tracing_controller();
if (frameExceededThreshold || tracingController.picture_tracing_enabled()) {
std::string path = tracingController.PictureTracingPathForCurrentTime();
LOG(INFO) << "Frame threshold exceeded. Capturing SKP to " << path;
std::string path = tracing_controller.PictureTracingPathForCurrentTime();
LOG(INFO) << "Frame threshold exceeded. Capturing SKP to " << path;
SkPictureRecorder recorder;
recorder.beginRecording(SkRect::MakeWH(size.width(), size.height()));
SkPictureRecorder recorder;
{
auto frame = compositor_context_.AcquireFrame(
nullptr, *recorder.getRecordingCanvas(), false);
layer_tree->Raster(frame, true);
}
recorder.beginRecording(layer_tree.frame_size().width(),
layer_tree.frame_size().height());
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
SerializePicture(path, picture.get());
}
auto compositor_frame = compositor_context_.AcquireFrame(
nullptr, *recorder.getRecordingCanvas(), false);
layer_tree.Raster(compositor_frame, true /* ignore raster cache */);
last_layer_tree_ = std::move(layer_tree);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
SerializePicture(path, picture.get());
}
} // namespace shell
......@@ -7,23 +7,24 @@
#include "flutter/flow/compositor_context.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/gpu/gpu_canvas.h"
#include "lib/ftl/memory/weak_ptr.h"
#include "lib/ftl/synchronization/waitable_event.h"
namespace shell {
class Surface;
class GPURasterizer : public Rasterizer {
public:
GPURasterizer();
~GPURasterizer() override;
void Setup(PlatformView* platform_view,
void Setup(std::unique_ptr<Surface> surface,
ftl::Closure continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) override;
void Clear(SkColor color) override;
void Clear(SkColor color, const SkISize& size) override;
void Teardown(
ftl::AutoResetWaitableEvent* teardown_completion_event) override;
......@@ -35,16 +36,18 @@ class GPURasterizer : public Rasterizer {
void Draw(ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) override;
private:
std::unique_ptr<GPUCanvas> gpu_canvas_;
std::unique_ptr<Surface> surface_;
flow::CompositorContext compositor_context_;
std::unique_ptr<flow::LayerTree> last_layer_tree_;
PlatformView* platform_view_;
ftl::WeakPtrFactory<GPURasterizer> weak_factory_;
FTL_WARN_UNUSED_RESULT
bool Setup(PlatformView* platform_view);
void DoDraw(std::unique_ptr<flow::LayerTree> layer_tree);
void DrawToSurface(flow::LayerTree& layer_tree);
bool ShouldDrawToTrace(flow::LayerTree& layer_tree);
void DoDraw(std::unique_ptr<flow::LayerTree> tree);
void DrawToTraceIfNecessary(flow::LayerTree& layer_tree);
FTL_DISALLOW_COPY_AND_ASSIGN(GPURasterizer);
};
......
......@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu_canvas_gl.h"
#include "gpu_surface_gl.h"
#include "flutter/flow/gl_connection.h"
#include "lib/ftl/arraysize.h"
#include "lib/ftl/logging.h"
#include "flutter/flow/gl_connection.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace shell {
......@@ -21,16 +21,59 @@ static const int kMaxGaneshResourceCacheCount = 2048;
// GPU cache.
static const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
GPUCanvasGL::GPUCanvasGL(intptr_t fbo) : fbo_(fbo) {}
GPUSurfaceFrameGL::GPUSurfaceFrameGL(sk_sp<SkSurface> surface,
SubmitCallback submit_callback)
: surface_(surface), submit_callback_(submit_callback) {}
GPUSurfaceFrameGL::~GPUSurfaceFrameGL() {
if (submit_callback_) {
// Dropping without a Submit. Callback with nullptr so that the current
// context on the thread is cleared.
submit_callback_(nullptr);
}
}
SkCanvas* GPUSurfaceFrameGL::SkiaCanvas() {
return surface_->getCanvas();
}
bool GPUSurfaceFrameGL::PerformSubmit() {
if (submit_callback_ == nullptr) {
return false;
}
GPUCanvasGL::~GPUCanvasGL() = default;
FLUTTER_THREAD_CHECKER_CHECK(checker_);
if (submit_callback_(surface_->getCanvas())) {
surface_ = nullptr;
return true;
}
return false;
}
GPUSurfaceGL::GPUSurfaceGL(GPUSurfaceGLDelegate* delegate)
: delegate_(delegate), weak_factory_(this) {}
GPUSurfaceGL::~GPUSurfaceGL() = default;
bool GPUSurfaceGL::Setup() {
if (delegate_ == nullptr) {
// Invalid delegate.
return false;
}
bool GPUCanvasGL::Setup() {
if (context_ != nullptr) {
// Already setup.
return false;
}
if (!delegate_->GLContextMakeCurrent()) {
// Could not make the context current to create the native interface.
return false;
}
// Create the native interface.
auto backend_context =
reinterpret_cast<GrBackendContext>(GrGLCreateNativeInterface());
......@@ -46,24 +89,59 @@ bool GPUCanvasGL::Setup() {
context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
kMaxGaneshResourceCacheBytes);
// Clean up the current context.
delegate_->GLContextClearCurrent();
return true;
}
bool GPUCanvasGL::IsValid() {
bool GPUSurfaceGL::IsValid() {
return context_ != nullptr;
}
SkCanvas* GPUCanvasGL::AcquireCanvas(const SkISize& size) {
auto surface = AcquireSurface(size);
std::unique_ptr<SurfaceFrame> GPUSurfaceGL::AcquireFrame(const SkISize& size) {
if (delegate_ == nullptr) {
return nullptr;
}
sk_sp<SkSurface> surface = AcquireSurface(size);
if (surface == nullptr) {
return nullptr;
}
return surface->getCanvas();
if (!delegate_->GLContextMakeCurrent()) {
return nullptr;
}
auto weak_this = weak_factory_.GetWeakPtr();
GPUSurfaceFrameGL::SubmitCallback submit_callback =
[weak_this](SkCanvas* canvas) {
return weak_this ? weak_this->PresentSurface(canvas) : false;
};
return std::unique_ptr<GPUSurfaceFrameGL>(
new GPUSurfaceFrameGL(surface, submit_callback));
}
bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) {
if (delegate_ == nullptr || canvas == nullptr) {
delegate_->GLContextClearCurrent();
return false;
}
canvas->flush();
delegate_->GLContextPresent();
delegate_->GLContextClearCurrent();
return true;
}
bool GPUCanvasGL::SelectPixelConfig(GrPixelConfig* config) {
bool GPUSurfaceGL::SelectPixelConfig(GrPixelConfig* config) {
static const GrPixelConfig kConfigOptions[] = {
kSkia8888_GrPixelConfig, kRGBA_4444_GrPixelConfig,
};
......@@ -78,8 +156,8 @@ bool GPUCanvasGL::SelectPixelConfig(GrPixelConfig* config) {
return false;
}
sk_sp<SkSurface> GPUCanvasGL::CreateSurface(const SkISize& size) {
if (context_ == nullptr) {
sk_sp<SkSurface> GPUSurfaceGL::CreateSurface(const SkISize& size) {
if (delegate_ == nullptr || context_ == nullptr) {
return nullptr;
}
......@@ -93,12 +171,12 @@ sk_sp<SkSurface> GPUCanvasGL::CreateSurface(const SkISize& size) {
desc.fHeight = size.height();
desc.fStencilBits = 8;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
desc.fRenderTargetHandle = fbo_;
desc.fRenderTargetHandle = delegate_->GLContextFBO();
return SkSurface::MakeFromBackendRenderTarget(context_.get(), desc, nullptr);
}
sk_sp<SkSurface> GPUCanvasGL::AcquireSurface(const SkISize& size) {
sk_sp<SkSurface> GPUSurfaceGL::AcquireSurface(const SkISize& size) {
// There is no cached surface.
if (cached_surface_ == nullptr) {
cached_surface_ = CreateSurface(size);
......@@ -115,7 +193,7 @@ sk_sp<SkSurface> GPUCanvasGL::AcquireSurface(const SkISize& size) {
return cached_surface_;
}
GrContext* GPUCanvasGL::GetContext() {
GrContext* GPUSurfaceGL::GetContext() {
return context_.get();
}
......
......@@ -2,42 +2,78 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_GPU_GPU_CANVAS_GL_H_
#define SHELL_GPU_GPU_CANVAS_GL_H_
#ifndef SHELL_GPU_GPU_SURFACE_GL_H_
#define SHELL_GPU_GPU_SURFACE_GL_H_
#include "flutter/shell/common/surface.h"
#include "flutter/synchronization/debug_thread_checker.h"
#include "lib/ftl/macros.h"
#include "gpu_canvas.h"
#include "lib/ftl/memory/weak_ptr.h"
namespace shell {
class GPUCanvasGL : public GPUCanvas {
class GPUSurfaceGLDelegate {
public:
GPUCanvasGL(intptr_t fbo);
virtual bool GLContextMakeCurrent() = 0;
~GPUCanvasGL() override;
virtual bool GLContextClearCurrent() = 0;
virtual bool GLContextPresent() = 0;
virtual intptr_t GLContextFBO() const = 0;
};
class GPUSurfaceGL : public Surface {
public:
GPUSurfaceGL(GPUSurfaceGLDelegate* delegate);
~GPUSurfaceGL() override;
bool Setup() override;
bool IsValid() override;
SkCanvas* AcquireCanvas(const SkISize& size) override;
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;
GrContext* GetContext() override;
private:
intptr_t fbo_;
GPUSurfaceGLDelegate* delegate_;
sk_sp<GrContext> context_;
sk_sp<SkSurface> cached_surface_;
ftl::WeakPtrFactory<GPUSurfaceGL> weak_factory_;
sk_sp<SkSurface> CreateSurface(const SkISize& size);
sk_sp<SkSurface> AcquireSurface(const SkISize& size);
bool PresentSurface(SkCanvas* canvas);
bool SelectPixelConfig(GrPixelConfig* config);
FTL_DISALLOW_COPY_AND_ASSIGN(GPUCanvasGL);
FTL_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGL);
};
class GPUSurfaceFrameGL : public SurfaceFrame {
public:
using SubmitCallback = std::function<bool(SkCanvas* canvas)>;
GPUSurfaceFrameGL(sk_sp<SkSurface> surface, SubmitCallback submit_callback);
~GPUSurfaceFrameGL();
SkCanvas* SkiaCanvas() override;
private:
FLUTTER_THREAD_CHECKER_DECLARE(checker_);
sk_sp<SkSurface> surface_;
SubmitCallback submit_callback_;
bool PerformSubmit() override;
FTL_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceFrameGL);
};
} // namespace shell
#endif // SHELL_GPU_GPU_CANVAS_GL_H_
#endif // SHELL_GPU_GPU_SURFACE_GL_H_
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu_canvas_vulkan.h"
#include "flutter/shell/gpu/gpu_surface_vulkan.h"
namespace shell {
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_GPU_GPU_CANVAS_VULKAN_H_
#define SHELL_GPU_GPU_CANVAS_VULKAN_H_
#ifndef SHELL_GPU_GPU_SURFACE_VULKAN_H_
#define SHELL_GPU_GPU_SURFACE_VULKAN_H_
#include "lib/ftl/macros.h"
......@@ -13,4 +13,4 @@ namespace shell {
} // namespace shell
#endif // SHELL_GPU_GPU_CANVAS_VULKAN_H_
#endif // SHELL_GPU_GPU_SURFACE_VULKAN_H_
......@@ -19,6 +19,14 @@ shared_library("sky_shell") {
visibility = [ ":*" ]
sources = [
"android_context_gl.cc",
"android_context_gl.h",
"android_environment_gl.cc",
"android_environment_gl.h",
"android_native_window.cc",
"android_native_window.h",
"android_surface_gl.cc",
"android_surface_gl.h",
"flutter_main.cc",
"flutter_main.h",
"library_loader.cc",
......
// 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/shell/platform/android/android_context_gl.h"
#include <utility>
namespace shell {
template <class T>
using EGLResult = std::pair<bool, T>;
static void LogLastEGLError() {
struct EGLNameErrorPair {
const char* name;
EGLint code;
};
#define _EGL_ERROR_DESC(a) \
{ #a, a }
const EGLNameErrorPair pairs[] = {
_EGL_ERROR_DESC(EGL_SUCCESS),
_EGL_ERROR_DESC(EGL_NOT_INITIALIZED),
_EGL_ERROR_DESC(EGL_BAD_ACCESS),
_EGL_ERROR_DESC(EGL_BAD_ALLOC),
_EGL_ERROR_DESC(EGL_BAD_ATTRIBUTE),
_EGL_ERROR_DESC(EGL_BAD_CONTEXT),
_EGL_ERROR_DESC(EGL_BAD_CONFIG),
_EGL_ERROR_DESC(EGL_BAD_CURRENT_SURFACE),
_EGL_ERROR_DESC(EGL_BAD_DISPLAY),
_EGL_ERROR_DESC(EGL_BAD_SURFACE),
_EGL_ERROR_DESC(EGL_BAD_MATCH),
_EGL_ERROR_DESC(EGL_BAD_PARAMETER),
_EGL_ERROR_DESC(EGL_BAD_NATIVE_PIXMAP),
_EGL_ERROR_DESC(EGL_BAD_NATIVE_WINDOW),
_EGL_ERROR_DESC(EGL_CONTEXT_LOST),
};
#undef _EGL_ERROR_DESC
const auto count = sizeof(pairs) / sizeof(EGLNameErrorPair);
EGLint last_error = eglGetError();
for (size_t i = 0; i < count; i++) {
if (last_error == pairs[i].code) {
DLOG(INFO) << "EGL Error: " << pairs[i].name << " (" << pairs[i].code
<< ")";
return;
}
}
DLOG(WARNING) << "Unknown EGL Error";
}
static EGLResult<EGLSurface> CreateContext(EGLDisplay display,
EGLConfig config,
EGLContext share = EGL_NO_CONTEXT) {
EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLContext context = eglCreateContext(display, config, share, attributes);
return {context != EGL_NO_CONTEXT, context};
}
static EGLResult<EGLConfig> ChooseEGLConfiguration(
EGLDisplay display,
PlatformView::SurfaceConfig config) {
EGLint attributes[] = {
// clang-format off
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, config.red_bits,
EGL_GREEN_SIZE, config.green_bits,
EGL_BLUE_SIZE, config.blue_bits,
EGL_ALPHA_SIZE, config.alpha_bits,
EGL_DEPTH_SIZE, config.depth_bits,
EGL_STENCIL_SIZE, config.stencil_bits,
EGL_NONE, // termination sentinel
// clang-format on
};
EGLint config_count = 0;
EGLConfig egl_config = nullptr;
if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) !=
EGL_TRUE) {
return {false, nullptr};
}
bool success = config_count > 0 && egl_config != nullptr;
return {success, success ? egl_config : nullptr};
}
static bool TeardownContext(EGLDisplay display, EGLContext context) {
if (context != EGL_NO_CONTEXT) {
return eglDestroyContext(display, context) == EGL_TRUE;
}
return true;
}
static bool TeardownSurface(EGLDisplay display, EGLSurface surface) {
if (surface != EGL_NO_SURFACE) {
return eglDestroySurface(display, surface) == EGL_TRUE;
}
return true;
}
// For onscreen rendering.
static EGLResult<EGLSurface> CreateWindowSurface(
EGLDisplay display,
EGLConfig config,
AndroidNativeWindow::Handle window_handle) {
// The configurations are only required when dealing with extensions or VG.
// We do neither.
EGLSurface surface = eglCreateWindowSurface(
display, config, reinterpret_cast<EGLNativeWindowType>(window_handle),
nullptr);
return {surface != EGL_NO_SURFACE, surface};
}
// For offscreen rendering.
static EGLResult<EGLSurface> CreatePBufferSurface(EGLDisplay display,
EGLConfig config) {
// We only ever create pbuffer surfaces for background resource loading
// contexts. We never bind the pbuffer to anything.
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface surface = eglCreatePbufferSurface(display, config, attribs);
return {surface != EGL_NO_SURFACE, surface};
}
static EGLResult<EGLSurface> CreateSurface(EGLDisplay display,
EGLConfig config,
const AndroidNativeWindow& window) {
return window.IsValid()
? CreateWindowSurface(display, config, window.handle())
: CreatePBufferSurface(display, config);
}
AndroidContextGL::AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
AndroidNativeWindow window,
PlatformView::SurfaceConfig config,
const AndroidContextGL* share_context)
: environment_(env),
window_(std::move(window)),
config_(nullptr),
surface_(EGL_NO_SURFACE),
context_(EGL_NO_CONTEXT),
valid_(false) {
if (!environment_->IsValid()) {
return;
}
bool success = false;
// Choose a valid configuration.
std::tie(success, config_) =
ChooseEGLConfiguration(environment_->Display(), config);
if (!success) {
DLOG(INFO) << "Could not choose a configuration.";
LogLastEGLError();
return;
}
// Create a surface for the configuration.
std::tie(success, surface_) =
CreateSurface(environment_->Display(), config_, window_);
if (!success) {
DLOG(INFO) << "Could not create the surface.";
LogLastEGLError();
return;
}
// Create a context for the configuration.
std::tie(success, context_) = CreateContext(
environment_->Display(), config_,
share_context != nullptr ? share_context->context_ : EGL_NO_CONTEXT);
if (!success) {
DLOG(INFO) << "Could not create a context";
LogLastEGLError();
return;
}
// All done!
valid_ = true;
}
AndroidContextGL::AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
PlatformView::SurfaceConfig config,
const AndroidContextGL* share_context)
: AndroidContextGL(env,
AndroidNativeWindow{nullptr},
config,
share_context) {}
AndroidContextGL::~AndroidContextGL() {
if (!TeardownContext(environment_->Display(), context_)) {
LOG(INFO) << "Could not tear down the EGL context. Possible resource leak.";
LogLastEGLError();
}
if (!TeardownSurface(environment_->Display(), surface_)) {
LOG(INFO) << "Could not tear down the EGL surface. Possible resource leak.";
LogLastEGLError();
}
}
ftl::RefPtr<AndroidEnvironmentGL> AndroidContextGL::Environment() const {
return environment_;
}
bool AndroidContextGL::IsValid() const {
return valid_;
}
bool AndroidContextGL::MakeCurrent() {
if (eglMakeCurrent(environment_->Display(), surface_, surface_, context_) !=
EGL_TRUE) {
LOG(INFO) << "Could not make the context current";
LogLastEGLError();
return false;
}
return true;
}
bool AndroidContextGL::ClearCurrent() {
if (eglMakeCurrent(environment_->Display(), EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT) != EGL_TRUE) {
LOG(INFO) << "Could not clear the current context";
LogLastEGLError();
return false;
}
return true;
}
bool AndroidContextGL::SwapBuffers() {
return eglSwapBuffers(environment_->Display(), surface_);
}
SkISize AndroidContextGL::GetSize() {
EGLint width = 0;
EGLint height = 0;
if (!eglQuerySurface(environment_->Display(), surface_, EGL_WIDTH, &width) ||
!eglQuerySurface(environment_->Display(), surface_, EGL_HEIGHT,
&height)) {
LOG(ERROR) << "Unable to query EGL surface size";
LogLastEGLError();
return SkISize::Make(0, 0);
}
return SkISize::Make(width, height);
}
bool AndroidContextGL::Resize(const SkISize& size) {
if (size == GetSize()) {
return true;
}
ClearCurrent();
TeardownSurface(environment_->Display(), surface_);
bool success = false;
std::tie(success, surface_) =
CreateSurface(environment_->Display(), config_, window_);
if (!success) {
LOG(ERROR) << "Unable to create EGL window surface on resize.";
return false;
}
return true;
}
} // namespace shell
// 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_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_H_
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/android/android_environment_gl.h"
#include "flutter/shell/platform/android/android_native_window.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/ref_counted.h"
#include "lib/ftl/memory/ref_ptr.h"
#include "third_party/skia/include/core/SkSize.h"
namespace shell {
class AndroidContextGL : public ftl::RefCountedThreadSafe<AndroidContextGL> {
private:
/// Creates a window surface context tied to the window handle for on-screen
/// rendering.
// MakeRefCounted
AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
AndroidNativeWindow window,
PlatformView::SurfaceConfig config,
const AndroidContextGL* share_context = nullptr);
/// Creates a pbuffer surface context for offscreen rendering.
// MakeRefCounted
AndroidContextGL(ftl::RefPtr<AndroidEnvironmentGL> env,
PlatformView::SurfaceConfig config,
const AndroidContextGL* share_context = nullptr);
~AndroidContextGL();
public:
ftl::RefPtr<AndroidEnvironmentGL> Environment() const;
bool IsValid() const;
bool MakeCurrent();
bool ClearCurrent();
bool SwapBuffers();
SkISize GetSize();
bool Resize(const SkISize& size);
private:
ftl::RefPtr<AndroidEnvironmentGL> environment_;
AndroidNativeWindow window_;
EGLConfig config_;
EGLSurface surface_;
EGLContext context_;
bool valid_;
FRIEND_MAKE_REF_COUNTED(AndroidContextGL);
FRIEND_REF_COUNTED_THREAD_SAFE(AndroidContextGL);
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidContextGL);
};
} // namespace shell
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_H_
// 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/shell/platform/android/android_environment_gl.h"
namespace shell {
AndroidEnvironmentGL::AndroidEnvironmentGL()
: display_(EGL_NO_DISPLAY), valid_(false) {
// Get the display.
display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display_ == EGL_NO_DISPLAY) {
return;
}
// Initialize the display connection.
if (eglInitialize(display_, nullptr, nullptr) != EGL_TRUE) {
return;
}
valid_ = true;
}
AndroidEnvironmentGL::~AndroidEnvironmentGL() {
// Diconnect the display if valid.
if (display_ != EGL_NO_CONTEXT) {
eglTerminate(display_);
}
}
bool AndroidEnvironmentGL::IsValid() const {
return valid_;
}
EGLDisplay AndroidEnvironmentGL::Display() const {
return display_;
}
} // namespace shell
// 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_SHELL_PLATFORM_ANDROID_ANDROID_ENVIRONMENT_GL_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_ENVIRONMENT_GL_H_
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/ref_counted.h"
#include <EGL/egl.h>
namespace shell {
class AndroidEnvironmentGL
: public ftl::RefCountedThreadSafe<AndroidEnvironmentGL> {
private:
// MakeRefCounted
AndroidEnvironmentGL();
// MakeRefCounted
~AndroidEnvironmentGL();
public:
bool IsValid() const;
EGLDisplay Display() const;
private:
EGLDisplay display_;
bool valid_;
FRIEND_MAKE_REF_COUNTED(AndroidEnvironmentGL);
FRIEND_REF_COUNTED_THREAD_SAFE(AndroidEnvironmentGL);
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidEnvironmentGL);
};
} // namespace shell
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_ENVIRONMENT_GL_H_
// 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/shell/platform/android/android_native_window.h"
namespace shell {
AndroidNativeWindow::AndroidNativeWindow(Handle window) : window_(window) {
if (window_ != nullptr) {
ANativeWindow_acquire(window_);
}
}
AndroidNativeWindow::AndroidNativeWindow(AndroidNativeWindow&& o)
: window_(o.window_) {
o.window_ = nullptr;
}
AndroidNativeWindow::~AndroidNativeWindow() {
if (window_ != nullptr) {
ANativeWindow_release(window_);
window_ = nullptr;
}
}
bool AndroidNativeWindow::IsValid() const {
return window_ != nullptr;
}
AndroidNativeWindow::Handle AndroidNativeWindow::handle() const {
return window_;
}
} // namespace shell
// 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_SHELL_PLATFORM_ANDROID_ANDROID_NATIVE_WINDOW_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_NATIVE_WINDOW_H_
#include <android/native_window.h>
#include "lib/ftl/macros.h"
namespace shell {
class AndroidNativeWindow {
public:
using Handle = ANativeWindow*;
AndroidNativeWindow(Handle window);
AndroidNativeWindow(AndroidNativeWindow&& other);
~AndroidNativeWindow();
bool IsValid() const;
Handle handle() const;
private:
Handle window_;
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidNativeWindow);
};
} // namespace shell
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_NATIVE_WINDOW_H_
// 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 <utility>
#include "flutter/shell/platform/android/android_surface_gl.h"
#include "lib/ftl/logging.h"
#include "lib/ftl/memory/ref_ptr.h"
namespace shell {
static ftl::RefPtr<AndroidContextGL> GlobalResourceLoadingContext(
PlatformView::SurfaceConfig offscreen_config) {
// AndroidSurfaceGL instances are only ever created on the platform thread. So
// there is no need to lock here.
static ftl::RefPtr<AndroidContextGL> global_context;
if (global_context) {
return global_context;
}
auto environment = ftl::MakeRefCounted<AndroidEnvironmentGL>();
if (!environment->IsValid()) {
return nullptr;
}
// TODO(chinmaygarde): We should check that the configurations are stable
// across multiple invocations.
auto context =
ftl::MakeRefCounted<AndroidContextGL>(environment, offscreen_config);
if (!context->IsValid()) {
return nullptr;
}
global_context = context;
return global_context;
}
AndroidSurfaceGL::AndroidSurfaceGL(AndroidNativeWindow window,
PlatformView::SurfaceConfig onscreen_config,
PlatformView::SurfaceConfig offscreen_config)
: valid_(false) {
// Acquire the offscreen context.
offscreen_context_ = GlobalResourceLoadingContext(offscreen_config);
if (!offscreen_context_ || !offscreen_context_->IsValid()) {
return;
}
// Create the onscreen context.
onscreen_context_ = ftl::MakeRefCounted<AndroidContextGL>(
offscreen_context_->Environment(), std::move(window), onscreen_config,
offscreen_context_.get() /* sharegroup */);
if (!onscreen_context_->IsValid()) {
return;
}
// All done.
valid_ = true;
}
AndroidSurfaceGL::~AndroidSurfaceGL() = default;
bool AndroidSurfaceGL::IsValid() const {
return valid_;
}
SkISize AndroidSurfaceGL::OnScreenSurfaceSize() const {
FTL_DCHECK(valid_);
return onscreen_context_->GetSize();
}
bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) const {
FTL_DCHECK(valid_);
return onscreen_context_->Resize(size);
}
bool AndroidSurfaceGL::GLOffscreenContextMakeCurrent() {
FTL_DCHECK(valid_);
return offscreen_context_->MakeCurrent();
}
bool AndroidSurfaceGL::GLContextMakeCurrent() {
FTL_DCHECK(valid_);
return onscreen_context_->MakeCurrent();
}
bool AndroidSurfaceGL::GLContextClearCurrent() {
FTL_DCHECK(valid_);
return onscreen_context_->ClearCurrent();
}
bool AndroidSurfaceGL::GLContextPresent() {
FTL_DCHECK(valid_);
return onscreen_context_->SwapBuffers();
}
intptr_t AndroidSurfaceGL::GLContextFBO() const {
FTL_DCHECK(valid_);
// The default window bound framebuffer on Android.
return 0;
}
} // namespace shell
// 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_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
#include <memory>
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/platform/android/android_context_gl.h"
#include "flutter/shell/platform/android/android_environment_gl.h"
#include "flutter/shell/platform/android/android_native_window.h"
#include "lib/ftl/macros.h"
namespace shell {
class AndroidSurfaceGL : public GPUSurfaceGLDelegate {
public:
AndroidSurfaceGL(AndroidNativeWindow window,
PlatformView::SurfaceConfig onscreen_config,
PlatformView::SurfaceConfig offscreen_config);
~AndroidSurfaceGL();
bool IsValid() const;
SkISize OnScreenSurfaceSize() const;
bool OnScreenSurfaceResize(const SkISize& size) const;
bool GLOffscreenContextMakeCurrent();
bool GLContextMakeCurrent() override;
bool GLContextClearCurrent() override;
bool GLContextPresent() override;
intptr_t GLContextFBO() const override;
private:
ftl::RefPtr<AndroidContextGL> onscreen_context_;
ftl::RefPtr<AndroidContextGL> offscreen_context_;
bool valid_;
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL);
};
} // namespace shell
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_
......@@ -4,380 +4,29 @@
#include "flutter/shell/platform/android/platform_view_android.h"
#include <android/input.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <EGL/egl.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <memory>
#include <utility>
#include "base/android/jni_android.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/trace_event/trace_event.h"
#include "flutter/common/threads.h"
#include "flutter/flow/compositor_context.h"
#include "flutter/runtime/dart_service_isolate.h"
#include "flutter/shell/common/engine.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/gpu/gpu_rasterizer.h"
#include "jni/FlutterView_jni.h"
#include "lib/ftl/functional/wrap_lambda.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace shell {
namespace {
template <class T>
using EGLResult = std::pair<bool, T>;
EGLDisplay g_display = EGL_NO_DISPLAY;
EGLContext g_resource_context = EGL_NO_CONTEXT;
EGLSurface g_resource_surface = EGL_NO_SURFACE;
void LogLastEGLError() {
struct EGLNameErrorPair {
const char* name;
EGLint code;
};
#define _EGL_ERROR_DESC(a) \
{ #a, a }
const EGLNameErrorPair pairs[] = {
_EGL_ERROR_DESC(EGL_SUCCESS),
_EGL_ERROR_DESC(EGL_NOT_INITIALIZED),
_EGL_ERROR_DESC(EGL_BAD_ACCESS),
_EGL_ERROR_DESC(EGL_BAD_ALLOC),
_EGL_ERROR_DESC(EGL_BAD_ATTRIBUTE),
_EGL_ERROR_DESC(EGL_BAD_CONTEXT),
_EGL_ERROR_DESC(EGL_BAD_CONFIG),
_EGL_ERROR_DESC(EGL_BAD_CURRENT_SURFACE),
_EGL_ERROR_DESC(EGL_BAD_DISPLAY),
_EGL_ERROR_DESC(EGL_BAD_SURFACE),
_EGL_ERROR_DESC(EGL_BAD_MATCH),
_EGL_ERROR_DESC(EGL_BAD_PARAMETER),
_EGL_ERROR_DESC(EGL_BAD_NATIVE_PIXMAP),
_EGL_ERROR_DESC(EGL_BAD_NATIVE_WINDOW),
_EGL_ERROR_DESC(EGL_CONTEXT_LOST),
};
#undef _EGL_ERROR_DESC
const auto count = sizeof(pairs) / sizeof(EGLNameErrorPair);
EGLint last_error = eglGetError();
for (size_t i = 0; i < count; i++) {
if (last_error == pairs[i].code) {
DLOG(INFO) << "EGL Error: " << pairs[i].name << " (" << pairs[i].code
<< ")";
return;
}
}
DLOG(WARNING) << "Unknown EGL Error";
}
EGLResult<EGLSurface> CreatePBufferSurface(EGLDisplay display,
EGLConfig config) {
// We only ever create pbuffer surfaces for background resource loading
// contexts. We never bind the pbuffer to anything.
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface surface = eglCreatePbufferSurface(display, config, attribs);
return {surface != EGL_NO_SURFACE, surface};
}
EGLResult<EGLSurface> CreateContext(EGLDisplay display,
EGLConfig config,
EGLContext share = EGL_NO_CONTEXT) {
EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLContext context = eglCreateContext(display, config, share, attributes);
return {context != EGL_NO_CONTEXT, context};
}
EGLResult<EGLConfig> ChooseEGLConfiguration(
EGLDisplay display,
PlatformView::SurfaceConfig config) {
EGLint attributes[] = {
// clang-format off
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, config.red_bits,
EGL_GREEN_SIZE, config.green_bits,
EGL_BLUE_SIZE, config.blue_bits,
EGL_ALPHA_SIZE, config.alpha_bits,
EGL_DEPTH_SIZE, config.depth_bits,
EGL_STENCIL_SIZE, config.stencil_bits,
EGL_NONE, // termination sentinel
// clang-format on
};
EGLint config_count = 0;
EGLConfig egl_config = nullptr;
if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) !=
EGL_TRUE) {
return {false, nullptr};
}
bool success = config_count > 0 && egl_config != nullptr;
return {success, success ? egl_config : nullptr};
}
void InitGlobal() {
// Get the display.
g_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (g_display == EGL_NO_DISPLAY)
return;
// Initialize the display connection.
if (eglInitialize(g_display, nullptr, nullptr) != EGL_TRUE)
return;
bool success;
// Choose a config for resource loading.
PlatformView::SurfaceConfig resource_config;
resource_config.stencil_bits = 0;
EGLConfig resource_egl_config;
std::tie(success, resource_egl_config) =
ChooseEGLConfiguration(g_display, resource_config);
if (!success) {
DLOG(INFO) << "Could not choose a resource configuration.";
LogLastEGLError();
return;
}
// Create a pbuffer surface for the configuration for resource loading.
std::tie(success, g_resource_surface) =
CreatePBufferSurface(g_display, resource_egl_config);
if (!success) {
DLOG(INFO) << "Could not create the pbuffer surface for resource loading.";
LogLastEGLError();
return;
}
// Create a resource context for the configuration.
std::tie(success, g_resource_context) =
CreateContext(g_display, resource_egl_config);
if (!success) {
DLOG(INFO) << "Could not create the resource context.";
LogLastEGLError();
return;
}
}
} // namespace
class AndroidNativeWindow {
public:
using Handle = ANativeWindow*;
explicit AndroidNativeWindow(Handle window) : window_(window) {
if (window_ != nullptr) {
ANativeWindow_acquire(window_);
}
}
~AndroidNativeWindow() {
if (window_ != nullptr) {
ANativeWindow_release(window_);
window_ = nullptr;
}
}
bool IsValid() const { return window_ != nullptr; }
Handle handle() const { return window_; }
private:
Handle window_;
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidNativeWindow);
};
class AndroidGLContext {
public:
explicit AndroidGLContext(AndroidNativeWindow::Handle window_handle,
PlatformView::SurfaceConfig config)
: window_(window_handle),
config_(nullptr),
surface_(EGL_NO_SURFACE),
context_(EGL_NO_CONTEXT),
valid_(false) {
if (!window_.IsValid()) {
// We always require a valid window since we are only going to deal
// with window surfaces.
return;
}
bool success = false;
// Choose a valid configuration.
std::tie(success, config_) = ChooseEGLConfiguration(g_display, config);
if (!success) {
DLOG(INFO) << "Could not choose a window configuration.";
LogLastEGLError();
return;
}
// Create a window surface for the configuration.
std::tie(success, surface_) =
CreateWindowSurface(g_display, config_, window_.handle());
if (!success) {
DLOG(INFO) << "Could not create the window surface.";
LogLastEGLError();
return;
}
// Create a context for the configuration.
std::tie(success, context_) =
CreateContext(g_display, config_, g_resource_context);
if (!success) {
DLOG(INFO) << "Could not create the main rendering context";
LogLastEGLError();
return;
}
// All done!
valid_ = true;
}
~AndroidGLContext() {
if (!TeardownContext(g_display, context_)) {
LOG(INFO)
<< "Could not tear down the EGL context. Possible resource leak.";
LogLastEGLError();
}
if (!TeardownSurface(g_display, surface_)) {
LOG(INFO)
<< "Could not tear down the EGL surface. Possible resource leak.";
LogLastEGLError();
}
}
bool IsValid() const { return valid_; }
bool ContextMakeCurrent() {
if (eglMakeCurrent(g_display, surface_, surface_, context_) != EGL_TRUE) {
LOG(INFO) << "Could not make the context current";
LogLastEGLError();
return false;
}
return true;
}
bool SwapBuffers() { return eglSwapBuffers(g_display, surface_); }
SkISize GetSize() {
EGLint width = 0;
EGLint height = 0;
if (!eglQuerySurface(g_display, surface_, EGL_WIDTH, &width) ||
!eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height)) {
LOG(ERROR) << "Unable to query EGL surface size";
LogLastEGLError();
return SkISize::Make(0, 0);
}
return SkISize::Make(width, height);
}
void Resize(const SkISize& size) {
eglMakeCurrent(g_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
TeardownSurface(g_display, surface_);
bool success;
std::tie(success, surface_) =
CreateWindowSurface(g_display, config_, window_.handle());
if (!success) {
LOG(ERROR) << "Unable to create EGL window surface";
}
}
private:
AndroidNativeWindow window_;
EGLConfig config_;
EGLSurface surface_;
EGLContext context_;
bool valid_;
static bool TeardownContext(EGLDisplay display, EGLContext context) {
if (context != EGL_NO_CONTEXT) {
return eglDestroyContext(display, context) == EGL_TRUE;
}
return true;
}
static bool TeardownSurface(EGLDisplay display, EGLSurface surface) {
if (surface != EGL_NO_SURFACE) {
return eglDestroySurface(display, surface) == EGL_TRUE;
}
return true;
}
static EGLResult<EGLSurface> CreateWindowSurface(
EGLDisplay display,
EGLConfig config,
AndroidNativeWindow::Handle window_handle) {
// The configurations are only required when dealing with extensions or VG.
// We do neither.
EGLSurface surface = eglCreateWindowSurface(
display, config, reinterpret_cast<EGLNativeWindowType>(window_handle),
nullptr);
return {surface != EGL_NO_SURFACE, surface};
}
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidGLContext);
};
static jlong Attach(JNIEnv* env,
jclass clazz,
jint skyEngineHandle,
jobject flutterView) {
PlatformViewAndroid* view = new PlatformViewAndroid();
view->ConnectToEngine(mojo::InterfaceRequest<sky::SkyEngine>(
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(skyEngineHandle))));
// Create a weak reference to the flutterView Java object so that we can make
// calls into it later.
view->set_flutter_view(JavaObjectWeakGlobalRef(env, flutterView));
return reinterpret_cast<jlong>(view);
}
jint GetObservatoryPort(JNIEnv* env, jclass clazz) {
return blink::DartServiceIsolate::GetObservatoryPort();
}
// static
bool PlatformViewAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
PlatformViewAndroid::PlatformViewAndroid() : weak_factory_(this) {
// If this is the first PlatformView, then intiialize EGL and set up
// the resource context.
if (g_display == EGL_NO_DISPLAY)
InitGlobal();
}
PlatformViewAndroid::PlatformViewAndroid()
: PlatformView(std::make_unique<GPURasterizer>()), weak_factory_(this) {}
PlatformViewAndroid::~PlatformViewAndroid() = default;
......@@ -389,26 +38,43 @@ void PlatformViewAndroid::Detach(JNIEnv* env, jobject obj) {
void PlatformViewAndroid::SurfaceCreated(JNIEnv* env,
jobject obj,
jobject jsurface) {
// Note: This ensures that any local references used by
// Note: This frame ensures that any local references used by
// ANativeWindow_fromSurface are released immediately. This is needed as a
// workaround for https://code.google.com/p/android/issues/detail?id=68174
{
base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
ANativeWindow* window = ANativeWindow_fromSurface(env, jsurface);
std::unique_ptr<AndroidGLContext> context(
new AndroidGLContext(window, surface_config_));
if (context->IsValid()) {
context_ = std::move(context);
}
ANativeWindow_release(window);
base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
ANativeWindow* window = ANativeWindow_fromSurface(env, jsurface);
// Use the default onscreen configuration.
PlatformView::SurfaceConfig onscreen_config;
// The offscreen config is the same as the default except we know we don't
// need the stencil buffer.
PlatformView::SurfaceConfig offscreen_config;
offscreen_config.stencil_bits = 0;
auto surface = std::make_unique<AndroidSurfaceGL>(window, onscreen_config,
offscreen_config);
if (surface->IsValid()) {
surface_gl_ = std::move(surface);
} else {
LOG(INFO) << "Could not create the OpenGL Android Surface.";
}
ANativeWindow_release(window);
}
void PlatformViewAndroid::SurfaceChanged(JNIEnv* env,
jobject obj,
jint backgroundColor) {
NotifyCreated(
[this, backgroundColor] { config_.rasterizer->Clear(backgroundColor); });
if (!surface_gl_) {
return;
}
auto surface = std::make_unique<GPUSurfaceGL>(surface_gl_.get());
NotifyCreated(std::move(surface), [this, backgroundColor] {
config_.rasterizer->Clear(backgroundColor, GetSize());
});
SetupResourceContextOnIOThread();
UpdateThreadPriorities();
}
......@@ -441,9 +107,9 @@ void PlatformViewAndroid::DispatchPointerDataPacket(JNIEnv* env,
}
void PlatformViewAndroid::ReleaseSurface() {
if (context_) {
if (surface_gl_) {
NotifyDestroyed();
context_ = nullptr;
surface_gl_ = nullptr;
}
}
......@@ -451,36 +117,18 @@ ftl::WeakPtr<shell::PlatformView> PlatformViewAndroid::GetWeakViewPtr() {
return weak_factory_.GetWeakPtr();
}
uint64_t PlatformViewAndroid::DefaultFramebuffer() const {
// FBO 0 is the default window bound framebuffer on Android.
return 0;
}
bool PlatformViewAndroid::ContextMakeCurrent() {
return context_ != nullptr ? context_->ContextMakeCurrent() : false;
}
bool PlatformViewAndroid::ResourceContextMakeCurrent() {
if (eglMakeCurrent(g_display, g_resource_surface, g_resource_surface,
g_resource_context) != EGL_TRUE) {
LOG(INFO) << "Could not make the resource context current";
LogLastEGLError();
return false;
}
return true;
}
bool PlatformViewAndroid::SwapBuffers() {
TRACE_EVENT0("flutter", "PlatformViewAndroid::SwapBuffers");
return context_ != nullptr ? context_->SwapBuffers() : false;
return surface_gl_ ? surface_gl_->GLOffscreenContextMakeCurrent() : false;
}
SkISize PlatformViewAndroid::GetSize() {
return context_->GetSize();
return surface_gl_ ? surface_gl_->OnScreenSurfaceSize() : SkISize::Make(0, 0);
}
void PlatformViewAndroid::Resize(const SkISize& size) {
context_->Resize(size);
if (surface_gl_) {
surface_gl_->OnScreenSurfaceResize(size);
}
}
void PlatformViewAndroid::RunFromSource(const std::string& main,
......@@ -625,4 +273,26 @@ void PlatformViewAndroid::GetBitmapGpuTask(ftl::AutoResetWaitableEvent* latch,
latch->Signal();
}
jint GetObservatoryPort(JNIEnv* env, jclass clazz) {
return blink::DartServiceIsolate::GetObservatoryPort();
}
bool PlatformViewAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
static jlong Attach(JNIEnv* env,
jclass clazz,
jint skyEngineHandle,
jobject flutterView) {
PlatformViewAndroid* view = new PlatformViewAndroid();
view->ConnectToEngine(mojo::InterfaceRequest<sky::SkyEngine>(
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(skyEngineHandle))));
// Create a weak reference to the flutterView Java object so that we can make
// calls into it later.
view->set_flutter_view(JavaObjectWeakGlobalRef(env, flutterView));
return reinterpret_cast<jlong>(view);
}
} // namespace shell
......@@ -7,16 +7,15 @@
#include <string>
#include <memory>
#include "base/android/jni_android.h"
#include "base/android/jni_weak_ref.h"
#include "lib/ftl/memory/weak_ptr.h"
#include "lib/ftl/synchronization/waitable_event.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/android/android_surface_gl.h"
#include "lib/ftl/memory/weak_ptr.h"
namespace shell {
class AndroidGLContext;
class PlatformViewAndroid : public PlatformView {
public:
static bool Register(JNIEnv* env);
......@@ -33,7 +32,9 @@ class PlatformViewAndroid : public PlatformView {
void SurfaceDestroyed(JNIEnv* env, jobject obj);
void DispatchPointerDataPacket(JNIEnv* env, jobject obj, jobject buffer,
void DispatchPointerDataPacket(JNIEnv* env,
jobject obj,
jobject buffer,
jint position);
base::android::ScopedJavaLocalRef<jobject> GetBitmap(JNIEnv* env,
......@@ -41,14 +42,8 @@ class PlatformViewAndroid : public PlatformView {
ftl::WeakPtr<shell::PlatformView> GetWeakViewPtr() override;
uint64_t DefaultFramebuffer() const override;
bool ContextMakeCurrent() override;
bool ResourceContextMakeCurrent() override;
bool SwapBuffers() override;
virtual SkISize GetSize();
virtual void Resize(const SkISize& size);
......@@ -62,18 +57,18 @@ class PlatformViewAndroid : public PlatformView {
}
private:
std::unique_ptr<AndroidSurfaceGL> surface_gl_;
JavaObjectWeakGlobalRef flutter_view_;
ftl::WeakPtrFactory<PlatformViewAndroid> weak_factory_;
void UpdateThreadPriorities();
void ReleaseSurface();
void GetBitmapGpuTask(ftl::AutoResetWaitableEvent* latch,
jobject* pixels_out,
SkISize* size_out);
std::unique_ptr<AndroidGLContext> context_;
ftl::WeakPtrFactory<PlatformViewAndroid> weak_factory_;
JavaObjectWeakGlobalRef flutter_view_;
void UpdateThreadPriorities();
FTL_DISALLOW_COPY_AND_ASSIGN(PlatformViewAndroid);
};
......
......@@ -25,6 +25,7 @@ source_set("mac_desktop_platform") {
"//base",
"//flutter/common",
"//flutter/shell/common",
"//flutter/shell/gpu",
"//flutter/shell/platform/darwin/common",
"//flutter/shell/testing",
"//flutter/skia",
......
......@@ -7,6 +7,7 @@
#include "base/mac/scoped_nsobject.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "lib/ftl/memory/weak_ptr.h"
@class NSOpenGLView;
......@@ -14,7 +15,7 @@
namespace shell {
class PlatformViewMac : public PlatformView {
class PlatformViewMac : public PlatformView, public GPUSurfaceGLDelegate {
public:
PlatformViewMac(NSOpenGLView* gl_view);
......@@ -26,13 +27,15 @@ class PlatformViewMac : public PlatformView {
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
uint64_t DefaultFramebuffer() const override;
bool GLContextMakeCurrent() override;
bool ContextMakeCurrent() override;
bool GLContextClearCurrent() override;
bool ResourceContextMakeCurrent() override;
bool GLContextPresent() override;
intptr_t GLContextFBO() const override;
bool SwapBuffers() override;
bool ResourceContextMakeCurrent() override;
void RunFromSource(const std::string& main,
const std::string& packages,
......
......@@ -4,12 +4,13 @@
#include "flutter/shell/platform/darwin/desktop/platform_view_mac.h"
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#include <Foundation/Foundation.h>
#include "base/command_line.h"
#include "base/trace_event/trace_event.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/gpu/gpu_rasterizer.h"
#include "flutter/shell/platform/darwin/common/platform_mac.h"
#include "flutter/shell/platform/darwin/common/platform_service_provider.h"
#include "flutter/shell/platform/darwin/common/view_service_provider.h"
......@@ -18,7 +19,8 @@
namespace shell {
PlatformViewMac::PlatformViewMac(NSOpenGLView* gl_view)
: opengl_view_([gl_view retain]),
: PlatformView(std::make_unique<GPURasterizer>()),
opengl_view_([gl_view retain]),
resource_loading_context_([[NSOpenGLContext alloc]
initWithFormat:gl_view.pixelFormat
shareContext:gl_view.openGLContext]),
......@@ -95,12 +97,13 @@ ftl::WeakPtr<PlatformView> PlatformViewMac::GetWeakViewPtr() {
return weak_factory_.GetWeakPtr();
}
uint64_t PlatformViewMac::DefaultFramebuffer() const {
intptr_t PlatformViewMac::GLContextFBO() const {
// Default window bound framebuffer FBO 0.
return 0;
}
bool PlatformViewMac::ContextMakeCurrent() {
bool PlatformViewMac::GLContextMakeCurrent() {
TRACE_EVENT0("flutter", "PlatformViewMac::GLContextMakeCurrent");
if (!IsValid()) {
return false;
}
......@@ -109,20 +112,18 @@ bool PlatformViewMac::ContextMakeCurrent() {
return true;
}
bool PlatformViewMac::ResourceContextMakeCurrent() {
NSOpenGLContext* context = resource_loading_context_.get();
if (context == nullptr) {
bool PlatformViewMac::GLContextClearCurrent() {
TRACE_EVENT0("flutter", "PlatformViewMac::GLContextClearCurrent");
if (!IsValid()) {
return false;
}
[context makeCurrentContext];
[NSOpenGLContext clearCurrentContext];
return true;
}
bool PlatformViewMac::SwapBuffers() {
TRACE_EVENT0("flutter", "PlatformViewMac::SwapBuffers");
bool PlatformViewMac::GLContextPresent() {
TRACE_EVENT0("flutter", "PlatformViewMac::GLContextPresent");
if (!IsValid()) {
return false;
}
......@@ -131,6 +132,17 @@ bool PlatformViewMac::SwapBuffers() {
return true;
}
bool PlatformViewMac::ResourceContextMakeCurrent() {
NSOpenGLContext* context = resource_loading_context_.get();
if (context == nullptr) {
return false;
}
[context makeCurrentContext];
return true;
}
bool PlatformViewMac::IsValid() const {
if (opengl_view_ == nullptr) {
return false;
......
......@@ -4,8 +4,8 @@
#import "sky_window.h"
#include "lib/ftl/time/time_delta.h"
#include "flutter/common/threads.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/platform/darwin/desktop/platform_view_mac.h"
@interface SkyWindow ()<NSWindowDelegate>
......@@ -58,7 +58,8 @@ static inline blink::PointerData::Change PointerChangeFromNSEventPhase(
_platformView.reset(new shell::PlatformViewMac(self.renderSurface));
_platformView->SetupResourceContextOnIOThread();
_platformView->NotifyCreated();
_platformView->NotifyCreated(
std::make_unique<shell::GPUSurfaceGL>(_platformView.get()));
}
// TODO(eseidel): This does not belong in sky_window!
......
......@@ -9,14 +9,16 @@
#include "base/mac/scoped_block.h"
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "lib/ftl/time/time_delta.h"
#include "lib/ftl/functional/wrap_lambda.h"
#include "flutter/common/threads.h"
#include "flutter/services/platform/ios/system_chrome_impl.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h"
#include "flutter/shell/gpu/gpu_rasterizer.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/platform/darwin/common/platform_mac.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h"
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
#include "flutter/shell/platform/darwin/common/platform_mac.h"
#include "lib/ftl/functional/wrap_lambda.h"
#include "lib/ftl/time/time_delta.h"
@interface FlutterViewController ()<UIAlertViewDelegate>
@end
......@@ -198,7 +200,8 @@ enum MapperPhase {
Removed,
};
using PointerChangeMapperPhase = std::pair<blink::PointerData::Change, MapperPhase>;
using PointerChangeMapperPhase =
std::pair<blink::PointerData::Change, MapperPhase>;
static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(
UITouchPhase phase) {
switch (phase) {
......@@ -266,12 +269,11 @@ static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(
}
blink::Threads::UI()->PostTask(ftl::WrapLambda([
engine = _platformView->engine().GetWeakPtr(),
packet = std::move(packet)
] {
if (engine.get())
engine->DispatchPointerDataPacket(*packet);
}));
engine = _platformView->engine().GetWeakPtr(), packet = std::move(packet)
] {
if (engine.get())
engine->DispatchPointerDataPacket(*packet);
}));
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
......@@ -385,7 +387,8 @@ static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(
CHECK(_platformView != nullptr);
if (appeared) {
_platformView->NotifyCreated();
_platformView->NotifyCreated(
std::make_unique<shell::GPUSurfaceGL>(_platformView.get()));
} else {
_platformView->NotifyDestroyed();
}
......
......@@ -7,13 +7,14 @@
#include <memory>
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/weak_ptr.h"
#include "base/mac/scoped_nsobject.h"
#include "flutter/services/platform/app_messages.mojom.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/application_messages_impl.h"
#include "flutter/shell/common/platform_view.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/weak_ptr.h"
@class CAEAGLLayer;
@class UIView;
......@@ -22,7 +23,7 @@ namespace shell {
class IOSGLContext;
class PlatformViewIOS : public PlatformView {
class PlatformViewIOS : public PlatformView, public GPUSurfaceGLDelegate {
public:
explicit PlatformViewIOS(CAEAGLLayer* layer);
......@@ -40,13 +41,15 @@ class PlatformViewIOS : public PlatformView {
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
uint64_t DefaultFramebuffer() const override;
bool ResourceContextMakeCurrent() override;
bool GLContextMakeCurrent() override;
bool ContextMakeCurrent() override;
bool GLContextClearCurrent() override;
bool ResourceContextMakeCurrent() override;
bool GLContextPresent() override;
bool SwapBuffers() override;
intptr_t GLContextFBO() const override;
void RunFromSource(const std::string& main,
const std::string& packages,
......
......@@ -4,19 +4,18 @@
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <QuartzCore/CAEAGLLayer.h>
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/trace_event/trace_event.h"
#include "flutter/shell/platform/darwin/common/view_service_provider.h"
#include "flutter/shell/gpu/gpu_rasterizer.h"
#include "flutter/shell/platform/darwin/common/platform_service_provider.h"
#include "flutter/sky/engine/wtf/MakeUnique.h"
#include "flutter/shell/platform/darwin/common/view_service_provider.h"
#include "lib/ftl/synchronization/waitable_event.h"
#include "mojo/public/cpp/application/connect.h"
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <OpenGLES/EAGL.h>
#import <QuartzCore/CAEAGLLayer.h>
namespace shell {
struct GLintSize {
......@@ -273,7 +272,8 @@ class IOSGLContext {
};
PlatformViewIOS::PlatformViewIOS(CAEAGLLayer* layer)
: context_(WTF::MakeUnique<IOSGLContext>(surface_config_, layer)),
: PlatformView(std::make_unique<GPURasterizer>()),
context_(std::make_unique<IOSGLContext>(surface_config_, layer)),
weak_factory_(this) {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
......@@ -351,20 +351,25 @@ ftl::WeakPtr<PlatformView> PlatformViewIOS::GetWeakViewPtr() {
return weak_factory_.GetWeakPtr();
}
uint64_t PlatformViewIOS::DefaultFramebuffer() const {
bool PlatformViewIOS::ResourceContextMakeCurrent() {
return context_ != nullptr ? context_->ResourceMakeCurrent() : false;
}
intptr_t PlatformViewIOS::GLContextFBO() const {
return context_ != nullptr ? context_->framebuffer() : GL_NONE;
}
bool PlatformViewIOS::ContextMakeCurrent() {
bool PlatformViewIOS::GLContextMakeCurrent() {
return context_ != nullptr ? context_->MakeCurrent() : false;
}
bool PlatformViewIOS::ResourceContextMakeCurrent() {
return context_ != nullptr ? context_->ResourceMakeCurrent() : false;
bool PlatformViewIOS::GLContextClearCurrent() {
[EAGLContext setCurrentContext:nil];
return true;
}
bool PlatformViewIOS::SwapBuffers() {
TRACE_EVENT0("flutter", "PlatformViewIOS::SwapBuffers");
bool PlatformViewIOS::GLContextPresent() {
TRACE_EVENT0("flutter", "PlatformViewIOS::GLContextPresent");
return context_ != nullptr ? context_->PresentRenderBuffer() : false;
}
......
......@@ -10,6 +10,7 @@
#include "base/message_loop/message_loop.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "flutter/shell/platform/linux/message_pump_glfw.h"
#include "flutter/shell/platform/linux/platform_view_glfw.h"
#include "flutter/shell/testing/testing.h"
......@@ -66,7 +67,8 @@ int RunInteractive() {
platform_view->ConnectToEngineAndSetupServices();
platform_view->NotifyCreated();
platform_view->NotifyCreated(
std::make_unique<shell::GPUSurfaceGL>(platform_view.get()));
if (IsDartFile(bundle_path)) {
// Load directly from source.
......
......@@ -3,12 +3,11 @@
// found in the LICENSE file.
#include "flutter/shell/platform/linux/platform_view_glfw.h"
#include <GLFW/glfw3.h>
#include "flutter/common/threads.h"
#include "flutter/shell/gpu/gpu_rasterizer.h"
#include "flutter/shell/platform/linux/glfw_service_provider.h"
#include <GLFW/glfw3.h>
namespace shell {
inline PlatformViewGLFW* ToPlatformView(GLFWwindow* window) {
......@@ -16,7 +15,11 @@ inline PlatformViewGLFW* ToPlatformView(GLFWwindow* window) {
}
PlatformViewGLFW::PlatformViewGLFW()
: valid_(false), glfw_window_(nullptr), buttons_(0), weak_factory_(this) {
: PlatformView(std::make_unique<GPURasterizer>()),
valid_(false),
glfw_window_(nullptr),
buttons_(0),
weak_factory_(this) {
if (!glfwInit()) {
return;
}
......@@ -79,22 +82,27 @@ ftl::WeakPtr<PlatformView> PlatformViewGLFW::GetWeakViewPtr() {
return weak_factory_.GetWeakPtr();
}
uint64_t PlatformViewGLFW::DefaultFramebuffer() const {
intptr_t PlatformViewGLFW::GLContextFBO() const {
// The default window bound FBO.
return 0;
}
bool PlatformViewGLFW::ContextMakeCurrent() {
bool PlatformViewGLFW::GLContextMakeCurrent() {
glfwMakeContextCurrent(glfw_window_);
return true;
}
bool PlatformViewGLFW::GLContextClearCurrent() {
glfwMakeContextCurrent(nullptr);
return true;
}
bool PlatformViewGLFW::ResourceContextMakeCurrent() {
// Resource loading contexts are not supported on this platform.
return false;
}
bool PlatformViewGLFW::SwapBuffers() {
bool PlatformViewGLFW::GLContextPresent() {
glfwSwapBuffers(glfw_window_);
return true;
}
......
......@@ -6,15 +6,15 @@
#define SHELL_PLATFORM_GLFW_PLATFORM_VIEW_GLFW_H_
#include <string>
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/gpu/gpu_surface_gl.h"
#include "lib/ftl/memory/weak_ptr.h"
struct GLFWwindow;
namespace shell {
class PlatformViewGLFW : public PlatformView {
class PlatformViewGLFW : public PlatformView, public GPUSurfaceGLDelegate {
public:
PlatformViewGLFW();
......@@ -28,13 +28,15 @@ class PlatformViewGLFW : public PlatformView {
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
uint64_t DefaultFramebuffer() const override;
bool ResourceContextMakeCurrent() override;
bool GLContextMakeCurrent() override;
bool ContextMakeCurrent() override;
bool GLContextClearCurrent() override;
bool ResourceContextMakeCurrent() override;
bool GLContextPresent() override;
bool SwapBuffers() override;
intptr_t GLContextFBO() const override;
void RunFromSource(const std::string& main,
const std::string& packages,
......
......@@ -5,10 +5,13 @@
#include "flutter/shell/testing/platform_view_test.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/null_rasterizer.h"
namespace shell {
PlatformViewTest::PlatformViewTest() : weak_factory_(this) {}
PlatformViewTest::PlatformViewTest()
: PlatformView(std::unique_ptr<Rasterizer>(new NullRasterizer())),
weak_factory_(this) {}
PlatformViewTest::~PlatformViewTest() = default;
......@@ -16,22 +19,10 @@ ftl::WeakPtr<PlatformView> PlatformViewTest::GetWeakViewPtr() {
return weak_factory_.GetWeakPtr();
}
uint64_t PlatformViewTest::DefaultFramebuffer() const {
return 0;
}
bool PlatformViewTest::ContextMakeCurrent() {
return false;
}
bool PlatformViewTest::ResourceContextMakeCurrent() {
return false;
}
bool PlatformViewTest::SwapBuffers() {
return false;
}
void PlatformViewTest::RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) {}
......
......@@ -21,14 +21,8 @@ class PlatformViewTest : public PlatformView {
ftl::WeakPtr<PlatformView> GetWeakViewPtr() override;
uint64_t DefaultFramebuffer() const override;
bool ContextMakeCurrent() override;
bool ResourceContextMakeCurrent() override;
bool SwapBuffers() override;
void RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) override;
......
......@@ -4,6 +4,7 @@
source_set("synchronization") {
sources = [
"debug_thread_checker.h",
"pipeline.cc",
"pipeline.h",
"semaphore.cc",
......
// 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_SYNCHRONIZATION_DEBUG_THREAD_CHECKER_H_
#define FLUTTER_SYNCHRONIZATION_DEBUG_THREAD_CHECKER_H_
#ifndef NDEBUG
#include <pthread.h>
#include "lib/ftl/synchronization/thread_checker.h"
#define FLUTTER_THREAD_CHECKER_DECLARE(x) ::ftl::ThreadChecker x;
#define FLUTTER_THREAD_CHECKER_CHECK(x) FTL_CHECK(x.IsCreationThreadCurrent());
#else // NDEBUG
#define FLUTTER_THREAD_CHECKER_DECLARE(x)
#define FLUTTER_THREAD_CHECKER_CHECK(x)
#endif // NDEBUG
#endif // FLUTTER_SYNCHRONIZATION_DEBUG_THREAD_CHECKER_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册