Cherry-pick: aw: Track UI request GL separately from other threads

Clean cherry-pick of chromium crrev.com/r287713

BUG: 16550863, 16708848

Original description:

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.

Change-Id: Ic3cd8c30db9f12caaf9a692425447482ea6106fb
diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc
index 8a137a8..93f6c16 100644
--- a/android_webview/browser/deferred_gpu_command_service.cc
+++ b/android_webview/browser/deferred_gpu_command_service.cc
@@ -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 @@
   ThreadSafeBool();
   void Set(bool boolean);
   bool Get();
+  bool GetAndSet();
 
  private:
   base::Lock lock_;
@@ -35,6 +37,13 @@
   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 @@
 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() {
   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 @@
 
     // Initialize global booleans.
     g_request_pending.Get().Set(false);
+    g_request_pending_on_ui.Get().Set(false);
   }
 }
 
@@ -109,7 +125,10 @@
     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::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);
diff --git a/android_webview/browser/shared_renderer_state.cc b/android_webview/browser/shared_renderer_state.cc
index 200e2ab..7c7238e 100644
--- a/android_webview/browser/shared_renderer_state.cc
+++ b/android_webview/browser/shared_renderer_state.cc
@@ -33,6 +33,10 @@
   DCHECK(ui_loop_->BelongsToCurrentThread());
 }
 
+bool SharedRendererState::CurrentlyOnUIThread() {
+  return ui_loop_->BelongsToCurrentThread();
+}
+
 void SharedRendererState::ClientRequestDrawGL() {
   if (ui_loop_->BelongsToCurrentThread()) {
     ClientRequestDrawGLOnUIThread();
diff --git a/android_webview/browser/shared_renderer_state.h b/android_webview/browser/shared_renderer_state.h
index cf0c889..218b7b2 100644
--- a/android_webview/browser/shared_renderer_state.h
+++ b/android_webview/browser/shared_renderer_state.h
@@ -45,6 +45,7 @@
                       BrowserViewRendererClient* client);
   ~SharedRendererState();
 
+  bool CurrentlyOnUIThread();
   void ClientRequestDrawGL();
 
   void SetDrawGLInput(scoped_ptr<DrawGLInput> input);