9#include "flutter/fml/trace_event.h"
16 : proc_table_(
std::move(
gl)) {
17 if (!proc_table_ || !proc_table_->IsValid()) {
21 can_set_debug_labels_ = proc_table_->GetDescription()->HasDebugExtension();
32 Lock lock(workers_mutex_);
34 workers_[
id] = std::move(worker);
39 Lock lock(workers_mutex_);
40 return workers_.erase(worker) == 1;
43bool ReactorGLES::HasPendingOperations()
const {
44 Lock ops_lock(ops_mutex_);
55 if (
auto found = handles_.find(handle); found != handles_.end()) {
56 if (found->second.pending_collection) {
58 <<
"Attempted to acquire a handle that was pending collection.";
61 if (!found->second.name.has_value()) {
62 VALIDATION_LOG <<
"Attempt to acquire a handle outside of an operation.";
65 return found->second.name;
76 Lock ops_lock(ops_mutex_);
86 GLuint handle = GL_NONE;
91 gl.GenTextures(1u, &handle);
94 gl.GenBuffers(1u, &handle);
97 return gl.CreateProgram();
99 gl.GenRenderbuffers(1u, &handle);
102 gl.GenFramebuffers(1u, &handle);
115 gl.DeleteTextures(1u, &handle);
118 gl.DeleteBuffers(1u, &handle);
121 gl.DeleteProgram(handle);
124 gl.DeleteRenderbuffers(1u, &handle);
127 gl.DeleteFramebuffers(1u, &handle);
137 auto new_handle = HandleGLES::Create(
type);
138 if (new_handle.IsDead()) {
142 auto gl_handle = CanReactOnCurrentThread()
145 handles_[new_handle] = LiveHandle{gl_handle};
151 if (
auto found = handles_.find(handle); found != handles_.end()) {
152 found->second.pending_collection =
true;
157 if (!CanReactOnCurrentThread()) {
161 while (HasPendingOperations()) {
164 Lock execution_lock(ops_execution_mutex_);
191bool ReactorGLES::ReactOnce() {
196 return ConsolidateHandles() && FlushOps();
199bool ReactorGLES::ConsolidateHandles() {
202 WriterLock handles_lock(handles_mutex_);
203 std::vector<HandleGLES> handles_to_delete;
204 for (
auto& handle : handles_) {
206 if (handle.second.pending_collection) {
209 if (handle.second.name.has_value()) {
212 handles_to_delete.push_back(handle.first);
216 if (!handle.second.name.has_value()) {
222 handle.second.name = gl_handle;
225 if (handle.second.pending_debug_label.has_value()) {
227 handle.second.name.value(),
228 handle.second.pending_debug_label.value())) {
229 handle.second.pending_debug_label = std::nullopt;
233 for (
const auto& handle_to_delete : handles_to_delete) {
234 handles_.erase(handle_to_delete);
239bool ReactorGLES::FlushOps() {
252 Lock ops_lock(ops_mutex_);
255 for (
const auto& op :
ops) {
262void ReactorGLES::SetupDebugGroups() {
264 if (proc_table_->DebugMessageControlKHR.IsAvailable()) {
265 proc_table_->DebugMessageControlKHR(GL_DONT_CARE,
275 if (!can_set_debug_labels_) {
282 if (
auto found = handles_.find(handle); found != handles_.end()) {
283 found->second.pending_debug_label = std::move(label);
287bool ReactorGLES::CanReactOnCurrentThread()
const {
288 std::vector<WorkerID> dead_workers;
289 Lock lock(workers_mutex_);
290 for (
const auto& worker : workers_) {
291 auto worker_ptr = worker.second.lock();
293 dead_workers.push_back(worker.first);
296 if (worker_ptr->CanReactorReactOnCurrentThreadNow(*
this)) {
300 for (
const auto& worker_id : dead_workers) {
301 workers_.erase(worker_id);
static void operation(T operation, uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint8_t s, uint32_t t)
void swap(sk_sp< T > &a, sk_sp< T > &b)
std::optional< GLuint > GetGLHandle(const HandleGLES &handle) const
Returns the OpenGL handle for a reactor handle if one is available. This is typically only safe to ca...
ReactorGLES(std::unique_ptr< ProcTableGLES > gl)
Create a new reactor. There are expensive and only one per application instance is necessary.
void CollectHandle(HandleGLES handle)
Collect a reactor handle.
std::function< void(const ReactorGLES &reactor)> Operation
bool React()
Perform a reaction on the current thread if able.
~ReactorGLES()
Destroy a reactor.
const ProcTableGLES & GetProcTable() const
Get the OpenGL proc. table the reactor uses to manage handles.
HandleGLES CreateHandle(HandleType type)
Create a reactor handle.
void SetDebugLabel(const HandleGLES &handle, std::string label)
Set the debug label on a reactor handle.
bool AddOperation(Operation operation)
Adds an operation that the reactor runs on a worker that ensures that an OpenGL context is current.
bool RemoveWorker(WorkerID id)
Remove a previously added worker from the reactor. If the reactor has no workers, pending added opera...
WorkerID AddWorker(std::weak_ptr< Worker > worker)
Adds a worker to the reactor. Each new worker must ensure that the context it manages is the same as ...
bool IsValid() const
If this is a valid reactor. Invalid reactors must be discarded immediately.
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
static bool CollectGLHandle(const ProcTableGLES &gl, HandleType type, GLuint handle)
static DebugResourceType ToDebugResourceType(HandleType type)
static std::optional< GLuint > CreateGLHandle(const ProcTableGLES &gl, HandleType type)
constexpr bool IsDead() const
static HandleGLES DeadHandle()
#define TRACE_EVENT0(category_group, name)