diff --git a/shell/gpu/gpu_surface_vulkan.cc b/shell/gpu/gpu_surface_vulkan.cc index e334196a83e4a..37432503f7087 100644 --- a/shell/gpu/gpu_surface_vulkan.cc +++ b/shell/gpu/gpu_surface_vulkan.cc @@ -12,7 +12,20 @@ GPUSurfaceVulkan::GPUSurfaceVulkan( GPUSurfaceVulkanDelegate* delegate, std::unique_ptr native_surface, bool render_to_surface) - : window_(delegate->vk(), std::move(native_surface), render_to_surface), + : GPUSurfaceVulkan(/*context=*/nullptr, + delegate, + std::move(native_surface), + render_to_surface) {} + +GPUSurfaceVulkan::GPUSurfaceVulkan( + const sk_sp& context, + GPUSurfaceVulkanDelegate* delegate, + std::unique_ptr native_surface, + bool render_to_surface) + : window_(context, + delegate->vk(), + std::move(native_surface), + render_to_surface), render_to_surface_(render_to_surface), weak_factory_(this) {} diff --git a/shell/gpu/gpu_surface_vulkan.h b/shell/gpu/gpu_surface_vulkan.h index 1c9c2470fe2e5..242ecef3d3d06 100644 --- a/shell/gpu/gpu_surface_vulkan.h +++ b/shell/gpu/gpu_surface_vulkan.h @@ -13,15 +13,29 @@ #include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h" #include "flutter/vulkan/vulkan_native_surface.h" #include "flutter/vulkan/vulkan_window.h" +#include "include/core/SkRefCnt.h" namespace flutter { class GPUSurfaceVulkan : public Surface { public: + //------------------------------------------------------------------------------ + /// @brief Create a GPUSurfaceVulkan which implicitly creates its own + /// GrDirectContext for Skia. + /// GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate, std::unique_ptr native_surface, bool render_to_surface); + //------------------------------------------------------------------------------ + /// @brief Create a GPUSurfaceVulkan while letting it reuse an existing + /// GrDirectContext. + /// + GPUSurfaceVulkan(const sk_sp& context, + GPUSurfaceVulkanDelegate* delegate, + std::unique_ptr native_surface, + bool render_to_surface); + ~GPUSurfaceVulkan() override; // |Surface| diff --git a/shell/platform/android/android_surface_gl.cc b/shell/platform/android/android_surface_gl.cc index 8d778957095ac..1178434514d7c 100644 --- a/shell/platform/android/android_surface_gl.cc +++ b/shell/platform/android/android_surface_gl.cc @@ -20,14 +20,14 @@ constexpr char kEmulatorRendererPrefix[] = } // anonymous namespace AndroidSurfaceGL::AndroidSurfaceGL( - const AndroidContext& android_context, + const std::shared_ptr& android_context, std::shared_ptr jni_facade) - : android_context_(static_cast(android_context)), + : AndroidSurface(android_context), native_window_(nullptr), onscreen_surface_(nullptr), offscreen_surface_(nullptr) { // Acquire the offscreen surface. - offscreen_surface_ = android_context_.CreateOffscreenSurface(); + offscreen_surface_ = GLContextPtr()->CreateOffscreenSurface(); if (!offscreen_surface_->IsValid()) { offscreen_surface_ = nullptr; } @@ -39,20 +39,27 @@ void AndroidSurfaceGL::TeardownOnScreenContext() { // When the onscreen surface is destroyed, the context and the surface // instance should be deleted. Issue: // https://github.com/flutter/flutter/issues/64414 - android_context_.ClearCurrent(); + GLContextPtr()->ClearCurrent(); onscreen_surface_ = nullptr; } bool AndroidSurfaceGL::IsValid() const { - return offscreen_surface_ && android_context_.IsValid(); + return offscreen_surface_ && GLContextPtr()->IsValid(); } std::unique_ptr AndroidSurfaceGL::CreateGPUSurface( GrDirectContext* gr_context) { if (gr_context) { return std::make_unique(sk_ref_sp(gr_context), this, true); + } else { + sk_sp main_skia_context = + GLContextPtr()->GetMainSkiaContext(); + if (!main_skia_context) { + main_skia_context = GPUSurfaceGL::MakeGLContext(this); + GLContextPtr()->SetMainSkiaContext(main_skia_context); + } + return std::make_unique(main_skia_context, this, true); } - return std::make_unique(this, true); } bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) { @@ -64,12 +71,12 @@ bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) { return true; } - android_context_.ClearCurrent(); + GLContextPtr()->ClearCurrent(); // Ensure the destructor is called since it destroys the `EGLSurface` before // creating a new onscreen surface. onscreen_surface_ = nullptr; - onscreen_surface_ = android_context_.CreateOnscreenSurface(native_window_); + onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(native_window_); if (!onscreen_surface_->IsValid()) { FML_LOG(ERROR) << "Unable to create EGL window surface on resize."; return false; @@ -85,7 +92,7 @@ bool AndroidSurfaceGL::ResourceContextMakeCurrent() { bool AndroidSurfaceGL::ResourceContextClearCurrent() { FML_DCHECK(IsValid()); - return android_context_.ClearCurrent(); + return GLContextPtr()->ClearCurrent(); } bool AndroidSurfaceGL::SetNativeWindow( @@ -97,7 +104,7 @@ bool AndroidSurfaceGL::SetNativeWindow( // creating a new onscreen surface. onscreen_surface_ = nullptr; // Create the onscreen surface. - onscreen_surface_ = android_context_.CreateOnscreenSurface(window); + onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(window); if (!onscreen_surface_->IsValid()) { return false; } @@ -114,7 +121,7 @@ std::unique_ptr AndroidSurfaceGL::GLContextMakeCurrent() { bool AndroidSurfaceGL::GLContextClearCurrent() { FML_DCHECK(IsValid()); - return android_context_.ClearCurrent(); + return GLContextPtr()->ClearCurrent(); } bool AndroidSurfaceGL::GLContextPresent(uint32_t fbo_id) { @@ -143,7 +150,7 @@ sk_sp AndroidSurfaceGL::GetGLInterface() const { reinterpret_cast(glGetString(GL_RENDERER)); if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix, strlen(kEmulatorRendererPrefix)) == 0) { - EGLContext new_context = android_context_.CreateNewContext(); + EGLContext new_context = GLContextPtr()->CreateNewContext(); if (new_context != EGL_NO_CONTEXT) { EGLContext old_context = eglGetCurrentContext(); EGLDisplay display = eglGetCurrentDisplay(); @@ -162,4 +169,8 @@ sk_sp AndroidSurfaceGL::GetGLInterface() const { return GPUSurfaceGLDelegate::GetGLInterface(); } +AndroidContextGL* AndroidSurfaceGL::GLContextPtr() const { + return reinterpret_cast(android_context_.get()); +} + } // namespace flutter diff --git a/shell/platform/android/android_surface_gl.h b/shell/platform/android/android_surface_gl.h index 1028f3c2b3d31..8db60f3176b3e 100644 --- a/shell/platform/android/android_surface_gl.h +++ b/shell/platform/android/android_surface_gl.h @@ -21,7 +21,7 @@ namespace flutter { class AndroidSurfaceGL final : public GPUSurfaceGLDelegate, public AndroidSurface { public: - AndroidSurfaceGL(const AndroidContext& android_context, + AndroidSurfaceGL(const std::shared_ptr& android_context, std::shared_ptr jni_facade); ~AndroidSurfaceGL() override; @@ -64,12 +64,16 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate, sk_sp GetGLInterface() const override; private: - const AndroidContextGL& android_context_; - fml::RefPtr native_window_; std::unique_ptr onscreen_surface_; std::unique_ptr offscreen_surface_; + //---------------------------------------------------------------------------- + /// @brief Takes the super class AndroidSurface's AndroidContext and + /// return a raw pointer to an AndroidContextGL. + /// + AndroidContextGL* GLContextPtr() const; + FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL); }; diff --git a/shell/platform/android/android_surface_software.cc b/shell/platform/android/android_surface_software.cc index 8a84204c21439..04775fd8463c7 100644 --- a/shell/platform/android/android_surface_software.cc +++ b/shell/platform/android/android_surface_software.cc @@ -38,8 +38,9 @@ bool GetSkColorType(int32_t buffer_format, } // anonymous namespace AndroidSurfaceSoftware::AndroidSurfaceSoftware( - const AndroidContext& android_context, - std::shared_ptr jni_facade) { + const std::shared_ptr& android_context, + std::shared_ptr jni_facade) + : AndroidSurface(android_context) { GetSkColorType(WINDOW_FORMAT_RGBA_8888, &target_color_type_, &target_alpha_type_); } @@ -60,6 +61,8 @@ bool AndroidSurfaceSoftware::ResourceContextClearCurrent() { } std::unique_ptr AndroidSurfaceSoftware::CreateGPUSurface( + // The software AndroidSurface neither uses any passed in Skia context + // nor does it interact with the AndroidContext's raster Skia context. GrDirectContext* gr_context) { if (!IsValid()) { return nullptr; diff --git a/shell/platform/android/android_surface_software.h b/shell/platform/android/android_surface_software.h index 9c3025e194960..151c05c15a310 100644 --- a/shell/platform/android/android_surface_software.h +++ b/shell/platform/android/android_surface_software.h @@ -17,7 +17,7 @@ namespace flutter { class AndroidSurfaceSoftware final : public AndroidSurface, public GPUSurfaceSoftwareDelegate { public: - AndroidSurfaceSoftware(const AndroidContext& android_context, + AndroidSurfaceSoftware(const std::shared_ptr& android_context, std::shared_ptr jni_facade); ~AndroidSurfaceSoftware() override; diff --git a/shell/platform/android/android_surface_vulkan.cc b/shell/platform/android/android_surface_vulkan.cc index ab3e68ca60985..2815e0a40d38e 100644 --- a/shell/platform/android/android_surface_vulkan.cc +++ b/shell/platform/android/android_surface_vulkan.cc @@ -4,18 +4,21 @@ #include "flutter/shell/platform/android/android_surface_vulkan.h" +#include #include #include "flutter/fml/logging.h" #include "flutter/shell/gpu/gpu_surface_vulkan.h" #include "flutter/vulkan/vulkan_native_surface_android.h" +#include "include/core/SkRefCnt.h" namespace flutter { AndroidSurfaceVulkan::AndroidSurfaceVulkan( - const AndroidContext& android_context, + const std::shared_ptr& android_context, std::shared_ptr jni_facade) - : proc_table_(fml::MakeRefCounted()) {} + : AndroidSurface(android_context), + proc_table_(fml::MakeRefCounted()) {} AndroidSurfaceVulkan::~AndroidSurfaceVulkan() = default; @@ -45,8 +48,22 @@ std::unique_ptr AndroidSurfaceVulkan::CreateGPUSurface( return nullptr; } - auto gpu_surface = std::make_unique( - this, std::move(vulkan_surface_android), true); + sk_sp provided_gr_context; + if (gr_context) { + provided_gr_context = sk_ref_sp(gr_context); + } else if (android_context_->GetMainSkiaContext()) { + provided_gr_context = android_context_->GetMainSkiaContext(); + } + + std::unique_ptr gpu_surface; + if (provided_gr_context) { + gpu_surface = std::make_unique( + provided_gr_context, this, std::move(vulkan_surface_android), true); + } else { + gpu_surface = std::make_unique( + this, std::move(vulkan_surface_android), true); + android_context_->SetMainSkiaContext(sk_ref_sp(gpu_surface->GetContext())); + } if (!gpu_surface->IsValid()) { return nullptr; diff --git a/shell/platform/android/android_surface_vulkan.h b/shell/platform/android/android_surface_vulkan.h index cf9c6fa7d0491..7639d01ab26a3 100644 --- a/shell/platform/android/android_surface_vulkan.h +++ b/shell/platform/android/android_surface_vulkan.h @@ -20,7 +20,7 @@ namespace flutter { class AndroidSurfaceVulkan : public AndroidSurface, public GPUSurfaceVulkanDelegate { public: - AndroidSurfaceVulkan(const AndroidContext& android_context, + AndroidSurfaceVulkan(const std::shared_ptr& android_context, std::shared_ptr jni_facade); ~AndroidSurfaceVulkan() override; diff --git a/shell/platform/android/context/BUILD.gn b/shell/platform/android/context/BUILD.gn index 70035e58a3fa8..e7c6c44725fe4 100644 --- a/shell/platform/android/context/BUILD.gn +++ b/shell/platform/android/context/BUILD.gn @@ -12,5 +12,8 @@ source_set("context") { public_configs = [ "//flutter:config" ] - deps = [ "//flutter/fml" ] + deps = [ + "//flutter/fml", + "//third_party/skia", + ] } diff --git a/shell/platform/android/context/android_context.cc b/shell/platform/android/context/android_context.cc index 4ff6550c15abb..1d4badf9543b7 100644 --- a/shell/platform/android/context/android_context.cc +++ b/shell/platform/android/context/android_context.cc @@ -9,7 +9,11 @@ namespace flutter { AndroidContext::AndroidContext(AndroidRenderingAPI rendering_api) : rendering_api_(rendering_api) {} -AndroidContext::~AndroidContext() = default; +AndroidContext::~AndroidContext() { + if (main_context_) { + main_context_->releaseResourcesAndAbandonContext(); + } +}; AndroidRenderingAPI AndroidContext::RenderingApi() const { return rendering_api_; @@ -19,4 +23,13 @@ bool AndroidContext::IsValid() const { return true; } +void AndroidContext::SetMainSkiaContext( + const sk_sp& main_context) { + main_context_ = main_context; +} + +sk_sp AndroidContext::GetMainSkiaContext() const { + return main_context_; +} + } // namespace flutter diff --git a/shell/platform/android/context/android_context.h b/shell/platform/android/context/android_context.h index 3412c0182e3d9..6f4e40bb10021 100644 --- a/shell/platform/android/context/android_context.h +++ b/shell/platform/android/context/android_context.h @@ -6,6 +6,7 @@ #define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_H_ #include "flutter/fml/macros.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { @@ -28,9 +29,37 @@ class AndroidContext { virtual bool IsValid() const; + //---------------------------------------------------------------------------- + /// @brief Setter for the Skia context to be used by subsequent + /// AndroidSurfaces. + /// @details This is useful to reduce memory consumption when creating + /// multiple AndroidSurfaces for the same AndroidContext. + /// + /// The first AndroidSurface should set this for the + /// AndroidContext if the AndroidContext does not yet have a + /// Skia context to share via GetMainSkiaContext. + /// + void SetMainSkiaContext(const sk_sp& main_context); + + //---------------------------------------------------------------------------- + /// @brief Accessor for the Skia context associated with AndroidSurfaces + /// and the raster thread. + /// @details This context is created lazily by the AndroidSurface based + /// on their respective rendering backend and set on this + /// AndroidContext to share via SetMainSkiaContext. + /// @returns `nullptr` when no Skia context has been set yet by its + /// AndroidSurface via SetMainSkiaContext. + /// @attention The software context doesn't have a Skia context, so this + /// value will be nullptr. + /// + sk_sp GetMainSkiaContext() const; + private: const AndroidRenderingAPI rendering_api_; + // This is the Skia context used for on-screen rendering. + sk_sp main_context_; + FML_DISALLOW_COPY_AND_ASSIGN(AndroidContext); }; diff --git a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc index 5aaa5bb5bf65c..9bbad774d3f1c 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc @@ -2,6 +2,7 @@ // 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/external_view_embedder/external_view_embedder.h" #include "flutter/flow/embedded_views.h" @@ -278,13 +279,14 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect__ChangedParams) { TEST(AndroidExternalViewEmbedder, SubmitFrame) { auto jni_mock = std::make_shared(); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto window = fml::MakeRefCounted(nullptr); auto gr_context = GrDirectContext::MakeMock(nullptr); auto frame_size = SkISize::Make(1000, 1000); auto surface_factory = std::make_shared( - [gr_context, window, frame_size]() { + [&android_context, gr_context, window, frame_size]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), false, [](const SurfaceFrame& surface_frame, SkCanvas* canvas) { @@ -302,7 +304,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { .WillOnce(Return(ByMove(std::move(surface_frame_1)))) .WillOnce(Return(ByMove(std::move(surface_frame_2)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -313,7 +316,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { return android_surface_mock; }); auto embedder = std::make_unique( - android_context, jni_mock, surface_factory); + *android_context, jni_mock, surface_factory); auto raster_thread_merger = GetThreadMergerFromPlatformThread(/*merged=*/true); @@ -496,11 +499,13 @@ TEST(AndroidExternalViewEmbedder, DoesNotCallJNIPlatformThreadOnlyMethods) { TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { auto jni_mock = std::make_shared(); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto window = fml::MakeRefCounted(nullptr); auto gr_context = GrDirectContext::MakeMock(nullptr); auto frame_size = SkISize::Make(1000, 1000); auto surface_factory = std::make_shared( - [gr_context, window, frame_size]() { + [&android_context, gr_context, window, frame_size]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), false, [](const SurfaceFrame& surface_frame, SkCanvas* canvas) { @@ -511,7 +516,8 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -522,9 +528,8 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { return android_surface_mock; }); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); auto embedder = std::make_unique( - android_context, jni_mock, surface_factory); + *android_context, jni_mock, surface_factory); auto raster_thread_merger = GetThreadMergerFromPlatformThread(); // ------------------ First frame ------------------ // @@ -575,13 +580,14 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { auto jni_mock = std::make_shared(); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto window = fml::MakeRefCounted(nullptr); auto gr_context = GrDirectContext::MakeMock(nullptr); auto frame_size = SkISize::Make(1000, 1000); auto surface_factory = std::make_shared( - [gr_context, window, frame_size]() { + [&android_context, gr_context, window, frame_size]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), false, [](const SurfaceFrame& surface_frame, SkCanvas* canvas) { @@ -592,7 +598,8 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -604,7 +611,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { }); auto embedder = std::make_unique( - android_context, jni_mock, surface_factory); + *android_context, jni_mock, surface_factory); // ------------------ First frame ------------------ // { diff --git a/shell/platform/android/external_view_embedder/surface_pool_unittests.cc b/shell/platform/android/external_view_embedder/surface_pool_unittests.cc index 652951f474ea0..ce37e8c81a8e7 100644 --- a/shell/platform/android/external_view_embedder/surface_pool_unittests.cc +++ b/shell/platform/android/external_view_embedder/surface_pool_unittests.cc @@ -2,6 +2,7 @@ // 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/external_view_embedder/surface_pool.h" #include "flutter/fml/make_copyable.h" @@ -39,7 +40,8 @@ TEST(SurfacePool, GetLayer__AllocateOneLayer) { auto pool = std::make_unique(); auto gr_context = GrDirectContext::MakeMock(nullptr); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto jni_mock = std::make_shared(); auto window = fml::MakeRefCounted(nullptr); @@ -48,15 +50,16 @@ TEST(SurfacePool, GetLayer__AllocateOneLayer) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); return android_surface_mock; }); - auto layer = pool->GetLayer(gr_context.get(), android_context, jni_mock, + auto layer = pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory); ASSERT_NE(nullptr, layer); @@ -68,7 +71,8 @@ TEST(SurfacePool, GetUnusedLayers) { auto pool = std::make_unique(); auto gr_context = GrDirectContext::MakeMock(nullptr); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto jni_mock = std::make_shared(); auto window = fml::MakeRefCounted(nullptr); @@ -77,15 +81,16 @@ TEST(SurfacePool, GetUnusedLayers) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); return android_surface_mock; }); - auto layer = pool->GetLayer(gr_context.get(), android_context, jni_mock, + auto layer = pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory); ASSERT_EQ(0UL, pool->GetUnusedLayers().size()); @@ -106,12 +111,14 @@ TEST(SurfacePool, GetLayer__Recycle) { ByMove(std::make_unique( 0, window)))); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto gr_context_2 = GrDirectContext::MakeMock(nullptr); auto surface_factory = std::make_shared( - [gr_context_1, gr_context_2, window]() { - auto android_surface_mock = std::make_unique(); + [&android_context, gr_context_1, gr_context_2, window]() { + auto android_surface_mock = + std::make_unique(android_context); // Allocate two GPU surfaces for each gr context. EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context_1.get())); @@ -122,12 +129,12 @@ TEST(SurfacePool, GetLayer__Recycle) { EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); return android_surface_mock; }); - auto layer_1 = pool->GetLayer(gr_context_1.get(), android_context, jni_mock, + auto layer_1 = pool->GetLayer(gr_context_1.get(), *android_context, jni_mock, surface_factory); pool->RecycleLayers(); - auto layer_2 = pool->GetLayer(gr_context_2.get(), android_context, jni_mock, + auto layer_2 = pool->GetLayer(gr_context_2.get(), *android_context, jni_mock, surface_factory); ASSERT_NE(nullptr, layer_1); @@ -142,7 +149,8 @@ TEST(SurfacePool, GetLayer__AllocateTwoLayers) { auto pool = std::make_unique(); auto gr_context = GrDirectContext::MakeMock(nullptr); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto jni_mock = std::make_shared(); auto window = fml::MakeRefCounted(nullptr); @@ -155,17 +163,18 @@ TEST(SurfacePool, GetLayer__AllocateTwoLayers) { ByMove(std::make_unique( 1, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); return android_surface_mock; }); - auto layer_1 = pool->GetLayer(gr_context.get(), android_context, jni_mock, + auto layer_1 = pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory); - auto layer_2 = pool->GetLayer(gr_context.get(), android_context, jni_mock, + auto layer_2 = pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory); ASSERT_NE(nullptr, layer_1); ASSERT_NE(nullptr, layer_2); @@ -182,7 +191,8 @@ TEST(SurfacePool, DestroyLayers) { pool->DestroyLayers(jni_mock); auto gr_context = GrDirectContext::MakeMock(nullptr); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto window = fml::MakeRefCounted(nullptr); EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface()) @@ -191,15 +201,16 @@ TEST(SurfacePool, DestroyLayers) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); return android_surface_mock; }); - pool->GetLayer(gr_context.get(), android_context, jni_mock, surface_factory); + pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory); EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()); pool->DestroyLayers(jni_mock); @@ -213,13 +224,15 @@ TEST(SurfacePool, DestroyLayers__frameSizeChanged) { auto jni_mock = std::make_shared(); auto gr_context = GrDirectContext::MakeMock(nullptr); - auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware); + auto android_context = + std::make_shared(AndroidRenderingAPI::kSoftware); auto window = fml::MakeRefCounted(nullptr); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -233,7 +246,7 @@ TEST(SurfacePool, DestroyLayers__frameSizeChanged) { ByMove(std::make_unique( 0, window)))); - pool->GetLayer(gr_context.get(), android_context, jni_mock, surface_factory); + pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory); pool->SetFrameSize(SkISize::Make(20, 20)); EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()).Times(1); @@ -242,7 +255,7 @@ TEST(SurfacePool, DestroyLayers__frameSizeChanged) { .WillOnce(Return( ByMove(std::make_unique( 1, window)))); - pool->GetLayer(gr_context.get(), android_context, jni_mock, surface_factory); + pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory); ASSERT_TRUE(pool->GetUnusedLayers().empty()); } diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index b580b4049bc05..e7b25f75393ef 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -29,14 +29,14 @@ namespace flutter { AndroidSurfaceFactoryImpl::AndroidSurfaceFactoryImpl( - const AndroidContext& context, + const std::shared_ptr& context, std::shared_ptr jni_facade) : android_context_(context), jni_facade_(jni_facade) {} AndroidSurfaceFactoryImpl::~AndroidSurfaceFactoryImpl() = default; std::unique_ptr AndroidSurfaceFactoryImpl::CreateSurface() { - switch (android_context_.RenderingApi()) { + switch (android_context_->RenderingApi()) { case AndroidRenderingAPI::kSoftware: return std::make_unique(android_context_, jni_facade_); @@ -68,13 +68,13 @@ PlatformViewAndroid::PlatformViewAndroid( #if SHELL_ENABLE_VULKAN android_context_ = std::make_shared(AndroidRenderingAPI::kVulkan); -#else // SHELL_ENABLE_VULKAN +#else // SHELL_ENABLE_VULKAN android_context_ = std::make_unique( AndroidRenderingAPI::kOpenGLES, fml::MakeRefCounted()); #endif // SHELL_ENABLE_VULKAN } - surface_factory_ = MakeSurfaceFactory(*android_context_, *jni_facade_); + surface_factory_ = MakeSurfaceFactory(android_context_, *jni_facade_); android_surface_ = MakeSurface(surface_factory_); } @@ -87,7 +87,7 @@ PlatformViewAndroid::PlatformViewAndroid( jni_facade_(jni_facade), android_context_(android_context), platform_view_android_delegate_(jni_facade) { - surface_factory_ = MakeSurfaceFactory(*android_context_, *jni_facade_); + surface_factory_ = MakeSurfaceFactory(android_context_, *jni_facade_); android_surface_ = MakeSurface(surface_factory_); } @@ -103,9 +103,9 @@ PlatformViewAndroid::~PlatformViewAndroid() = default; std::shared_ptr PlatformViewAndroid::MakeSurfaceFactory( - const AndroidContext& android_context, + const std::shared_ptr& android_context, const PlatformViewAndroidJNI& jni_facade) { - FML_CHECK(android_context.IsValid()) + FML_CHECK(android_context->IsValid()) << "Could not create surface from invalid Android context."; return std::make_shared(android_context, @@ -317,7 +317,8 @@ std::unique_ptr PlatformViewAndroid::CreateRenderingSurface() { if (!android_surface_) { return nullptr; } - return android_surface_->CreateGPUSurface(); + return android_surface_->CreateGPUSurface( + android_context_->GetMainSkiaContext().get()); } // |PlatformView| diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index 2bdbb2c02a958..83f4e0494edf3 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -25,7 +25,7 @@ namespace flutter { class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory { public: - AndroidSurfaceFactoryImpl(const AndroidContext& context, + AndroidSurfaceFactoryImpl(const std::shared_ptr& context, std::shared_ptr jni_facade); ~AndroidSurfaceFactoryImpl() override; @@ -33,7 +33,7 @@ class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory { std::unique_ptr CreateSurface() override; private: - const AndroidContext& android_context_; + const std::shared_ptr& android_context_; std::shared_ptr jni_facade_; }; @@ -171,7 +171,7 @@ class PlatformViewAndroid final : public PlatformView { void RequestDartDeferredLibrary(intptr_t loading_unit_id) override; std::shared_ptr MakeSurfaceFactory( - const AndroidContext& android_context, + const std::shared_ptr& android_context, const PlatformViewAndroidJNI& jni_facade); std::unique_ptr MakeSurface( diff --git a/shell/platform/android/surface/android_surface.cc b/shell/platform/android/surface/android_surface.cc index 1f5032d8917cf..afa4a1ba73479 100644 --- a/shell/platform/android/surface/android_surface.cc +++ b/shell/platform/android/surface/android_surface.cc @@ -3,9 +3,16 @@ // found in the LICENSE file. #include "flutter/shell/platform/android/surface/android_surface.h" +#include "flutter/fml/logging.h" namespace flutter { +AndroidSurface::AndroidSurface( + const std::shared_ptr& android_context) { + FML_DCHECK(android_context->IsValid()); + android_context_ = android_context; +} + AndroidSurface::~AndroidSurface() = default; } // namespace flutter diff --git a/shell/platform/android/surface/android_surface.h b/shell/platform/android/surface/android_surface.h index 1fd4847fae27b..74b3fe0efe656 100644 --- a/shell/platform/android/surface/android_surface.h +++ b/shell/platform/android/surface/android_surface.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_H_ #define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_SURFACE_H_ +#include #include "flutter/flow/embedded_views.h" #include "flutter/flow/surface.h" #include "flutter/fml/macros.h" @@ -35,6 +36,11 @@ class AndroidSurface { virtual bool ResourceContextClearCurrent() = 0; virtual bool SetNativeWindow(fml::RefPtr window) = 0; + + protected: + explicit AndroidSurface( + const std::shared_ptr& android_context); + std::shared_ptr android_context_; }; class AndroidSurfaceFactory { diff --git a/shell/platform/android/surface/android_surface_mock.cc b/shell/platform/android/surface/android_surface_mock.cc index fc9ca103211b3..a0b08cb4892d6 100644 --- a/shell/platform/android/surface/android_surface_mock.cc +++ b/shell/platform/android/surface/android_surface_mock.cc @@ -6,6 +6,10 @@ namespace flutter { +AndroidSurfaceMock::AndroidSurfaceMock( + const std::shared_ptr& android_context) + : AndroidSurface(android_context) {} + std::unique_ptr AndroidSurfaceMock::GLContextMakeCurrent() { return std::make_unique(/*static_result=*/true); } diff --git a/shell/platform/android/surface/android_surface_mock.h b/shell/platform/android/surface/android_surface_mock.h index b0e5be87747aa..f710133f64c5d 100644 --- a/shell/platform/android/surface/android_surface_mock.h +++ b/shell/platform/android/surface/android_surface_mock.h @@ -18,6 +18,9 @@ namespace flutter { class AndroidSurfaceMock final : public GPUSurfaceGLDelegate, public AndroidSurface { public: + explicit AndroidSurfaceMock( + const std::shared_ptr& android_context); + MOCK_METHOD(bool, IsValid, (), (const, override)); MOCK_METHOD(void, TeardownOnScreenContext, (), (override)); diff --git a/vulkan/vulkan_window.cc b/vulkan/vulkan_window.cc index 2c4618f06e796..3ca06b3b23e8a 100644 --- a/vulkan/vulkan_window.cc +++ b/vulkan/vulkan_window.cc @@ -21,7 +21,16 @@ namespace vulkan { VulkanWindow::VulkanWindow(fml::RefPtr proc_table, std::unique_ptr native_surface, bool render_to_surface) - : valid_(false), vk(std::move(proc_table)) { + : VulkanWindow(/*context/*/ nullptr, + proc_table, + std::move(native_surface), + render_to_surface) {} + +VulkanWindow::VulkanWindow(const sk_sp& context, + fml::RefPtr proc_table, + std::unique_ptr native_surface, + bool render_to_surface) + : valid_(false), vk(std::move(proc_table)), skia_gr_context_(context) { if (!vk || !vk->HasAcquiredMandatoryProcAddresses()) { FML_DLOG(INFO) << "Proc table has not acquired mandatory proc addresses."; return; @@ -78,7 +87,7 @@ VulkanWindow::VulkanWindow(fml::RefPtr proc_table, // Create the Skia GrDirectContext. - if (!CreateSkiaGrContext()) { + if (!skia_gr_context_ && !CreateSkiaGrContext()) { FML_DLOG(INFO) << "Could not create Skia context."; return; } diff --git a/vulkan/vulkan_window.h b/vulkan/vulkan_window.h index b67f49707d5db..685825024f7b8 100644 --- a/vulkan/vulkan_window.h +++ b/vulkan/vulkan_window.h @@ -31,10 +31,23 @@ class VulkanBackbuffer; class VulkanWindow { public: + //------------------------------------------------------------------------------ + /// @brief Construct a VulkanWindow. Let it implicitly create a + /// GrDirectContext. + /// VulkanWindow(fml::RefPtr proc_table, std::unique_ptr native_surface, bool render_to_surface); + //------------------------------------------------------------------------------ + /// @brief Construct a VulkanWindow. Let reuse an existing + /// GrDirectContext built by another VulkanWindow. + /// + VulkanWindow(const sk_sp& context, + fml::RefPtr proc_table, + std::unique_ptr native_surface, + bool render_to_surface); + ~VulkanWindow(); bool IsValid() const;