diff options
| author | 2015-10-12 20:47:38 +0000 | |
|---|---|---|
| committer | 2015-10-12 20:47:38 +0000 | |
| commit | 34259092854d389f6f85508a1dd53aeebcc6f6cc (patch) | |
| tree | a87e08e3ee5337e598b1e496a77408b9e29fbdc4 | |
| parent | c7e19d9f141ad702bc94a7a97aea41e07da57d59 (diff) | |
| parent | 8dbd9ad68248a921637c4b2b866e86854b5860f6 (diff) | |
Merge "Fix missing frame or wrong frame position when resize starts"
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 55 | ||||
| -rw-r--r-- | core/java/android/view/WindowCallbacks.java | 11 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/NonClientDecorView.java | 53 |
3 files changed, 103 insertions, 16 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 14e7d6c4e81e..3d10289ac8e9 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -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. diff --git a/core/java/android/view/WindowCallbacks.java b/core/java/android/view/WindowCallbacks.java index 1aeaec8c6d15..def02365dfed 100644 --- a/core/java/android/view/WindowCallbacks.java +++ b/core/java/android/view/WindowCallbacks.java @@ -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); } diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java index 6557ed159a0b..ed7492aae47b 100644 --- a/core/java/com/android/internal/widget/NonClientDecorView.java +++ b/core/java/com/android/internal/widget/NonClientDecorView.java @@ -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; + } } /** |