diff options
author | Romain Guy <romainguy@android.com> | 2009-05-14 21:27:18 -0700 |
---|---|---|
committer | Romain Guy <romainguy@android.com> | 2009-05-14 21:48:35 -0700 |
commit | 5bcdff45bf4ada77ae7c95f520b795876adef75c (patch) | |
tree | 12ef49b6b7c848be6f41f129785a359b37ee2606 /core | |
parent | 14ad07f604ecd08436680a046363d37952c278f6 (diff) | |
download | frameworks_base-5bcdff45bf4ada77ae7c95f520b795876adef75c.zip frameworks_base-5bcdff45bf4ada77ae7c95f520b795876adef75c.tar.gz frameworks_base-5bcdff45bf4ada77ae7c95f520b795876adef75c.tar.bz2 |
Fixes #1846038. The dirty region can sometimes be modified by SurfaceFlinger. When this happens, force the view hierarchy to ignore the dirty flags.
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/View.java | 25 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 5 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 5 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 49 |
4 files changed, 57 insertions, 27 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9e709cf..16b70ed 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1449,7 +1449,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED, name = "LAYOUT_REQUIRED"), @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID, - name = "DRAWING_CACHE_VALID", outputIf = false), + name = "DRAWING_CACHE_INVALID", outputIf = false), @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true), @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false), @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), @@ -5739,13 +5739,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback { final int restoreCount = canvas.save(); canvas.translate(-mScrollX, -mScrollY); - mPrivateFlags = (mPrivateFlags & ~DIRTY_MASK) | DRAWN; + mPrivateFlags |= DRAWN; // Fast path for layouts with no backgrounds if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); } + mPrivateFlags &= ~DIRTY_MASK; dispatchDraw(canvas); } else { draw(canvas); @@ -5792,7 +5793,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { canvas = new Canvas(bitmap); } - if ((backgroundColor&0xff000000) != 0) { + if ((backgroundColor & 0xff000000) != 0) { bitmap.eraseColor(backgroundColor); } @@ -5800,6 +5801,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback { final int restoreCount = canvas.save(); canvas.translate(-mScrollX, -mScrollY); + // Temporarily remove the dirty mask + int flags = mPrivateFlags; + mPrivateFlags &= ~DIRTY_MASK; + // Fast path for layouts with no backgrounds if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { dispatchDraw(canvas); @@ -5807,6 +5812,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback { draw(canvas); } + mPrivateFlags = flags; + canvas.restoreToCount(restoreCount); if (attachInfo != null) { @@ -5927,8 +5934,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); } - final boolean dirtyOpaque = (mPrivateFlags & DIRTY_MASK) == DIRTY_OPAQUE; - mPrivateFlags = (mPrivateFlags & ~DIRTY_MASK) | DRAWN; + final int privateFlags = mPrivateFlags; + final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE && + (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); + mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN; /* * Draw traversal performs several drawing steps which must be executed @@ -8158,7 +8167,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * window. */ static class AttachInfo { - interface Callbacks { void playSoundEffect(int effectId); boolean performHapticFeedback(int effectId, boolean always); @@ -8288,6 +8296,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback { long mDrawingTime; /** + * Indicates whether or not ignoring the DIRTY_MASK flags. + */ + boolean mIgnoreDirtyState; + + /** * Indicates whether the view's window is currently in touch mode. */ boolean mInTouchMode; diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 74a248f..aaaadef 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -1235,10 +1235,11 @@ public class ViewDebug { for (int j = 0; j < count; j++) { final FlagToString flagMapping = mapping[j]; final boolean ifTrue = flagMapping.outputIf(); - final boolean test = (intValue & flagMapping.mask()) == flagMapping.equals(); + final int maskResult = intValue & flagMapping.mask(); + final boolean test = maskResult == flagMapping.equals(); if ((test && ifTrue) || (!test && !ifTrue)) { final String name = flagMapping.name(); - final String value = ifTrue ? "true" : "false"; + final String value = "0x" + Integer.toHexString(maskResult); writeEntry(out, prefix, name, "", value); } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 26fe776..db5177f 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1403,9 +1403,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } - // Clear the flag as early as possible to allow draw() implementations + // Sets the flag as early as possible to allow draw() implementations // to call invalidate() successfully when doing animations - child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN; + child.mPrivateFlags |= DRAWN; if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) && (child.mPrivateFlags & DRAW_ANIMATION) == 0) { @@ -1482,6 +1482,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); } + child.mPrivateFlags &= ~DIRTY_MASK; child.dispatchDraw(canvas); } else { child.draw(canvas); diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 5090c56..dbfb194 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -537,7 +537,6 @@ public final class ViewRoot extends Handler implements ViewParent, } dirty = mTempRect; } - // TODO: When doing a union with mDirty != empty, we must cancel all the DIRTY_OPAQUE flags mDirty.union(dirty); if (!mWillDrawSoon) { scheduleTraversals(); @@ -1142,8 +1141,7 @@ public final class ViewRoot extends Handler implements ViewParent, } int yoff; - final boolean scrolling = mScroller != null - && mScroller.computeScrollOffset(); + final boolean scrolling = mScroller != null && mScroller.computeScrollOffset(); if (scrolling) { yoff = mScroller.getCurrY(); } else { @@ -1158,13 +1156,14 @@ public final class ViewRoot extends Handler implements ViewParent, if (mUseGL) { if (!dirty.isEmpty()) { Canvas canvas = mGlCanvas; - if (mGL!=null && canvas != null) { + if (mGL != null && canvas != null) { mGL.glDisable(GL_SCISSOR_TEST); mGL.glClearColor(0, 0, 0, 0); mGL.glClear(GL_COLOR_BUFFER_BIT); mGL.glEnable(GL_SCISSOR_TEST); mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); + mAttachInfo.mIgnoreDirtyState = true; mView.mPrivateFlags |= View.DRAWN; float scale = mAppScale; @@ -1182,6 +1181,8 @@ public final class ViewRoot extends Handler implements ViewParent, canvas.restoreToCount(saveCount); } + mAttachInfo.mIgnoreDirtyState = false; + mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); checkEglErrors(); @@ -1201,8 +1202,10 @@ public final class ViewRoot extends Handler implements ViewParent, return; } - if (fullRedrawNeeded) + if (fullRedrawNeeded) { + mAttachInfo.mIgnoreDirtyState = true; dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale)); + } if (DEBUG_ORIENTATION || DEBUG_DRAW) { Log.v("ViewRoot", "Draw " + mView + "/" @@ -1214,7 +1217,18 @@ public final class ViewRoot extends Handler implements ViewParent, Canvas canvas; try { + int left = dirty.left; + int top = dirty.top; + int right = dirty.right; + int bottom = dirty.bottom; + canvas = surface.lockCanvas(dirty); + + if (left != dirty.left || top != dirty.top || right != dirty.right || + bottom != dirty.bottom) { + mAttachInfo.mIgnoreDirtyState = true; + } + // TODO: Do this in native canvas.setDensityScale(mDensity); } catch (Surface.OutOfResourcesException e) { @@ -1242,12 +1256,11 @@ public final class ViewRoot extends Handler implements ViewParent, // need to clear it before drawing so that the child will // properly re-composite its drawing on a transparent // background. This automatically respects the clip/dirty region - if (!canvas.isOpaque()) { - canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR); - } else if (yoff != 0) { - // If we are applying an offset, we need to clear the area - // where the offset doesn't appear to avoid having garbage - // left in the blank areas. + // or + // If we are applying an offset, we need to clear the area + // where the offset doesn't appear to avoid having garbage + // left in the blank areas. + if (!canvas.isOpaque() || yoff != 0) { canvas.drawColor(0, PorterDuff.Mode.CLEAR); } @@ -1257,9 +1270,10 @@ public final class ViewRoot extends Handler implements ViewParent, mView.mPrivateFlags |= View.DRAWN; float scale = mAppScale; - Context cxt = mView.getContext(); if (DEBUG_DRAW) { - Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + ", appScale=" + mAppScale); + Context cxt = mView.getContext(); + Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + + ", appScale=" + mAppScale); } int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { @@ -1269,14 +1283,15 @@ public final class ViewRoot extends Handler implements ViewParent, canvas.scale(scale, scale); } mView.draw(canvas); - - if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { - mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING); - } } finally { + mAttachInfo.mIgnoreDirtyState = false; canvas.restoreToCount(saveCount); } + if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { + mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING); + } + if (Config.DEBUG && ViewDebug.showFps) { int now = (int)SystemClock.elapsedRealtime(); if (sDrawTime != 0) { |