mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Refactor AndroidContextGL, AndroidSurface and AndroidSurfaceGL (flutter/engine#18670)
This commit is contained in:
parent
f6b8e644c4
commit
2bee676fe5
@ -645,6 +645,8 @@ FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan.h
|
||||
FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_delegate.cc
|
||||
FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_delegate.h
|
||||
FILE: ../../../flutter/shell/platform/android/AndroidManifest.xml
|
||||
FILE: ../../../flutter/shell/platform/android/android_context.cc
|
||||
FILE: ../../../flutter/shell/platform/android/android_context.h
|
||||
FILE: ../../../flutter/shell/platform/android/android_context_gl.cc
|
||||
FILE: ../../../flutter/shell/platform/android/android_context_gl.h
|
||||
FILE: ../../../flutter/shell/platform/android/android_environment_gl.cc
|
||||
|
||||
@ -23,6 +23,8 @@ shared_library("flutter_shell_native") {
|
||||
|
||||
sources = [
|
||||
"$root_build_dir/flutter_icu/icudtl.o",
|
||||
"android_context.cc",
|
||||
"android_context.h",
|
||||
"android_context_gl.cc",
|
||||
"android_context_gl.h",
|
||||
"android_environment_gl.cc",
|
||||
|
||||
37
engine/src/flutter/shell/platform/android/android_context.cc
Normal file
37
engine/src/flutter/shell/platform/android/android_context.cc
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2013 The Flutter 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.h"
|
||||
|
||||
#include "flutter/shell/platform/android/android_context_gl.h"
|
||||
#include "flutter/shell/platform/android/android_environment_gl.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
std::shared_ptr<AndroidContext> CreateContextGL() {
|
||||
auto context_gl = std::make_shared<AndroidContextGL>(
|
||||
AndroidRenderingAPI::kOpenGLES,
|
||||
fml::MakeRefCounted<AndroidEnvironmentGL>());
|
||||
FML_CHECK(context_gl->IsValid()) << "Could not create an Android context GL.";
|
||||
return context_gl;
|
||||
}
|
||||
|
||||
AndroidContext::AndroidContext(AndroidRenderingAPI rendering_api)
|
||||
: rendering_api_(rendering_api) {}
|
||||
|
||||
AndroidContext::~AndroidContext() = default;
|
||||
|
||||
AndroidRenderingAPI AndroidContext::RenderingApi() const {
|
||||
return rendering_api_;
|
||||
}
|
||||
|
||||
std::shared_ptr<AndroidContext> AndroidContext::Create(
|
||||
AndroidRenderingAPI rendering_api) {
|
||||
if (rendering_api == AndroidRenderingAPI::kOpenGLES) {
|
||||
return CreateContextGL();
|
||||
}
|
||||
return std::make_shared<AndroidContext>(rendering_api);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
43
engine/src/flutter/shell/platform/android/android_context.h
Normal file
43
engine/src/flutter/shell/platform/android/android_context.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2013 The Flutter 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_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_H_
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/fml/memory/ref_counted.h"
|
||||
#include "flutter/fml/memory/ref_ptr.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
enum class AndroidRenderingAPI {
|
||||
kSoftware,
|
||||
kOpenGLES,
|
||||
kVulkan,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief Holds state that is shared across Android surfaces.
|
||||
///
|
||||
class AndroidContext {
|
||||
public:
|
||||
AndroidContext(AndroidRenderingAPI rendering_api);
|
||||
|
||||
~AndroidContext();
|
||||
|
||||
static std::shared_ptr<AndroidContext> Create(
|
||||
AndroidRenderingAPI rendering_api);
|
||||
|
||||
AndroidRenderingAPI RenderingApi() const;
|
||||
|
||||
private:
|
||||
const AndroidRenderingAPI rendering_api_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContext);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_H_
|
||||
@ -105,62 +105,21 @@ static bool TeardownContext(EGLDisplay display, EGLContext context) {
|
||||
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.
|
||||
bool AndroidContextGL::CreateWindowSurface(
|
||||
fml::RefPtr<AndroidNativeWindow> window) {
|
||||
// The configurations are only required when dealing with extensions or VG.
|
||||
// We do neither.
|
||||
|
||||
window_ = std::move(window);
|
||||
EGLDisplay display = environment_->Display();
|
||||
|
||||
const EGLint attribs[] = {EGL_NONE};
|
||||
|
||||
surface_ = eglCreateWindowSurface(
|
||||
display, config_,
|
||||
reinterpret_cast<EGLNativeWindowType>(window_->handle()), attribs);
|
||||
return surface_ != EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
// For offscreen rendering.
|
||||
bool AndroidContextGL::CreatePBufferSurface() {
|
||||
// We only ever create pbuffer surfaces for background resource loading
|
||||
// contexts. We never bind the pbuffer to anything.
|
||||
|
||||
EGLDisplay display = environment_->Display();
|
||||
|
||||
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||
|
||||
surface_ = eglCreatePbufferSurface(display, config_, attribs);
|
||||
return surface_ != EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
AndroidContextGL::AndroidContextGL(fml::RefPtr<AndroidEnvironmentGL> env,
|
||||
const AndroidContextGL* share_context)
|
||||
: environment_(env),
|
||||
window_(nullptr),
|
||||
config_(nullptr),
|
||||
surface_(EGL_NO_SURFACE),
|
||||
context_(EGL_NO_CONTEXT),
|
||||
valid_(false) {
|
||||
AndroidContextGL::AndroidContextGL(
|
||||
AndroidRenderingAPI rendering_api,
|
||||
fml::RefPtr<AndroidEnvironmentGL> environment)
|
||||
: AndroidContext(AndroidRenderingAPI::kOpenGLES),
|
||||
environment_(environment),
|
||||
config_(nullptr) {
|
||||
if (!environment_->IsValid()) {
|
||||
FML_LOG(ERROR) << "Could not create an Android GL environment.";
|
||||
return;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Choose a valid configuration.
|
||||
|
||||
std::tie(success, config_) = ChooseEGLConfiguration(environment_->Display());
|
||||
|
||||
if (!success) {
|
||||
FML_LOG(ERROR) << "Could not choose an EGL configuration.";
|
||||
LogLastEGLError();
|
||||
@ -168,19 +127,18 @@ AndroidContextGL::AndroidContextGL(fml::RefPtr<AndroidEnvironmentGL> env,
|
||||
}
|
||||
|
||||
// Create a context for the configuration.
|
||||
|
||||
std::tie(success, context_) = CreateContext(
|
||||
environment_->Display(), config_,
|
||||
share_context != nullptr ? share_context->context_ : EGL_NO_CONTEXT);
|
||||
|
||||
std::tie(success, context_) =
|
||||
CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
|
||||
if (!success) {
|
||||
FML_LOG(ERROR) << "Could not create an EGL context";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->CreatePBufferSurface()) {
|
||||
FML_LOG(ERROR) << "Could not create the EGL surface.";
|
||||
std::tie(success, resource_context_) =
|
||||
CreateContext(environment_->Display(), config_, context_);
|
||||
if (!success) {
|
||||
FML_LOG(ERROR) << "Could not create an EGL resource context";
|
||||
LogLastEGLError();
|
||||
return;
|
||||
}
|
||||
@ -196,13 +154,34 @@ AndroidContextGL::~AndroidContextGL() {
|
||||
LogLastEGLError();
|
||||
}
|
||||
|
||||
if (!TeardownSurface(environment_->Display(), surface_)) {
|
||||
FML_LOG(ERROR)
|
||||
<< "Could not tear down the EGL surface. Possible resource leak.";
|
||||
if (!TeardownContext(environment_->Display(), resource_context_)) {
|
||||
FML_LOG(ERROR) << "Could not tear down the EGL resource context. Possible "
|
||||
"resource leak.";
|
||||
LogLastEGLError();
|
||||
}
|
||||
}
|
||||
|
||||
EGLSurface AndroidContextGL::CreateOnscreenSurface(
|
||||
fml::RefPtr<AndroidNativeWindow> window) const {
|
||||
EGLDisplay display = environment_->Display();
|
||||
|
||||
const EGLint attribs[] = {EGL_NONE};
|
||||
|
||||
return eglCreateWindowSurface(
|
||||
display, config_, reinterpret_cast<EGLNativeWindowType>(window->handle()),
|
||||
attribs);
|
||||
}
|
||||
|
||||
EGLSurface AndroidContextGL::CreateOffscreenSurface() const {
|
||||
// We only ever create pbuffer surfaces for background resource loading
|
||||
// contexts. We never bind the pbuffer to anything.
|
||||
EGLDisplay display = environment_->Display();
|
||||
|
||||
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||
|
||||
return eglCreatePbufferSurface(display, config_, attribs);
|
||||
}
|
||||
|
||||
fml::RefPtr<AndroidEnvironmentGL> AndroidContextGL::Environment() const {
|
||||
return environment_;
|
||||
}
|
||||
@ -211,8 +190,8 @@ bool AndroidContextGL::IsValid() const {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::MakeCurrent() {
|
||||
if (eglMakeCurrent(environment_->Display(), surface_, surface_, context_) !=
|
||||
bool AndroidContextGL::MakeCurrent(EGLSurface& surface) {
|
||||
if (eglMakeCurrent(environment_->Display(), surface, surface, context_) !=
|
||||
EGL_TRUE) {
|
||||
FML_LOG(ERROR) << "Could not make the context current";
|
||||
LogLastEGLError();
|
||||
@ -221,6 +200,16 @@ bool AndroidContextGL::MakeCurrent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::ResourceMakeCurrent(EGLSurface& surface) {
|
||||
if (eglMakeCurrent(environment_->Display(), surface, surface,
|
||||
resource_context_) != EGL_TRUE) {
|
||||
FML_LOG(ERROR) << "Could not make the context current";
|
||||
LogLastEGLError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::ClearCurrent() {
|
||||
if (eglGetCurrentContext() != context_) {
|
||||
return true;
|
||||
@ -234,18 +223,17 @@ bool AndroidContextGL::ClearCurrent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidContextGL::SwapBuffers() {
|
||||
bool AndroidContextGL::SwapBuffers(EGLSurface& surface) {
|
||||
TRACE_EVENT0("flutter", "AndroidContextGL::SwapBuffers");
|
||||
return eglSwapBuffers(environment_->Display(), surface_);
|
||||
return eglSwapBuffers(environment_->Display(), surface);
|
||||
}
|
||||
|
||||
SkISize AndroidContextGL::GetSize() {
|
||||
SkISize AndroidContextGL::GetSize(EGLSurface& surface) {
|
||||
EGLint width = 0;
|
||||
EGLint height = 0;
|
||||
|
||||
if (!eglQuerySurface(environment_->Display(), surface_, EGL_WIDTH, &width) ||
|
||||
!eglQuerySurface(environment_->Display(), surface_, EGL_HEIGHT,
|
||||
&height)) {
|
||||
if (!eglQuerySurface(environment_->Display(), surface, EGL_WIDTH, &width) ||
|
||||
!eglQuerySurface(environment_->Display(), surface, EGL_HEIGHT, &height)) {
|
||||
FML_LOG(ERROR) << "Unable to query EGL surface size";
|
||||
LogLastEGLError();
|
||||
return SkISize::Make(0, 0);
|
||||
@ -253,22 +241,11 @@ SkISize AndroidContextGL::GetSize() {
|
||||
return SkISize::Make(width, height);
|
||||
}
|
||||
|
||||
bool AndroidContextGL::Resize(const SkISize& size) {
|
||||
if (size == GetSize()) {
|
||||
return true;
|
||||
bool AndroidContextGL::TeardownSurface(EGLSurface& surface) {
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
return eglDestroySurface(environment_->Display(), surface) == EGL_TRUE;
|
||||
}
|
||||
|
||||
ClearCurrent();
|
||||
|
||||
TeardownSurface(environment_->Display(), surface_);
|
||||
|
||||
if (!this->CreateWindowSurface(window_)) {
|
||||
FML_LOG(ERROR) << "Unable to create EGL window surface on resize.";
|
||||
return false;
|
||||
}
|
||||
|
||||
MakeCurrent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -9,47 +9,111 @@
|
||||
#include "flutter/fml/memory/ref_counted.h"
|
||||
#include "flutter/fml/memory/ref_ptr.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/platform/android/android_context.h"
|
||||
#include "flutter/shell/platform/android/android_environment_gl.h"
|
||||
#include "flutter/shell/platform/android/android_native_window.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class AndroidContextGL : public fml::RefCountedThreadSafe<AndroidContextGL> {
|
||||
//------------------------------------------------------------------------------
|
||||
/// The Android context is used by `AndroidSurfaceGL` to create and manage
|
||||
/// EGL surfaces.
|
||||
///
|
||||
/// This context binds `EGLContext` to the current rendering thread and to the
|
||||
/// draw and read `EGLSurface`s.
|
||||
///
|
||||
class AndroidContextGL : public AndroidContext {
|
||||
public:
|
||||
bool CreateWindowSurface(fml::RefPtr<AndroidNativeWindow> window);
|
||||
|
||||
bool CreatePBufferSurface();
|
||||
|
||||
fml::RefPtr<AndroidEnvironmentGL> Environment() const;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
bool MakeCurrent();
|
||||
|
||||
bool ClearCurrent();
|
||||
|
||||
bool SwapBuffers();
|
||||
|
||||
SkISize GetSize();
|
||||
|
||||
bool Resize(const SkISize& size);
|
||||
|
||||
private:
|
||||
fml::RefPtr<AndroidEnvironmentGL> environment_;
|
||||
fml::RefPtr<AndroidNativeWindow> window_;
|
||||
EGLConfig config_;
|
||||
EGLSurface surface_;
|
||||
EGLContext context_;
|
||||
bool valid_;
|
||||
|
||||
AndroidContextGL(fml::RefPtr<AndroidEnvironmentGL> env,
|
||||
const AndroidContextGL* share_context = nullptr);
|
||||
AndroidContextGL(AndroidRenderingAPI rendering_api,
|
||||
fml::RefPtr<AndroidEnvironmentGL> environment);
|
||||
|
||||
~AndroidContextGL();
|
||||
|
||||
FML_FRIEND_MAKE_REF_COUNTED(AndroidContextGL);
|
||||
FML_FRIEND_REF_COUNTED_THREAD_SAFE(AndroidContextGL);
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Allocates an new EGL window surface that is used for on-screen
|
||||
/// pixels.
|
||||
///
|
||||
/// @attention Consumers must tear down the surface by calling
|
||||
/// `AndroidContextGL::TeardownSurface`.
|
||||
///
|
||||
/// @return The window surface.
|
||||
///
|
||||
EGLSurface CreateOnscreenSurface(
|
||||
fml::RefPtr<AndroidNativeWindow> window) const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Allocates an 1x1 pbuffer surface that is used for making the
|
||||
/// offscreen current for texture uploads.
|
||||
///
|
||||
/// @attention Consumers must tear down the surface by calling
|
||||
/// `AndroidContextGL::TeardownSurface`.
|
||||
///
|
||||
/// @return The pbuffer surface.
|
||||
///
|
||||
EGLSurface CreateOffscreenSurface() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @return The Android environment that contains a reference to the
|
||||
/// display.
|
||||
///
|
||||
fml::RefPtr<AndroidEnvironmentGL> Environment() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @return Whether the current context is valid. That is, if the EGL
|
||||
/// contexts
|
||||
/// were successfully created.
|
||||
///
|
||||
bool IsValid() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @return Whether the current context was successfully clear.
|
||||
///
|
||||
bool ClearCurrent();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Binds the EGLContext context to the current rendering thread
|
||||
/// and to the draw and read surface.
|
||||
///
|
||||
/// @return Whether the surface was made current.
|
||||
///
|
||||
bool MakeCurrent(EGLSurface& surface);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Binds the resource EGLContext context to the current rendering
|
||||
/// thread and to the draw and read surface.
|
||||
///
|
||||
/// @return Whether the surface was made current.
|
||||
///
|
||||
bool ResourceMakeCurrent(EGLSurface& surface);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief This only applies to on-screen surfaces such as those created
|
||||
/// by `AndroidContextGL::CreateOnscreenSurface`.
|
||||
///
|
||||
/// @return Whether the EGL surface color buffer was swapped.
|
||||
///
|
||||
bool SwapBuffers(EGLSurface& surface);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @return The size of an `EGLSurface`.
|
||||
///
|
||||
SkISize GetSize(EGLSurface& surface);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Destroys an `EGLSurface`.
|
||||
///
|
||||
/// @return Whether the surface was destroyed.
|
||||
///
|
||||
bool TeardownSurface(EGLSurface& surface);
|
||||
|
||||
private:
|
||||
fml::RefPtr<AndroidEnvironmentGL> environment_;
|
||||
EGLConfig config_;
|
||||
EGLContext context_;
|
||||
EGLContext resource_context_;
|
||||
bool valid_ = false;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextGL);
|
||||
};
|
||||
|
||||
|
||||
@ -15,19 +15,24 @@
|
||||
namespace flutter {
|
||||
|
||||
std::unique_ptr<AndroidSurface> AndroidSurface::Create(
|
||||
bool use_software_rendering) {
|
||||
if (use_software_rendering) {
|
||||
auto software_surface = std::make_unique<AndroidSurfaceSoftware>();
|
||||
return software_surface->IsValid() ? std::move(software_surface) : nullptr;
|
||||
}
|
||||
std::shared_ptr<AndroidContext> android_context) {
|
||||
std::unique_ptr<AndroidSurface> surface;
|
||||
switch (android_context->RenderingApi()) {
|
||||
case AndroidRenderingAPI::kSoftware:
|
||||
surface = std::make_unique<AndroidSurfaceSoftware>();
|
||||
break;
|
||||
case AndroidRenderingAPI::kOpenGLES:
|
||||
surface = std::make_unique<AndroidSurfaceGL>(android_context);
|
||||
break;
|
||||
case AndroidRenderingAPI::kVulkan:
|
||||
#if SHELL_ENABLE_VULKAN
|
||||
auto vulkan_surface = std::make_unique<AndroidSurfaceVulkan>();
|
||||
return vulkan_surface->IsValid() ? std::move(vulkan_surface) : nullptr;
|
||||
#else // SHELL_ENABLE_VULKAN
|
||||
auto gl_surface = std::make_unique<AndroidSurfaceGL>();
|
||||
return gl_surface->IsOffscreenContextValid() ? std::move(gl_surface)
|
||||
: nullptr;
|
||||
surface = std::make_unique<AndroidSurfaceVulkan>();
|
||||
#endif // SHELL_ENABLE_VULKAN
|
||||
break;
|
||||
}
|
||||
FML_CHECK(surface);
|
||||
return surface->IsValid() ? std::move(surface) : nullptr;
|
||||
;
|
||||
}
|
||||
|
||||
AndroidSurface::~AndroidSurface() = default;
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "flutter/fml/platform/android/jni_weak_ref.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
#include "flutter/shell/common/surface.h"
|
||||
#include "flutter/shell/platform/android/android_context.h"
|
||||
#include "flutter/shell/platform/android/android_native_window.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
@ -19,7 +20,8 @@ namespace flutter {
|
||||
|
||||
class AndroidSurface {
|
||||
public:
|
||||
static std::unique_ptr<AndroidSurface> Create(bool use_software_rendering);
|
||||
static std::unique_ptr<AndroidSurface> Create(
|
||||
std::shared_ptr<AndroidContext> android_context);
|
||||
|
||||
virtual ~AndroidSurface();
|
||||
|
||||
@ -27,9 +29,10 @@ class AndroidSurface {
|
||||
|
||||
virtual void TeardownOnScreenContext() = 0;
|
||||
|
||||
virtual std::unique_ptr<Surface> CreateGPUSurface() = 0;
|
||||
virtual std::unique_ptr<Surface> CreateGPUSurface(
|
||||
GrContext* gr_context = nullptr) = 0;
|
||||
|
||||
virtual bool OnScreenSurfaceResize(const SkISize& size) const = 0;
|
||||
virtual bool OnScreenSurfaceResize(const SkISize& size) = 0;
|
||||
|
||||
virtual bool ResourceContextMakeCurrent() = 0;
|
||||
|
||||
|
||||
@ -11,120 +11,113 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
static fml::RefPtr<AndroidContextGL> CreateResourceLoadingContext() {
|
||||
auto environment = fml::MakeRefCounted<AndroidEnvironmentGL>();
|
||||
if (!environment->IsValid()) {
|
||||
return nullptr;
|
||||
AndroidSurfaceGL::AndroidSurfaceGL(
|
||||
std::shared_ptr<AndroidContext> android_context)
|
||||
: native_window_(nullptr),
|
||||
onscreen_surface_(nullptr),
|
||||
offscreen_surface_(nullptr) {
|
||||
android_context_ =
|
||||
std::static_pointer_cast<AndroidContextGL>(android_context);
|
||||
// Acquire the offscreen surface.
|
||||
offscreen_surface_ = android_context_->CreateOffscreenSurface();
|
||||
if (offscreen_surface_ == EGL_NO_SURFACE) {
|
||||
offscreen_surface_ = nullptr;
|
||||
}
|
||||
|
||||
auto context = fml::MakeRefCounted<AndroidContextGL>(environment);
|
||||
if (!context->IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
AndroidSurfaceGL::AndroidSurfaceGL() {
|
||||
// Acquire the offscreen context.
|
||||
offscreen_context_ = CreateResourceLoadingContext();
|
||||
|
||||
if (!offscreen_context_ || !offscreen_context_->IsValid()) {
|
||||
offscreen_context_ = nullptr;
|
||||
}
|
||||
|
||||
external_view_embedder_ = std::make_unique<AndroidExternalViewEmbedder>();
|
||||
}
|
||||
|
||||
AndroidSurfaceGL::~AndroidSurfaceGL() = default;
|
||||
|
||||
bool AndroidSurfaceGL::IsOffscreenContextValid() const {
|
||||
return offscreen_context_ && offscreen_context_->IsValid();
|
||||
AndroidSurfaceGL::~AndroidSurfaceGL() {
|
||||
if (offscreen_surface_) {
|
||||
android_context_->TeardownSurface(offscreen_surface_);
|
||||
offscreen_surface_ = nullptr;
|
||||
}
|
||||
if (onscreen_surface_) {
|
||||
android_context_->TeardownSurface(onscreen_surface_);
|
||||
onscreen_surface_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidSurfaceGL::TeardownOnScreenContext() {
|
||||
if (onscreen_context_) {
|
||||
onscreen_context_->ClearCurrent();
|
||||
}
|
||||
onscreen_context_ = nullptr;
|
||||
android_context_->ClearCurrent();
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::IsValid() const {
|
||||
if (!onscreen_context_ || !offscreen_context_) {
|
||||
return false;
|
||||
return offscreen_surface_ && android_context_->IsValid();
|
||||
}
|
||||
|
||||
std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface(
|
||||
GrContext* gr_context) {
|
||||
if (gr_context) {
|
||||
return std::make_unique<GPUSurfaceGL>(sk_ref_sp(gr_context), this, true);
|
||||
}
|
||||
return std::make_unique<GPUSurfaceGL>(this, true);
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) {
|
||||
FML_DCHECK(IsValid());
|
||||
FML_DCHECK(onscreen_surface_);
|
||||
FML_DCHECK(native_window_);
|
||||
|
||||
if (size == android_context_->GetSize(onscreen_surface_)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return onscreen_context_->IsValid() && offscreen_context_->IsValid();
|
||||
}
|
||||
android_context_->ClearCurrent();
|
||||
android_context_->TeardownSurface(onscreen_surface_);
|
||||
|
||||
std::unique_ptr<Surface> AndroidSurfaceGL::CreateGPUSurface() {
|
||||
auto surface = std::make_unique<GPUSurfaceGL>(this, true);
|
||||
return surface->IsValid() ? std::move(surface) : nullptr;
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::OnScreenSurfaceResize(const SkISize& size) const {
|
||||
FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
|
||||
return onscreen_context_->Resize(size);
|
||||
onscreen_surface_ = android_context_->CreateOnscreenSurface(native_window_);
|
||||
if (!onscreen_surface_ || onscreen_surface_ == EGL_NO_SURFACE) {
|
||||
FML_LOG(ERROR) << "Unable to create EGL window surface on resize.";
|
||||
return false;
|
||||
}
|
||||
android_context_->MakeCurrent(onscreen_surface_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::ResourceContextMakeCurrent() {
|
||||
FML_DCHECK(offscreen_context_ && offscreen_context_->IsValid());
|
||||
return offscreen_context_->MakeCurrent();
|
||||
FML_DCHECK(IsValid());
|
||||
return android_context_->ResourceMakeCurrent(offscreen_surface_);
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::ResourceContextClearCurrent() {
|
||||
FML_DCHECK(offscreen_context_ && offscreen_context_->IsValid());
|
||||
return offscreen_context_->ClearCurrent();
|
||||
FML_DCHECK(IsValid());
|
||||
return android_context_->ClearCurrent();
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::SetNativeWindow(
|
||||
fml::RefPtr<AndroidNativeWindow> window) {
|
||||
// In any case, we want to get rid of our current onscreen context.
|
||||
onscreen_context_ = nullptr;
|
||||
|
||||
// If the offscreen context has not been setup, we dont have the sharegroup.
|
||||
// So bail.
|
||||
if (!offscreen_context_ || !offscreen_context_->IsValid()) {
|
||||
FML_DCHECK(IsValid());
|
||||
FML_DCHECK(window);
|
||||
native_window_ = window;
|
||||
// Create the onscreen surface.
|
||||
onscreen_surface_ = android_context_->CreateOnscreenSurface(window);
|
||||
if (onscreen_surface_ == EGL_NO_SURFACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the onscreen context.
|
||||
onscreen_context_ = fml::MakeRefCounted<AndroidContextGL>(
|
||||
offscreen_context_->Environment(),
|
||||
offscreen_context_.get() /* sharegroup */);
|
||||
|
||||
if (!onscreen_context_->IsValid()) {
|
||||
onscreen_context_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!onscreen_context_->CreateWindowSurface(std::move(window))) {
|
||||
onscreen_context_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<GLContextResult> AndroidSurfaceGL::GLContextMakeCurrent() {
|
||||
FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
|
||||
FML_DCHECK(IsValid());
|
||||
FML_DCHECK(onscreen_surface_);
|
||||
auto default_context_result = std::make_unique<GLContextDefaultResult>(
|
||||
onscreen_context_->MakeCurrent());
|
||||
android_context_->MakeCurrent(onscreen_surface_));
|
||||
return std::move(default_context_result);
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::GLContextClearCurrent() {
|
||||
FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
|
||||
return onscreen_context_->ClearCurrent();
|
||||
FML_DCHECK(IsValid());
|
||||
return android_context_->ClearCurrent();
|
||||
}
|
||||
|
||||
bool AndroidSurfaceGL::GLContextPresent() {
|
||||
FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
|
||||
return onscreen_context_->SwapBuffers();
|
||||
FML_DCHECK(IsValid());
|
||||
FML_DCHECK(onscreen_surface_);
|
||||
return android_context_->SwapBuffers(onscreen_surface_);
|
||||
}
|
||||
|
||||
intptr_t AndroidSurfaceGL::GLContextFBO() const {
|
||||
FML_DCHECK(onscreen_context_ && onscreen_context_->IsValid());
|
||||
FML_DCHECK(IsValid());
|
||||
// The default window bound framebuffer on Android.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -20,23 +20,21 @@ namespace flutter {
|
||||
class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
|
||||
public AndroidSurface {
|
||||
public:
|
||||
AndroidSurfaceGL();
|
||||
AndroidSurfaceGL(std::shared_ptr<AndroidContext> android_context);
|
||||
|
||||
~AndroidSurfaceGL() override;
|
||||
|
||||
bool IsOffscreenContextValid() const;
|
||||
|
||||
// |AndroidSurface|
|
||||
bool IsValid() const override;
|
||||
|
||||
// |AndroidSurface|
|
||||
std::unique_ptr<Surface> CreateGPUSurface() override;
|
||||
std::unique_ptr<Surface> CreateGPUSurface(GrContext* gr_context) override;
|
||||
|
||||
// |AndroidSurface|
|
||||
void TeardownOnScreenContext() override;
|
||||
|
||||
// |AndroidSurface|
|
||||
bool OnScreenSurfaceResize(const SkISize& size) const override;
|
||||
bool OnScreenSurfaceResize(const SkISize& size) override;
|
||||
|
||||
// |AndroidSurface|
|
||||
bool ResourceContextMakeCurrent() override;
|
||||
@ -63,9 +61,11 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
|
||||
ExternalViewEmbedder* GetExternalViewEmbedder() override;
|
||||
|
||||
private:
|
||||
fml::RefPtr<AndroidContextGL> onscreen_context_;
|
||||
fml::RefPtr<AndroidContextGL> offscreen_context_;
|
||||
fml::RefPtr<AndroidNativeWindow> native_window_;
|
||||
std::unique_ptr<AndroidExternalViewEmbedder> external_view_embedder_;
|
||||
std::shared_ptr<AndroidContextGL> android_context_;
|
||||
EGLSurface onscreen_surface_;
|
||||
EGLSurface offscreen_surface_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGL);
|
||||
};
|
||||
|
||||
@ -57,7 +57,8 @@ bool AndroidSurfaceSoftware::ResourceContextClearCurrent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<Surface> AndroidSurfaceSoftware::CreateGPUSurface() {
|
||||
std::unique_ptr<Surface> AndroidSurfaceSoftware::CreateGPUSurface(
|
||||
GrContext* gr_context) {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -143,7 +144,7 @@ ExternalViewEmbedder* AndroidSurfaceSoftware::GetExternalViewEmbedder() {
|
||||
|
||||
void AndroidSurfaceSoftware::TeardownOnScreenContext() {}
|
||||
|
||||
bool AndroidSurfaceSoftware::OnScreenSurfaceResize(const SkISize& size) const {
|
||||
bool AndroidSurfaceSoftware::OnScreenSurfaceResize(const SkISize& size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -31,13 +31,13 @@ class AndroidSurfaceSoftware final : public AndroidSurface,
|
||||
bool ResourceContextClearCurrent() override;
|
||||
|
||||
// |AndroidSurface|
|
||||
std::unique_ptr<Surface> CreateGPUSurface() override;
|
||||
std::unique_ptr<Surface> CreateGPUSurface(GrContext* gr_context) override;
|
||||
|
||||
// |AndroidSurface|
|
||||
void TeardownOnScreenContext() override;
|
||||
|
||||
// |AndroidSurface|
|
||||
bool OnScreenSurfaceResize(const SkISize& size) const override;
|
||||
bool OnScreenSurfaceResize(const SkISize& size) override;
|
||||
|
||||
// |AndroidSurface|
|
||||
bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) override;
|
||||
|
||||
@ -27,7 +27,8 @@ void AndroidSurfaceVulkan::TeardownOnScreenContext() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
std::unique_ptr<Surface> AndroidSurfaceVulkan::CreateGPUSurface() {
|
||||
std::unique_ptr<Surface> AndroidSurfaceVulkan::CreateGPUSurface(
|
||||
GrContext* gr_context) {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -54,7 +55,7 @@ std::unique_ptr<Surface> AndroidSurfaceVulkan::CreateGPUSurface() {
|
||||
return gpu_surface;
|
||||
}
|
||||
|
||||
bool AndroidSurfaceVulkan::OnScreenSurfaceResize(const SkISize& size) const {
|
||||
bool AndroidSurfaceVulkan::OnScreenSurfaceResize(const SkISize& size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -27,13 +27,13 @@ class AndroidSurfaceVulkan : public AndroidSurface,
|
||||
bool IsValid() const override;
|
||||
|
||||
// |AndroidSurface|
|
||||
std::unique_ptr<Surface> CreateGPUSurface() override;
|
||||
std::unique_ptr<Surface> CreateGPUSurface(GrContext* gr_context) override;
|
||||
|
||||
// |AndroidSurface|
|
||||
void TeardownOnScreenContext() override;
|
||||
|
||||
// |AndroidSurface|
|
||||
bool OnScreenSurfaceResize(const SkISize& size) const override;
|
||||
bool OnScreenSurfaceResize(const SkISize& size) override;
|
||||
|
||||
// |AndroidSurface|
|
||||
bool ResourceContextMakeCurrent() override;
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "flutter/fml/synchronization/waitable_event.h"
|
||||
#include "flutter/shell/common/shell_io_manager.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
|
||||
#include "flutter/shell/platform/android/android_context.h"
|
||||
#include "flutter/shell/platform/android/android_external_texture_gl.h"
|
||||
#include "flutter/shell/platform/android/android_surface_gl.h"
|
||||
#include "flutter/shell/platform/android/platform_message_response_android.h"
|
||||
@ -24,8 +25,18 @@ PlatformViewAndroid::PlatformViewAndroid(
|
||||
fml::jni::JavaObjectWeakGlobalRef java_object,
|
||||
bool use_software_rendering)
|
||||
: PlatformView(delegate, std::move(task_runners)),
|
||||
java_object_(java_object),
|
||||
android_surface_(AndroidSurface::Create(use_software_rendering)) {
|
||||
java_object_(java_object) {
|
||||
std::shared_ptr<AndroidContext> android_context;
|
||||
if (use_software_rendering) {
|
||||
android_context = AndroidContext::Create(AndroidRenderingAPI::kSoftware);
|
||||
} else {
|
||||
#if SHELL_ENABLE_VULKAN
|
||||
android_context = AndroidContext::Create(AndroidRenderingAPI::kVulkan);
|
||||
#else // SHELL_ENABLE_VULKAN
|
||||
android_context = AndroidContext::Create(AndroidRenderingAPI::kOpenGLES);
|
||||
#endif // SHELL_ENABLE_VULKAN
|
||||
}
|
||||
android_surface_ = AndroidSurface::Create(android_context);
|
||||
FML_CHECK(android_surface_)
|
||||
<< "Could not create an OpenGL, Vulkan or Software surface to setup "
|
||||
"rendering.";
|
||||
|
||||
@ -75,7 +75,8 @@ class PlatformViewAndroid final : public PlatformView {
|
||||
|
||||
private:
|
||||
const fml::jni::JavaObjectWeakGlobalRef java_object_;
|
||||
const std::unique_ptr<AndroidSurface> android_surface_;
|
||||
|
||||
std::unique_ptr<AndroidSurface> android_surface_;
|
||||
// We use id 0 to mean that no response is expected.
|
||||
int next_response_id_ = 1;
|
||||
std::unordered_map<int, fml::RefPtr<flutter::PlatformMessageResponse>>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user