summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/browser/browser_view_renderer.cc2
-rw-r--r--android_webview/browser/browser_view_renderer_client.h8
-rw-r--r--android_webview/browser/shared_renderer_state.cc38
-rw-r--r--android_webview/browser/shared_renderer_state.h13
-rw-r--r--android_webview/buildbot/aosp_manifest.xml2
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContents.java41
-rw-r--r--android_webview/native/aw_contents.cc82
-rw-r--r--android_webview/native/aw_contents.h14
-rw-r--r--android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java7
9 files changed, 134 insertions, 73 deletions
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 9e9711d..c6188e3 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -109,7 +109,7 @@ bool BrowserViewRenderer::OnDraw(jobject java_canvas,
// We should be performing a hardware draw here. If we don't have the
// compositor yet or if RequestDrawGL fails, it means we failed this draw
// and thus return false here to clear to background color for this draw.
- return has_compositor_ && client_->RequestDrawGL(java_canvas);
+ return has_compositor_ && client_->RequestDrawGL(java_canvas, false);
}
// Perform a software draw
return DrawSWInternal(java_canvas, clip);
diff --git a/android_webview/browser/browser_view_renderer_client.h b/android_webview/browser/browser_view_renderer_client.h
index 382ce0d..fce1c80 100644
--- a/android_webview/browser/browser_view_renderer_client.h
+++ b/android_webview/browser/browser_view_renderer_client.h
@@ -15,9 +15,11 @@ namespace android_webview {
class BrowserViewRendererClient {
public:
// Request DrawGL be called. Passing null |canvas| implies the request
- // will be of AwDrawGLInfo::kModeProcess type. The callback
- // may never be made, and the mode may be promoted to kModeDraw.
- virtual bool RequestDrawGL(jobject canvas) = 0;
+ // will be of AwDrawGLInfo::kModeProcess type. |wait_for_completion|
+ // will cause the call to block until DrawGL has happened; it does not
+ // work when |canvas| is not NULL. The callback may never be made, and
+ // the mode may be promoted to kModeDraw.
+ virtual bool RequestDrawGL(jobject canvas, bool wait_for_completion) = 0;
// Called when a new Picture is available. Needs to be enabled
// via the EnableOnNewPicture method.
diff --git a/android_webview/browser/shared_renderer_state.cc b/android_webview/browser/shared_renderer_state.cc
index 1e82438..ffc91ea 100644
--- a/android_webview/browser/shared_renderer_state.cc
+++ b/android_webview/browser/shared_renderer_state.cc
@@ -20,7 +20,8 @@ SharedRendererState::SharedRendererState(
: ui_loop_(ui_loop),
client_on_ui_(client),
weak_factory_on_ui_thread_(this),
- ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()) {
+ ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
+ hardware_initialized_(false) {
DCHECK(ui_loop_->BelongsToCurrentThread());
DCHECK(client_on_ui_);
}
@@ -40,7 +41,7 @@ void SharedRendererState::ClientRequestDrawGL() {
void SharedRendererState::ClientRequestDrawGLOnUIThread() {
DCHECK(ui_loop_->BelongsToCurrentThread());
- if (!client_on_ui_->RequestDrawGL(NULL)) {
+ if (!client_on_ui_->RequestDrawGL(NULL, false)) {
LOG(ERROR) << "Failed to request GL process. Deadlock likely";
}
}
@@ -68,4 +69,37 @@ DrawGLInput SharedRendererState::GetDrawGLInput() const {
return draw_gl_input_;
}
+void SharedRendererState::ClearClosureQueue() {
+ base::AutoLock lock(lock_);
+ std::queue<base::Closure> empty;
+ std::swap(closure_queue_, empty);
+}
+
+void SharedRendererState::AppendClosure(const base::Closure& closure) {
+ base::AutoLock lock(lock_);
+ closure_queue_.push(closure);
+}
+
+base::Closure SharedRendererState::PopFrontClosure() {
+ base::Closure closure;
+
+ base::AutoLock lock(lock_);
+ if (!closure_queue_.empty()) {
+ closure = closure_queue_.front();
+ closure_queue_.pop();
+ }
+
+ return closure;
+}
+
+void SharedRendererState::SetHardwareInitialized(bool initialized) {
+ base::AutoLock lock(lock_);
+ hardware_initialized_ = initialized;
+}
+
+bool SharedRendererState::IsHardwareInitialized() const {
+ base::AutoLock lock(lock_);
+ return hardware_initialized_;
+}
+
} // namespace android_webview
diff --git a/android_webview/browser/shared_renderer_state.h b/android_webview/browser/shared_renderer_state.h
index ec21663..c2c1eee 100644
--- a/android_webview/browser/shared_renderer_state.h
+++ b/android_webview/browser/shared_renderer_state.h
@@ -5,6 +5,9 @@
#ifndef ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_
#define ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_
+#include <queue>
+
+#include "base/callback.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/android/synchronous_compositor.h"
@@ -55,6 +58,14 @@ class SharedRendererState {
void SetDrawGLInput(const DrawGLInput& input);
DrawGLInput GetDrawGLInput() const;
+ void ClearClosureQueue();
+ void AppendClosure(const base::Closure& closure);
+ // Will return empty closure if queue empty.
+ base::Closure PopFrontClosure();
+
+ void SetHardwareInitialized(bool initialized);
+ bool IsHardwareInitialized() const;
+
private:
void ClientRequestDrawGLOnUIThread();
@@ -68,6 +79,8 @@ class SharedRendererState {
mutable base::Lock lock_;
content::SynchronousCompositor* compositor_;
DrawGLInput draw_gl_input_;
+ std::queue<base::Closure> closure_queue_;
+ bool hardware_initialized_;
};
} // namespace android_webview
diff --git a/android_webview/buildbot/aosp_manifest.xml b/android_webview/buildbot/aosp_manifest.xml
index 7597cc89..aa91a54 100644
--- a/android_webview/buildbot/aosp_manifest.xml
+++ b/android_webview/buildbot/aosp_manifest.xml
@@ -244,7 +244,7 @@
<project path="frameworks/testing" name="platform/frameworks/testing" />
<project path="frameworks/uiautomator" name="platform/frameworks/uiautomator" />
<project path="frameworks/volley" name="platform/frameworks/volley" />
- <project path="frameworks/webview" name="platform/frameworks/webview" revision="2e8d713894b88bf8df125735d28963690b78f154" remote="aosp" />
+ <project path="frameworks/webview" name="platform/frameworks/webview" revision="24c4a3d70e8a2f1001e100ac78c0c1673c5710c3" remote="aosp" />
<project path="frameworks/wilhelm" name="platform/frameworks/wilhelm" />
<project path="hardware/akm" name="platform/hardware/akm" />
<project path="hardware/broadcom/libbt" name="platform/hardware/broadcom/libbt" groups="pdk" />
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 875f2a0..f166d99 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -136,18 +136,14 @@ public class AwContents {
* Requests a callback on the native DrawGL method (see getAwDrawGLFunction)
* if called from within onDraw, |canvas| will be non-null and hardware accelerated.
* otherwise, |canvas| will be null, and the container view itself will be hardware
- * accelerated.
+ * accelerated. If |waitForCompletion| is true, this method will not return until
+ * functor has returned.
+ * Should avoid setting |waitForCompletion| when |canvas| is not null.
*
* @return false indicates the GL draw request was not accepted, and the caller
* should fallback to the SW path.
*/
- boolean requestDrawGL(Canvas canvas);
-
- /**
- * Run the action on with EGLContext current or return false.
- * See hidden View#executeHardwareAction for details.
- */
- public boolean executeHardwareAction(Runnable action);
+ boolean requestDrawGL(Canvas canvas, boolean waitForCompletion);
}
/**
@@ -444,14 +440,7 @@ public class AwContents {
if (mNativeAwContents == 0) return;
boolean visibleRectEmpty = getGlobalVisibleRect().isEmpty();
final boolean visible = mIsViewVisible && mIsWindowVisible && !visibleRectEmpty;
- // Don't care about return value of executeHardwareAction since if view is not
- // hardware accelerated, then there is nothing to clean up anyway.
- mInternalAccessAdapter.executeHardwareAction(new Runnable() {
- @Override
- public void run() {
- nativeTrimMemoryOnRenderThread(mNativeAwContents, level, visible);
- }
- });
+ nativeTrimMemory(mNativeAwContents, level, visible);
}
@Override
@@ -1630,18 +1619,6 @@ public class AwContents {
mIsAttachedToWindow = false;
hideAutofillPopup();
if (mNativeAwContents != 0) {
- Runnable releaseHardware = new Runnable() {
- @Override
- public void run() {
- nativeReleaseHardwareDrawOnRenderThread(mNativeAwContents);
- }
- };
- boolean result = mInternalAccessAdapter.executeHardwareAction(releaseHardware);
- if (!result) {
- Log.e(TAG, "May leak or deadlock. Leaked window?");
- releaseHardware.run();
- }
-
nativeOnDetachedFromWindow(mNativeAwContents);
}
@@ -1933,8 +1910,8 @@ public class AwContents {
}
@CalledByNative
- private boolean requestDrawGL(Canvas canvas) {
- return mInternalAccessAdapter.requestDrawGL(canvas);
+ private boolean requestDrawGL(Canvas canvas, boolean waitForCompletion) {
+ return mInternalAccessAdapter.requestDrawGL(canvas, waitForCompletion);
}
private static final boolean SUPPORTS_ON_ANIMATION =
@@ -2133,7 +2110,6 @@ public class AwContents {
private native void nativeSetIsPaused(long nativeAwContents, boolean paused);
private native void nativeOnAttachedToWindow(long nativeAwContents, int w, int h);
private static native void nativeOnDetachedFromWindow(long nativeAwContents);
- private static native void nativeReleaseHardwareDrawOnRenderThread(long nativeAwContents);
private native void nativeSetDipScale(long nativeAwContents, float dipScale);
private native void nativeSetFixedLayoutSize(long nativeAwContents,
int widthDip, int heightDip);
@@ -2160,8 +2136,7 @@ public class AwContents {
private native void nativeSetJsOnlineProperty(long nativeAwContents, boolean networkUp);
- private native void nativeTrimMemoryOnRenderThread(long nativeAwContents, int level,
- boolean visible);
+ private native void nativeTrimMemory(long nativeAwContents, int level, boolean visible);
private native void nativeCreatePdfExporter(long nativeAwContents, AwPdfExporter awPdfExporter);
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index c9d38d6..ee0e87b 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -316,15 +316,14 @@ jlong AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) {
}
void AwContents::DrawGL(AwDrawGLInfo* draw_info) {
- if (!hardware_renderer_) {
- // TODO(boliu): Use executeHardwareAction to synchronously initialize
- // hardware on first functor request. Then functor can point directly
- // to HardwareRenderer.
- hardware_renderer_.reset(new HardwareRenderer(&shared_renderer_state_));
+ for (base::Closure c = shared_renderer_state_.PopFrontClosure(); !c.is_null();
+ c = shared_renderer_state_.PopFrontClosure()) {
+ c.Run();
}
+ // TODO(boliu): Make this a task as well.
DrawGLResult result;
- if (hardware_renderer_->DrawGL(draw_info, &result)) {
+ if (hardware_renderer_ && hardware_renderer_->DrawGL(draw_info, &result)) {
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
@@ -605,13 +604,15 @@ void AwContents::OnReceivedTouchIconUrl(const std::string& url,
env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed);
}
-bool AwContents::RequestDrawGL(jobject canvas) {
+bool AwContents::RequestDrawGL(jobject canvas, bool wait_for_completion) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!canvas || !wait_for_completion);
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return false;
- return Java_AwContents_requestDrawGL(env, obj.obj(), canvas);
+ return Java_AwContents_requestDrawGL(
+ env, obj.obj(), canvas, wait_for_completion);
}
void AwContents::PostInvalidate() {
@@ -726,16 +727,47 @@ void AwContents::SetIsPaused(JNIEnv* env, jobject obj, bool paused) {
void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Add task but don't schedule it. It will run when DrawGL is called for
+ // the first time.
+ shared_renderer_state_.AppendClosure(
+ base::Bind(&AwContents::InitializeHardwareDrawOnRenderThread,
+ base::Unretained(this)));
browser_view_renderer_.OnAttachedToWindow(w, h);
}
+void AwContents::InitializeHardwareDrawOnRenderThread() {
+ DCHECK(!hardware_renderer_);
+ DCHECK(!shared_renderer_state_.IsHardwareInitialized());
+ hardware_renderer_.reset(new HardwareRenderer(&shared_renderer_state_));
+ shared_renderer_state_.SetHardwareInitialized(true);
+}
+
void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ shared_renderer_state_.ClearClosureQueue();
+ shared_renderer_state_.AppendClosure(base::Bind(
+ &AwContents::ReleaseHardwareDrawOnRenderThread, base::Unretained(this)));
+ bool draw_functor_succeeded = RequestDrawGL(NULL, true);
+ if (!draw_functor_succeeded &&
+ shared_renderer_state_.IsHardwareInitialized()) {
+ LOG(ERROR) << "Unable to free GL resources. Has the Window leaked";
+ // Calling release on wrong thread intentionally.
+ ReleaseHardwareDrawOnRenderThread();
+ } else {
+ shared_renderer_state_.ClearClosureQueue();
+ }
+
browser_view_renderer_.OnDetachedFromWindow();
}
-void AwContents::ReleaseHardwareDrawOnRenderThread(JNIEnv* env, jobject obj) {
+void AwContents::ReleaseHardwareDrawOnRenderThread() {
+ DCHECK(hardware_renderer_);
+ DCHECK(shared_renderer_state_.IsHardwareInitialized());
+ // No point in running any other commands if we released hardware already.
+ shared_renderer_state_.ClearClosureQueue();
hardware_renderer_.reset();
+ shared_renderer_state_.SetHardwareInitialized(false);
}
base::android::ScopedJavaLocalRef<jbyteArray>
@@ -994,17 +1026,27 @@ void AwContents::SetJsOnlineProperty(JNIEnv* env,
render_view_host_ext_->SetJsOnlineProperty(network_up);
}
-void AwContents::TrimMemoryOnRenderThread(JNIEnv* env,
- jobject obj,
- jint level,
- jboolean visible) {
- if (hardware_renderer_) {
- if (hardware_renderer_->TrimMemory(level, visible)) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(&AwContents::ForceFakeComposite, ui_thread_weak_ptr_));
- }
+void AwContents::TrimMemory(JNIEnv* env,
+ jobject obj,
+ jint level,
+ jboolean visible) {
+ if (!shared_renderer_state_.IsHardwareInitialized())
+ return;
+
+ shared_renderer_state_.AppendClosure(
+ base::Bind(&AwContents::TrimMemoryOnRenderThread,
+ base::Unretained(this),
+ level,
+ visible));
+ RequestDrawGL(NULL, true);
+}
+
+void AwContents::TrimMemoryOnRenderThread(int level, bool visible) {
+ if (hardware_renderer_ && hardware_renderer_->TrimMemory(level, visible)) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&AwContents::ForceFakeComposite, ui_thread_weak_ptr_));
}
}
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index 24e430f..6c7d467 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -100,7 +100,6 @@ class AwContents : public FindHelper::Listener,
void SetIsPaused(JNIEnv* env, jobject obj, bool paused);
void OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h);
void OnDetachedFromWindow(JNIEnv* env, jobject obj);
- void ReleaseHardwareDrawOnRenderThread(JNIEnv* env, jobject obj);
base::android::ScopedJavaLocalRef<jbyteArray> GetOpaqueState(
JNIEnv* env, jobject obj);
jboolean RestoreFromOpaqueState(JNIEnv* env, jobject obj, jbyteArray state);
@@ -163,8 +162,8 @@ class AwContents : public FindHelper::Listener,
virtual void OnWebLayoutContentsSizeChanged(
const gfx::Size& contents_size) OVERRIDE;
- // BrowserViewRenderer::Client implementation.
- virtual bool RequestDrawGL(jobject canvas) OVERRIDE;
+ // BrowserViewRendererClient implementation.
+ virtual bool RequestDrawGL(jobject canvas, bool wait_for_completion) OVERRIDE;
virtual void PostInvalidate() OVERRIDE;
virtual void OnNewPicture() OVERRIDE;
virtual gfx::Point GetLocationOnScreen() OVERRIDE;
@@ -197,16 +196,17 @@ class AwContents : public FindHelper::Listener,
void SetAwAutofillManagerDelegate(jobject delegate);
void SetJsOnlineProperty(JNIEnv* env, jobject obj, jboolean network_up);
- void TrimMemoryOnRenderThread(JNIEnv* env,
- jobject obj,
- jint level,
- jboolean visible);
+ void TrimMemory(JNIEnv* env, jobject obj, jint level, jboolean visible);
private:
void InitAutofillIfNecessary(bool enabled);
void DidDrawGL(const DrawGLResult& result);
void ForceFakeComposite();
+ void InitializeHardwareDrawOnRenderThread();
+ void ReleaseHardwareDrawOnRenderThread();
+ void TrimMemoryOnRenderThread(int level, bool visible);
+
base::WeakPtrFactory<AwContents> weak_factory_on_ui_thread_;
base::WeakPtr<AwContents> ui_thread_weak_ptr_;
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
index a106096..e82c29b 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
@@ -254,12 +254,7 @@ public class AwTestContainerView extends FrameLayout {
}
@Override
- public boolean requestDrawGL(Canvas canvas) {
- return false;
- }
-
- @Override
- public boolean executeHardwareAction(Runnable action) {
+ public boolean requestDrawGL(Canvas canvas, boolean waitForCompletion) {
return false;
}
}