10de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
20de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
30de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// found in the LICENSE file.
40de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
50de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "android_webview/browser/deferred_gpu_command_service.h"
60de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
70de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "android_webview/browser/gl_view_renderer_manager.h"
80de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "android_webview/browser/shared_renderer_state.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/debug/trace_event.h"
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/lazy_instance.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/synchronization/lock.h"
120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "content/public/browser/android/synchronous_compositor.h"
130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "gpu/command_buffer/service/shader_translator_cache.h"
140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)namespace android_webview {
160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)namespace {
180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    g_service = LAZY_INSTANCE_INITIALIZER;
200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}  // namespace
210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl;
230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// static
250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)bool ScopedAllowGL::IsAllowed() {
260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  return allow_gl.Get().Get();
270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)ScopedAllowGL::ScopedAllowGL() {
300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(!allow_gl.Get().Get());
310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  allow_gl.Get().Set(true);
320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (g_service.Get())
340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    g_service.Get()->RunTasks();
350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ScopedAllowGL::~ScopedAllowGL() {
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  allow_gl.Get().Set(false);
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DeferredGpuCommandService* service = g_service.Get();
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (service) {
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    service->RunTasks();
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (service->IdleQueueSize()) {
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      service->RequestProcessGL();
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// static
500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void DeferredGpuCommandService::SetInstance() {
510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!g_service.Get()) {
520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    g_service.Get() = new DeferredGpuCommandService;
530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    content::SynchronousCompositor::SetGpuService(g_service.Get());
540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)DeferredGpuCommandService* DeferredGpuCommandService::GetInstance() {
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(g_service.Get().get());
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return g_service.Get().get();
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)DeferredGpuCommandService::DeferredGpuCommandService() {}
640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)DeferredGpuCommandService::~DeferredGpuCommandService() {
660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  base::AutoLock lock(tasks_lock_);
670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  DCHECK(tasks_.empty());
680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This method can be called on any thread.
710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// static
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DeferredGpuCommandService::RequestProcessGL() {
730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  SharedRendererState* renderer_state =
740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!renderer_state) {
760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    LOG(ERROR) << "No hardware renderer. Deadlock likely";
770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    return;
780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  renderer_state->ClientRequestDrawGL();
800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Called from different threads!
830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  {
850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    base::AutoLock lock(tasks_lock_);
860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    tasks_.push(task);
870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (ScopedAllowGL::IsAllowed()) {
890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    RunTasks();
900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  } else {
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RequestProcessGL();
920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)size_t DeferredGpuCommandService::IdleQueueSize() {
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::AutoLock lock(tasks_lock_);
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return idle_tasks_.size();
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1000de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void DeferredGpuCommandService::ScheduleIdleWork(
1010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    const base::Closure& callback) {
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::AutoLock lock(tasks_lock_);
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    idle_tasks_.push(std::make_pair(base::Time::Now(), callback));
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RequestProcessGL();
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DeferredGpuCommandService::PerformIdleWork(bool is_idle) {
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TRACE_EVENT1("android_webview",
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               "DeferredGpuCommandService::PerformIdleWork",
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               "is_idle",
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               is_idle);
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(ScopedAllowGL::IsAllowed());
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static const base::TimeDelta kMaxIdleAge =
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(16);
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const base::Time now = base::Time::Now();
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  size_t queue_size = IdleQueueSize();
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  while (queue_size--) {
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::Closure task;
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    {
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::AutoLock lock(tasks_lock_);
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!is_idle) {
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // Only run old tasks if we are not really idle right now.
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::TimeDelta age(now - idle_tasks_.front().first);
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (age < kMaxIdleAge)
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          break;
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      task = idle_tasks_.front().second;
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      idle_tasks_.pop();
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    task.Run();
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
1360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DeferredGpuCommandService::PerformAllIdleWork() {
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  TRACE_EVENT0("android_webview",
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               "DeferredGpuCommandService::PerformAllIdleWork");
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  while (IdleQueueSize()) {
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    PerformIdleWork(true);
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
1460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)scoped_refptr<gpu::gles2::ShaderTranslatorCache>
1480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)DeferredGpuCommandService::shader_translator_cache() {
1490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  if (!shader_translator_cache_.get())
1500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
1510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  return shader_translator_cache_;
1520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
1530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void DeferredGpuCommandService::RunTasks() {
1550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  bool has_more_tasks;
1560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  {
1570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    base::AutoLock lock(tasks_lock_);
1580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    has_more_tasks = tasks_.size() > 0;
1590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
1600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  while (has_more_tasks) {
1620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    base::Closure task;
1630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    {
1640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      base::AutoLock lock(tasks_lock_);
1650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      task = tasks_.front();
1660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      tasks_.pop();
1670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    }
1680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    task.Run();
1690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    {
1700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      base::AutoLock lock(tasks_lock_);
1710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      has_more_tasks = tasks_.size() > 0;
1720de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    }
1730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
1740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
1750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void DeferredGpuCommandService::AddRef() const {
1770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
1780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
1790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void DeferredGpuCommandService::Release() const {
1810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
1820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
1830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}  // namespace android_webview
185