Index: services/ui/gles2/command_buffer_task_runner.cc |
diff --git a/services/ui/gles2/command_buffer_task_runner.cc b/services/ui/gles2/command_buffer_task_runner.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3f4355ffa49d16e7011d8781e3e3fe3cfdebab7e |
--- /dev/null |
+++ b/services/ui/gles2/command_buffer_task_runner.cc |
@@ -0,0 +1,77 @@ |
+// Copyright 2014 The Chromium 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 "services/ui/gles2/command_buffer_task_runner.h" |
+ |
+#include "base/bind.h" |
+#include "base/threading/thread_task_runner_handle.h" |
+#include "services/ui/gles2/command_buffer_driver.h" |
+ |
+namespace ui { |
+ |
+CommandBufferTaskRunner::CommandBufferTaskRunner() |
+ : task_runner_(base::ThreadTaskRunnerHandle::Get()), |
+ need_post_task_(true) { |
+} |
+ |
+bool CommandBufferTaskRunner::PostTask( |
+ const CommandBufferDriver* driver, |
+ const TaskCallback& task) { |
+ base::AutoLock locker(lock_); |
+ driver_map_[driver].push_back(task); |
+ ScheduleTaskIfNecessaryLocked(); |
+ return true; |
+} |
+ |
+CommandBufferTaskRunner::~CommandBufferTaskRunner() {} |
+ |
+bool CommandBufferTaskRunner::RunOneTaskInternalLocked() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ lock_.AssertAcquired(); |
+ |
+ for (auto it = driver_map_.begin(); it != driver_map_.end(); ++it) { |
+ if (!it->first->IsScheduled()) |
+ continue; |
+ TaskQueue& task_queue = it->second; |
+ DCHECK(!task_queue.empty()); |
+ const TaskCallback& callback = task_queue.front(); |
+ bool complete = false; |
+ { |
+ base::AutoUnlock unlocker(lock_); |
+ complete = callback.Run(); |
+ } |
+ if (complete) { |
+ // Only remove the task if it is complete. |
+ task_queue.pop_front(); |
+ if (task_queue.empty()) |
+ driver_map_.erase(it); |
+ } |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+void CommandBufferTaskRunner::ScheduleTaskIfNecessaryLocked() { |
+ lock_.AssertAcquired(); |
+ if (!need_post_task_) |
+ return; |
+ task_runner()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&CommandBufferTaskRunner::RunCommandBufferTask, this)); |
+ need_post_task_ = false; |
+} |
+ |
+void CommandBufferTaskRunner::RunCommandBufferTask() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ base::AutoLock locker(lock_); |
+ |
+ // Try executing all tasks in |driver_map_| until |RunOneTaskInternalLock()| |
+ // returns false (Returning false means |driver_map_| is empty or all tasks |
+ // in it aren't executable currently). |
+ while (RunOneTaskInternalLocked()) |
+ ; |
+ need_post_task_ = true; |
+} |
+ |
+} // namespace ui |