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

Share Android surface GrDirectContext #23798

Merged
merged 8 commits into from
Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion shell/gpu/gpu_surface_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,20 @@ GPUSurfaceVulkan::GPUSurfaceVulkan(
GPUSurfaceVulkanDelegate* delegate,
std::unique_ptr<vulkan::VulkanNativeSurface> 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<GrDirectContext>& context,
GPUSurfaceVulkanDelegate* delegate,
std::unique_ptr<vulkan::VulkanNativeSurface> 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) {}

Expand Down
14 changes: 14 additions & 0 deletions shell/gpu/gpu_surface_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<vulkan::VulkanNativeSurface> native_surface,
bool render_to_surface);

//------------------------------------------------------------------------------
/// @brief Create a GPUSurfaceVulkan while letting it reuse an existing
/// GrDirectContext.
///
GPUSurfaceVulkan(const sk_sp<GrDirectContext>& context,
GPUSurfaceVulkanDelegate* delegate,
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
bool render_to_surface);

~GPUSurfaceVulkan() override;

// |Surface|
Expand Down
35 changes: 23 additions & 12 deletions shell/platform/android/android_surface_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ constexpr char kEmulatorRendererPrefix[] =
} // anonymous namespace

AndroidSurfaceGL::AndroidSurfaceGL(
const AndroidContext& android_context,
const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: android_context_(static_cast<const AndroidContextGL&>(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;
}
Expand All @@ -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<Surface> AndroidSurfaceGL::CreateGPUSurface(
GrDirectContext* gr_context) {
if (gr_context) {
return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
} else {
sk_sp<GrDirectContext> main_skia_context =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more or less 1 of 2 of the actual interesting parts of this PR. When AndroidSurfaceGL needs to make a GPUSurfaceGL (which would then make a GrDirectContext implicitly), the AndroidSurfaceGL makes one explicitly, then stores it in the AndroidContext for reuse if more AndroidSurfaceGLs are made with the same AndroidContext.

GLContextPtr()->GetMainSkiaContext();
if (!main_skia_context) {
main_skia_context = GPUSurfaceGL::MakeGLContext(this);
GLContextPtr()->SetMainSkiaContext(main_skia_context);
}
return std::make_unique<GPUSurfaceGL>(main_skia_context, this, true);
}
return std::make_unique<GPUSurfaceGL>(this, true);
}

bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) {
Expand All @@ -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;
Expand All @@ -85,7 +92,7 @@ bool AndroidSurfaceGL::ResourceContextMakeCurrent() {

bool AndroidSurfaceGL::ResourceContextClearCurrent() {
FML_DCHECK(IsValid());
return android_context_.ClearCurrent();
return GLContextPtr()->ClearCurrent();
}

bool AndroidSurfaceGL::SetNativeWindow(
Expand All @@ -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;
}
Expand All @@ -114,7 +121,7 @@ std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {

bool AndroidSurfaceGL::GLContextClearCurrent() {
FML_DCHECK(IsValid());
return android_context_.ClearCurrent();
return GLContextPtr()->ClearCurrent();
}

bool AndroidSurfaceGL::GLContextPresent(uint32_t fbo_id) {
Expand Down Expand Up @@ -143,7 +150,7 @@ sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
reinterpret_cast<const char*>(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();
Expand All @@ -162,4 +169,8 @@ sk_sp<const GrGLInterface> AndroidSurfaceGL::GetGLInterface() const {
return GPUSurfaceGLDelegate::GetGLInterface();
}

AndroidContextGL* AndroidSurfaceGL::GLContextPtr() const {
return reinterpret_cast<AndroidContextGL*>(android_context_.get());
}

} // namespace flutter
10 changes: 7 additions & 3 deletions shell/platform/android/android_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace flutter {
class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
public AndroidSurface {
public:
AndroidSurfaceGL(const AndroidContext& android_context,
AndroidSurfaceGL(const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);

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

private:
const AndroidContextGL& android_context_;

fml::RefPtr<AndroidNativeWindow> native_window_;
std::unique_ptr<AndroidEGLSurface> onscreen_surface_;
std::unique_ptr<AndroidEGLSurface> 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);
};

Expand Down
7 changes: 5 additions & 2 deletions shell/platform/android/android_surface_software.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ bool GetSkColorType(int32_t buffer_format,
} // anonymous namespace

AndroidSurfaceSoftware::AndroidSurfaceSoftware(
const AndroidContext& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade) {
const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: AndroidSurface(android_context) {
GetSkColorType(WINDOW_FORMAT_RGBA_8888, &target_color_type_,
&target_alpha_type_);
}
Expand All @@ -60,6 +61,8 @@ bool AndroidSurfaceSoftware::ResourceContextClearCurrent() {
}

std::unique_ptr<Surface> 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;
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/android/android_surface_software.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace flutter {
class AndroidSurfaceSoftware final : public AndroidSurface,
public GPUSurfaceSoftwareDelegate {
public:
AndroidSurfaceSoftware(const AndroidContext& android_context,
AndroidSurfaceSoftware(const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);

~AndroidSurfaceSoftware() override;
Expand Down
25 changes: 21 additions & 4 deletions shell/platform/android/android_surface_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@

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

#include <memory>
#include <utility>

#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<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: proc_table_(fml::MakeRefCounted<vulkan::VulkanProcTable>()) {}
: AndroidSurface(android_context),
proc_table_(fml::MakeRefCounted<vulkan::VulkanProcTable>()) {}

AndroidSurfaceVulkan::~AndroidSurfaceVulkan() = default;

Expand Down Expand Up @@ -45,8 +48,22 @@ std::unique_ptr<Surface> AndroidSurfaceVulkan::CreateGPUSurface(
return nullptr;
}

auto gpu_surface = std::make_unique<GPUSurfaceVulkan>(
this, std::move(vulkan_surface_android), true);
sk_sp<GrDirectContext> 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<GPUSurfaceVulkan> gpu_surface;
if (provided_gr_context) {
gpu_surface = std::make_unique<GPUSurfaceVulkan>(
provided_gr_context, this, std::move(vulkan_surface_android), true);
} else {
gpu_surface = std::make_unique<GPUSurfaceVulkan>(
this, std::move(vulkan_surface_android), true);
android_context_->SetMainSkiaContext(sk_ref_sp(gpu_surface->GetContext()));
}

if (!gpu_surface->IsValid()) {
return nullptr;
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/android/android_surface_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace flutter {
class AndroidSurfaceVulkan : public AndroidSurface,
public GPUSurfaceVulkanDelegate {
public:
AndroidSurfaceVulkan(const AndroidContext& android_context,
AndroidSurfaceVulkan(const std::shared_ptr<AndroidContext>& android_context,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade);

~AndroidSurfaceVulkan() override;
Expand Down
5 changes: 4 additions & 1 deletion shell/platform/android/context/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ source_set("context") {

public_configs = [ "//flutter:config" ]

deps = [ "//flutter/fml" ]
deps = [
"//flutter/fml",
"//third_party/skia",
]
}
15 changes: 14 additions & 1 deletion shell/platform/android/context/android_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand All @@ -19,4 +23,13 @@ bool AndroidContext::IsValid() const {
return true;
}

void AndroidContext::SetMainSkiaContext(
const sk_sp<GrDirectContext>& main_context) {
main_context_ = main_context;
}

sk_sp<GrDirectContext> AndroidContext::GetMainSkiaContext() const {
return main_context_;
}

} // namespace flutter
29 changes: 29 additions & 0 deletions shell/platform/android/context/android_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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<GrDirectContext>& 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<GrDirectContext> GetMainSkiaContext() const;

private:
const AndroidRenderingAPI rendering_api_;

// This is the Skia context used for on-screen rendering.
sk_sp<GrDirectContext> main_context_;

FML_DISALLOW_COPY_AND_ASSIGN(AndroidContext);
};

Expand Down
Loading