Commit 0dcee537 authored by boliu@chromium.org's avatar boliu@chromium.org

aw: Track UI request GL separately from other threads

Track UI and other threads differently in requesting DrawGL. The request
itself is posted through UI thread, so not tracking them separately can
lead to deadlocks. See bug for more detail.

BUG=399745

Review URL: https://codereview.chromium.org/431383003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287713 0039d316-1c4b-4281-b951-d872f2087c98
parent 4765de44
......@@ -6,6 +6,7 @@
#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/synchronization/lock.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "gpu/command_buffer/service/shader_translator_cache.h"
......@@ -20,6 +21,7 @@ class ThreadSafeBool {
ThreadSafeBool();
void Set(bool boolean);
bool Get();
bool GetAndSet();
private:
base::Lock lock_;
......@@ -35,6 +37,13 @@ void ThreadSafeBool::Set(bool boolean) {
boolean_ = boolean;
}
bool ThreadSafeBool::GetAndSet() {
base::AutoLock lock(lock_);
bool rv = boolean_;
boolean_ = true;
return rv;
}
bool ThreadSafeBool::Get() {
base::AutoLock lock(lock_);
return boolean_;
......@@ -43,6 +52,11 @@ bool ThreadSafeBool::Get() {
base::LazyInstance<ThreadSafeBool> g_request_pending =
LAZY_INSTANCE_INITIALIZER;
// Because request is posted to UI thread, have to treat requests on UI thread
// specifically because UI can immediately block waiting for the request.
base::LazyInstance<ThreadSafeBool> g_request_pending_on_ui =
LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
g_service = LAZY_INSTANCE_INITIALIZER;
} // namespace
......@@ -65,6 +79,7 @@ ScopedAllowGL::ScopedAllowGL() {
ScopedAllowGL::~ScopedAllowGL() {
allow_gl.Get().Set(false);
g_request_pending.Get().Set(false);
g_request_pending_on_ui.Get().Set(false);
DeferredGpuCommandService* service = g_service.Get();
if (service) {
......@@ -83,6 +98,7 @@ void DeferredGpuCommandService::SetInstance() {
// Initialize global booleans.
g_request_pending.Get().Set(false);
g_request_pending_on_ui.Get().Set(false);
}
}
......@@ -109,7 +125,10 @@ void DeferredGpuCommandService::RequestProcessGL() {
return;
}
if (!g_request_pending.Get().Get()) {
bool on_ui_thread = renderer_state->CurrentlyOnUIThread();
bool need_request = on_ui_thread ? !g_request_pending_on_ui.Get().GetAndSet()
: !g_request_pending.Get().GetAndSet();
if (need_request) {
g_request_pending.Get().Set(true);
renderer_state->ClientRequestDrawGL();
}
......@@ -143,6 +162,10 @@ void DeferredGpuCommandService::ScheduleIdleWork(
}
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);
......
......@@ -33,6 +33,10 @@ SharedRendererState::~SharedRendererState() {
DCHECK(ui_loop_->BelongsToCurrentThread());
}
bool SharedRendererState::CurrentlyOnUIThread() {
return ui_loop_->BelongsToCurrentThread();
}
void SharedRendererState::ClientRequestDrawGL() {
if (ui_loop_->BelongsToCurrentThread()) {
ClientRequestDrawGLOnUIThread();
......
......@@ -45,6 +45,7 @@ class SharedRendererState {
BrowserViewRendererClient* client);
~SharedRendererState();
bool CurrentlyOnUIThread();
void ClientRequestDrawGL();
void SetDrawGLInput(scoped_ptr<DrawGLInput> input);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment