Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / android_webview / browser / deferred_gpu_command_service.cc
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.
4
5 #include "android_webview/browser/deferred_gpu_command_service.h"
6
7 #include "android_webview/browser/gl_view_renderer_manager.h"
8 #include "android_webview/browser/shared_renderer_state.h"
9 #include "base/debug/trace_event.h"
10 #include "base/lazy_instance.h"
11 #include "base/synchronization/lock.h"
12 #include "content/public/browser/android/synchronous_compositor.h"
13 #include "gpu/command_buffer/service/shader_translator_cache.h"
14
15 namespace android_webview {
16
17 namespace {
18 base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
19     g_service = LAZY_INSTANCE_INITIALIZER;
20 }  // namespace
21
22 base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl;
23
24 // static
25 bool ScopedAllowGL::IsAllowed() {
26   return allow_gl.Get().Get();
27 }
28
29 ScopedAllowGL::ScopedAllowGL() {
30   DCHECK(!allow_gl.Get().Get());
31   allow_gl.Get().Set(true);
32
33   if (g_service.Get().get())
34     g_service.Get()->RunTasks();
35 }
36
37 ScopedAllowGL::~ScopedAllowGL() {
38   allow_gl.Get().Set(false);
39
40   DeferredGpuCommandService* service = g_service.Get().get();
41   if (service) {
42     service->RunTasks();
43     if (service->IdleQueueSize()) {
44       service->RequestProcessGL();
45     }
46   }
47 }
48
49 // static
50 void DeferredGpuCommandService::SetInstance() {
51   if (!g_service.Get().get()) {
52     g_service.Get() = new DeferredGpuCommandService;
53     content::SynchronousCompositor::SetGpuService(g_service.Get());
54   }
55 }
56
57 // static
58 DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() {
59   DCHECK(g_service.Get().get());
60   return g_service.Get().get();
61 }
62
63 DeferredGpuCommandService::DeferredGpuCommandService() {}
64
65 DeferredGpuCommandService::~DeferredGpuCommandService() {
66   base::AutoLock lock(tasks_lock_);
67   DCHECK(tasks_.empty());
68 }
69
70 // This method can be called on any thread.
71 // static
72 void DeferredGpuCommandService::RequestProcessGL() {
73   SharedRendererState* renderer_state =
74       GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
75   if (!renderer_state) {
76     LOG(ERROR) << "No hardware renderer. Deadlock likely";
77     return;
78   }
79   renderer_state->ClientRequestDrawGL();
80 }
81
82 // Called from different threads!
83 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
84   {
85     base::AutoLock lock(tasks_lock_);
86     tasks_.push(task);
87   }
88   if (ScopedAllowGL::IsAllowed()) {
89     RunTasks();
90   } else {
91     RequestProcessGL();
92   }
93 }
94
95 size_t DeferredGpuCommandService::IdleQueueSize() {
96   base::AutoLock lock(tasks_lock_);
97   return idle_tasks_.size();
98 }
99
100 void DeferredGpuCommandService::ScheduleIdleWork(
101     const base::Closure& callback) {
102   {
103     base::AutoLock lock(tasks_lock_);
104     idle_tasks_.push(std::make_pair(base::Time::Now(), callback));
105   }
106   RequestProcessGL();
107 }
108
109 void DeferredGpuCommandService::PerformIdleWork(bool is_idle) {
110   TRACE_EVENT1("android_webview",
111                "DeferredGpuCommandService::PerformIdleWork",
112                "is_idle",
113                is_idle);
114   DCHECK(ScopedAllowGL::IsAllowed());
115   static const base::TimeDelta kMaxIdleAge =
116       base::TimeDelta::FromMilliseconds(16);
117
118   const base::Time now = base::Time::Now();
119   size_t queue_size = IdleQueueSize();
120   while (queue_size--) {
121     base::Closure task;
122     {
123       base::AutoLock lock(tasks_lock_);
124       if (!is_idle) {
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)
128           break;
129       }
130       task = idle_tasks_.front().second;
131       idle_tasks_.pop();
132     }
133     task.Run();
134   }
135 }
136
137 void DeferredGpuCommandService::PerformAllIdleWork() {
138   TRACE_EVENT0("android_webview",
139                "DeferredGpuCommandService::PerformAllIdleWork");
140   while (IdleQueueSize()) {
141     PerformIdleWork(true);
142   }
143 }
144
145 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
146
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_;
152 }
153
154 void DeferredGpuCommandService::RunTasks() {
155   bool has_more_tasks;
156   {
157     base::AutoLock lock(tasks_lock_);
158     has_more_tasks = tasks_.size() > 0;
159   }
160
161   while (has_more_tasks) {
162     base::Closure task;
163     {
164       base::AutoLock lock(tasks_lock_);
165       task = tasks_.front();
166       tasks_.pop();
167     }
168     task.Run();
169     {
170       base::AutoLock lock(tasks_lock_);
171       has_more_tasks = tasks_.size() > 0;
172     }
173   }
174 }
175
176 void DeferredGpuCommandService::AddRef() const {
177   base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
178 }
179
180 void DeferredGpuCommandService::Release() const {
181   base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
182 }
183
184 }  // namespace android_webview