Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(694)

Side by Side Diff: android_webview/browser/deferred_gpu_command_service.cc

Issue 444173003: aw: Improve idle task scheduling (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove CurrentlyOnUIThread Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "android_webview/browser/deferred_gpu_command_service.h" 5 #include "android_webview/browser/deferred_gpu_command_service.h"
6 6
7 #include "android_webview/browser/gl_view_renderer_manager.h" 7 #include "android_webview/browser/gl_view_renderer_manager.h"
8 #include "android_webview/browser/shared_renderer_state.h" 8 #include "android_webview/browser/shared_renderer_state.h"
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/lazy_instance.h"
10 #include "base/synchronization/lock.h" 11 #include "base/synchronization/lock.h"
11 #include "content/public/browser/android/synchronous_compositor.h" 12 #include "content/public/browser/android/synchronous_compositor.h"
12 #include "gpu/command_buffer/service/shader_translator_cache.h" 13 #include "gpu/command_buffer/service/shader_translator_cache.h"
13 14
14 namespace android_webview { 15 namespace android_webview {
15 16
16 namespace { 17 namespace {
17
18 // TODO(boliu): Consider using base/atomicops.h.
19 class ThreadSafeBool {
20 public:
21 ThreadSafeBool();
22 void Set(bool boolean);
23 bool Get();
24 bool GetAndSet();
25
26 private:
27 base::Lock lock_;
28 bool boolean_;
29 DISALLOW_COPY_AND_ASSIGN(ThreadSafeBool);
30 };
31
32 ThreadSafeBool::ThreadSafeBool() : boolean_(false) {
33 }
34
35 void ThreadSafeBool::Set(bool boolean) {
36 base::AutoLock lock(lock_);
37 boolean_ = boolean;
38 }
39
40 bool ThreadSafeBool::GetAndSet() {
41 base::AutoLock lock(lock_);
42 bool rv = boolean_;
43 boolean_ = true;
44 return rv;
45 }
46
47 bool ThreadSafeBool::Get() {
48 base::AutoLock lock(lock_);
49 return boolean_;
50 }
51
52 base::LazyInstance<ThreadSafeBool> g_request_pending =
53 LAZY_INSTANCE_INITIALIZER;
54
55 // Because request is posted to UI thread, have to treat requests on UI thread
56 // specifically because UI can immediately block waiting for the request.
57 base::LazyInstance<ThreadSafeBool> g_request_pending_on_ui =
58 LAZY_INSTANCE_INITIALIZER;
59
60 base::LazyInstance<scoped_refptr<DeferredGpuCommandService> > 18 base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
61 g_service = LAZY_INSTANCE_INITIALIZER; 19 g_service = LAZY_INSTANCE_INITIALIZER;
62 } // namespace 20 } // namespace
63 21
64 base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl; 22 base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl;
65 23
66 // static 24 // static
67 bool ScopedAllowGL::IsAllowed() { 25 bool ScopedAllowGL::IsAllowed() {
68 return allow_gl.Get().Get(); 26 return allow_gl.Get().Get();
69 } 27 }
70 28
71 ScopedAllowGL::ScopedAllowGL() { 29 ScopedAllowGL::ScopedAllowGL() {
72 DCHECK(!allow_gl.Get().Get()); 30 DCHECK(!allow_gl.Get().Get());
73 allow_gl.Get().Set(true); 31 allow_gl.Get().Set(true);
74 32
75 if (g_service.Get()) 33 if (g_service.Get())
76 g_service.Get()->RunTasks(); 34 g_service.Get()->RunTasks();
77 } 35 }
78 36
79 ScopedAllowGL::~ScopedAllowGL() { 37 ScopedAllowGL::~ScopedAllowGL() {
80 allow_gl.Get().Set(false); 38 allow_gl.Get().Set(false);
81 g_request_pending.Get().Set(false);
82 g_request_pending_on_ui.Get().Set(false);
83 39
84 DeferredGpuCommandService* service = g_service.Get(); 40 DeferredGpuCommandService* service = g_service.Get();
85 if (service) { 41 if (service) {
86 service->RunTasks(); 42 service->RunTasks();
87 if (service->HasIdleWork()) { 43 if (service->IdleQueueSize()) {
88 service->RequestProcessGL(); 44 service->RequestProcessGL();
89 } 45 }
90 } 46 }
91 } 47 }
92 48
93 // static 49 // static
94 void DeferredGpuCommandService::SetInstance() { 50 void DeferredGpuCommandService::SetInstance() {
95 if (!g_service.Get()) { 51 if (!g_service.Get()) {
96 g_service.Get() = new DeferredGpuCommandService; 52 g_service.Get() = new DeferredGpuCommandService;
97 content::SynchronousCompositor::SetGpuService(g_service.Get()); 53 content::SynchronousCompositor::SetGpuService(g_service.Get());
98
99 // Initialize global booleans.
100 g_request_pending.Get().Set(false);
101 g_request_pending_on_ui.Get().Set(false);
102 } 54 }
103 } 55 }
104 56
105 // static 57 // static
106 DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() { 58 DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() {
107 DCHECK(g_service.Get().get()); 59 DCHECK(g_service.Get().get());
108 return g_service.Get().get(); 60 return g_service.Get().get();
109 } 61 }
110 62
111 DeferredGpuCommandService::DeferredGpuCommandService() {} 63 DeferredGpuCommandService::DeferredGpuCommandService() {}
112 64
113 DeferredGpuCommandService::~DeferredGpuCommandService() { 65 DeferredGpuCommandService::~DeferredGpuCommandService() {
114 base::AutoLock lock(tasks_lock_); 66 base::AutoLock lock(tasks_lock_);
115 DCHECK(tasks_.empty()); 67 DCHECK(tasks_.empty());
116 } 68 }
117 69
118 // This method can be called on any thread. 70 // This method can be called on any thread.
119 // static 71 // static
120 void DeferredGpuCommandService::RequestProcessGL() { 72 void DeferredGpuCommandService::RequestProcessGL() {
121 SharedRendererState* renderer_state = 73 SharedRendererState* renderer_state =
122 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn(); 74 GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
123 if (!renderer_state) { 75 if (!renderer_state) {
124 LOG(ERROR) << "No hardware renderer. Deadlock likely"; 76 LOG(ERROR) << "No hardware renderer. Deadlock likely";
125 return; 77 return;
126 } 78 }
127 79 renderer_state->ClientRequestDrawGL();
128 bool on_ui_thread = renderer_state->CurrentlyOnUIThread();
129 bool need_request = on_ui_thread ? !g_request_pending_on_ui.Get().GetAndSet()
130 : !g_request_pending.Get().GetAndSet();
131 if (need_request) {
132 g_request_pending.Get().Set(true);
133 renderer_state->ClientRequestDrawGL();
134 }
135 } 80 }
136 81
137 // Called from different threads! 82 // Called from different threads!
138 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) { 83 void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
139 { 84 {
140 base::AutoLock lock(tasks_lock_); 85 base::AutoLock lock(tasks_lock_);
141 tasks_.push(task); 86 tasks_.push(task);
142 } 87 }
143 if (ScopedAllowGL::IsAllowed()) { 88 if (ScopedAllowGL::IsAllowed()) {
144 RunTasks(); 89 RunTasks();
145 } else { 90 } else {
146 RequestProcessGL(); 91 RequestProcessGL();
147 } 92 }
148 } 93 }
149 94
150 bool DeferredGpuCommandService::HasIdleWork() { 95 size_t DeferredGpuCommandService::IdleQueueSize() {
151 base::AutoLock lock(tasks_lock_); 96 base::AutoLock lock(tasks_lock_);
152 return idle_tasks_.size() > 0; 97 return idle_tasks_.size();
153 } 98 }
154 99
155 void DeferredGpuCommandService::ScheduleIdleWork( 100 void DeferredGpuCommandService::ScheduleIdleWork(
156 const base::Closure& callback) { 101 const base::Closure& callback) {
157 { 102 {
158 base::AutoLock lock(tasks_lock_); 103 base::AutoLock lock(tasks_lock_);
159 idle_tasks_.push(std::make_pair(base::Time::Now(), callback)); 104 idle_tasks_.push(std::make_pair(base::Time::Now(), callback));
160 } 105 }
161 RequestProcessGL(); 106 RequestProcessGL();
162 } 107 }
163 108
164 void DeferredGpuCommandService::PerformIdleWork(bool is_idle) { 109 void DeferredGpuCommandService::PerformIdleWork(bool is_idle) {
165 TRACE_EVENT1("android_webview", 110 TRACE_EVENT1("android_webview",
166 "DeferredGpuCommandService::PerformIdleWork", 111 "DeferredGpuCommandService::PerformIdleWork",
167 "is_idle", 112 "is_idle",
168 is_idle); 113 is_idle);
169 DCHECK(ScopedAllowGL::IsAllowed()); 114 DCHECK(ScopedAllowGL::IsAllowed());
170 static const base::TimeDelta kMaxIdleAge = 115 static const base::TimeDelta kMaxIdleAge =
171 base::TimeDelta::FromMilliseconds(16); 116 base::TimeDelta::FromMilliseconds(16);
172 117
173 const base::Time now = base::Time::Now(); 118 const base::Time now = base::Time::Now();
174 while (HasIdleWork()) { 119 size_t queue_size = IdleQueueSize();
120 while (queue_size--) {
175 base::Closure task; 121 base::Closure task;
176 { 122 {
177 base::AutoLock lock(tasks_lock_); 123 base::AutoLock lock(tasks_lock_);
178 if (!is_idle) { 124 if (!is_idle) {
179 // Only run old tasks if we are not really idle right now. 125 // Only run old tasks if we are not really idle right now.
180 base::TimeDelta age(now - idle_tasks_.front().first); 126 base::TimeDelta age(now - idle_tasks_.front().first);
181 if (age < kMaxIdleAge) 127 if (age < kMaxIdleAge)
182 break; 128 break;
183 } 129 }
184 task = idle_tasks_.front().second; 130 task = idle_tasks_.front().second;
185 idle_tasks_.pop(); 131 idle_tasks_.pop();
186 } 132 }
187 task.Run(); 133 task.Run();
188 } 134 }
189 } 135 }
190 136
137 void DeferredGpuCommandService::PerformAllIdleWork() {
138 TRACE_EVENT0("android_webview",
139 "DeferredGpuCommandService::PerformAllIdleWork");
140 while (IdleQueueSize()) {
141 PerformIdleWork(true);
142 }
143 }
144
191 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; } 145 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
192 146
193 scoped_refptr<gpu::gles2::ShaderTranslatorCache> 147 scoped_refptr<gpu::gles2::ShaderTranslatorCache>
194 DeferredGpuCommandService::shader_translator_cache() { 148 DeferredGpuCommandService::shader_translator_cache() {
195 if (!shader_translator_cache_.get()) 149 if (!shader_translator_cache_.get())
196 shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache; 150 shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
197 return shader_translator_cache_; 151 return shader_translator_cache_;
198 } 152 }
199 153
200 void DeferredGpuCommandService::RunTasks() { 154 void DeferredGpuCommandService::RunTasks() {
(...skipping 20 matching lines...) Expand all
221 175
222 void DeferredGpuCommandService::AddRef() const { 176 void DeferredGpuCommandService::AddRef() const {
223 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); 177 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
224 } 178 }
225 179
226 void DeferredGpuCommandService::Release() const { 180 void DeferredGpuCommandService::Release() const {
227 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); 181 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
228 } 182 }
229 183
230 } // namespace android_webview 184 } // namespace android_webview
OLDNEW
« no previous file with comments | « android_webview/browser/deferred_gpu_command_service.h ('k') | android_webview/browser/shared_renderer_state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698