Commit cc06ae16 authored by Bo Liu's avatar Bo Liu Committed by Commit Bot

weblayer: Avoid some flicker scenarios

Ideally, during a surface swap, the new view is inserted *below* the
existing view in hwui. Then swap chromium compositor to the surface from
the new view, and only detach the existing view when chromium compositor
has swapped a frame into the surface of the new view. This should in
theory avoid flickers of blank frames during surface swaps.

This CL does various things to achieve the the above behavior:
* Insert new view below old view. New view is inserted at position 0.
* For SurfaceView that uses surface control, need retain the EGL surface
  to keep the surface alive.
* Use postOnAnimation to manipulate view tree. It is unsafe to
  add/remove child views during draw.
* Separate SurfaceData.destroy into markForDestroy and destroy.
  markForDestroy stops surface notifications. destroy will now be called
  after the first swap to remove the view from the view tree.
* Ensure surfaceDestroyed is always called in markForDestroy.
  surfaceCreated and surfaceDestroyed is not guaranteed to be paired.

And a clean up: remove all unused caller args in jni.

Note there is still no guarantee there is no flicker. There will
probably need to require more manul experimentation and manual testing.
Potential more hacks:
* TextureView may not have drawn the frame that chromium compositor
  produced. Can consider listening to TextureView's invalidate.
* SurfaceView will teardown its own surface before removing the "hole"
  it draws into hwui surface, leading to a flicker. May need to either
  avoid this or cover it up before detaching it.

Change-Id: I350f7da1890fdf72253759af00cb9f7f74dff0d3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1830080
Commit-Queue: Bo <boliu@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701392}
parent 1e500465
...@@ -51,14 +51,12 @@ static jlong JNI_ContentViewRenderView_Init( ...@@ -51,14 +51,12 @@ static jlong JNI_ContentViewRenderView_Init(
return reinterpret_cast<intptr_t>(content_view_render_view); return reinterpret_cast<intptr_t>(content_view_render_view);
} }
void ContentViewRenderView::Destroy(JNIEnv* env, void ContentViewRenderView::Destroy(JNIEnv* env) {
const JavaParamRef<jobject>& obj) {
delete this; delete this;
} }
void ContentViewRenderView::SetCurrentWebContents( void ContentViewRenderView::SetCurrentWebContents(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& jweb_contents) { const JavaParamRef<jobject>& jweb_contents) {
InitCompositor(); InitCompositor();
content::WebContents* web_contents = content::WebContents* web_contents =
...@@ -74,7 +72,6 @@ void ContentViewRenderView::SetCurrentWebContents( ...@@ -74,7 +72,6 @@ void ContentViewRenderView::SetCurrentWebContents(
void ContentViewRenderView::OnPhysicalBackingSizeChanged( void ContentViewRenderView::OnPhysicalBackingSizeChanged(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& jweb_contents, const JavaParamRef<jobject>& jweb_contents,
jint width, jint width,
jint height) { jint height) {
...@@ -84,19 +81,20 @@ void ContentViewRenderView::OnPhysicalBackingSizeChanged( ...@@ -84,19 +81,20 @@ void ContentViewRenderView::OnPhysicalBackingSizeChanged(
web_contents->GetNativeView()->OnPhysicalBackingSizeChanged(size); web_contents->GetNativeView()->OnPhysicalBackingSizeChanged(size);
} }
void ContentViewRenderView::SurfaceCreated(JNIEnv* env, void ContentViewRenderView::SurfaceCreated(JNIEnv* env) {
const JavaParamRef<jobject>& obj) {
InitCompositor(); InitCompositor();
} }
void ContentViewRenderView::SurfaceDestroyed(JNIEnv* env, void ContentViewRenderView::SurfaceDestroyed(JNIEnv* env,
const JavaParamRef<jobject>& obj) { jboolean cache_back_buffer) {
evict_back_buffer_on_next_swap_ = cache_back_buffer;
if (evict_back_buffer_on_next_swap_)
compositor_->CacheBackBufferForCurrentSurface();
compositor_->SetSurface(nullptr, false); compositor_->SetSurface(nullptr, false);
} }
void ContentViewRenderView::SurfaceChanged( void ContentViewRenderView::SurfaceChanged(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean can_be_used_with_surface_control, jboolean can_be_used_with_surface_control,
jint width, jint width,
jint height, jint height,
...@@ -107,9 +105,7 @@ void ContentViewRenderView::SurfaceChanged( ...@@ -107,9 +105,7 @@ void ContentViewRenderView::SurfaceChanged(
} }
base::android::ScopedJavaLocalRef<jobject> base::android::ScopedJavaLocalRef<jobject>
ContentViewRenderView::GetResourceManager( ContentViewRenderView::GetResourceManager(JNIEnv* env) {
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jobj) {
return compositor_->GetResourceManager().GetJavaObject(); return compositor_->GetResourceManager().GetJavaObject();
} }
...@@ -121,6 +117,10 @@ void ContentViewRenderView::UpdateLayerTreeHost() { ...@@ -121,6 +117,10 @@ void ContentViewRenderView::UpdateLayerTreeHost() {
void ContentViewRenderView::DidSwapFrame(int pending_frames) { void ContentViewRenderView::DidSwapFrame(int pending_frames) {
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
Java_ContentViewRenderView_didSwapFrame(env, java_obj_); Java_ContentViewRenderView_didSwapFrame(env, java_obj_);
if (evict_back_buffer_on_next_swap_) {
compositor_->EvictCachedBackBuffer();
evict_back_buffer_on_next_swap_ = false;
}
} }
void ContentViewRenderView::InitCompositor() { void ContentViewRenderView::InitCompositor() {
......
...@@ -37,30 +37,23 @@ class ContentViewRenderView : public content::CompositorClient { ...@@ -37,30 +37,23 @@ class ContentViewRenderView : public content::CompositorClient {
} }
// Methods called from Java via JNI ----------------------------------------- // Methods called from Java via JNI -----------------------------------------
void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void Destroy(JNIEnv* env);
void SetCurrentWebContents( void SetCurrentWebContents(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& jweb_contents); const base::android::JavaParamRef<jobject>& jweb_contents);
void OnPhysicalBackingSizeChanged( void OnPhysicalBackingSizeChanged(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& jweb_contents, const base::android::JavaParamRef<jobject>& jweb_contents,
jint width, jint width,
jint height); jint height);
void SurfaceCreated(JNIEnv* env, void SurfaceCreated(JNIEnv* env);
const base::android::JavaParamRef<jobject>& obj); void SurfaceDestroyed(JNIEnv* env, jboolean cache_back_buffer);
void SurfaceDestroyed(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
void SurfaceChanged(JNIEnv* env, void SurfaceChanged(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean can_be_used_with_surface_control, jboolean can_be_used_with_surface_control,
jint width, jint width,
jint height, jint height,
const base::android::JavaParamRef<jobject>& surface); const base::android::JavaParamRef<jobject>& surface);
base::android::ScopedJavaLocalRef<jobject> GetResourceManager( base::android::ScopedJavaLocalRef<jobject> GetResourceManager(JNIEnv* env);
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jobj);
// CompositorClient implementation // CompositorClient implementation
void UpdateLayerTreeHost() override; void UpdateLayerTreeHost() override;
...@@ -81,6 +74,8 @@ class ContentViewRenderView : public content::CompositorClient { ...@@ -81,6 +74,8 @@ class ContentViewRenderView : public content::CompositorClient {
scoped_refptr<cc::Layer> root_container_layer_; scoped_refptr<cc::Layer> root_container_layer_;
scoped_refptr<cc::Layer> web_contents_layer_; scoped_refptr<cc::Layer> web_contents_layer_;
bool evict_back_buffer_on_next_swap_ = false;
DISALLOW_COPY_AND_ASSIGN(ContentViewRenderView); DISALLOW_COPY_AND_ASSIGN(ContentViewRenderView);
}; };
......
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