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