From 8fb954263dd2f918ad339045cc6d82e346515599 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 17 Aug 2010 18:38:51 -0700 Subject: [PATCH] Fix save()/restore() issues in the OpenGL renderer. The save stack now behaves exactly like in Skia. Change-Id: If7e642f41f2c8f693f6e8c26cba81507d466562e --- core/java/android/view/HardwareRenderer.java | 2 +- core/java/android/view/View.java | 14 ++++----- core/java/android/view/ViewRoot.java | 2 -- .../android/widget/ScrollBarDrawable.java | 3 +- libs/hwui/OpenGLRenderer.cpp | 31 ++++++++++++------- libs/hwui/Snapshot.h | 9 +++++- .../res/layout/list_activity.xml | 25 +++++++++++++++ .../test/hwui/QuickRejectActivity.java | 27 ++++++++++++++++ 8 files changed, 87 insertions(+), 26 deletions(-) diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 44bd6d47d6782..ca60a8966fe52 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -385,7 +385,7 @@ public abstract class HardwareRenderer { onPreDraw(); Canvas canvas = mCanvas; - int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); + int saveCount = canvas.save(); canvas.translate(0, -yOffset); try { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 570793bda6e04..a0e840d63bac2 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6630,9 +6630,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @see android.widget.ScrollBarDrawable * @hide */ - protected void onDrawHorizontalScrollBar(Canvas canvas, - Drawable scrollBar, - int l, int t, int r, int b) { + protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, + int l, int t, int r, int b) { scrollBar.setBounds(l, t, r, b); scrollBar.draw(canvas); } @@ -6651,9 +6650,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @see android.widget.ScrollBarDrawable * @hide */ - protected void onDrawVerticalScrollBar(Canvas canvas, - Drawable scrollBar, - int l, int t, int r, int b) { + protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, + int l, int t, int r, int b) { scrollBar.setBounds(l, t, r, b); scrollBar.draw(canvas); } @@ -10018,8 +10016,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); - private final float[] mOpaque = {255.0f}; - private final float[] mTransparent = {0.0f}; + private final float[] mOpaque = { 255.0f }; + private final float[] mTransparent = { 0.0f }; /** * When fading should start. This time moves into the future every time diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index faa478309fc48..d32ccb1ddbbc5 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1363,7 +1363,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn ", metrics=" + cxt.getResources().getDisplayMetrics() + ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo()); } - int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); if (mTranslator != null) { @@ -1374,7 +1373,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mView.draw(canvas); } finally { mAttachInfo.mIgnoreDirtyState = false; - canvas.restoreToCount(saveCount); } if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java index 3b113ae332dd9..93a1179c8c0da 100644 --- a/core/java/android/widget/ScrollBarDrawable.java +++ b/core/java/android/widget/ScrollBarDrawable.java @@ -111,8 +111,7 @@ public class ScrollBarDrawable extends Drawable { } Rect r = getBounds(); - if (canvas.quickReject(r.left, r.top, r.right, r.bottom, - Canvas.EdgeType.AA)) { + if (canvas.quickReject(r.left, r.top, r.right, r.bottom, Canvas.EdgeType.AA)) { return; } if (drawTrack) { diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index f35c3808a5722..35e17bfb4a9e7 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -193,7 +193,7 @@ void OpenGLRenderer::setViewport(int width, int height) { void OpenGLRenderer::prepare() { mSnapshot = new Snapshot(mFirstSnapshot); - mSaveCount = 0; + mSaveCount = 1; glDisable(GL_SCISSOR_TEST); @@ -219,19 +219,17 @@ int OpenGLRenderer::save(int flags) { } void OpenGLRenderer::restore() { - if (mSaveCount == 0) return; - - if (restoreSnapshot()) { + if (mSaveCount > 1 && restoreSnapshot()) { setScissorFromClip(); } } void OpenGLRenderer::restoreToCount(int saveCount) { - if (saveCount <= 0 || saveCount > mSaveCount) return; + if (saveCount < 1) saveCount = 1; bool restoreClip = false; - while (mSaveCount != saveCount - 1) { + while (mSaveCount > saveCount) { restoreClip |= restoreSnapshot(); } @@ -242,7 +240,7 @@ void OpenGLRenderer::restoreToCount(int saveCount) { int OpenGLRenderer::saveSnapshot() { mSnapshot = new Snapshot(mSnapshot); - return ++mSaveCount; + return mSaveCount++; } bool OpenGLRenderer::restoreSnapshot() { @@ -263,10 +261,18 @@ bool OpenGLRenderer::restoreSnapshot() { composeLayer(current, previous); } + bool skip = mSnapshot->skip; + if (!skip) { + mSaveCount--; + } mSnapshot = previous; - mSaveCount--; - return restoreClip; + if (!skip) { + return restoreClip; + } else { + bool restorePreviousClip = restoreSnapshot(); + return restoreClip || restorePreviousClip; + } } /////////////////////////////////////////////////////////////////////////////// @@ -324,18 +330,20 @@ bool OpenGLRenderer::createLayer(sp snapshot, float left, float top, glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); - // Save the layer in the snapshot - snapshot->flags |= Snapshot::kFlagIsLayer; layer->mode = mode; layer->alpha = alpha / 255.0f; layer->layer.set(left, top, right, bottom); + // Save the layer in the snapshot + snapshot->flags |= Snapshot::kFlagIsLayer; snapshot->layer = layer; snapshot->fbo = layer->fbo; // Creates a new snapshot to draw into the FBO saveSnapshot(); + mSaveCount--; + mSnapshot->skip = true; mSnapshot->transform.loadTranslate(-left, -top, 0.0f); mSnapshot->setClip(0.0f, 0.0f, right - left, bottom - top); mSnapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top); @@ -432,7 +440,6 @@ const Rect& OpenGLRenderer::getClipBounds() { bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { Rect r(left, top, right, bottom); mSnapshot->transform.mapRect(r); - return !mSnapshot->clipRect.intersects(r); } diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index 21b2bef16442d..77650a3e4e367 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -42,7 +42,7 @@ namespace uirenderer { */ class Snapshot: public LightRefBase { public: - Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0) { } + Snapshot(): skip(false), flags(0), previous(NULL), layer(NULL), fbo(0) { } /** * Copies the specified snapshot. Only the transform and clip rectangle @@ -54,6 +54,7 @@ public: height(s->height), transform(s->transform), clipRect(s->clipRect), + skip(false), flags(0), previous(s), layer(NULL), @@ -164,6 +165,12 @@ public: */ Rect clipRect; + /** + * This snapshot should be skipped. Snapshots marked as skipped are + * created by the renderer and should be hidden from the user. + */ + bool skip; + /** * Dirty flags. */ diff --git a/tests/HwAccelerationTest/res/layout/list_activity.xml b/tests/HwAccelerationTest/res/layout/list_activity.xml index f548f53ed5d78..6bba3702069aa 100644 --- a/tests/HwAccelerationTest/res/layout/list_activity.xml +++ b/tests/HwAccelerationTest/res/layout/list_activity.xml @@ -19,6 +19,31 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + +