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/framebuffer_completeness_cache.h"
14 #include "gpu/command_buffer/service/shader_translator_cache.h"
15 #include "gpu/command_buffer/service/sync_point_manager.h"
17 namespace android_webview
{
20 base::LazyInstance
<scoped_refptr
<DeferredGpuCommandService
> >
21 g_service
= LAZY_INSTANCE_INITIALIZER
;
24 base::LazyInstance
<base::ThreadLocalBoolean
> ScopedAllowGL::allow_gl
;
27 bool ScopedAllowGL::IsAllowed() {
28 return allow_gl
.Get().Get();
31 ScopedAllowGL::ScopedAllowGL() {
32 DCHECK(!allow_gl
.Get().Get());
33 allow_gl
.Get().Set(true);
35 if (g_service
.Get().get())
36 g_service
.Get()->RunTasks();
39 ScopedAllowGL::~ScopedAllowGL() {
40 allow_gl
.Get().Set(false);
42 DeferredGpuCommandService
* service
= g_service
.Get().get();
45 if (service
->IdleQueueSize()) {
46 service
->RequestProcessGL(true);
52 void DeferredGpuCommandService::SetInstance() {
53 if (!g_service
.Get().get()) {
54 g_service
.Get() = new DeferredGpuCommandService
;
55 content::SynchronousCompositor::SetGpuService(g_service
.Get());
60 DeferredGpuCommandService
* DeferredGpuCommandService::GetInstance() {
61 DCHECK(g_service
.Get().get());
62 return g_service
.Get().get();
65 DeferredGpuCommandService::DeferredGpuCommandService()
66 : sync_point_manager_(new gpu::SyncPointManager(true)) {}
68 DeferredGpuCommandService::~DeferredGpuCommandService() {
69 base::AutoLock
lock(tasks_lock_
);
70 DCHECK(tasks_
.empty());
73 // This method can be called on any thread.
75 void DeferredGpuCommandService::RequestProcessGL(bool for_idle
) {
76 SharedRendererState
* renderer_state
=
77 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
78 if (!renderer_state
) {
79 LOG(ERROR
) << "No hardware renderer. Deadlock likely";
82 renderer_state
->ClientRequestDrawGL(for_idle
);
85 // Called from different threads!
86 void DeferredGpuCommandService::ScheduleTask(const base::Closure
& task
) {
88 base::AutoLock
lock(tasks_lock_
);
91 if (ScopedAllowGL::IsAllowed()) {
94 RequestProcessGL(false);
98 size_t DeferredGpuCommandService::IdleQueueSize() {
99 base::AutoLock
lock(tasks_lock_
);
100 return idle_tasks_
.size();
103 void DeferredGpuCommandService::ScheduleIdleWork(
104 const base::Closure
& callback
) {
106 base::AutoLock
lock(tasks_lock_
);
107 idle_tasks_
.push(std::make_pair(base::Time::Now(), callback
));
109 RequestProcessGL(true);
112 void DeferredGpuCommandService::PerformIdleWork(bool is_idle
) {
113 TRACE_EVENT1("android_webview",
114 "DeferredGpuCommandService::PerformIdleWork",
117 DCHECK(ScopedAllowGL::IsAllowed());
118 static const base::TimeDelta kMaxIdleAge
=
119 base::TimeDelta::FromMilliseconds(16);
121 const base::Time now
= base::Time::Now();
122 size_t queue_size
= IdleQueueSize();
123 while (queue_size
--) {
126 base::AutoLock
lock(tasks_lock_
);
128 // Only run old tasks if we are not really idle right now.
129 base::TimeDelta
age(now
- idle_tasks_
.front().first
);
130 if (age
< kMaxIdleAge
)
133 task
= idle_tasks_
.front().second
;
140 void DeferredGpuCommandService::PerformAllIdleWork() {
141 TRACE_EVENT0("android_webview",
142 "DeferredGpuCommandService::PerformAllIdleWork");
143 while (IdleQueueSize()) {
144 PerformIdleWork(true);
148 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
150 scoped_refptr
<gpu::gles2::ShaderTranslatorCache
>
151 DeferredGpuCommandService::shader_translator_cache() {
152 if (!shader_translator_cache_
.get())
153 shader_translator_cache_
= new gpu::gles2::ShaderTranslatorCache
;
154 return shader_translator_cache_
;
157 scoped_refptr
<gpu::gles2::FramebufferCompletenessCache
>
158 DeferredGpuCommandService::framebuffer_completeness_cache() {
159 if (!framebuffer_completeness_cache_
.get()) {
160 framebuffer_completeness_cache_
=
161 new gpu::gles2::FramebufferCompletenessCache
;
163 return framebuffer_completeness_cache_
;
166 gpu::SyncPointManager
* DeferredGpuCommandService::sync_point_manager() {
167 return sync_point_manager_
.get();
170 void DeferredGpuCommandService::RunTasks() {
171 TRACE_EVENT0("android_webview", "DeferredGpuCommandService::RunTasks");
174 base::AutoLock
lock(tasks_lock_
);
175 has_more_tasks
= tasks_
.size() > 0;
178 while (has_more_tasks
) {
181 base::AutoLock
lock(tasks_lock_
);
182 task
= tasks_
.front();
187 base::AutoLock
lock(tasks_lock_
);
188 has_more_tasks
= tasks_
.size() > 0;
193 void DeferredGpuCommandService::AddRef() const {
194 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::AddRef();
197 void DeferredGpuCommandService::Release() const {
198 base::RefCountedThreadSafe
<DeferredGpuCommandService
>::Release();
201 } // namespace android_webview