diff --git a/engine/src/flutter/impeller/base/comparable.h b/engine/src/flutter/impeller/base/comparable.h index 0e6b0e8c18..5c059c2630 100644 --- a/engine/src/flutter/impeller/base/comparable.h +++ b/engine/src/flutter/impeller/base/comparable.h @@ -103,4 +103,12 @@ struct hash { } }; +template <> +struct less { + constexpr bool operator()(const impeller::UniqueID& lhs, + const impeller::UniqueID& rhs) const { + return lhs.id < rhs.id; + } +}; + } // namespace std diff --git a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc index 020b87cdd4..7f3cb49063 100644 --- a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc +++ b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc @@ -16,6 +16,33 @@ namespace impeller { +class PlaygroundImplGLES::ReactorWorker final : public ReactorGLES::Worker { + public: + ReactorWorker() = default; + + // |ReactorGLES::Worker| + bool CanReactorReactOnCurrentThreadNow( + const ReactorGLES& reactor) const override { + ReaderLock lock(mutex_); + auto found = reactions_allowed_.find(std::this_thread::get_id()); + if (found == reactions_allowed_.end()) { + return false; + } + return found->second; + } + + void SetReactionsAllowedOnCurrentThread(bool allowed) { + WriterLock lock(mutex_); + reactions_allowed_[std::this_thread::get_id()] = allowed; + } + + private: + mutable RWMutex mutex_; + std::map reactions_allowed_ IPLR_GUARDED_BY(mutex_); + + FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); +}; + void PlaygroundImplGLES::DestroyWindowHandle(WindowHandle handle) { if (!handle) { return; @@ -24,7 +51,8 @@ void PlaygroundImplGLES::DestroyWindowHandle(WindowHandle handle) { } PlaygroundImplGLES::PlaygroundImplGLES() - : handle_(nullptr, &DestroyWindowHandle) { + : handle_(nullptr, &DestroyWindowHandle), + worker_(std::shared_ptr(new ReactorWorker())) { ::glfwDefaultWindowHints(); #if FML_OS_MACOSX @@ -48,6 +76,7 @@ PlaygroundImplGLES::PlaygroundImplGLES() auto window = ::glfwCreateWindow(1, 1, "Test", nullptr, nullptr); ::glfwMakeContextCurrent(window); + worker_->SetReactionsAllowedOnCurrentThread(true); handle_.reset(window); } @@ -79,8 +108,19 @@ std::shared_ptr PlaygroundImplGLES::GetContext() const { return nullptr; } - return ContextGLES::Create(std::move(gl), - ShaderLibraryMappingsForPlayground()); + auto context = + ContextGLES::Create(std::move(gl), ShaderLibraryMappingsForPlayground()); + if (!context) { + FML_LOG(ERROR) << "Could not create context."; + return nullptr; + } + + auto worker_id = context->AddReactorWorker(worker_); + if (!worker_id.has_value()) { + FML_LOG(ERROR) << "Could not add reactor worker."; + return nullptr; + } + return context; } // |PlaygroundImpl| diff --git a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h index 881fe61967..99f0c300b0 100644 --- a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h +++ b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h @@ -16,9 +16,12 @@ class PlaygroundImplGLES final : public PlaygroundImpl { ~PlaygroundImplGLES(); private: + class ReactorWorker; + static void DestroyWindowHandle(WindowHandle handle); using UniqueHandle = std::unique_ptr; UniqueHandle handle_; + std::shared_ptr worker_; // |PlaygroundImpl| std::shared_ptr GetContext() const override; diff --git a/engine/src/flutter/impeller/renderer/backend/gles/context_gles.cc b/engine/src/flutter/impeller/renderer/backend/gles/context_gles.cc index 7b57ddb18a..6306ab886e 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/context_gles.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/context_gles.cc @@ -9,10 +9,10 @@ namespace impeller { -std::shared_ptr ContextGLES::Create( +std::shared_ptr ContextGLES::Create( std::unique_ptr gl, std::vector> shader_libraries) { - return std::shared_ptr( + return std::shared_ptr( new ContextGLES(std::move(gl), std::move(shader_libraries))); } @@ -70,10 +70,25 @@ ContextGLES::ContextGLES( ContextGLES::~ContextGLES() = default; -const ReactorGLES::Ref ContextGLES::GetReactor() const { +const ReactorGLES::Ref& ContextGLES::GetReactor() const { return reactor_; } +std::optional ContextGLES::AddReactorWorker( + std::shared_ptr worker) { + if (!IsValid()) { + return std::nullopt; + } + return reactor_->AddWorker(std::move(worker)); +} + +bool ContextGLES::RemoveReactorWorker(ReactorGLES::WorkerID id) { + if (!IsValid()) { + return false; + } + return reactor_->RemoveWorker(id); +} + bool ContextGLES::IsValid() const { return is_valid_; } diff --git a/engine/src/flutter/impeller/renderer/backend/gles/context_gles.h b/engine/src/flutter/impeller/renderer/backend/gles/context_gles.h index 43287f9c7c..fbf0d72853 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/context_gles.h +++ b/engine/src/flutter/impeller/renderer/backend/gles/context_gles.h @@ -19,14 +19,19 @@ namespace impeller { class ContextGLES final : public Context, public BackendCast { public: - static std::shared_ptr Create( + static std::shared_ptr Create( std::unique_ptr gl, std::vector> shader_libraries); // |Context| ~ContextGLES() override; - const ReactorGLES::Ref GetReactor() const; + const ReactorGLES::Ref& GetReactor() const; + + std::optional AddReactorWorker( + std::shared_ptr worker); + + bool RemoveReactorWorker(ReactorGLES::WorkerID id); private: ReactorGLES::Ref reactor_; diff --git a/engine/src/flutter/impeller/renderer/backend/gles/proc_table_gles.h b/engine/src/flutter/impeller/renderer/backend/gles/proc_table_gles.h index 08dd16e049..84dfb9c2cc 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/proc_table_gles.h +++ b/engine/src/flutter/impeller/renderer/backend/gles/proc_table_gles.h @@ -27,9 +27,11 @@ struct AutoErrorCheck { ~AutoErrorCheck() { if (error_fn) { auto error = error_fn(); - FML_CHECK(error == GL_NO_ERROR) - << "GL Error " << GLErrorToString(error) << "(" << error << ")" - << " encountered on call to " << name; + if (error != GL_NO_ERROR) { + FML_LOG(ERROR) << "GL Error " << GLErrorToString(error) << "(" << error + << ")" + << " encountered on call to " << name; + } } } }; diff --git a/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc b/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc index d68a723800..165a895650 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc @@ -27,7 +27,20 @@ bool ReactorGLES::IsValid() const { return is_valid_; } +ReactorGLES::WorkerID ReactorGLES::AddWorker(std::weak_ptr worker) { + Lock lock(workers_mutex_); + auto id = WorkerID{}; + workers_[id] = std::move(worker); + return id; +} + +bool ReactorGLES::RemoveWorker(WorkerID worker) { + Lock lock(workers_mutex_); + return workers_.erase(worker) == 1; +} + bool ReactorGLES::HasPendingOperations() const { + Lock ops_lock(ops_mutex_); return !pending_operations_.empty() || !gl_handles_to_collect_.empty(); } @@ -37,6 +50,7 @@ const ProcTableGLES& ReactorGLES::GetProcTable() const { } std::optional ReactorGLES::GetGLHandle(const HandleGLES& handle) const { + ReaderLock handles_lock(handles_mutex_); auto found = live_gl_handles_.find(handle); if (found != live_gl_handles_.end()) { return found->second; @@ -48,8 +62,13 @@ bool ReactorGLES::AddOperation(Operation operation) { if (!operation) { return false; } - pending_operations_.emplace_back(std::move(operation)); - return React(); + { + Lock ops_lock(ops_mutex_); + pending_operations_.emplace_back(std::move(operation)); + } + // Attempt a reaction if able but it is not an error if this isn't possible. + [[maybe_unused]] auto result = React(); + return true; } static std::optional CreateGLHandle(const ProcTableGLES& gl, @@ -109,17 +128,20 @@ HandleGLES ReactorGLES::CreateHandle(HandleType type) { if (new_handle.IsDead()) { return HandleGLES::DeadHandle(); } + WriterLock handles_lock(handles_mutex_); live_gl_handles_[new_handle] = in_reaction_ ? CreateGLHandle(GetProcTable(), type) : std::nullopt; return new_handle; } void ReactorGLES::CollectHandle(HandleGLES handle) { + WriterLock handles_lock(handles_mutex_); auto live_handle = live_gl_handles_.find(handle); if (live_handle == live_gl_handles_.end()) { return; } if (live_handle->second.has_value()) { + Lock ops_lock(ops_mutex_); gl_handles_to_collect_[live_handle->first] = live_handle->second.value(); } live_gl_handles_.erase(live_handle); @@ -127,6 +149,9 @@ void ReactorGLES::CollectHandle(HandleGLES handle) { bool ReactorGLES::React() { TRACE_EVENT0("impeller", "ReactorGLES::React"); + if (!CanReactOnCurrentThread()) { + return false; + } in_reaction_ = true; fml::ScopedCleanupClosure reset_in_reaction([&]() { in_reaction_ = false; }); while (HasPendingOperations()) { @@ -165,7 +190,13 @@ bool ReactorGLES::ReactOnce() { //---------------------------------------------------------------------------- /// Collect all the handles for whom there is a GL handle sibling. /// - for (const auto& handle_to_collect : gl_handles_to_collect_) { + decltype(gl_handles_to_collect_) gl_handles_to_collect; + { + Lock ops_lock(ops_mutex_); + std::swap(gl_handles_to_collect_, gl_handles_to_collect); + FML_DCHECK(gl_handles_to_collect_.empty()); + } + for (const auto& handle_to_collect : gl_handles_to_collect) { if (!CollectGLHandle(gl, // proc table handle_to_collect.first.type, // handle type handle_to_collect.second // GL handle name @@ -174,26 +205,52 @@ bool ReactorGLES::ReactOnce() { return false; } } - gl_handles_to_collect_.clear(); //---------------------------------------------------------------------------- /// Make sure all pending handles have a GL handle sibling. /// - for (auto& live_handle : live_gl_handles_) { - if (live_handle.second.has_value()) { - // Already a realized GL handle. - continue; + { + WriterLock handles_lock(handles_mutex_); + for (auto& live_handle : live_gl_handles_) { + if (live_handle.second.has_value()) { + // Already a realized GL handle. + continue; + } + auto gl_handle = CreateGLHandle(gl, live_handle.first.type); + if (!gl_handle.has_value()) { + VALIDATION_LOG << "Could not create GL handle."; + return false; + } + live_handle.second = gl_handle; } - auto gl_handle = CreateGLHandle(gl, live_handle.first.type); - if (!gl_handle.has_value()) { - VALIDATION_LOG << "Could not create GL handle."; - return false; - } - live_handle.second = gl_handle; } - if (can_set_debug_labels_) { - for (const auto& label : pending_debug_labels_) { + //---------------------------------------------------------------------------- + /// Flush all pending operations in order. + /// + decltype(pending_operations_) pending_operations; + { + Lock ops_lock(ops_mutex_); + std::swap(pending_operations_, pending_operations); + FML_DCHECK(pending_operations_.empty()); + } + for (const auto& operation : pending_operations) { + TRACE_EVENT0("impeller", "ReactorGLES::Operation"); + operation(*this); + } + + //---------------------------------------------------------------------------- + /// Make sure all pending debug labels have been flushed. + /// + decltype(pending_debug_labels_) pending_debug_labels; + { + WriterLock handles_lock(handles_mutex_); + std::swap(pending_debug_labels_, pending_debug_labels); + FML_DCHECK(pending_debug_labels_.empty()); + } + if (!pending_debug_labels.empty()) { + ReaderLock handles_lock(handles_mutex_); + for (const auto& label : pending_debug_labels) { auto live_handle = live_gl_handles_.find(label.first); if (live_handle == live_gl_handles_.end() || !live_handle->second.has_value()) { @@ -205,16 +262,6 @@ bool ReactorGLES::ReactOnce() { ); } } - pending_debug_labels_.clear(); - - //---------------------------------------------------------------------------- - /// Flush all pending operations in order. - /// - auto operations = std::move(pending_operations_); - for (const auto& operation : operations) { - operation(*this); - } - pending_operations_.clear(); return true; } @@ -229,18 +276,27 @@ void ReactorGLES::SetDebugLabel(const HandleGLES& handle, std::string label) { if (handle.IsDead()) { return; } - if (in_reaction_) { - if (auto found = live_gl_handles_.find(handle); - found != live_gl_handles_.end() && found->second.has_value()) { - GetProcTable().SetDebugLabel( - ToDebugResourceType(found->first.type), // type - found->second.value(), // name - label // label - ); - return; - } - } + WriterLock handles_lock(handles_mutex_); pending_debug_labels_[handle] = std::move(label); } +bool ReactorGLES::CanReactOnCurrentThread() const { + std::vector dead_workers; + Lock lock(workers_mutex_); + for (const auto& worker : workers_) { + auto worker_ptr = worker.second.lock(); + if (!worker_ptr) { + dead_workers.push_back(worker.first); + continue; + } + if (worker_ptr->CanReactorReactOnCurrentThreadNow(*this)) { + return true; + } + } + for (const auto& worker_id : dead_workers) { + workers_.erase(worker_id); + } + return false; +} + } // namespace impeller diff --git a/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.h b/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.h index 4306f697be..01a379b77f 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.h +++ b/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.h @@ -10,6 +10,7 @@ #include "flutter/fml/closure.h" #include "flutter/fml/macros.h" +#include "impeller/base/thread.h" #include "impeller/renderer/backend/gles/handle_gles.h" #include "impeller/renderer/backend/gles/proc_table_gles.h" @@ -17,6 +18,16 @@ namespace impeller { class ReactorGLES { public: + using WorkerID = UniqueID; + + class Worker { + public: + virtual ~Worker() = default; + + virtual bool CanReactorReactOnCurrentThreadNow( + const ReactorGLES& reactor) const = 0; + }; + using Ref = std::shared_ptr; ReactorGLES(std::unique_ptr gl); @@ -25,7 +36,9 @@ class ReactorGLES { bool IsValid() const; - bool HasPendingOperations() const; + WorkerID AddWorker(std::weak_ptr worker); + + bool RemoveWorker(WorkerID); const ProcTableGLES& GetProcTable() const; @@ -44,10 +57,22 @@ class ReactorGLES { private: std::unique_ptr proc_table_; - std::vector pending_operations_; - GLESHandleMap> live_gl_handles_; - GLESHandleMap gl_handles_to_collect_; - GLESHandleMap pending_debug_labels_; + + mutable Mutex ops_mutex_; + std::vector pending_operations_ IPLR_GUARDED_BY(ops_mutex_); + GLESHandleMap gl_handles_to_collect_ IPLR_GUARDED_BY(ops_mutex_); + + mutable RWMutex handles_mutex_; + GLESHandleMap> live_gl_handles_ + IPLR_GUARDED_BY(handles_mutex_); + GLESHandleMap pending_debug_labels_ + IPLR_GUARDED_BY(handles_mutex_); + + mutable Mutex workers_mutex_; + mutable std::map> workers_ + IPLR_GUARDED_BY(workers_mutex_); + + // TODO(csg): Make this thread safe. bool in_reaction_ = false; bool can_set_debug_labels_ = false; @@ -55,6 +80,10 @@ class ReactorGLES { bool ReactOnce(); + bool HasPendingOperations() const; + + bool CanReactOnCurrentThread() const; + FML_DISALLOW_COPY_AND_ASSIGN(ReactorGLES); }; diff --git a/engine/src/flutter/impeller/toolkit/egl/BUILD.gn b/engine/src/flutter/impeller/toolkit/egl/BUILD.gn index 6393adb148..ec34bfead9 100644 --- a/engine/src/flutter/impeller/toolkit/egl/BUILD.gn +++ b/engine/src/flutter/impeller/toolkit/egl/BUILD.gn @@ -18,7 +18,10 @@ impeller_component("egl") { "surface.h", ] - deps = [ "//flutter/fml" ] + deps = [ + "../../base", + "//flutter/fml", + ] libs = [] if (is_android) { diff --git a/engine/src/flutter/impeller/toolkit/egl/context.cc b/engine/src/flutter/impeller/toolkit/egl/context.cc index ed9c224139..c89971c7fb 100644 --- a/engine/src/flutter/impeller/toolkit/egl/context.cc +++ b/engine/src/flutter/impeller/toolkit/egl/context.cc @@ -54,10 +54,12 @@ bool Context::MakeCurrent(const Surface& surface) const { if (!result) { IMPELLER_LOG_EGL_ERROR; } + DispatchLifecyleEvent(LifecycleEvent::kDidMakeCurrent); return result; } bool Context::ClearCurrent() const { + DispatchLifecyleEvent(LifecycleEvent::kWillClearCurrent); const auto result = EGLMakeCurrentIfNecessary(display_, // EGL_NO_SURFACE, // EGL_NO_SURFACE, // @@ -69,5 +71,33 @@ bool Context::ClearCurrent() const { return result; } +std::optional Context::AddLifecycleListener( + LifecycleListener listener) { + if (!listener) { + return std::nullopt; + } + WriterLock lock(listeners_mutex_); + UniqueID id; + listeners_[id] = listener; + return id; +} + +bool Context::RemoveLifecycleListener(UniqueID id) { + WriterLock lock(listeners_mutex_); + auto found = listeners_.find(id); + if (found == listeners_.end()) { + return false; + } + listeners_.erase(found); + return true; +} + +void Context::DispatchLifecyleEvent(LifecycleEvent event) const { + ReaderLock lock(listeners_mutex_); + for (const auto& listener : listeners_) { + listener.second(event); + } +} + } // namespace egl } // namespace impeller diff --git a/engine/src/flutter/impeller/toolkit/egl/context.h b/engine/src/flutter/impeller/toolkit/egl/context.h index e5666c3289..19d4a25181 100644 --- a/engine/src/flutter/impeller/toolkit/egl/context.h +++ b/engine/src/flutter/impeller/toolkit/egl/context.h @@ -4,7 +4,11 @@ #pragma once +#include + #include "flutter/fml/macros.h" +#include "impeller/base/comparable.h" +#include "impeller/base/thread.h" #include "impeller/toolkit/egl/egl.h" namespace impeller { @@ -26,9 +30,23 @@ class Context { bool ClearCurrent() const; + enum class LifecycleEvent { + kDidMakeCurrent, + kWillClearCurrent, + }; + using LifecycleListener = std::function; + std::optional AddLifecycleListener(LifecycleListener listener); + + bool RemoveLifecycleListener(UniqueID id); + private: EGLDisplay display_ = EGL_NO_DISPLAY; EGLContext context_ = EGL_NO_CONTEXT; + mutable RWMutex listeners_mutex_; + std::map listeners_ + IPLR_GUARDED_BY(listeners_mutex_); + + void DispatchLifecyleEvent(LifecycleEvent event) const; FML_DISALLOW_COPY_AND_ASSIGN(Context); }; diff --git a/engine/src/flutter/lib/ui/painting/image_decoder_impeller.cc b/engine/src/flutter/lib/ui/painting/image_decoder_impeller.cc index e067a18c3e..64160298ad 100644 --- a/engine/src/flutter/lib/ui/painting/image_decoder_impeller.cc +++ b/engine/src/flutter/lib/ui/painting/image_decoder_impeller.cc @@ -61,6 +61,7 @@ static sk_sp DecompressAndUploadTexture( TRACE_EVENT0("flutter", __FUNCTION__); if (!context || !descriptor) { + FML_DLOG(ERROR) << "Invalid context or descriptor."; return nullptr; } diff --git a/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.cc b/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.cc index 8c4ab3d474..f573094f63 100644 --- a/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.cc +++ b/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.cc @@ -14,7 +14,39 @@ namespace flutter { -static std::shared_ptr CreateImpellerContext() { +class AndroidSurfaceGLImpeller::ReactorWorker final + : public impeller::ReactorGLES::Worker { + public: + ReactorWorker() = default; + + // |impeller::ReactorGLES::Worker| + ~ReactorWorker() override = default; + + // |impeller::ReactorGLES::Worker| + bool CanReactorReactOnCurrentThreadNow( + const impeller::ReactorGLES& reactor) const override { + impeller::ReaderLock lock(mutex_); + auto found = reactions_allowed_.find(std::this_thread::get_id()); + if (found == reactions_allowed_.end()) { + return false; + } + return found->second; + } + + void SetReactionsAllowedOnCurrentThread(bool allowed) { + impeller::WriterLock lock(mutex_); + reactions_allowed_[std::this_thread::get_id()] = allowed; + } + + private: + mutable impeller::RWMutex mutex_; + std::map reactions_allowed_ IPLR_GUARDED_BY(mutex_); + + FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); +}; + +static std::shared_ptr CreateImpellerContext( + std::shared_ptr worker) { auto proc_table = std::make_unique( impeller::egl::CreateProcAddressResolver()); @@ -35,13 +67,20 @@ static std::shared_ptr CreateImpellerContext() { FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context."; return nullptr; } + + if (!context->AddReactorWorker(std::move(worker)).has_value()) { + FML_LOG(ERROR) << "Could not add reactor worker."; + return nullptr; + } + return context; } AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( const std::shared_ptr& android_context, std::shared_ptr jni_facade) - : AndroidSurface(android_context) { + : AndroidSurface(android_context), + reactor_worker_(std::shared_ptr(new ReactorWorker())) { auto display = std::make_unique(); if (!display->IsValid()) { FML_DLOG(ERROR) << "Could not create EGL display."; @@ -94,7 +133,7 @@ AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( return; } - auto impeller_context = CreateImpellerContext(); + auto impeller_context = CreateImpellerContext(reactor_worker_); if (!impeller_context) { FML_DLOG(ERROR) << "Could not create Impeller context."; @@ -106,6 +145,24 @@ AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( return; } + // Setup context listeners. + impeller::egl::Context::LifecycleListener listener = + [worker = + reactor_worker_](impeller::egl ::Context::LifecycleEvent event) { + switch (event) { + case impeller::egl::Context::LifecycleEvent::kDidMakeCurrent: + worker->SetReactionsAllowedOnCurrentThread(true); + break; + case impeller::egl::Context::LifecycleEvent::kWillClearCurrent: + worker->SetReactionsAllowedOnCurrentThread(false); + break; + } + }; + if (!onscreen_context->AddLifecycleListener(listener).has_value() || + !offscreen_context->AddLifecycleListener(listener).has_value()) { + FML_DLOG(ERROR) << "Could not add lifecycle listeners"; + } + display_ = std::move(display); onscreen_config_ = std::move(onscreen_config); offscreen_config_ = std::move(offscreen_config); @@ -182,6 +239,12 @@ std::unique_ptr AndroidSurfaceGLImpeller::CreateSnapshotSurface() { FML_UNREACHABLE(); } +// |AndroidSurface| +std::shared_ptr +AndroidSurfaceGLImpeller::GetImpellerContext() { + return impeller_context_; +} + // |GPUSurfaceGLDelegate| std::unique_ptr AndroidSurfaceGLImpeller::GLContextMakeCurrent() { diff --git a/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.h b/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.h index 187414c49d..d491c76a4d 100644 --- a/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.h +++ b/engine/src/flutter/shell/platform/android/android_surface_gl_impeller.h @@ -49,6 +49,9 @@ class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate, // |AndroidSurface| std::unique_ptr CreateSnapshotSurface() override; + // |AndroidSurface| + std::shared_ptr GetImpellerContext() override; + // |GPUSurfaceGLDelegate| std::unique_ptr GLContextMakeCurrent() override; @@ -72,6 +75,9 @@ class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate, sk_sp GetGLInterface() const override; private: + class ReactorWorker; + + std::shared_ptr reactor_worker_; std::unique_ptr display_; std::unique_ptr onscreen_config_; std::unique_ptr offscreen_config_; diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.cc b/engine/src/flutter/shell/platform/android/platform_view_android.cc index f6f439059d..305948de8a 100644 --- a/engine/src/flutter/shell/platform/android/platform_view_android.cc +++ b/engine/src/flutter/shell/platform/android/platform_view_android.cc @@ -332,6 +332,15 @@ void PlatformViewAndroid::ReleaseResourceContext() const { } } +// |PlatformView| +std::shared_ptr PlatformViewAndroid::GetImpellerContext() + const { + if (android_surface_) { + return android_surface_->GetImpellerContext(); + } + return nullptr; +} + // |PlatformView| std::unique_ptr> PlatformViewAndroid::ComputePlatformResolvedLocales( diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.h b/engine/src/flutter/shell/platform/android/platform_view_android.h index 073676cc13..e03d4c54b7 100644 --- a/engine/src/flutter/shell/platform/android/platform_view_android.h +++ b/engine/src/flutter/shell/platform/android/platform_view_android.h @@ -158,6 +158,9 @@ class PlatformViewAndroid final : public PlatformView { // |PlatformView| void ReleaseResourceContext() const override; + // |PlatformView| + std::shared_ptr GetImpellerContext() const override; + // |PlatformView| std::unique_ptr> ComputePlatformResolvedLocales( const std::vector& supported_locale_data) override; diff --git a/engine/src/flutter/shell/platform/android/surface/android_surface.cc b/engine/src/flutter/shell/platform/android/surface/android_surface.cc index dbecfe69dc..ab96387edb 100644 --- a/engine/src/flutter/shell/platform/android/surface/android_surface.cc +++ b/engine/src/flutter/shell/platform/android/surface/android_surface.cc @@ -19,4 +19,8 @@ std::unique_ptr AndroidSurface::CreateSnapshotSurface() { return nullptr; } +std::shared_ptr AndroidSurface::GetImpellerContext() { + return nullptr; +} + } // namespace flutter diff --git a/engine/src/flutter/shell/platform/android/surface/android_surface.h b/engine/src/flutter/shell/platform/android/surface/android_surface.h index 632b84ea14..485f619e1a 100644 --- a/engine/src/flutter/shell/platform/android/surface/android_surface.h +++ b/engine/src/flutter/shell/platform/android/surface/android_surface.h @@ -14,6 +14,10 @@ #include "flutter/shell/platform/android/surface/android_native_window.h" #include "third_party/skia/include/core/SkSize.h" +namespace impeller { +class Context; +} // namespace impeller + namespace flutter { class AndroidExternalViewEmbedder; @@ -39,6 +43,8 @@ class AndroidSurface { virtual std::unique_ptr CreateSnapshotSurface(); + virtual std::shared_ptr GetImpellerContext(); + protected: explicit AndroidSurface( const std::shared_ptr& android_context);