#include "android_webview/browser/gl_view_renderer_manager.h"
#include "android_webview/browser/shared_renderer_state.h"
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "base/synchronization/lock.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "gpu/command_buffer/service/shader_translator_cache.h"
g_service.Get()->RunTasks();
}
-ScopedAllowGL::~ScopedAllowGL() { allow_gl.Get().Set(false); }
+ScopedAllowGL::~ScopedAllowGL() {
+ allow_gl.Get().Set(false);
+
+ DeferredGpuCommandService* service = g_service.Get();
+ if (service) {
+ service->RunTasks();
+ if (service->IdleQueueSize()) {
+ service->RequestProcessGL();
+ }
+ }
+}
// static
void DeferredGpuCommandService::SetInstance() {
}
}
+// static
+DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() {
+ DCHECK(g_service.Get().get());
+ return g_service.Get().get();
+}
+
DeferredGpuCommandService::DeferredGpuCommandService() {}
DeferredGpuCommandService::~DeferredGpuCommandService() {
DCHECK(tasks_.empty());
}
+// This method can be called on any thread.
// static
-void DeferredGpuCommandService::RequestProcessGLOnUIThread() {
+void DeferredGpuCommandService::RequestProcessGL() {
SharedRendererState* renderer_state =
GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
if (!renderer_state) {
if (ScopedAllowGL::IsAllowed()) {
RunTasks();
} else {
- RequestProcessGLOnUIThread();
+ RequestProcessGL();
}
}
+size_t DeferredGpuCommandService::IdleQueueSize() {
+ base::AutoLock lock(tasks_lock_);
+ return idle_tasks_.size();
+}
+
void DeferredGpuCommandService::ScheduleIdleWork(
const base::Closure& callback) {
- // TODO(sievers): Should this do anything?
+ {
+ base::AutoLock lock(tasks_lock_);
+ idle_tasks_.push(std::make_pair(base::Time::Now(), callback));
+ }
+ RequestProcessGL();
+}
+
+void DeferredGpuCommandService::PerformIdleWork(bool is_idle) {
+ TRACE_EVENT1("android_webview",
+ "DeferredGpuCommandService::PerformIdleWork",
+ "is_idle",
+ is_idle);
+ DCHECK(ScopedAllowGL::IsAllowed());
+ static const base::TimeDelta kMaxIdleAge =
+ base::TimeDelta::FromMilliseconds(16);
+
+ const base::Time now = base::Time::Now();
+ size_t queue_size = IdleQueueSize();
+ while (queue_size--) {
+ base::Closure task;
+ {
+ base::AutoLock lock(tasks_lock_);
+ if (!is_idle) {
+ // Only run old tasks if we are not really idle right now.
+ base::TimeDelta age(now - idle_tasks_.front().first);
+ if (age < kMaxIdleAge)
+ break;
+ }
+ task = idle_tasks_.front().second;
+ idle_tasks_.pop();
+ }
+ task.Run();
+ }
+}
+
+void DeferredGpuCommandService::PerformAllIdleWork() {
+ TRACE_EVENT0("android_webview",
+ "DeferredGpuCommandService::PerformAllIdleWork");
+ while (IdleQueueSize()) {
+ PerformIdleWork(true);
+ }
}
bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }