blob: 601334ae7f923f6860811a76a163ad612ecc4585 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/browser/deferred_gpu_command_service.h"
#include "android_webview/browser/gl_view_renderer_manager.h"
#include "android_webview/browser/shared_renderer_state.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "gpu/command_buffer/service/shader_translator_cache.h"
namespace android_webview {
namespace {
base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
g_service = LAZY_INSTANCE_INITIALIZER;
} // namespace
base::LazyInstance<base::ThreadLocalBoolean> ScopedAllowGL::allow_gl;
// static
bool ScopedAllowGL::IsAllowed() {
return allow_gl.Get().Get();
}
ScopedAllowGL::ScopedAllowGL() {
DCHECK(!allow_gl.Get().Get());
allow_gl.Get().Set(true);
if (g_service.Get())
g_service.Get()->RunTasks();
}
ScopedAllowGL::~ScopedAllowGL() { allow_gl.Get().Set(false); }
// static
void DeferredGpuCommandService::SetInstance() {
if (!g_service.Get()) {
g_service.Get() = new DeferredGpuCommandService;
content::SynchronousCompositor::SetGpuService(g_service.Get());
}
}
DeferredGpuCommandService::DeferredGpuCommandService() {}
DeferredGpuCommandService::~DeferredGpuCommandService() {
base::AutoLock lock(tasks_lock_);
DCHECK(tasks_.empty());
}
// static
void DeferredGpuCommandService::RequestProcessGLOnUIThread() {
SharedRendererState* renderer_state =
GLViewRendererManager::GetInstance()->GetMostRecentlyDrawn();
if (!renderer_state) {
LOG(ERROR) << "No hardware renderer. Deadlock likely";
return;
}
renderer_state->ClientRequestDrawGL();
}
// Called from different threads!
void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
{
base::AutoLock lock(tasks_lock_);
tasks_.push(task);
}
if (ScopedAllowGL::IsAllowed()) {
RunTasks();
} else {
RequestProcessGLOnUIThread();
}
}
void DeferredGpuCommandService::ScheduleIdleWork(
const base::Closure& callback) {
// TODO(sievers): Should this do anything?
}
bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
scoped_refptr<gpu::gles2::ShaderTranslatorCache>
DeferredGpuCommandService::shader_translator_cache() {
if (!shader_translator_cache_.get())
shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
return shader_translator_cache_;
}
void DeferredGpuCommandService::RunTasks() {
bool has_more_tasks;
{
base::AutoLock lock(tasks_lock_);
has_more_tasks = tasks_.size() > 0;
}
while (has_more_tasks) {
base::Closure task;
{
base::AutoLock lock(tasks_lock_);
task = tasks_.front();
tasks_.pop();
}
task.Run();
{
base::AutoLock lock(tasks_lock_);
has_more_tasks = tasks_.size() > 0;
}
}
}
void DeferredGpuCommandService::AddRef() const {
base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
}
void DeferredGpuCommandService::Release() const {
base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
}
} // namespace android_webview