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 @@ ...@@ -6,6 +6,7 @@
#include "android_webview/browser/gl_view_renderer_manager.h" #include "android_webview/browser/gl_view_renderer_manager.h"
#include "android_webview/browser/shared_renderer_state.h" #include "android_webview/browser/shared_renderer_state.h"
#include "base/debug/trace_event.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "content/public/browser/android/synchronous_compositor.h" #include "content/public/browser/android/synchronous_compositor.h"
#include "gpu/command_buffer/service/shader_translator_cache.h" #include "gpu/command_buffer/service/shader_translator_cache.h"
...@@ -20,6 +21,7 @@ class ThreadSafeBool { ...@@ -20,6 +21,7 @@ class ThreadSafeBool {
ThreadSafeBool(); ThreadSafeBool();
void Set(bool boolean); void Set(bool boolean);
bool Get(); bool Get();
bool GetAndSet();
private: private:
base::Lock lock_; base::Lock lock_;
...@@ -35,6 +37,13 @@ void ThreadSafeBool::Set(bool boolean) { ...@@ -35,6 +37,13 @@ void ThreadSafeBool::Set(bool boolean) {
boolean_ = boolean; boolean_ = boolean;
} }
bool ThreadSafeBool::GetAndSet() {
base::AutoLock lock(lock_);
bool rv = boolean_;
boolean_ = true;
return rv;
}
bool ThreadSafeBool::Get() { bool ThreadSafeBool::Get() {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
return boolean_; return boolean_;
...@@ -43,6 +52,11 @@ bool ThreadSafeBool::Get() { ...@@ -43,6 +52,11 @@ bool ThreadSafeBool::Get() {
base::LazyInstance<ThreadSafeBool> g_request_pending = base::LazyInstance<ThreadSafeBool> g_request_pending =
LAZY_INSTANCE_INITIALIZER; 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> > base::LazyInstance<scoped_refptr<DeferredGpuCommandService> >
g_service = LAZY_INSTANCE_INITIALIZER; g_service = LAZY_INSTANCE_INITIALIZER;
} // namespace } // namespace
...@@ -65,6 +79,7 @@ ScopedAllowGL::ScopedAllowGL() { ...@@ -65,6 +79,7 @@ ScopedAllowGL::ScopedAllowGL() {
ScopedAllowGL::~ScopedAllowGL() { ScopedAllowGL::~ScopedAllowGL() {
allow_gl.Get().Set(false); allow_gl.Get().Set(false);
g_request_pending.Get().Set(false); g_request_pending.Get().Set(false);
g_request_pending_on_ui.Get().Set(false);
DeferredGpuCommandService* service = g_service.Get(); DeferredGpuCommandService* service = g_service.Get();
if (service) { if (service) {
...@@ -83,6 +98,7 @@ void DeferredGpuCommandService::SetInstance() { ...@@ -83,6 +98,7 @@ void DeferredGpuCommandService::SetInstance() {
// Initialize global booleans. // Initialize global booleans.
g_request_pending.Get().Set(false); g_request_pending.Get().Set(false);
g_request_pending_on_ui.Get().Set(false);
} }
} }
...@@ -109,7 +125,10 @@ void DeferredGpuCommandService::RequestProcessGL() { ...@@ -109,7 +125,10 @@ void DeferredGpuCommandService::RequestProcessGL() {
return; 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); g_request_pending.Get().Set(true);
renderer_state->ClientRequestDrawGL(); renderer_state->ClientRequestDrawGL();
} }
...@@ -143,6 +162,10 @@ void DeferredGpuCommandService::ScheduleIdleWork( ...@@ -143,6 +162,10 @@ void DeferredGpuCommandService::ScheduleIdleWork(
} }
void DeferredGpuCommandService::PerformIdleWork(bool is_idle) { void DeferredGpuCommandService::PerformIdleWork(bool is_idle) {
TRACE_EVENT1("android_webview",
"DeferredGpuCommandService::PerformIdleWork",
"is_idle",
is_idle);
DCHECK(ScopedAllowGL::IsAllowed()); DCHECK(ScopedAllowGL::IsAllowed());
static const base::TimeDelta kMaxIdleAge = static const base::TimeDelta kMaxIdleAge =
base::TimeDelta::FromMilliseconds(16); base::TimeDelta::FromMilliseconds(16);
......
...@@ -33,6 +33,10 @@ SharedRendererState::~SharedRendererState() { ...@@ -33,6 +33,10 @@ SharedRendererState::~SharedRendererState() {
DCHECK(ui_loop_->BelongsToCurrentThread()); DCHECK(ui_loop_->BelongsToCurrentThread());
} }
bool SharedRendererState::CurrentlyOnUIThread() {
return ui_loop_->BelongsToCurrentThread();
}
void SharedRendererState::ClientRequestDrawGL() { void SharedRendererState::ClientRequestDrawGL() {
if (ui_loop_->BelongsToCurrentThread()) { if (ui_loop_->BelongsToCurrentThread()) {
ClientRequestDrawGLOnUIThread(); ClientRequestDrawGLOnUIThread();
......
...@@ -45,6 +45,7 @@ class SharedRendererState { ...@@ -45,6 +45,7 @@ class SharedRendererState {
BrowserViewRendererClient* client); BrowserViewRendererClient* client);
~SharedRendererState(); ~SharedRendererState();
bool CurrentlyOnUIThread();
void ClientRequestDrawGL(); void ClientRequestDrawGL();
void SetDrawGLInput(scoped_ptr<DrawGLInput> input); 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