Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a4f02b7

Browse files
authored
Share Android surface GrDirectContext (#23798)
1 parent 7c2da3b commit a4f02b7

21 files changed

+253
-83
lines changed

shell/gpu/gpu_surface_vulkan.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,20 @@ GPUSurfaceVulkan::GPUSurfaceVulkan(
1212
GPUSurfaceVulkanDelegate* delegate,
1313
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
1414
bool render_to_surface)
15-
: window_(delegate->vk(), std::move(native_surface), render_to_surface),
15+
: GPUSurfaceVulkan(/*context=*/nullptr,
16+
delegate,
17+
std::move(native_surface),
18+
render_to_surface) {}
19+
20+
GPUSurfaceVulkan::GPUSurfaceVulkan(
21+
const sk_sp<GrDirectContext>& context,
22+
GPUSurfaceVulkanDelegate* delegate,
23+
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
24+
bool render_to_surface)
25+
: window_(context,
26+
delegate->vk(),
27+
std::move(native_surface),
28+
render_to_surface),
1629
render_to_surface_(render_to_surface),
1730
weak_factory_(this) {}
1831

shell/gpu/gpu_surface_vulkan.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,29 @@
1313
#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h"
1414
#include "flutter/vulkan/vulkan_native_surface.h"
1515
#include "flutter/vulkan/vulkan_window.h"
16+
#include "include/core/SkRefCnt.h"
1617

1718
namespace flutter {
1819

1920
class GPUSurfaceVulkan : public Surface {
2021
public:
22+
//------------------------------------------------------------------------------
23+
/// @brief Create a GPUSurfaceVulkan which implicitly creates its own
24+
/// GrDirectContext for Skia.
25+
///
2126
GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
2227
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
2328
bool render_to_surface);
2429

30+
//------------------------------------------------------------------------------
31+
/// @brief Create a GPUSurfaceVulkan while letting it reuse an existing
32+
/// GrDirectContext.
33+
///
34+
GPUSurfaceVulkan(const sk_sp<GrDirectContext>& context,
35+
GPUSurfaceVulkanDelegate* delegate,
36+
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
37+
bool render_to_surface);
38+
2539
~GPUSurfaceVulkan() override;
2640

2741
// |Surface|

shell/platform/android/android_surface_gl.cc

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ constexpr char kEmulatorRendererPrefix[] =
2020
} // anonymous namespace
2121

2222
AndroidSurfaceGL::AndroidSurfaceGL(
23-
const AndroidContext& android_context,
23+
const std::shared_ptr<AndroidContext>& android_context,
2424
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
25-
: android_context_(static_cast<const AndroidContextGL&>(android_context)),
25+
: AndroidSurface(android_context),
2626
native_window_(nullptr),
2727
onscreen_surface_(nullptr),
2828
offscreen_surface_(nullptr) {
2929
// Acquire the offscreen surface.
30-
offscreen_surface_ = android_context_.CreateOffscreenSurface();
30+
offscreen_surface_ = GLContextPtr()->CreateOffscreenSurface();
3131
if (!offscreen_surface_->IsValid()) {
3232
offscreen_surface_ = nullptr;
3333
}
@@ -39,20 +39,27 @@ void AndroidSurfaceGL::TeardownOnScreenContext() {
3939
// When the onscreen surface is destroyed, the context and the surface
4040
// instance should be deleted. Issue:
4141
// https://github.com/flutter/flutter/issues/64414
42-
android_context_.ClearCurrent();
42+
GLContextPtr()->ClearCurrent();
4343
onscreen_surface_ = nullptr;
4444
}
4545

4646
bool AndroidSurfaceGL::IsValid() const {
47-
return offscreen_surface_ && android_context_.IsValid();
47+
return offscreen_surface_ && GLContextPtr()->IsValid();
4848
}
4949

5050
std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface(
5151
GrDirectContext* gr_context) {
5252
if (gr_context) {
5353
return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
54+
} else {
55+
sk_sp<GrDirectContext> main_skia_context =
56+
GLContextPtr()->GetMainSkiaContext();
57+
if (!main_skia_context) {
58+
main_skia_context = GPUSurfaceGL::MakeGLContext(this);
59+
GLContextPtr()->SetMainSkiaContext(main_skia_context);
60+
}
61+
return std::make_unique<GPUSurfaceGL>(main_skia_context, this, true);
5462
}
55-
return std::make_unique<GPUSurfaceGL>(this, true);
5663
}
5764

5865
bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) {
@@ -64,12 +71,12 @@ bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) {
6471
return true;
6572
}
6673

67-
android_context_.ClearCurrent();
74+
GLContextPtr()->ClearCurrent();
6875

6976
// Ensure the destructor is called since it destroys the `EGLSurface` before
7077
// creating a new onscreen surface.
7178
onscreen_surface_ = nullptr;
72-
onscreen_surface_ = android_context_.CreateOnscreenSurface(native_window_);
79+
onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(native_window_);
7380
if (!onscreen_surface_->IsValid()) {
7481
FML_LOG(ERROR) << "Unable to create EGL window surface on resize.";
7582
return false;
@@ -85,7 +92,7 @@ bool AndroidSurfaceGL::ResourceContextMakeCurrent() {
8592

8693
bool AndroidSurfaceGL::ResourceContextClearCurrent() {
8794
FML_DCHECK(IsValid());
88-
return android_context_.ClearCurrent();
95+
return GLContextPtr()->ClearCurrent();
8996
}
9097

9198
bool AndroidSurfaceGL::SetNativeWindow(
@@ -97,7 +104,7 @@ bool AndroidSurfaceGL::SetNativeWindow(
97104
// creating a new onscreen surface.
98105
onscreen_surface_ = nullptr;
99106
// Create the onscreen surface.
100-
onscreen_surface_ = android_context_.CreateOnscreenSurface(window);
107+
onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(window);
101108
if (!onscreen_surface_->IsValid()) {
102109
return false;
103110
}
@@ -114,7 +121,7 @@ std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {
114121

115122
bool AndroidSurfaceGL::GLContextClearCurrent() {
116123
FML_DCHECK(IsValid());
117-
return android_context_.ClearCurrent();
124+
return GLContextPtr()->ClearCurrent();
118125
}
119126

120127
bool AndroidSurfaceGL::GLContextPresent(uint32_t fbo_id) {
@@ -143,7 +150,7 @@ sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
143150
reinterpret_cast<const char*>(glGetString(GL_RENDERER));
144151
if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix,
145152
strlen(kEmulatorRendererPrefix)) == 0) {
146-
EGLContext new_context = android_context_.CreateNewContext();
153+
EGLContext new_context = GLContextPtr()->CreateNewContext();
147154
if (new_context != EGL_NO_CONTEXT) {
148155
EGLContext old_context = eglGetCurrentContext();
149156
EGLDisplay display = eglGetCurrentDisplay();
@@ -162,4 +169,8 @@ sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
162169
return GPUSurfaceGLDelegate::GetGLInterface();
163170
}
164171

172+
AndroidContextGL* AndroidSurfaceGL::GLContextPtr() const {
173+
return reinterpret_cast<AndroidContextGL*>(android_context_.get());
174+
}
175+
165176
} // namespace flutter

shell/platform/android/android_surface_gl.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace flutter {
2121
class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
2222
public AndroidSurface {
2323
public:
24-
AndroidSurfaceGL(const AndroidContext& android_context,
24+
AndroidSurfaceGL(const std::shared_ptr<AndroidContext>& android_context,
2525
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
2626

2727
~AndroidSurfaceGL() override;
@@ -64,12 +64,16 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
6464
sk_sp<const GrGLInterface> GetGLInterface() const override;
6565

6666
private:
67-
const AndroidContextGL& android_context_;
68-
6967
fml::RefPtr<AndroidNativeWindow> native_window_;
7068
std::unique_ptr<AndroidEGLSurface> onscreen_surface_;
7169
std::unique_ptr<AndroidEGLSurface> offscreen_surface_;
7270

71+
//----------------------------------------------------------------------------
72+
/// @brief Takes the super class AndroidSurface's AndroidContext and
73+
/// return a raw pointer to an AndroidContextGL.
74+
///
75+
AndroidContextGL* GLContextPtr() const;
76+
7377
FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL);
7478
};
7579

shell/platform/android/android_surface_software.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ bool GetSkColorType(int32_t buffer_format,
3838
} // anonymous namespace
3939

4040
AndroidSurfaceSoftware::AndroidSurfaceSoftware(
41-
const AndroidContext& android_context,
42-
std::shared_ptr<PlatformViewAndroidJNI> jni_facade) {
41+
const std::shared_ptr<AndroidContext>& android_context,
42+
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
43+
: AndroidSurface(android_context) {
4344
GetSkColorType(WINDOW_FORMAT_RGBA_8888, &target_color_type_,
4445
&target_alpha_type_);
4546
}
@@ -60,6 +61,8 @@ bool AndroidSurfaceSoftware::ResourceContextClearCurrent() {
6061
}
6162

6263
std::unique_ptr<Surface> AndroidSurfaceSoftware::CreateGPUSurface(
64+
// The software AndroidSurface neither uses any passed in Skia context
65+
// nor does it interact with the AndroidContext's raster Skia context.
6366
GrDirectContext* gr_context) {
6467
if (!IsValid()) {
6568
return nullptr;

shell/platform/android/android_surface_software.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace flutter {
1717
class AndroidSurfaceSoftware final : public AndroidSurface,
1818
public GPUSurfaceSoftwareDelegate {
1919
public:
20-
AndroidSurfaceSoftware(const AndroidContext& android_context,
20+
AndroidSurfaceSoftware(const std::shared_ptr<AndroidContext>& android_context,
2121
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
2222

2323
~AndroidSurfaceSoftware() override;

shell/platform/android/android_surface_vulkan.cc

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@
44

55
#include "flutter/shell/platform/android/android_surface_vulkan.h"
66

7+
#include <memory>
78
#include <utility>
89

910
#include "flutter/fml/logging.h"
1011
#include "flutter/shell/gpu/gpu_surface_vulkan.h"
1112
#include "flutter/vulkan/vulkan_native_surface_android.h"
13+
#include "include/core/SkRefCnt.h"
1214

1315
namespace flutter {
1416

1517
AndroidSurfaceVulkan::AndroidSurfaceVulkan(
16-
const AndroidContext& android_context,
18+
const std::shared_ptr<AndroidContext>& android_context,
1719
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
18-
: proc_table_(fml::MakeRefCounted<vulkan::VulkanProcTable>()) {}
20+
: AndroidSurface(android_context),
21+
proc_table_(fml::MakeRefCounted<vulkan::VulkanProcTable>()) {}
1922

2023
AndroidSurfaceVulkan::~AndroidSurfaceVulkan() = default;
2124

@@ -45,8 +48,22 @@ std::unique_ptr<Surface> AndroidSurfaceVulkan::CreateGPUSurface(
4548
return nullptr;
4649
}
4750

48-
auto gpu_surface = std::make_unique<GPUSurfaceVulkan>(
49-
this, std::move(vulkan_surface_android), true);
51+
sk_sp<GrDirectContext> provided_gr_context;
52+
if (gr_context) {
53+
provided_gr_context = sk_ref_sp(gr_context);
54+
} else if (android_context_->GetMainSkiaContext()) {
55+
provided_gr_context = android_context_->GetMainSkiaContext();
56+
}
57+
58+
std::unique_ptr<GPUSurfaceVulkan> gpu_surface;
59+
if (provided_gr_context) {
60+
gpu_surface = std::make_unique<GPUSurfaceVulkan>(
61+
provided_gr_context, this, std::move(vulkan_surface_android), true);
62+
} else {
63+
gpu_surface = std::make_unique<GPUSurfaceVulkan>(
64+
this, std::move(vulkan_surface_android), true);
65+
android_context_->SetMainSkiaContext(sk_ref_sp(gpu_surface->GetContext()));
66+
}
5067

5168
if (!gpu_surface->IsValid()) {
5269
return nullptr;

shell/platform/android/android_surface_vulkan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace flutter {
2020
class AndroidSurfaceVulkan : public AndroidSurface,
2121
public GPUSurfaceVulkanDelegate {
2222
public:
23-
AndroidSurfaceVulkan(const AndroidContext& android_context,
23+
AndroidSurfaceVulkan(const std::shared_ptr<AndroidContext>& android_context,
2424
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);
2525

2626
~AndroidSurfaceVulkan() override;

shell/platform/android/context/BUILD.gn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@ source_set("context") {
1212

1313
public_configs = [ "//flutter:config" ]
1414

15-
deps = [ "//flutter/fml" ]
15+
deps = [
16+
"//flutter/fml",
17+
"//third_party/skia",
18+
]
1619
}

shell/platform/android/context/android_context.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ namespace flutter {
99
AndroidContext::AndroidContext(AndroidRenderingAPI rendering_api)
1010
: rendering_api_(rendering_api) {}
1111

12-
AndroidContext::~AndroidContext() = default;
12+
AndroidContext::~AndroidContext() {
13+
if (main_context_) {
14+
main_context_->releaseResourcesAndAbandonContext();
15+
}
16+
};
1317

1418
AndroidRenderingAPI AndroidContext::RenderingApi() const {
1519
return rendering_api_;
@@ -19,4 +23,13 @@ bool AndroidContext::IsValid() const {
1923
return true;
2024
}
2125

26+
void AndroidContext::SetMainSkiaContext(
27+
const sk_sp<GrDirectContext>& main_context) {
28+
main_context_ = main_context;
29+
}
30+
31+
sk_sp<GrDirectContext> AndroidContext::GetMainSkiaContext() const {
32+
return main_context_;
33+
}
34+
2235
} // namespace flutter

shell/platform/android/context/android_context.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_H_
77

88
#include "flutter/fml/macros.h"
9+
#include "third_party/skia/include/gpu/GrDirectContext.h"
910

1011
namespace flutter {
1112

@@ -28,9 +29,37 @@ class AndroidContext {
2829

2930
virtual bool IsValid() const;
3031

32+
//----------------------------------------------------------------------------
33+
/// @brief Setter for the Skia context to be used by subsequent
34+
/// AndroidSurfaces.
35+
/// @details This is useful to reduce memory consumption when creating
36+
/// multiple AndroidSurfaces for the same AndroidContext.
37+
///
38+
/// The first AndroidSurface should set this for the
39+
/// AndroidContext if the AndroidContext does not yet have a
40+
/// Skia context to share via GetMainSkiaContext.
41+
///
42+
void SetMainSkiaContext(const sk_sp<GrDirectContext>& main_context);
43+
44+
//----------------------------------------------------------------------------
45+
/// @brief Accessor for the Skia context associated with AndroidSurfaces
46+
/// and the raster thread.
47+
/// @details This context is created lazily by the AndroidSurface based
48+
/// on their respective rendering backend and set on this
49+
/// AndroidContext to share via SetMainSkiaContext.
50+
/// @returns `nullptr` when no Skia context has been set yet by its
51+
/// AndroidSurface via SetMainSkiaContext.
52+
/// @attention The software context doesn't have a Skia context, so this
53+
/// value will be nullptr.
54+
///
55+
sk_sp<GrDirectContext> GetMainSkiaContext() const;
56+
3157
private:
3258
const AndroidRenderingAPI rendering_api_;
3359

60+
// This is the Skia context used for on-screen rendering.
61+
sk_sp<GrDirectContext> main_context_;
62+
3463
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContext);
3564
};
3665

0 commit comments

Comments
 (0)