blob: cd4e85dc201942e7c2d5a383166bb7ea982e22a1 [file] [log] [blame]
[email protected]a0a15ed2014-05-09 23:16:421// 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"
tobiasjs1c63c2f2016-04-05 11:30:038#include "android_webview/browser/render_thread_manager.h"
penghuang7404df9882016-02-29 23:07:299#include "base/command_line.h"
[email protected]8c016b62014-08-08 09:43:5710#include "base/lazy_instance.h"
penghuang7404df9882016-02-29 23:07:2911#include "base/strings/string_number_conversions.h"
[email protected]86eb5b22014-05-28 00:44:4612#include "base/synchronization/lock.h"
ssid3bc4c0ee2015-01-27 14:21:2613#include "base/trace_event/trace_event.h"
penghuang2084d992016-03-10 03:32:5714#include "content/public/browser/gpu_utils.h"
penghuang7404df9882016-02-29 23:07:2915#include "content/public/common/content_switches.h"
tobiasjsfc199b472015-08-22 00:39:0616#include "gpu/command_buffer/service/framebuffer_completeness_cache.h"
penghuang7404df9882016-02-29 23:07:2917#include "gpu/command_buffer/service/gpu_preferences.h"
18#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]a0a15ed2014-05-09 23:16:4219#include "gpu/command_buffer/service/shader_translator_cache.h"
boliuc5befe72015-07-21 19:08:5620#include "gpu/command_buffer/service/sync_point_manager.h"
penghuang7404df9882016-02-29 23:07:2921#include "gpu/config/gpu_switches.h"
22#include "ui/gl/gl_switches.h"
[email protected]a0a15ed2014-05-09 23:16:4223
24namespace android_webview {
25
26namespace {
27base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
28 g_service = LAZY_INSTANCE_INITIALIZER;
penghuang7404df9882016-02-29 23:07:2929
[email protected]a0a15ed2014-05-09 23:16:4230} // namespace
31
32base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl;
33
34// static
35bool ScopedAllowGL::IsAllowed() {
36 return allow_gl.Get().Get();
37}
38
39ScopedAllowGL::ScopedAllowGL() {
40 DCHECK(!allow_gl.Get().Get());
41 allow_gl.Get().Set(true);
42
dcheng4cb42ab2014-10-07 16:41:1943 if (g_service.Get().get())
[email protected]a0a15ed2014-05-09 23:16:4244 g_service.Get()->RunTasks();
45}
46
[email protected]86eb5b22014-05-28 00:44:4647ScopedAllowGL::~ScopedAllowGL() {
48 allow_gl.Get().Set(false);
[email protected]86eb5b22014-05-28 00:44:4649
dcheng4cb42ab2014-10-07 16:41:1950 DeferredGpuCommandService* service = g_service.Get().get();
[email protected]2f7e5aeae2014-07-29 11:17:4751 if (service) {
52 service->RunTasks();
[email protected]8c016b62014-08-08 09:43:5753 if (service->IdleQueueSize()) {
boliu8fbf16a2015-08-07 19:50:1154 service->RequestProcessGL(true);
[email protected]2f7e5aeae2014-07-29 11:17:4755 }
56 }
[email protected]86eb5b22014-05-28 00:44:4657}
[email protected]a0a15ed2014-05-09 23:16:4258
59// static
60void DeferredGpuCommandService::SetInstance() {
boliu1384d6d2016-04-22 06:38:5061 if (!g_service.Get().get())
[email protected]a0a15ed2014-05-09 23:16:4262 g_service.Get() = new DeferredGpuCommandService;
[email protected]a0a15ed2014-05-09 23:16:4263}
64
[email protected]8705654b2014-05-24 01:16:1965// static
66DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() {
67 DCHECK(g_service.Get().get());
68 return g_service.Get().get();
69}
70
boliuc5befe72015-07-21 19:08:5671DeferredGpuCommandService::DeferredGpuCommandService()
penghuang2084d992016-03-10 03:32:5772 : gpu::InProcessCommandBuffer::Service(
73 content::GetGpuPreferencesFromCommandLine()),
penghuang7404df9882016-02-29 23:07:2974 sync_point_manager_(new gpu::SyncPointManager(true)) {
75}
[email protected]a0a15ed2014-05-09 23:16:4276
77DeferredGpuCommandService::~DeferredGpuCommandService() {
78 base::AutoLock lock(tasks_lock_);
79 DCHECK(tasks_.empty());
80}
81
[email protected]8705654b2014-05-24 01:16:1982// This method can be called on any thread.
[email protected]a0a15ed2014-05-09 23:16:4283// static
boliu8fbf16a2015-08-07 19:50:1184void DeferredGpuCommandService::RequestProcessGL(bool for_idle) {
tobiasjs1c63c2f2016-04-05 11:30:0385 RenderThreadManager* renderer_state =
[email protected]a0a15ed2014-05-09 23:16:4286 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
87 if (!renderer_state) {
88 LOG(ERROR) << "No hardware renderer. Deadlock likely";
89 return;
90 }
tobiasjsdbdd7552016-04-21 13:20:5391 renderer_state->ClientRequestInvokeGL(for_idle);
[email protected]a0a15ed2014-05-09 23:16:4292}
93
94// Called from different threads!
95void 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 {
boliu8fbf16a2015-08-07 19:50:11103 RequestProcessGL(false);
[email protected]a0a15ed2014-05-09 23:16:42104 }
105}
106
[email protected]8c016b62014-08-08 09:43:57107size_t DeferredGpuCommandService::IdleQueueSize() {
[email protected]2f7e5aeae2014-07-29 11:17:47108 base::AutoLock lock(tasks_lock_);
[email protected]8c016b62014-08-08 09:43:57109 return idle_tasks_.size();
[email protected]2f7e5aeae2014-07-29 11:17:47110}
111
reveman87580eb2015-09-17 21:45:22112void DeferredGpuCommandService::ScheduleDelayedWork(
[email protected]a0a15ed2014-05-09 23:16:42113 const base::Closure& callback) {
[email protected]2f7e5aeae2014-07-29 11:17:47114 {
115 base::AutoLock lock(tasks_lock_);
116 idle_tasks_.push(std::make_pair(base::Time::Now(), callback));
117 }
boliu8fbf16a2015-08-07 19:50:11118 RequestProcessGL(true);
[email protected]2f7e5aeae2014-07-29 11:17:47119}
120
121void DeferredGpuCommandService::PerformIdleWork(bool is_idle) {
[email protected]0dcee532014-08-06 06:45:15122 TRACE_EVENT1("android_webview",
123 "DeferredGpuCommandService::PerformIdleWork",
124 "is_idle",
125 is_idle);
[email protected]2f7e5aeae2014-07-29 11:17:47126 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]8c016b62014-08-08 09:43:57131 size_t queue_size = IdleQueueSize();
132 while (queue_size--) {
[email protected]2f7e5aeae2014-07-29 11:17:47133 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]a0a15ed2014-05-09 23:16:42147}
148
[email protected]8c016b62014-08-08 09:43:57149void DeferredGpuCommandService::PerformAllIdleWork() {
150 TRACE_EVENT0("android_webview",
151 "DeferredGpuCommandService::PerformAllIdleWork");
152 while (IdleQueueSize()) {
153 PerformIdleWork(true);
154 }
155}
156
[email protected]a0a15ed2014-05-09 23:16:42157bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
158
159scoped_refptr<gpu::gles2::ShaderTranslatorCache>
160DeferredGpuCommandService::shader_translator_cache() {
penghuang7404df9882016-02-29 23:07:29161 if (!shader_translator_cache_.get()) {
162 shader_translator_cache_ =
163 new gpu::gles2::ShaderTranslatorCache(gpu_preferences());
164 }
[email protected]a0a15ed2014-05-09 23:16:42165 return shader_translator_cache_;
166}
167
tobiasjsfc199b472015-08-22 00:39:06168scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
169DeferredGpuCommandService::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
boliuc5befe72015-07-21 19:08:56177gpu::SyncPointManager* DeferredGpuCommandService::sync_point_manager() {
178 return sync_point_manager_.get();
179}
180
[email protected]a0a15ed2014-05-09 23:16:42181void DeferredGpuCommandService::RunTasks() {
boliue2f869862014-12-03 21:13:48182 TRACE_EVENT0("android_webview", "DeferredGpuCommandService::RunTasks");
[email protected]a0a15ed2014-05-09 23:16:42183 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
204void DeferredGpuCommandService::AddRef() const {
205 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
206}
207
208void DeferredGpuCommandService::Release() const {
209 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
210}
211
212} // namespace android_webview