Index: android_webview/browser/deferred_gpu_command_service.cc |
diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..601334ae7f923f6860811a76a163ad612ecc4585 |
--- /dev/null |
+++ b/android_webview/browser/deferred_gpu_command_service.cc |
@@ -0,0 +1,119 @@ |
+// 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 "android_webview/browser/deferred_gpu_command_service.h" |
+ |
+#include "android_webview/browser/gl_view_renderer_manager.h" |
+#include "android_webview/browser/shared_renderer_state.h" |
+#include "content/public/browser/android/synchronous_compositor.h" |
+#include "gpu/command_buffer/service/shader_translator_cache.h" |
+ |
+namespace android_webview { |
+ |
+namespace { |
+base::LazyInstance<scoped_refptr<DeferredGpuCommandService> > |
+ g_service = LAZY_INSTANCE_INITIALIZER; |
+} // namespace |
+ |
+base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl; |
+ |
+// static |
+bool ScopedAllowGL::IsAllowed() { |
+ return allow_gl.Get().Get(); |
+} |
+ |
+ScopedAllowGL::ScopedAllowGL() { |
+ DCHECK(!allow_gl.Get().Get()); |
+ allow_gl.Get().Set(true); |
+ |
+ if (g_service.Get()) |
+ g_service.Get()->RunTasks(); |
+} |
+ |
+ScopedAllowGL::~ScopedAllowGL() { allow_gl.Get().Set(false); } |
+ |
+// static |
+void DeferredGpuCommandService::SetInstance() { |
+ if (!g_service.Get()) { |
+ g_service.Get() = new DeferredGpuCommandService; |
+ content::SynchronousCompositor::SetGpuService(g_service.Get()); |
+ } |
+} |
+ |
+DeferredGpuCommandService::DeferredGpuCommandService() {} |
+ |
+DeferredGpuCommandService::~DeferredGpuCommandService() { |
+ base::AutoLock lock(tasks_lock_); |
+ DCHECK(tasks_.empty()); |
+} |
+ |
+// static |
+void DeferredGpuCommandService::RequestProcessGLOnUIThread() { |
+ SharedRendererState* renderer_state = |
+ GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn(); |
+ if (!renderer_state) { |
+ LOG(ERROR) << "No hardware renderer. Deadlock likely"; |
+ return; |
+ } |
+ renderer_state->ClientRequestDrawGL(); |
+} |
+ |
+// Called from different threads! |
+void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) { |
+ { |
+ base::AutoLock lock(tasks_lock_); |
+ tasks_.push(task); |
+ } |
+ if (ScopedAllowGL::IsAllowed()) { |
+ RunTasks(); |
+ } else { |
+ RequestProcessGLOnUIThread(); |
+ } |
+} |
+ |
+void DeferredGpuCommandService::ScheduleIdleWork( |
+ const base::Closure& callback) { |
+ // TODO(sievers): Should this do anything? |
+} |
+ |
+bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; } |
+ |
+scoped_refptr<gpu::gles2::ShaderTranslatorCache> |
+DeferredGpuCommandService::shader_translator_cache() { |
+ if (!shader_translator_cache_.get()) |
+ shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache; |
+ return shader_translator_cache_; |
+} |
+ |
+void DeferredGpuCommandService::RunTasks() { |
+ bool has_more_tasks; |
+ { |
+ base::AutoLock lock(tasks_lock_); |
+ has_more_tasks = tasks_.size() > 0; |
+ } |
+ |
+ while (has_more_tasks) { |
+ base::Closure task; |
+ { |
+ base::AutoLock lock(tasks_lock_); |
+ task = tasks_.front(); |
+ tasks_.pop(); |
+ } |
+ task.Run(); |
+ { |
+ base::AutoLock lock(tasks_lock_); |
+ has_more_tasks = tasks_.size() > 0; |
+ } |
+ } |
+} |
+ |
+void DeferredGpuCommandService::AddRef() const { |
+ base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); |
+} |
+ |
+void DeferredGpuCommandService::Release() const { |
+ base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); |
+} |
+ |
+} // namespace android_webview |