[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 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" | ||||
tobiasjs | 1c63c2f | 2016-04-05 11:30:03 | [diff] [blame] | 8 | #include "android_webview/browser/render_thread_manager.h" |
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 9 | #include "base/command_line.h" |
[email protected] | 8c016b6 | 2014-08-08 09:43:57 | [diff] [blame] | 10 | #include "base/lazy_instance.h" |
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 11 | #include "base/strings/string_number_conversions.h" |
[email protected] | 86eb5b2 | 2014-05-28 00:44:46 | [diff] [blame] | 12 | #include "base/synchronization/lock.h" |
ssid | 3bc4c0ee | 2015-01-27 14:21:26 | [diff] [blame] | 13 | #include "base/trace_event/trace_event.h" |
penghuang | 2084d99 | 2016-03-10 03:32:57 | [diff] [blame] | 14 | #include "content/public/browser/gpu_utils.h" |
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 15 | #include "content/public/common/content_switches.h" |
tobiasjs | fc199b47 | 2015-08-22 00:39:06 | [diff] [blame] | 16 | #include "gpu/command_buffer/service/framebuffer_completeness_cache.h" |
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 17 | #include "gpu/command_buffer/service/gpu_preferences.h" |
18 | #include "gpu/command_buffer/service/gpu_switches.h" | ||||
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 19 | #include "gpu/command_buffer/service/shader_translator_cache.h" |
boliu | c5befe7 | 2015-07-21 19:08:56 | [diff] [blame] | 20 | #include "gpu/command_buffer/service/sync_point_manager.h" |
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 21 | #include "gpu/config/gpu_switches.h" |
22 | #include "ui/gl/gl_switches.h" | ||||
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 23 | |
24 | namespace android_webview { | ||||
25 | |||||
26 | namespace { | ||||
27 | base::LazyInstance<scoped_refptr<DeferredGpuCommandService> > | ||||
28 | g_service = LAZY_INSTANCE_INITIALIZER; | ||||
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 29 | |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 30 | } // namespace |
31 | |||||
32 | base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl; | ||||
33 | |||||
34 | // static | ||||
35 | bool ScopedAllowGL::IsAllowed() { | ||||
36 | return allow_gl.Get().Get(); | ||||
37 | } | ||||
38 | |||||
39 | ScopedAllowGL::ScopedAllowGL() { | ||||
40 | DCHECK(!allow_gl.Get().Get()); | ||||
41 | allow_gl.Get().Set(true); | ||||
42 | |||||
dcheng | 4cb42ab | 2014-10-07 16:41:19 | [diff] [blame] | 43 | if (g_service.Get().get()) |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 44 | g_service.Get()->RunTasks(); |
45 | } | ||||
46 | |||||
[email protected] | 86eb5b2 | 2014-05-28 00:44:46 | [diff] [blame] | 47 | ScopedAllowGL::~ScopedAllowGL() { |
48 | allow_gl.Get().Set(false); | ||||
[email protected] | 86eb5b2 | 2014-05-28 00:44:46 | [diff] [blame] | 49 | |
dcheng | 4cb42ab | 2014-10-07 16:41:19 | [diff] [blame] | 50 | DeferredGpuCommandService* service = g_service.Get().get(); |
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 51 | if (service) { |
52 | service->RunTasks(); | ||||
[email protected] | 8c016b6 | 2014-08-08 09:43:57 | [diff] [blame] | 53 | if (service->IdleQueueSize()) { |
boliu | 8fbf16a | 2015-08-07 19:50:11 | [diff] [blame] | 54 | service->RequestProcessGL(true); |
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 55 | } |
56 | } | ||||
[email protected] | 86eb5b2 | 2014-05-28 00:44:46 | [diff] [blame] | 57 | } |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 58 | |
59 | // static | ||||
60 | void DeferredGpuCommandService::SetInstance() { | ||||
boliu | 1384d6d | 2016-04-22 06:38:50 | [diff] [blame] | 61 | if (!g_service.Get().get()) |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 62 | g_service.Get() = new DeferredGpuCommandService; |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 63 | } |
64 | |||||
[email protected] | 8705654b | 2014-05-24 01:16:19 | [diff] [blame] | 65 | // static |
66 | DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() { | ||||
67 | DCHECK(g_service.Get().get()); | ||||
68 | return g_service.Get().get(); | ||||
69 | } | ||||
70 | |||||
boliu | c5befe7 | 2015-07-21 19:08:56 | [diff] [blame] | 71 | DeferredGpuCommandService::DeferredGpuCommandService() |
penghuang | 2084d99 | 2016-03-10 03:32:57 | [diff] [blame] | 72 | : gpu::InProcessCommandBuffer::Service( |
73 | content::GetGpuPreferencesFromCommandLine()), | ||||
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 74 | sync_point_manager_(new gpu::SyncPointManager(true)) { |
75 | } | ||||
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 76 | |
77 | DeferredGpuCommandService::~DeferredGpuCommandService() { | ||||
78 | base::AutoLock lock(tasks_lock_); | ||||
79 | DCHECK(tasks_.empty()); | ||||
80 | } | ||||
81 | |||||
[email protected] | 8705654b | 2014-05-24 01:16:19 | [diff] [blame] | 82 | // This method can be called on any thread. |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 83 | // static |
boliu | 8fbf16a | 2015-08-07 19:50:11 | [diff] [blame] | 84 | void DeferredGpuCommandService::RequestProcessGL(bool for_idle) { |
tobiasjs | 1c63c2f | 2016-04-05 11:30:03 | [diff] [blame] | 85 | RenderThreadManager* renderer_state = |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 86 | GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn(); |
87 | if (!renderer_state) { | ||||
88 | LOG(ERROR) << "No hardware renderer. Deadlock likely"; | ||||
89 | return; | ||||
90 | } | ||||
tobiasjs | dbdd755 | 2016-04-21 13:20:53 | [diff] [blame] | 91 | renderer_state->ClientRequestInvokeGL(for_idle); |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 92 | } |
93 | |||||
94 | // Called from different threads! | ||||
95 | void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) { | ||||
96 | { | ||||
97 | base::AutoLock lock(tasks_lock_); | ||||
98 | tasks_.push(task); | ||||
99 | } | ||||
100 | if (ScopedAllowGL::IsAllowed()) { | ||||
101 | RunTasks(); | ||||
102 | } else { | ||||
boliu | 8fbf16a | 2015-08-07 19:50:11 | [diff] [blame] | 103 | RequestProcessGL(false); |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 104 | } |
105 | } | ||||
106 | |||||
[email protected] | 8c016b6 | 2014-08-08 09:43:57 | [diff] [blame] | 107 | size_t DeferredGpuCommandService::IdleQueueSize() { |
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 108 | base::AutoLock lock(tasks_lock_); |
[email protected] | 8c016b6 | 2014-08-08 09:43:57 | [diff] [blame] | 109 | return idle_tasks_.size(); |
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 110 | } |
111 | |||||
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 112 | void DeferredGpuCommandService::ScheduleDelayedWork( |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 113 | const base::Closure& callback) { |
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 114 | { |
115 | base::AutoLock lock(tasks_lock_); | ||||
116 | idle_tasks_.push(std::make_pair(base::Time::Now(), callback)); | ||||
117 | } | ||||
boliu | 8fbf16a | 2015-08-07 19:50:11 | [diff] [blame] | 118 | RequestProcessGL(true); |
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 119 | } |
120 | |||||
121 | void DeferredGpuCommandService::PerformIdleWork(bool is_idle) { | ||||
[email protected] | 0dcee53 | 2014-08-06 06:45:15 | [diff] [blame] | 122 | TRACE_EVENT1("android_webview", |
123 | "DeferredGpuCommandService::PerformIdleWork", | ||||
124 | "is_idle", | ||||
125 | is_idle); | ||||
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 126 | DCHECK(ScopedAllowGL::IsAllowed()); |
127 | static const base::TimeDelta kMaxIdleAge = | ||||
128 | base::TimeDelta::FromMilliseconds(16); | ||||
129 | |||||
130 | const base::Time now = base::Time::Now(); | ||||
[email protected] | 8c016b6 | 2014-08-08 09:43:57 | [diff] [blame] | 131 | size_t queue_size = IdleQueueSize(); |
132 | while (queue_size--) { | ||||
[email protected] | 2f7e5aeae | 2014-07-29 11:17:47 | [diff] [blame] | 133 | base::Closure task; |
134 | { | ||||
135 | base::AutoLock lock(tasks_lock_); | ||||
136 | if (!is_idle) { | ||||
137 | // Only run old tasks if we are not really idle right now. | ||||
138 | base::TimeDelta age(now - idle_tasks_.front().first); | ||||
139 | if (age < kMaxIdleAge) | ||||
140 | break; | ||||
141 | } | ||||
142 | task = idle_tasks_.front().second; | ||||
143 | idle_tasks_.pop(); | ||||
144 | } | ||||
145 | task.Run(); | ||||
146 | } | ||||
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 147 | } |
148 | |||||
[email protected] | 8c016b6 | 2014-08-08 09:43:57 | [diff] [blame] | 149 | void DeferredGpuCommandService::PerformAllIdleWork() { |
150 | TRACE_EVENT0("android_webview", | ||||
151 | "DeferredGpuCommandService::PerformAllIdleWork"); | ||||
152 | while (IdleQueueSize()) { | ||||
153 | PerformIdleWork(true); | ||||
154 | } | ||||
155 | } | ||||
156 | |||||
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 157 | bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; } |
158 | |||||
159 | scoped_refptr<gpu::gles2::ShaderTranslatorCache> | ||||
160 | DeferredGpuCommandService::shader_translator_cache() { | ||||
penghuang | 7404df988 | 2016-02-29 23:07:29 | [diff] [blame] | 161 | if (!shader_translator_cache_.get()) { |
162 | shader_translator_cache_ = | ||||
163 | new gpu::gles2::ShaderTranslatorCache(gpu_preferences()); | ||||
164 | } | ||||
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 165 | return shader_translator_cache_; |
166 | } | ||||
167 | |||||
tobiasjs | fc199b47 | 2015-08-22 00:39:06 | [diff] [blame] | 168 | scoped_refptr<gpu::gles2::FramebufferCompletenessCache> |
169 | DeferredGpuCommandService::framebuffer_completeness_cache() { | ||||
170 | if (!framebuffer_completeness_cache_.get()) { | ||||
171 | framebuffer_completeness_cache_ = | ||||
172 | new gpu::gles2::FramebufferCompletenessCache; | ||||
173 | } | ||||
174 | return framebuffer_completeness_cache_; | ||||
175 | } | ||||
176 | |||||
boliu | c5befe7 | 2015-07-21 19:08:56 | [diff] [blame] | 177 | gpu::SyncPointManager* DeferredGpuCommandService::sync_point_manager() { |
178 | return sync_point_manager_.get(); | ||||
179 | } | ||||
180 | |||||
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 181 | void DeferredGpuCommandService::RunTasks() { |
boliu | e2f86986 | 2014-12-03 21:13:48 | [diff] [blame] | 182 | TRACE_EVENT0("android_webview", "DeferredGpuCommandService::RunTasks"); |
[email protected] | a0a15ed | 2014-05-09 23:16:42 | [diff] [blame] | 183 | bool has_more_tasks; |
184 | { | ||||
185 | base::AutoLock lock(tasks_lock_); | ||||
186 | has_more_tasks = tasks_.size() > 0; | ||||
187 | } | ||||
188 | |||||
189 | while (has_more_tasks) { | ||||
190 | base::Closure task; | ||||
191 | { | ||||
192 | base::AutoLock lock(tasks_lock_); | ||||
193 | task = tasks_.front(); | ||||
194 | tasks_.pop(); | ||||
195 | } | ||||
196 | task.Run(); | ||||
197 | { | ||||
198 | base::AutoLock lock(tasks_lock_); | ||||
199 | has_more_tasks = tasks_.size() > 0; | ||||
200 | } | ||||
201 | } | ||||
202 | } | ||||
203 | |||||
204 | void DeferredGpuCommandService::AddRef() const { | ||||
205 | base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); | ||||
206 | } | ||||
207 | |||||
208 | void DeferredGpuCommandService::Release() const { | ||||
209 | base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); | ||||
210 | } | ||||
211 | |||||
212 | } // namespace android_webview |