Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / android_webview / browser / deferred_gpu_command_service.cc
index 601334a..bc1eec0 100644 (file)
@@ -6,6 +6,9 @@
 
 #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"
 
@@ -31,7 +34,17 @@ ScopedAllowGL::ScopedAllowGL() {
     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() {
@@ -41,6 +54,12 @@ void DeferredGpuCommandService::SetInstance() {
   }
 }
 
+// static
+DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() {
+  DCHECK(g_service.Get().get());
+  return g_service.Get().get();
+}
+
 DeferredGpuCommandService::DeferredGpuCommandService() {}
 
 DeferredGpuCommandService::~DeferredGpuCommandService() {
@@ -48,8 +67,9 @@ 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) {
@@ -68,13 +88,58 @@ void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
   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; }