9 #include "flutter/fml/trace_event.h"
10 #include "fml/logging.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;
43 bool 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_);
77 ops_.emplace_back(std::move(operation));
80 [[maybe_unused]]
auto result =
React();
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()) {
143 std::optional<GLuint> gl_handle;
144 if (external_handle != GL_NONE) {
145 gl_handle = external_handle;
146 }
else if (CanReactOnCurrentThread()) {
149 handles_[new_handle] = LiveHandle{gl_handle};
155 if (
auto found = handles_.find(handle); found != handles_.end()) {
156 found->second.pending_collection =
true;
161 if (!CanReactOnCurrentThread()) {
164 TRACE_EVENT0(
"impeller",
"ReactorGLES::React");
165 while (HasPendingOperations()) {
168 Lock execution_lock(ops_execution_mutex_);
195 bool ReactorGLES::ReactOnce() {
199 TRACE_EVENT0(
"impeller", __FUNCTION__);
200 return ConsolidateHandles() && FlushOps();
203 bool ReactorGLES::ConsolidateHandles() {
204 TRACE_EVENT0(
"impeller", __FUNCTION__);
206 WriterLock handles_lock(handles_mutex_);
207 std::vector<HandleGLES> handles_to_delete;
208 for (
auto& handle : handles_) {
210 if (handle.second.pending_collection) {
213 if (handle.second.name.has_value()) {
216 handles_to_delete.push_back(handle.first);
220 if (!handle.second.name.has_value()) {
226 handle.second.name = gl_handle;
229 if (handle.second.pending_debug_label.has_value()) {
231 handle.second.name.value(),
232 handle.second.pending_debug_label.value())) {
233 handle.second.pending_debug_label = std::nullopt;
237 for (
const auto& handle_to_delete : handles_to_delete) {
238 handles_.erase(handle_to_delete);
243 bool ReactorGLES::FlushOps() {
244 TRACE_EVENT0(
"impeller", __FUNCTION__);
246 #ifdef IMPELLER_DEBUG
256 Lock ops_lock(ops_mutex_);
257 std::swap(ops_, ops);
259 for (
const auto& op : ops) {
260 TRACE_EVENT0(
"impeller",
"ReactorGLES::Operation");
266 void ReactorGLES::SetupDebugGroups() {
268 if (proc_table_->DebugMessageControlKHR.IsAvailable()) {
269 proc_table_->DebugMessageControlKHR(GL_DONT_CARE,
279 if (!can_set_debug_labels_) {
286 if (
auto found = handles_.find(handle); found != handles_.end()) {
287 found->second.pending_debug_label = std::move(label);
291 bool ReactorGLES::CanReactOnCurrentThread()
const {
292 std::vector<WorkerID> dead_workers;
293 Lock lock(workers_mutex_);
294 for (
const auto& worker : workers_) {
295 auto worker_ptr = worker.second.lock();
297 dead_workers.push_back(worker.first);
300 if (worker_ptr->CanReactorReactOnCurrentThreadNow(*
this)) {
304 for (
const auto& worker_id : dead_workers) {
305 workers_.erase(worker_id);