Merge "Fix missing frame or wrong frame position when resize starts"

This commit is contained in:
Chong Zhang
2015-10-12 20:47:38 +00:00
committed by Android (Google) Code Review
3 changed files with 103 additions and 16 deletions

View File

@@ -88,6 +88,7 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.HashSet;
/**
@@ -238,6 +239,7 @@ public final class ViewRootImpl implements ViewParent,
boolean mNewSurfaceNeeded;
boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
CountDownLatch mWindowDrawCountDown;
boolean mIsDrawing;
int mLastSystemUiVisibility;
@@ -436,6 +438,12 @@ public final class ViewRootImpl implements ViewParent,
}
}
public void reportDrawFinish() {
if (mWindowDrawCountDown != null) {
mWindowDrawCountDown.countDown();
}
}
// FIXME for perf testing only
private boolean mProfile = false;
@@ -2419,6 +2427,17 @@ public final class ViewRootImpl implements ViewParent,
if (mReportNextDraw) {
mReportNextDraw = false;
// if we're using multi-thread renderer, wait for the window frame draws
if (mWindowDrawCountDown != null) {
try {
mWindowDrawCountDown.await();
} catch (InterruptedException e) {
Log.e(TAG, "Window redraw count down interruped!");
}
mWindowDrawCountDown = null;
}
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.fence();
}
@@ -2568,13 +2587,13 @@ public final class ViewRootImpl implements ViewParent,
// Stage the content drawn size now. It will be transferred to the renderer
// shortly before the draw commands get send to the renderer.
synchronized (mWindowCallbacks) {
for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
mWindowCallbacks.get(i).onContentDraw(mWindowAttributes.surfaceInsets.left,
mWindowAttributes.surfaceInsets.top, mWidth, mHeight);
}
}
final boolean updated = updateContentDrawBounds();
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
if (updated) {
requestDrawWindow();
}
} else {
// If we get here with a disabled & requested hardware renderer, something went
// wrong (an invalidate posted right before we destroyed the hardware surface
@@ -6796,6 +6815,30 @@ public final class ViewRootImpl implements ViewParent,
}
}
private boolean updateContentDrawBounds() {
boolean updated = false;
synchronized (mWindowCallbacks) {
for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
updated |= mWindowCallbacks.get(i).onContentDrawn(
mWindowAttributes.surfaceInsets.left,
mWindowAttributes.surfaceInsets.top,
mWidth, mHeight);
}
}
return updated | (mDragResizing && mReportNextDraw);
}
private void requestDrawWindow() {
if (mReportNextDraw) {
mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
}
synchronized (mWindowCallbacks) {
for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw);
}
}
}
/**
* Class for managing the accessibility interaction connection
* based on the global accessibility state.

View File

@@ -49,7 +49,14 @@ public interface WindowCallbacks {
void onWindowDragResizeEnd();
/**
* The content will now be drawn to these bounds.
* The content will now be drawn to these bounds. Returns true if
* a draw should be requested after the next content draw.
*/
void onContentDraw(int offsetX, int offsetY, int sizeX, int sizeY);
boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY);
/**
* Called to request the window to draw one frame.
* @param reportNextDraw Whether it should report when the requested draw finishes.
*/
void onRequestDraw(boolean reportNextDraw);
}

View File

@@ -355,9 +355,22 @@ public class NonClientDecorView extends LinearLayout
}
@Override
public void onContentDraw(int xOffset, int yOffset, int xSize, int ySize) {
public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
if (mFrameRendererThread == null) {
return false;
}
return mFrameRendererThread.onContentDrawn(xOffset, yOffset, xSize, ySize);
}
@Override
public void onRequestDraw(boolean reportNextDraw) {
if (mFrameRendererThread != null) {
mFrameRendererThread.onContentDraw(xOffset, yOffset, xSize, ySize);
mFrameRendererThread.onRequsetDraw(reportNextDraw);
} else if (reportNextDraw) {
// If render thread is gone, just report immediately.
if (isAttachedToWindow()) {
getViewRootImpl().reportDrawFinish();
}
}
}
@@ -423,6 +436,9 @@ public class NonClientDecorView extends LinearLayout
private int mLastXOffset;
private int mLastYOffset;
// Whether to report when next frame is drawn or not.
private boolean mReportNextDraw;
ResizeFrameThread(ThreadedRenderer renderer, Rect initialBounds) {
setName("ResizeFrame");
mRenderer = renderer;
@@ -518,12 +534,13 @@ public class NonClientDecorView extends LinearLayout
public void doFrame(long frameTimeNanos) {
synchronized (this) {
if (mRenderer == null) {
reportDrawIfNeeded();
// Tell the looper to stop. We are done.
Looper.myLooper().quit();
return;
}
mNewTargetRect.set(mTargetRect);
if (!mNewTargetRect.equals(mOldTargetRect)) {
if (!mNewTargetRect.equals(mOldTargetRect) || mReportNextDraw) {
mOldTargetRect.set(mNewTargetRect);
changeWindowSizeLocked(mNewTargetRect);
}
@@ -538,8 +555,9 @@ public class NonClientDecorView extends LinearLayout
* @param yOffset The y offset where the content is drawn to.
* @param xSize The width size of the content. This should not be 0.
* @param ySize The height of the content.
* @return true if a frame should be requested after the content is drawn; false otherwise.
*/
public void onContentDraw(int xOffset, int yOffset, int xSize, int ySize) {
public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
synchronized (this) {
final boolean firstCall = mLastContentWidth == 0;
// The current content buffer is drawn here.
@@ -555,10 +573,15 @@ public class NonClientDecorView extends LinearLayout
mLastYOffset + mLastCaptionHeight + mLastContentHeight);
// If this was the first call and changeWindowSizeLocked got already called prior
// to us, we should re-issue a changeWindowSizeLocked now.
if (firstCall && (mLastCaptionHeight != 0 || !mShowDecor)) {
mOldTargetRect.set(0, 0, 0, 0);
pingRenderLocked();
}
return firstCall && (mLastCaptionHeight != 0 || !mShowDecor);
}
}
public void onRequsetDraw(boolean reportNextDraw) {
synchronized (this) {
mReportNextDraw = reportNextDraw;
mOldTargetRect.set(0, 0, 0, 0);
pingRenderLocked();
}
}
@@ -617,6 +640,20 @@ public class NonClientDecorView extends LinearLayout
// We need to render both rendered nodes explicitly.
mRenderer.drawRenderNode(mFrameNode);
mRenderer.drawRenderNode(mBackdropNode);
reportDrawIfNeeded();
}
/**
* Notify view root that a frame has been drawn by us, if it has requested so.
*/
private void reportDrawIfNeeded() {
if (mReportNextDraw) {
if (isAttachedToWindow()) {
getViewRootImpl().reportDrawFinish();
}
mReportNextDraw = false;
}
}
/**