1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "android_webview/browser/deferred_gpu_command_service.h"
7 #include "android_webview/browser/gl_view_renderer_manager.h"
8 #include "android_webview/browser/shared_renderer_state.h"
9 #include "base/lazy_instance.h"
10 #include "base/synchronization/lock.h"
11 #include "base/trace_event/trace_event.h"
12 #include "content/public/browser/android/synchronous_compositor.h"
13 #include "gpu/command_buffer/service/shader_translator_cache.h"
14 #include "gpu/command_buffer/service/sync_point_manager.h"
16 namespace android_webview
{
19 base::LazyInstance
<scoped_refptr
<DeferredGpuCommandService
> >
20 g_service
= LAZY_INSTANCE_INITIALIZER
;
23 base::LazyInstance
<base::ThreadLocalBoolean
> ScopedAllowGL::allow_gl
;
26 bool ScopedAllowGL::IsAllowed() {
27 return allow_gl
.Get().Get();
30 ScopedAllowGL::ScopedAllowGL() {
31 DCHECK(!allow_gl
.Get().Get());
32 allow_gl
.Get().Set(true);
34 if (g_service
.Get().get())
35 g_service
.Get()->RunTasks();
38 ScopedAllowGL::~ScopedAllowGL() {
39 allow_gl
.Get().Set(false);
41 DeferredGpuCommandService
* service
= g_service
.Get().get();
44 if (service
->IdleQueueSize()) {
45 service
->RequestProcessGL(true);
51 void DeferredGpuCommandService::SetInstance() {
52 if (!g_service
.Get().get()) {
53 g_service
.Get() = new DeferredGpuCommandService
;
54 content::SynchronousCompositor::SetGpuService(g_service
.Get());
59 DeferredGpuCommandService
* DeferredGpuCommandService::GetInstance() {
60 DCHECK(g_service
.Get().get());
61 return g_service
.Get().get();
64 DeferredGpuCommandService::DeferredGpuCommandService()
65 : sync_point_manager_(new gpu::SyncPointManager(true)) {}
67 DeferredGpuCommandService::~DeferredGpuCommandService() {
68 base::AutoLock
lock(tasks_lock_
);
69 DCHECK(tasks_
.empty());
72 // This method can be called on any thread.
74 void DeferredGpuCommandService::RequestProcessGL(bool for_idle
) {
75 SharedRendererState
* renderer_state
=
76 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
77 if (!renderer_state
) {
78 LOG(ERROR
) << "No hardware renderer. Deadlock likely";
81 renderer_state
->ClientRequestDrawGL(for_idle
);
84 // Called from different threads!
85 void DeferredGpuCommandService::ScheduleTask(const base::Closure
& task
) {
87 base::AutoLock
lock(tasks_lock_
);
90 if (ScopedAllowGL::IsAllowed()) {
93 RequestProcessGL(false);
97 size_t DeferredGpuCommandService::IdleQueueSize() {
98 base::AutoLock
lock(tasks_lock_
);
99 return idle_tasks_
.size();
102 void DeferredGpuCommandService::ScheduleIdleWork(
103 const base::Closure
& callback
) {
105 base::AutoLock
lock(tasks_lock_
);
106 idle_tasks_
.push(std::make_pair(base::Time::Now(), callback
));
108 RequestProcessGL(true);
111 void DeferredGpuCommandService::PerformIdleWork(bool is_idle
) {
112 TRACE_EVENT1("android_webview",
113 "DeferredGpuCommandService::PerformIdleWork",
116 DCHECK(ScopedAllowGL::IsAllowed());
117 static const base::TimeDelta kMaxIdleAge
=
118 base::TimeDelta::FromMilliseconds(16);
120 const base::Time now
= base::Time::Now();
121 size_t queue_size
= IdleQueueSize();
122 while (queue_size
--) {
125 base::AutoLock
lock(tasks_lock_
);
127 // Only run old tasks if we are not really idle right now.
128 base::TimeDelta
age(now
- idle_tasks_
.front().first
);
129 if (age
< kMaxIdleAge
)
132 task
= idle_tasks_
.front().second
;
139 void DeferredGpuCommandService::PerformAllIdleWork() {
140 TRACE_EVENT0("android_webview",
141 "DeferredGpuCommandService::PerformAllIdleWork");
142 while (IdleQueueSize()) {
143 PerformIdleWork(true);
147 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
149 scoped_refptr
<gpu::gles2::ShaderTranslatorCache
>
150 DeferredGpuCommandService::shader_translator_cache() {
151 if (!shader_translator_cache_
.get())
152 shader_translator_cache_
= new gpu::gles2::ShaderTranslatorCache
;
153 return shader_translator_cache_
;
156 gpu::SyncPointManager
* DeferredGpuCommandService::sync_point_manager() {
157 return sync_point_manager_
.get();
160 void DeferredGpuCommandService::RunTasks() {
161 TRACE_EVENT0("android_webview", "DeferredGpuCommandService::RunTasks");
164 base::AutoLock
lock(tasks_lock_
);
165 has_more_tasks
= tasks_
.size() > 0;
168 while (has_more_tasks
) {
171 base::AutoLock
lock(tasks_lock_
);
172 task
= tasks_
.front();
177 base::AutoLock
lock(tasks_lock_
);
178 has_more_tasks
= tasks_
.size() > 0;
183 void DeferredGpuCommandService::AddRef() const {
184 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::AddRef();
187 void DeferredGpuCommandService::Release() const {
188 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::Release();
191 } // namespace android_webview