MSE: Reduce spurious buffered range discontinuities
[chromium-blink-merge.git] / android_webview / browser / deferred_gpu_command_service.cc
blobbc1eec0e6c2d42bbcf0f6931d2b44c8fabe5bd33
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/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"
15 namespace android_webview {
17 namespace {
18 base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
19 g_service = LAZY_INSTANCE_INITIALIZER;
20 } // namespace
22 base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl;
24 // static
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())
34 g_service.Get()->RunTasks();
37 ScopedAllowGL::~ScopedAllowGL() {
38 allow_gl.Get().Set(false);
40 DeferredGpuCommandService* service = g_service.Get();
41 if (service) {
42 service->RunTasks();
43 if (service->IdleQueueSize()) {
44 service->RequestProcessGL();
49 // static
50 void DeferredGpuCommandService::SetInstance() {
51 if (!g_service.Get()) {
52 g_service.Get() = new DeferredGpuCommandService;
53 content::SynchronousCompositor::SetGpuService(g_service.Get());
57 // static
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.
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;
79 renderer_state->ClientRequestDrawGL();
82 // Called from different threads!
83 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
85 base::AutoLock lock(tasks_lock_);
86 tasks_.push(task);
88 if (ScopedAllowGL::IsAllowed()) {
89 RunTasks();
90 } else {
91 RequestProcessGL();
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));
106 RequestProcessGL();
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);
118 const base::Time now = base::Time::Now();
119 size_t queue_size = IdleQueueSize();
120 while (queue_size--) {
121 base::Closure task;
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;
130 task = idle_tasks_.front().second;
131 idle_tasks_.pop();
133 task.Run();
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 bool has_more_tasks;
157 base::AutoLock lock(tasks_lock_);
158 has_more_tasks = tasks_.size() > 0;
161 while (has_more_tasks) {
162 base::Closure task;
164 base::AutoLock lock(tasks_lock_);
165 task = tasks_.front();
166 tasks_.pop();
168 task.Run();
170 base::AutoLock lock(tasks_lock_);
171 has_more_tasks = tasks_.size() > 0;
176 void DeferredGpuCommandService::AddRef() const {
177 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
180 void DeferredGpuCommandService::Release() const {
181 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
184 } // namespace android_webview