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"
15 namespace android_webview
{
18 base::LazyInstance
<scoped_refptr
<DeferredGpuCommandService
> >
19 g_service
= LAZY_INSTANCE_INITIALIZER
;
22 base::LazyInstance
<base::ThreadLocalBoolean
> ScopedAllowGL::allow_gl
;
25 bool ScopedAllowGL::IsAllowed() {
26 return allow_gl
.Get().Get();
29 ScopedAllowGL::ScopedAllowGL() {
30 DCHECK(!allow_gl
.Get().Get());
31 allow_gl
.Get().Set(true);
33 if (g_service
.Get().get())
34 g_service
.Get()->RunTasks();
37 ScopedAllowGL::~ScopedAllowGL() {
38 allow_gl
.Get().Set(false);
40 DeferredGpuCommandService
* service
= g_service
.Get().get();
43 if (service
->IdleQueueSize()) {
44 service
->RequestProcessGL();
50 void DeferredGpuCommandService::SetInstance() {
51 if (!g_service
.Get().get()) {
52 g_service
.Get() = new DeferredGpuCommandService
;
53 content::SynchronousCompositor::SetGpuService(g_service
.Get());
58 DeferredGpuCommandService
* DeferredGpuCommandService::GetInstance() {
59 DCHECK(g_service
.Get().get());
60 return g_service
.Get().get();
63 DeferredGpuCommandService::DeferredGpuCommandService() {}
65 DeferredGpuCommandService::~DeferredGpuCommandService() {
66 base::AutoLock
lock(tasks_lock_
);
67 DCHECK(tasks_
.empty());
70 // This method can be called on any thread.
72 void DeferredGpuCommandService::RequestProcessGL() {
73 SharedRendererState
* renderer_state
=
74 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
75 if (!renderer_state
) {
76 LOG(ERROR
) << "No hardware renderer. Deadlock likely";
79 renderer_state
->ClientRequestDrawGL();
82 // Called from different threads!
83 void DeferredGpuCommandService::ScheduleTask(const base::Closure
& task
) {
85 base::AutoLock
lock(tasks_lock_
);
88 if (ScopedAllowGL::IsAllowed()) {
95 size_t DeferredGpuCommandService::IdleQueueSize() {
96 base::AutoLock
lock(tasks_lock_
);
97 return idle_tasks_
.size();
100 void DeferredGpuCommandService::ScheduleIdleWork(
101 const base::Closure
& callback
) {
103 base::AutoLock
lock(tasks_lock_
);
104 idle_tasks_
.push(std::make_pair(base::Time::Now(), callback
));
109 void DeferredGpuCommandService::PerformIdleWork(bool is_idle
) {
110 TRACE_EVENT1("android_webview",
111 "DeferredGpuCommandService::PerformIdleWork",
114 DCHECK(ScopedAllowGL::IsAllowed());
115 static const base::TimeDelta kMaxIdleAge
=
116 base::TimeDelta::FromMilliseconds(16);
118 const base::Time now
= base::Time::Now();
119 size_t queue_size
= IdleQueueSize();
120 while (queue_size
--) {
123 base::AutoLock
lock(tasks_lock_
);
125 // Only run old tasks if we are not really idle right now.
126 base::TimeDelta
age(now
- idle_tasks_
.front().first
);
127 if (age
< kMaxIdleAge
)
130 task
= idle_tasks_
.front().second
;
137 void DeferredGpuCommandService::PerformAllIdleWork() {
138 TRACE_EVENT0("android_webview",
139 "DeferredGpuCommandService::PerformAllIdleWork");
140 while (IdleQueueSize()) {
141 PerformIdleWork(true);
145 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
147 scoped_refptr
<gpu::gles2::ShaderTranslatorCache
>
148 DeferredGpuCommandService::shader_translator_cache() {
149 if (!shader_translator_cache_
.get())
150 shader_translator_cache_
= new gpu::gles2::ShaderTranslatorCache
;
151 return shader_translator_cache_
;
154 void DeferredGpuCommandService::RunTasks() {
155 TRACE_EVENT0("android_webview", "DeferredGpuCommandService::RunTasks");
158 base::AutoLock
lock(tasks_lock_
);
159 has_more_tasks
= tasks_
.size() > 0;
162 while (has_more_tasks
) {
165 base::AutoLock
lock(tasks_lock_
);
166 task
= tasks_
.front();
171 base::AutoLock
lock(tasks_lock_
);
172 has_more_tasks
= tasks_
.size() > 0;
177 void DeferredGpuCommandService::AddRef() const {
178 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::AddRef();
181 void DeferredGpuCommandService::Release() const {
182 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::Release();
185 } // namespace android_webview