Bug 827844 - Fix flickering when layout changes on Firefox/android. r=kats,bgirard
Fix flickering that can occur when the surface size changes due to a layout change (such as the virtual keyboard appearing/disappearing) on Android.
This commit is contained in:
@@ -384,8 +384,6 @@ CompositorParent::SetEGLSurfaceSize(int width, int height)
|
||||
void
|
||||
CompositorParent::ResumeCompositionAndResize(int width, int height)
|
||||
{
|
||||
mWidgetSize.width = width;
|
||||
mWidgetSize.height = height;
|
||||
SetEGLSurfaceSize(width, height);
|
||||
ResumeComposition();
|
||||
}
|
||||
@@ -1003,22 +1001,22 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
|
||||
// If the contents can fit entirely within the widget area on a particular
|
||||
// dimenson, we need to translate and scale so that the fixed layers remain
|
||||
// within the page boundaries.
|
||||
if (mContentRect.width * tempScaleDiffX < mWidgetSize.width) {
|
||||
if (mContentRect.width * tempScaleDiffX < metrics.mCompositionBounds.width) {
|
||||
offset.x = -metricsScrollOffset.x;
|
||||
scaleDiff.height = NS_MIN(1.0f, mWidgetSize.width / (float)mContentRect.width);
|
||||
scaleDiff.height = NS_MIN(1.0f, metrics.mCompositionBounds.width / (float)mContentRect.width);
|
||||
} else {
|
||||
offset.x = clamped(mScrollOffset.x / tempScaleDiffX, (float)mContentRect.x,
|
||||
mContentRect.XMost() - mWidgetSize.width / tempScaleDiffX) -
|
||||
mContentRect.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) -
|
||||
metricsScrollOffset.x;
|
||||
scaleDiff.height = tempScaleDiffX;
|
||||
}
|
||||
|
||||
if (mContentRect.height * tempScaleDiffY < mWidgetSize.height) {
|
||||
if (mContentRect.height * tempScaleDiffY < metrics.mCompositionBounds.height) {
|
||||
offset.y = -metricsScrollOffset.y;
|
||||
scaleDiff.width = NS_MIN(1.0f, mWidgetSize.height / (float)mContentRect.height);
|
||||
scaleDiff.width = NS_MIN(1.0f, metrics.mCompositionBounds.height / (float)mContentRect.height);
|
||||
} else {
|
||||
offset.y = clamped(mScrollOffset.y / tempScaleDiffY, (float)mContentRect.y,
|
||||
mContentRect.YMost() - mWidgetSize.height / tempScaleDiffY) -
|
||||
mContentRect.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) -
|
||||
metricsScrollOffset.y;
|
||||
scaleDiff.width = tempScaleDiffY;
|
||||
}
|
||||
@@ -1116,8 +1114,6 @@ CompositorParent::AllocPLayers(const LayersBackend& aBackendHint,
|
||||
// NULL before returning from this method, to avoid accessing it elsewhere.
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
mWidgetSize.width = rect.width;
|
||||
mWidgetSize.height = rect.height;
|
||||
|
||||
*aBackend = aBackendHint;
|
||||
|
||||
|
||||
@@ -275,7 +275,6 @@ private:
|
||||
float mYScale;
|
||||
nsIntPoint mScrollOffset;
|
||||
nsIntRect mContentRect;
|
||||
nsIntSize mWidgetSize;
|
||||
|
||||
// When this flag is set, the next composition will be the first for a
|
||||
// particular document (i.e. the document displayed on the screen will change).
|
||||
|
||||
@@ -246,8 +246,14 @@ public class GeckoAppShell
|
||||
public static native void notifyReadingMessageListFailed(int aError, int aRequestId);
|
||||
|
||||
public static native void scheduleComposite();
|
||||
|
||||
// Pausing and resuming the compositor is a synchronous request, so be
|
||||
// careful of possible deadlock. Resuming the compositor will also cause
|
||||
// a composition, so there is no need to schedule a composition after
|
||||
// resuming.
|
||||
public static native void schedulePauseComposition();
|
||||
public static native void scheduleResumeComposition(int width, int height);
|
||||
|
||||
public static native float computeRenderIntegrity();
|
||||
|
||||
public static native SurfaceBits getSurfaceBits(Surface surface);
|
||||
|
||||
@@ -74,6 +74,10 @@ public class GLController {
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public boolean hasValidSurface() {
|
||||
return mSurfaceValid;
|
||||
}
|
||||
|
||||
private void initEGL() {
|
||||
mEGL = (EGL10)EGLContext.getEGL();
|
||||
|
||||
|
||||
@@ -612,6 +612,14 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of LayerView.Listener */
|
||||
public void sizeChanged(int width, int height) {
|
||||
// We need to make sure a draw happens synchronously at this point,
|
||||
// but resizing the surface before the SurfaceView has resized will
|
||||
// cause a visible jump.
|
||||
compositionResumeRequested(mWindowSize.width, mWindowSize.height);
|
||||
}
|
||||
|
||||
/** Implementation of LayerView.Listener */
|
||||
public void surfaceChanged(int width, int height) {
|
||||
setViewportSize(width, height);
|
||||
@@ -620,7 +628,6 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
||||
// paused (e.g. during an orientation change), to make the compositor
|
||||
// aware of the changed surface.
|
||||
compositionResumeRequested(width, height);
|
||||
renderRequested();
|
||||
}
|
||||
|
||||
/** Implementation of LayerView.Listener */
|
||||
|
||||
@@ -154,7 +154,7 @@ public class LayerView extends FrameLayout {
|
||||
// from a SurfaceView, which is just not possible (the bitmap will be transparent).
|
||||
setWillNotCacheDrawing(false);
|
||||
|
||||
mSurfaceView = new SurfaceView(getContext());
|
||||
mSurfaceView = new LayerSurfaceView(getContext(), this);
|
||||
mSurfaceView.setBackgroundColor(Color.WHITE);
|
||||
addView(mSurfaceView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
|
||||
@@ -316,7 +316,36 @@ public class LayerView extends FrameLayout {
|
||||
return getDrawable(R.drawable.scrollbar);
|
||||
}
|
||||
|
||||
/* When using a SurfaceView (mSurfaceView != null), resizing happens in two
|
||||
* phases. First, the LayerView changes size, then, often some frames later,
|
||||
* the SurfaceView changes size. Because of this, we need to split the
|
||||
* resize into two phases to avoid jittering.
|
||||
*
|
||||
* The first phase is the LayerView size change. mListener is notified so
|
||||
* that a synchronous draw can be performed (otherwise a blank frame will
|
||||
* appear).
|
||||
*
|
||||
* The second phase is the SurfaceView size change. At this point, the
|
||||
* backing GL surface is resized and another synchronous draw is performed.
|
||||
* Gecko is also sent the new window size, and this will likely cause an
|
||||
* extra draw a few frames later, after it's re-rendered and caught up.
|
||||
*
|
||||
* In the case that there is no valid GL surface (for example, when
|
||||
* resuming, or when coming back from the awesomescreen), or we're using a
|
||||
* TextureView instead of a SurfaceView, the first phase is skipped.
|
||||
*/
|
||||
private void onSizeChanged(int width, int height) {
|
||||
if (!mGLController.hasValidSurface() || mSurfaceView == null) {
|
||||
surfaceChanged(width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mListener != null) {
|
||||
mListener.sizeChanged(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
private void surfaceChanged(int width, int height) {
|
||||
mGLController.surfaceChanged(width, height);
|
||||
|
||||
if (mListener != null) {
|
||||
@@ -356,6 +385,7 @@ public class LayerView extends FrameLayout {
|
||||
void renderRequested();
|
||||
void compositionPauseRequested();
|
||||
void compositionResumeRequested(int width, int height);
|
||||
void sizeChanged(int width, int height);
|
||||
void surfaceChanged(int width, int height);
|
||||
}
|
||||
|
||||
@@ -373,6 +403,24 @@ public class LayerView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/* A subclass of SurfaceView to listen to layout changes, as
|
||||
* View.OnLayoutChangeListener requires API level 11.
|
||||
*/
|
||||
private class LayerSurfaceView extends SurfaceView {
|
||||
LayerView mParent;
|
||||
|
||||
public LayerSurfaceView(Context aContext, LayerView aParent) {
|
||||
super(aContext);
|
||||
mParent = aParent;
|
||||
}
|
||||
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (changed) {
|
||||
mParent.surfaceChanged(right - left, bottom - top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
|
||||
// We don't do this for surfaceCreated above because it is always followed by a surfaceChanged,
|
||||
|
||||
Reference in New Issue
Block a user