From fdf13d720e307242d1d1bc46bb6c232992d07a99 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Thu, 6 Oct 2016 15:06:21 -0700 Subject: [PATCH] Make the PlatformView client rendering API agnostic. (#3099) --- .clang-format | 1 + flow/compositor_context.cc | 4 +- flow/compositor_context.h | 9 +- shell/common/BUILD.gn | 4 + shell/common/null_rasterizer.cc | 41 ++ shell/common/null_rasterizer.h | 41 ++ shell/common/platform_view.cc | 41 +- shell/common/platform_view.h | 16 +- shell/common/rasterizer.cc | 2 +- shell/common/rasterizer.h | 13 +- shell/common/surface.cc | 27 ++ shell/common/surface.h | 54 +++ shell/gpu/BUILD.gn | 17 +- shell/gpu/gpu_canvas.cc | 25 - shell/gpu/gpu_canvas.h | 34 -- shell/gpu/gpu_canvas_gl.h | 43 -- shell/gpu/gpu_rasterizer.cc | 181 ++++--- shell/gpu/gpu_rasterizer.h | 19 +- .../{gpu_canvas_gl.cc => gpu_surface_gl.cc} | 110 ++++- shell/gpu/gpu_surface_gl.h | 79 +++ ...canvas_vulkan.cc => gpu_surface_vulkan.cc} | 2 +- ...u_canvas_vulkan.h => gpu_surface_vulkan.h} | 6 +- shell/platform/android/BUILD.gn | 8 + shell/platform/android/android_context_gl.cc | 286 +++++++++++ shell/platform/android/android_context_gl.h | 66 +++ .../android/android_environment_gl.cc | 41 ++ .../platform/android/android_environment_gl.h | 40 ++ .../platform/android/android_native_window.cc | 35 ++ .../platform/android/android_native_window.h | 35 ++ shell/platform/android/android_surface_gl.cc | 109 +++++ shell/platform/android/android_surface_gl.h | 51 ++ .../platform/android/platform_view_android.cc | 454 +++--------------- .../platform/android/platform_view_android.h | 29 +- shell/platform/darwin/desktop/BUILD.gn | 1 + .../darwin/desktop/platform_view_mac.h | 13 +- .../darwin/desktop/platform_view_mac.mm | 42 +- shell/platform/darwin/desktop/sky_window.mm | 5 +- .../framework/Source/FlutterViewController.mm | 29 +- shell/platform/darwin/ios/platform_view_ios.h | 21 +- .../platform/darwin/ios/platform_view_ios.mm | 45 +- shell/platform/linux/main_linux.cc | 4 +- shell/platform/linux/platform_view_glfw.cc | 24 +- shell/platform/linux/platform_view_glfw.h | 16 +- shell/testing/platform_view_test.cc | 17 +- shell/testing/platform_view_test.h | 6 - synchronization/BUILD.gn | 1 + synchronization/debug_thread_checker.h | 25 + 47 files changed, 1391 insertions(+), 781 deletions(-) create mode 100644 shell/common/null_rasterizer.cc create mode 100644 shell/common/null_rasterizer.h create mode 100644 shell/common/surface.cc create mode 100644 shell/common/surface.h delete mode 100644 shell/gpu/gpu_canvas.cc delete mode 100644 shell/gpu/gpu_canvas.h delete mode 100644 shell/gpu/gpu_canvas_gl.h rename shell/gpu/{gpu_canvas_gl.cc => gpu_surface_gl.cc} (50%) create mode 100644 shell/gpu/gpu_surface_gl.h rename shell/gpu/{gpu_canvas_vulkan.cc => gpu_surface_vulkan.cc} (80%) rename shell/gpu/{gpu_canvas_vulkan.h => gpu_surface_vulkan.h} (66%) create mode 100644 shell/platform/android/android_context_gl.cc create mode 100644 shell/platform/android/android_context_gl.h create mode 100644 shell/platform/android/android_environment_gl.cc create mode 100644 shell/platform/android/android_environment_gl.h create mode 100644 shell/platform/android/android_native_window.cc create mode 100644 shell/platform/android/android_native_window.h create mode 100644 shell/platform/android/android_surface_gl.cc create mode 100644 shell/platform/android/android_surface_gl.h create mode 100644 synchronization/debug_thread_checker.h diff --git a/.clang-format b/.clang-format index 6fdf1dc888c..780d1a2d1ea 100644 --- a/.clang-format +++ b/.clang-format @@ -6,3 +6,4 @@ BasedOnStyle: Chromium # 'vector>'. ('Auto' means that clang-format will only use # 'int>>' if the file already contains at least one such instance.) Standard: Cpp11 +SortIncludes: true diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index 8e4ac1458d5..91d2f8a8023 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -8,9 +8,9 @@ namespace flow { -CompositorContext::CompositorContext() {} +CompositorContext::CompositorContext() = default; -CompositorContext::~CompositorContext() {} +CompositorContext::~CompositorContext() = default; void CompositorContext::BeginFrame(ScopedFrame& frame, bool enable_instrumentation) { diff --git a/flow/compositor_context.h b/flow/compositor_context.h index 97629adaf0d..f16f3c46029 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -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); diff --git a/shell/common/BUILD.gn b/shell/common/BUILD.gn index b67ba1c33b5..35bbd1a832f 100644 --- a/shell/common/BUILD.gn +++ b/shell/common/BUILD.gn @@ -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", diff --git a/shell/common/null_rasterizer.cc b/shell/common/null_rasterizer.cc new file mode 100644 index 00000000000..f428bc891b5 --- /dev/null +++ b/shell/common/null_rasterizer.cc @@ -0,0 +1,41 @@ +// 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_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 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> pipeline) { + // Null rasterizer. Nothing to do. +} + +} // namespace shell diff --git a/shell/common/null_rasterizer.h b/shell/common/null_rasterizer.h new file mode 100644 index 00000000000..99ff59b0e13 --- /dev/null +++ b/shell/common/null_rasterizer.h @@ -0,0 +1,41 @@ +// 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_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 GetWeakRasterizerPtr() override; + + flow::LayerTree* GetLastLayerTree() override; + + void Draw(ftl::RefPtr> pipeline) override; + + private: + ftl::WeakPtrFactory weak_factory_; + + FTL_DISALLOW_COPY_AND_ASSIGN(NullRasterizer); +}; + +} // namespace shell + +#endif // FLUTTER_SHELL_COMMON_NULL_RASTERIZER_H_ diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index ec4b709abf4..e310f745ae6 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -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_(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) { + NotifyCreated(std::move(surface), []() {}); } -void PlatformView::NotifyCreated(ftl::Closure rasterizer_continuation) { +void PlatformView::NotifyCreated(std::unique_ptr 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(); } diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index 543bcca927d..67d8feb438f 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -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 request); - void NotifyCreated(); + void NotifyCreated(std::unique_ptr surface); - void NotifyCreated(ftl::Closure continuation); + void NotifyCreated(std::unique_ptr surface, + ftl::Closure continuation); void NotifyDestroyed(); virtual ftl::WeakPtr 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_; std::unique_ptr engine_; - SkISize size_; - explicit PlatformView(); + explicit PlatformView(std::unique_ptr rasterizer); void SetupResourceContextOnIOThreadPerform( ftl::AutoResetWaitableEvent* event); diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 0c32386b107..905ee6285c5 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -6,6 +6,6 @@ namespace shell { -Rasterizer::~Rasterizer() {} +Rasterizer::~Rasterizer() = default; } // namespace shell diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 4c5619ccb20..37db03b4450 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -6,8 +6,8 @@ #define SHELL_COMMON_RASTERIZER_H_ #include - #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_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 GetWeakRasterizerPtr() = 0; virtual flow::LayerTree* GetLastLayerTree() = 0; virtual void Draw( ftl::RefPtr> pipeline) = 0; - - // Implemented by each GPU backend. - static std::unique_ptr Create(); }; } // namespace shell diff --git a/shell/common/surface.cc b/shell/common/surface.cc new file mode 100644 index 00000000000..e75f61e0153 --- /dev/null +++ b/shell/common/surface.cc @@ -0,0 +1,27 @@ +// 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/surface.h" + +namespace shell { + +SurfaceFrame::SurfaceFrame() : submitted_(false) {} + +SurfaceFrame::~SurfaceFrame() = default; + +bool SurfaceFrame::Submit() { + if (submitted_) { + return false; + } + + submitted_ = PerformSubmit(); + + return submitted_; +} + +Surface::Surface() = default; + +Surface::~Surface() = default; + +} // namespace shell diff --git a/shell/common/surface.h b/shell/common/surface.h new file mode 100644 index 00000000000..15052911c88 --- /dev/null +++ b/shell/common/surface.h @@ -0,0 +1,54 @@ +// 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_SURFACE_H_ +#define FLUTTER_SHELL_COMMON_SURFACE_H_ + +#include + +#include "lib/ftl/compiler_specific.h" +#include "lib/ftl/macros.h" +#include "third_party/skia/include/core/SkCanvas.h" + +namespace shell { + +class SurfaceFrame { + public: + SurfaceFrame(); + + virtual ~SurfaceFrame(); + + bool Submit(); + + virtual SkCanvas* SkiaCanvas() = 0; + + private: + bool submitted_; + + virtual bool PerformSubmit() = 0; + + FTL_DISALLOW_COPY_AND_ASSIGN(SurfaceFrame); +}; + +class Surface { + public: + Surface(); + + virtual ~Surface(); + + virtual bool Setup() = 0; + + virtual bool IsValid() = 0; + + virtual std::unique_ptr AcquireFrame(const SkISize& size) = 0; + + virtual GrContext* GetContext() = 0; + + private: + FTL_DISALLOW_COPY_AND_ASSIGN(Surface); +}; + +} // namespace shell + +#endif // FLUTTER_SHELL_COMMON_SURFACE_H_ diff --git a/shell/gpu/BUILD.gn b/shell/gpu/BUILD.gn index cec9cd3cd13..7a7989bfb0e 100644 --- a/shell/gpu/BUILD.gn +++ b/shell/gpu/BUILD.gn @@ -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", ] } diff --git a/shell/gpu/gpu_canvas.cc b/shell/gpu/gpu_canvas.cc deleted file mode 100644 index 45f5eb1a842..00000000000 --- a/shell/gpu/gpu_canvas.cc +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gpu_canvas.h" -#include "gpu_canvas_gl.h" -#include "gpu_canvas_vulkan.h" - -namespace shell { - -GPUCanvas::~GPUCanvas() = default; - -std::unique_ptr GPUCanvas::CreatePlatformCanvas( - const PlatformView& platform_view) { - std::unique_ptr canvas; - - // TODO: Vulkan capability detection will be added here to return a differnt - // canvas instance. - - canvas.reset(new GPUCanvasGL(platform_view.DefaultFramebuffer())); - - return canvas; -} - -} // namespace shell diff --git a/shell/gpu/gpu_canvas.h b/shell/gpu/gpu_canvas.h deleted file mode 100644 index 669bf75877b..00000000000 --- a/shell/gpu/gpu_canvas.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SHELL_GPU_GPU_CANVAS_H_ -#define SHELL_GPU_GPU_CANVAS_H_ - -#include "flutter/shell/common/platform_view.h" -#include "lib/ftl/macros.h" -#include "lib/ftl/compiler_specific.h" -#include "third_party/skia/include/core/SkCanvas.h" - -namespace shell { - -class GPUCanvas { - public: - static std::unique_ptr CreatePlatformCanvas( - const PlatformView& platform_view); - - virtual ~GPUCanvas(); - - FTL_WARN_UNUSED_RESULT - virtual bool Setup() = 0; - - virtual bool IsValid() = 0; - - virtual SkCanvas* AcquireCanvas(const SkISize& size) = 0; - - virtual GrContext* GetContext() = 0; -}; - -} // namespace shell - -#endif // SHELL_GPU_GPU_CANVAS_H_ diff --git a/shell/gpu/gpu_canvas_gl.h b/shell/gpu/gpu_canvas_gl.h deleted file mode 100644 index 0432c9a549d..00000000000 --- a/shell/gpu/gpu_canvas_gl.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SHELL_GPU_GPU_CANVAS_GL_H_ -#define SHELL_GPU_GPU_CANVAS_GL_H_ - -#include "lib/ftl/macros.h" -#include "gpu_canvas.h" - -namespace shell { - -class GPUCanvasGL : public GPUCanvas { - public: - GPUCanvasGL(intptr_t fbo); - - ~GPUCanvasGL() override; - - bool Setup() override; - - bool IsValid() override; - - SkCanvas* AcquireCanvas(const SkISize& size) override; - - GrContext* GetContext() override; - - private: - intptr_t fbo_; - sk_sp context_; - sk_sp cached_surface_; - - sk_sp CreateSurface(const SkISize& size); - - sk_sp AcquireSurface(const SkISize& size); - - bool SelectPixelConfig(GrPixelConfig* config); - - FTL_DISALLOW_COPY_AND_ASSIGN(GPUCanvasGL); -}; - -} // namespace shell - -#endif // SHELL_GPU_GPU_CANVAS_GL_H_ diff --git a/shell/gpu/gpu_rasterizer.cc b/shell/gpu/gpu_rasterizer.cc index e0f0aa2fefa..51a37ee91cf 100644 --- a/shell/gpu/gpu_rasterizer.cc +++ b/shell/gpu/gpu_rasterizer.cc @@ -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::Create() { - return std::unique_ptr(new GPURasterizer()); -} - ftl::WeakPtr 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, 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; } - SkCanvas* canvas = gpu_canvas_->AcquireCanvas(platform_view_->GetSize()); + auto frame = surface_->AcquireFrame(size); + + if (frame == nullptr) { + return; + } + + 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> pipeline) { TRACE_EVENT0("flutter", "GPURasterizer::Draw"); - if (!platform_view_) - return; - flutter::Pipeline::Consumer consumer = std::bind(&GPURasterizer::DoDraw, this, std::placeholders::_1); @@ -130,7 +101,7 @@ void GPURasterizer::Draw( } void GPURasterizer::DoDraw(std::unique_ptr layer_tree) { - if (!layer_tree || !gpu_canvas_) { + if (!layer_tree || !surface_) { return; } @@ -139,62 +110,76 @@ void GPURasterizer::DoDraw(std::unique_ptr 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); - if (!platform_view_->ContextMakeCurrent() || !layer_tree->root_layer()) { - 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); - - { - TRACE_EVENT0("flutter", "SkCanvas::Flush"); - canvas->flush(); - } - - platform_view_->SwapBuffers(); - } - - // 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; - } - - const auto& tracingController = Shell::Shared().tracing_controller(); - - if (frameExceededThreshold || tracingController.picture_tracing_enabled()) { - std::string path = tracingController.PictureTracingPathForCurrentTime(); - LOG(INFO) << "Frame threshold exceeded. Capturing SKP to " << path; - - SkPictureRecorder recorder; - recorder.beginRecording(SkRect::MakeWH(size.width(), size.height())); - - { - auto frame = compositor_context_.AcquireFrame( - nullptr, *recorder.getRecordingCanvas(), false); - layer_tree->Raster(frame, true); - } - - sk_sp picture = recorder.finishRecordingAsPicture(); - SerializePicture(path, picture.get()); - } + 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; + } + + auto canvas = frame->SkiaCanvas(); + + if (canvas == nullptr) { + return; + } + + auto compositor_frame = + compositor_context_.AcquireFrame(surface_->GetContext(), *canvas); + + canvas->clear(SK_ColorBLACK); + + layer_tree.Raster(compositor_frame); + + 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; + } + + return compositor_context_.frame_time().LastLap().ToMillisecondsF() > + threshold_interval * 1e3 / 60.0; +} + +void GPURasterizer::DrawToTraceIfNecessary(flow::LayerTree& layer_tree) { + if (!ShouldDrawToTrace(layer_tree)) { + return; + } + + auto& tracing_controller = Shell::Shared().tracing_controller(); + + std::string path = tracing_controller.PictureTracingPathForCurrentTime(); + LOG(INFO) << "Frame threshold exceeded. Capturing SKP to " << path; + + SkPictureRecorder recorder; + + recorder.beginRecording(layer_tree.frame_size().width(), + layer_tree.frame_size().height()); + + auto compositor_frame = compositor_context_.AcquireFrame( + nullptr, *recorder.getRecordingCanvas(), false); + layer_tree.Raster(compositor_frame, true /* ignore raster cache */); + + sk_sp picture = recorder.finishRecordingAsPicture(); + + SerializePicture(path, picture.get()); +} + } // namespace shell diff --git a/shell/gpu/gpu_rasterizer.h b/shell/gpu/gpu_rasterizer.h index 05508aedfd4..a60e2af36f9 100644 --- a/shell/gpu/gpu_rasterizer.h +++ b/shell/gpu/gpu_rasterizer.h @@ -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, 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> pipeline) override; private: - std::unique_ptr gpu_canvas_; + std::unique_ptr surface_; flow::CompositorContext compositor_context_; std::unique_ptr last_layer_tree_; - PlatformView* platform_view_; ftl::WeakPtrFactory weak_factory_; - FTL_WARN_UNUSED_RESULT - bool Setup(PlatformView* platform_view); + void DoDraw(std::unique_ptr layer_tree); - void DoDraw(std::unique_ptr tree); + void DrawToSurface(flow::LayerTree& layer_tree); + + bool ShouldDrawToTrace(flow::LayerTree& layer_tree); + + void DrawToTraceIfNecessary(flow::LayerTree& layer_tree); FTL_DISALLOW_COPY_AND_ASSIGN(GPURasterizer); }; diff --git a/shell/gpu/gpu_canvas_gl.cc b/shell/gpu/gpu_surface_gl.cc similarity index 50% rename from shell/gpu/gpu_canvas_gl.cc rename to shell/gpu/gpu_surface_gl.cc index 2ab23c6203b..207c7dbeab8 100644 --- a/shell/gpu/gpu_canvas_gl.cc +++ b/shell/gpu/gpu_surface_gl.cc @@ -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 surface, + SubmitCallback submit_callback) + : surface_(surface), submit_callback_(submit_callback) {} -GPUCanvasGL::~GPUCanvasGL() = default; +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; + } + + 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(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 GPUSurfaceGL::AcquireFrame(const SkISize& size) { + if (delegate_ == nullptr) { + return nullptr; + } + + sk_sp 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( + new GPUSurfaceFrameGL(surface, submit_callback)); } -bool GPUCanvasGL::SelectPixelConfig(GrPixelConfig* config) { +bool GPUSurfaceGL::PresentSurface(SkCanvas* canvas) { + if (delegate_ == nullptr || canvas == nullptr) { + delegate_->GLContextClearCurrent(); + + return false; + } + + canvas->flush(); + + delegate_->GLContextPresent(); + + delegate_->GLContextClearCurrent(); + + return true; +} + +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 GPUCanvasGL::CreateSurface(const SkISize& size) { - if (context_ == nullptr) { +sk_sp GPUSurfaceGL::CreateSurface(const SkISize& size) { + if (delegate_ == nullptr || context_ == nullptr) { return nullptr; } @@ -93,12 +171,12 @@ sk_sp 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 GPUCanvasGL::AcquireSurface(const SkISize& size) { +sk_sp GPUSurfaceGL::AcquireSurface(const SkISize& size) { // There is no cached surface. if (cached_surface_ == nullptr) { cached_surface_ = CreateSurface(size); @@ -115,7 +193,7 @@ sk_sp GPUCanvasGL::AcquireSurface(const SkISize& size) { return cached_surface_; } -GrContext* GPUCanvasGL::GetContext() { +GrContext* GPUSurfaceGL::GetContext() { return context_.get(); } diff --git a/shell/gpu/gpu_surface_gl.h b/shell/gpu/gpu_surface_gl.h new file mode 100644 index 00000000000..a29d0ff487a --- /dev/null +++ b/shell/gpu/gpu_surface_gl.h @@ -0,0 +1,79 @@ +// 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 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 "lib/ftl/memory/weak_ptr.h" + +namespace shell { + +class GPUSurfaceGLDelegate { + public: + virtual bool GLContextMakeCurrent() = 0; + + 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; + + std::unique_ptr AcquireFrame(const SkISize& size) override; + + GrContext* GetContext() override; + + private: + GPUSurfaceGLDelegate* delegate_; + sk_sp context_; + sk_sp cached_surface_; + ftl::WeakPtrFactory weak_factory_; + + sk_sp CreateSurface(const SkISize& size); + + sk_sp AcquireSurface(const SkISize& size); + + bool PresentSurface(SkCanvas* canvas); + + bool SelectPixelConfig(GrPixelConfig* config); + + FTL_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGL); +}; + +class GPUSurfaceFrameGL : public SurfaceFrame { + public: + using SubmitCallback = std::function; + + GPUSurfaceFrameGL(sk_sp surface, SubmitCallback submit_callback); + + ~GPUSurfaceFrameGL(); + + SkCanvas* SkiaCanvas() override; + + private: + FLUTTER_THREAD_CHECKER_DECLARE(checker_); + sk_sp surface_; + SubmitCallback submit_callback_; + + bool PerformSubmit() override; + + FTL_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceFrameGL); +}; + +} // namespace shell + +#endif // SHELL_GPU_GPU_SURFACE_GL_H_ diff --git a/shell/gpu/gpu_canvas_vulkan.cc b/shell/gpu/gpu_surface_vulkan.cc similarity index 80% rename from shell/gpu/gpu_canvas_vulkan.cc rename to shell/gpu/gpu_surface_vulkan.cc index 87a8230a41b..1a295d19b80 100644 --- a/shell/gpu/gpu_canvas_vulkan.cc +++ b/shell/gpu/gpu_surface_vulkan.cc @@ -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 { diff --git a/shell/gpu/gpu_canvas_vulkan.h b/shell/gpu/gpu_surface_vulkan.h similarity index 66% rename from shell/gpu/gpu_canvas_vulkan.h rename to shell/gpu/gpu_surface_vulkan.h index 0bcd3983b2b..d7cf57167e7 100644 --- a/shell/gpu/gpu_canvas_vulkan.h +++ b/shell/gpu/gpu_surface_vulkan.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef 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_ diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index a70791ac74c..1ff5cafbeff 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -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", diff --git a/shell/platform/android/android_context_gl.cc b/shell/platform/android/android_context_gl.cc new file mode 100644 index 00000000000..4e411e3ecd0 --- /dev/null +++ b/shell/platform/android/android_context_gl.cc @@ -0,0 +1,286 @@ +// 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 + +namespace shell { + +template +using EGLResult = std::pair; + +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 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 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 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(window_handle), + nullptr); + return {surface != EGL_NO_SURFACE, surface}; +} + +// For offscreen rendering. +static EGLResult 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 CreateSurface(EGLDisplay display, + EGLConfig config, + const AndroidNativeWindow& window) { + return window.IsValid() + ? CreateWindowSurface(display, config, window.handle()) + : CreatePBufferSurface(display, config); +} + +AndroidContextGL::AndroidContextGL(ftl::RefPtr 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 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 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 diff --git a/shell/platform/android/android_context_gl.h b/shell/platform/android/android_context_gl.h new file mode 100644 index 00000000000..5078031ae9d --- /dev/null +++ b/shell/platform/android/android_context_gl.h @@ -0,0 +1,66 @@ +// 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 { + private: + /// Creates a window surface context tied to the window handle for on-screen + /// rendering. + // MakeRefCounted + AndroidContextGL(ftl::RefPtr env, + AndroidNativeWindow window, + PlatformView::SurfaceConfig config, + const AndroidContextGL* share_context = nullptr); + + /// Creates a pbuffer surface context for offscreen rendering. + // MakeRefCounted + AndroidContextGL(ftl::RefPtr env, + PlatformView::SurfaceConfig config, + const AndroidContextGL* share_context = nullptr); + + ~AndroidContextGL(); + + public: + ftl::RefPtr Environment() const; + + bool IsValid() const; + + bool MakeCurrent(); + + bool ClearCurrent(); + + bool SwapBuffers(); + + SkISize GetSize(); + + bool Resize(const SkISize& size); + + private: + ftl::RefPtr 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_ diff --git a/shell/platform/android/android_environment_gl.cc b/shell/platform/android/android_environment_gl.cc new file mode 100644 index 00000000000..04823678236 --- /dev/null +++ b/shell/platform/android/android_environment_gl.cc @@ -0,0 +1,41 @@ +// 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 diff --git a/shell/platform/android/android_environment_gl.h b/shell/platform/android/android_environment_gl.h new file mode 100644 index 00000000000..3bfdc850c45 --- /dev/null +++ b/shell/platform/android/android_environment_gl.h @@ -0,0 +1,40 @@ +// 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 + +namespace shell { + +class AndroidEnvironmentGL + : public ftl::RefCountedThreadSafe { + 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_ diff --git a/shell/platform/android/android_native_window.cc b/shell/platform/android/android_native_window.cc new file mode 100644 index 00000000000..419ae132a2a --- /dev/null +++ b/shell/platform/android/android_native_window.cc @@ -0,0 +1,35 @@ +// 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 diff --git a/shell/platform/android/android_native_window.h b/shell/platform/android/android_native_window.h new file mode 100644 index 00000000000..3023cc7347f --- /dev/null +++ b/shell/platform/android/android_native_window.h @@ -0,0 +1,35 @@ +// 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 +#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_ diff --git a/shell/platform/android/android_surface_gl.cc b/shell/platform/android/android_surface_gl.cc new file mode 100644 index 00000000000..6d7ed6e9661 --- /dev/null +++ b/shell/platform/android/android_surface_gl.cc @@ -0,0 +1,109 @@ +// 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 +#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 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 global_context; + + if (global_context) { + return global_context; + } + + auto environment = ftl::MakeRefCounted(); + + if (!environment->IsValid()) { + return nullptr; + } + + // TODO(chinmaygarde): We should check that the configurations are stable + // across multiple invocations. + + auto context = + ftl::MakeRefCounted(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( + 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 diff --git a/shell/platform/android/android_surface_gl.h b/shell/platform/android/android_surface_gl.h new file mode 100644 index 00000000000..4fa3bfcd484 --- /dev/null +++ b/shell/platform/android/android_surface_gl.h @@ -0,0 +1,51 @@ +// 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 +#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 onscreen_context_; + ftl::RefPtr offscreen_context_; + bool valid_; + + FTL_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL); +}; + +} // namespace shell + +#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_GL_H_ diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index e19e6190da3..c8f0eec6126 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -4,380 +4,29 @@ #include "flutter/shell/platform/android/platform_view_android.h" -#include +#include #include -#include #include #include #include - #include #include - #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 -using EGLResult = std::pair; - -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 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 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 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 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(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( - 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(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()), 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 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(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(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 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( + 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(view); +} + } // namespace shell diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index 52c203cec25..d9fcb6e0405 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -7,16 +7,15 @@ #include +#include #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 GetBitmap(JNIEnv* env, @@ -41,14 +42,8 @@ class PlatformViewAndroid : public PlatformView { ftl::WeakPtr 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 surface_gl_; + JavaObjectWeakGlobalRef flutter_view_; + ftl::WeakPtrFactory weak_factory_; + + void UpdateThreadPriorities(); + void ReleaseSurface(); void GetBitmapGpuTask(ftl::AutoResetWaitableEvent* latch, jobject* pixels_out, SkISize* size_out); - std::unique_ptr context_; - ftl::WeakPtrFactory weak_factory_; - JavaObjectWeakGlobalRef flutter_view_; - - void UpdateThreadPriorities(); - FTL_DISALLOW_COPY_AND_ASSIGN(PlatformViewAndroid); }; diff --git a/shell/platform/darwin/desktop/BUILD.gn b/shell/platform/darwin/desktop/BUILD.gn index 143783ef746..8fb26edb282 100644 --- a/shell/platform/darwin/desktop/BUILD.gn +++ b/shell/platform/darwin/desktop/BUILD.gn @@ -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", diff --git a/shell/platform/darwin/desktop/platform_view_mac.h b/shell/platform/darwin/desktop/platform_view_mac.h index de666905afe..c4c7a23ea37 100644 --- a/shell/platform/darwin/desktop/platform_view_mac.h +++ b/shell/platform/darwin/desktop/platform_view_mac.h @@ -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,14 +27,16 @@ class PlatformViewMac : public PlatformView { ftl::WeakPtr GetWeakViewPtr() override; - uint64_t DefaultFramebuffer() const override; + bool GLContextMakeCurrent() override; - bool ContextMakeCurrent() override; + bool GLContextClearCurrent() override; + + bool GLContextPresent() override; + + intptr_t GLContextFBO() const override; bool ResourceContextMakeCurrent() override; - bool SwapBuffers() override; - void RunFromSource(const std::string& main, const std::string& packages, const std::string& assets_directory) override; diff --git a/shell/platform/darwin/desktop/platform_view_mac.mm b/shell/platform/darwin/desktop/platform_view_mac.mm index 87eedee280d..ea42c17c8f0 100644 --- a/shell/platform/darwin/desktop/platform_view_mac.mm +++ b/shell/platform/darwin/desktop/platform_view_mac.mm @@ -4,12 +4,13 @@ #include "flutter/shell/platform/darwin/desktop/platform_view_mac.h" -#include #include +#include #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()), + opengl_view_([gl_view retain]), resource_loading_context_([[NSOpenGLContext alloc] initWithFormat:gl_view.pixelFormat shareContext:gl_view.openGLContext]), @@ -95,12 +97,13 @@ ftl::WeakPtr 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,6 +112,26 @@ bool PlatformViewMac::ContextMakeCurrent() { return true; } +bool PlatformViewMac::GLContextClearCurrent() { + TRACE_EVENT0("flutter", "PlatformViewMac::GLContextClearCurrent"); + if (!IsValid()) { + return false; + } + + [NSOpenGLContext clearCurrentContext]; + return true; +} + +bool PlatformViewMac::GLContextPresent() { + TRACE_EVENT0("flutter", "PlatformViewMac::GLContextPresent"); + if (!IsValid()) { + return false; + } + + [opengl_view_.get().openGLContext flushBuffer]; + return true; +} + bool PlatformViewMac::ResourceContextMakeCurrent() { NSOpenGLContext* context = resource_loading_context_.get(); @@ -120,17 +143,6 @@ bool PlatformViewMac::ResourceContextMakeCurrent() { return true; } -bool PlatformViewMac::SwapBuffers() { - TRACE_EVENT0("flutter", "PlatformViewMac::SwapBuffers"); - - if (!IsValid()) { - return false; - } - - [opengl_view_.get().openGLContext flushBuffer]; - return true; -} - bool PlatformViewMac::IsValid() const { if (opengl_view_ == nullptr) { return false; diff --git a/shell/platform/darwin/desktop/sky_window.mm b/shell/platform/darwin/desktop/sky_window.mm index b066aa86e66..f6bc4139576 100644 --- a/shell/platform/darwin/desktop/sky_window.mm +++ b/shell/platform/darwin/desktop/sky_window.mm @@ -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 () @@ -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(_platformView.get())); } // TODO(eseidel): This does not belong in sky_window! diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 68d51dc840e..4299f51d56f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -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/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" -#include "flutter/shell/platform/darwin/ios/platform_view_ios.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 "lib/ftl/functional/wrap_lambda.h" +#include "lib/ftl/time/time_delta.h" @interface FlutterViewController () @end @@ -198,7 +200,8 @@ enum MapperPhase { Removed, }; -using PointerChangeMapperPhase = std::pair; +using PointerChangeMapperPhase = + std::pair; 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(_platformView.get())); } else { _platformView->NotifyDestroyed(); } diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index a3b42faec9f..b90ea89dcf1 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -7,13 +7,14 @@ #include -#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 GetWeakViewPtr() override; - uint64_t DefaultFramebuffer() const override; - - bool ContextMakeCurrent() override; - bool ResourceContextMakeCurrent() override; - bool SwapBuffers() override; + bool GLContextMakeCurrent() override; + + bool GLContextClearCurrent() override; + + bool GLContextPresent() override; + + intptr_t GLContextFBO() const override; void RunFromSource(const std::string& main, const std::string& packages, diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 4cce6536f7c..498796e3c20 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -4,18 +4,17 @@ #include "flutter/shell/platform/darwin/ios/platform_view_ios.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/platform/darwin/common/platform_service_provider.h" -#include "flutter/sky/engine/wtf/MakeUnique.h" -#include "lib/ftl/synchronization/waitable_event.h" -#include "mojo/public/cpp/application/connect.h" - +#import #import #import -#import #import +#include "base/mac/scoped_nsautorelease_pool.h" +#include "base/trace_event/trace_event.h" +#include "flutter/shell/gpu/gpu_rasterizer.h" +#include "flutter/shell/platform/darwin/common/platform_service_provider.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" namespace shell { @@ -273,7 +272,8 @@ class IOSGLContext { }; PlatformViewIOS::PlatformViewIOS(CAEAGLLayer* layer) - : context_(WTF::MakeUnique(surface_config_, layer)), + : PlatformView(std::make_unique()), + context_(std::make_unique(surface_config_, layer)), weak_factory_(this) { NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); @@ -351,20 +351,25 @@ ftl::WeakPtr PlatformViewIOS::GetWeakViewPtr() { return weak_factory_.GetWeakPtr(); } -uint64_t PlatformViewIOS::DefaultFramebuffer() const { - return context_ != nullptr ? context_->framebuffer() : GL_NONE; -} - -bool PlatformViewIOS::ContextMakeCurrent() { - return context_ != nullptr ? context_->MakeCurrent() : false; -} - bool PlatformViewIOS::ResourceContextMakeCurrent() { return context_ != nullptr ? context_->ResourceMakeCurrent() : false; } -bool PlatformViewIOS::SwapBuffers() { - TRACE_EVENT0("flutter", "PlatformViewIOS::SwapBuffers"); +intptr_t PlatformViewIOS::GLContextFBO() const { + return context_ != nullptr ? context_->framebuffer() : GL_NONE; +} + +bool PlatformViewIOS::GLContextMakeCurrent() { + return context_ != nullptr ? context_->MakeCurrent() : false; +} + +bool PlatformViewIOS::GLContextClearCurrent() { + [EAGLContext setCurrentContext:nil]; + return true; +} + +bool PlatformViewIOS::GLContextPresent() { + TRACE_EVENT0("flutter", "PlatformViewIOS::GLContextPresent"); return context_ != nullptr ? context_->PresentRenderBuffer() : false; } diff --git a/shell/platform/linux/main_linux.cc b/shell/platform/linux/main_linux.cc index 3d4164d4838..28cd08b72ae 100644 --- a/shell/platform/linux/main_linux.cc +++ b/shell/platform/linux/main_linux.cc @@ -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(platform_view.get())); if (IsDartFile(bundle_path)) { // Load directly from source. diff --git a/shell/platform/linux/platform_view_glfw.cc b/shell/platform/linux/platform_view_glfw.cc index 980a954bd69..b4b58190cbc 100644 --- a/shell/platform/linux/platform_view_glfw.cc +++ b/shell/platform/linux/platform_view_glfw.cc @@ -3,11 +3,10 @@ // found in the LICENSE file. #include "flutter/shell/platform/linux/platform_view_glfw.h" - -#include "flutter/common/threads.h" -#include "flutter/shell/platform/linux/glfw_service_provider.h" - #include +#include "flutter/common/threads.h" +#include "flutter/shell/gpu/gpu_rasterizer.h" +#include "flutter/shell/platform/linux/glfw_service_provider.h" namespace shell { @@ -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()), + valid_(false), + glfw_window_(nullptr), + buttons_(0), + weak_factory_(this) { if (!glfwInit()) { return; } @@ -79,22 +82,27 @@ ftl::WeakPtr 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; } diff --git a/shell/platform/linux/platform_view_glfw.h b/shell/platform/linux/platform_view_glfw.h index 329dc590cdc..ff193687851 100644 --- a/shell/platform/linux/platform_view_glfw.h +++ b/shell/platform/linux/platform_view_glfw.h @@ -6,15 +6,15 @@ #define SHELL_PLATFORM_GLFW_PLATFORM_VIEW_GLFW_H_ #include - #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 GetWeakViewPtr() override; - uint64_t DefaultFramebuffer() const override; - - bool ContextMakeCurrent() override; - bool ResourceContextMakeCurrent() override; - bool SwapBuffers() override; + bool GLContextMakeCurrent() override; + + bool GLContextClearCurrent() override; + + bool GLContextPresent() override; + + intptr_t GLContextFBO() const override; void RunFromSource(const std::string& main, const std::string& packages, diff --git a/shell/testing/platform_view_test.cc b/shell/testing/platform_view_test.cc index 392cd1db7f3..d3e6008a83c 100644 --- a/shell/testing/platform_view_test.cc +++ b/shell/testing/platform_view_test.cc @@ -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(new NullRasterizer())), + weak_factory_(this) {} PlatformViewTest::~PlatformViewTest() = default; @@ -16,22 +19,10 @@ ftl::WeakPtr 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) {} diff --git a/shell/testing/platform_view_test.h b/shell/testing/platform_view_test.h index 357e4f2db8e..f515ca69af9 100644 --- a/shell/testing/platform_view_test.h +++ b/shell/testing/platform_view_test.h @@ -21,14 +21,8 @@ class PlatformViewTest : public PlatformView { ftl::WeakPtr 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; diff --git a/synchronization/BUILD.gn b/synchronization/BUILD.gn index a48195eef5e..6a8eae7b8e9 100644 --- a/synchronization/BUILD.gn +++ b/synchronization/BUILD.gn @@ -4,6 +4,7 @@ source_set("synchronization") { sources = [ + "debug_thread_checker.h", "pipeline.cc", "pipeline.h", "semaphore.cc", diff --git a/synchronization/debug_thread_checker.h b/synchronization/debug_thread_checker.h new file mode 100644 index 00000000000..9d49460702d --- /dev/null +++ b/synchronization/debug_thread_checker.h @@ -0,0 +1,25 @@ +// 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 +#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_