diff options
-rw-r--r-- | libs/hwui/RenderNode.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 2 | ||||
-rw-r--r-- | libs/hwui/TreeInfo.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/TreeInfo.h | 1 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java | 90 |
5 files changed, 82 insertions, 19 deletions
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 1ff7ffe6bf87..e0ed3e4940a8 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -134,6 +134,7 @@ void RenderNode::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) { void RenderNode::damageSelf(TreeInfo& info) { if (isRenderable()) { + mDamageGenerationId = info.damageGenerationId; if (properties().getClipDamageToBounds()) { info.damageAccumulator->dirty(0, 0, properties().getWidth(), properties().getHeight()); } else { @@ -199,6 +200,12 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { * stencil buffer may be needed. Views that use a functor to draw will be forced onto a layer. */ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) { + if (mDamageGenerationId == info.damageGenerationId) { + // We hit the same node a second time in the same tree. We don't know the minimal + // damage rect anymore, so just push the biggest we can onto our parent's transform + // We push directly onto parent in case we are clipped to bounds but have moved position. + info.damageAccumulator->dirty(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX); + } info.damageAccumulator->pushTransform(this); if (info.mode == TreeInfo::MODE_FULL) { diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index 6060123ed759..23e7a0e60554 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -255,6 +255,8 @@ private: DisplayList* mDisplayList; DisplayList* mStagingDisplayList; + int64_t mDamageGenerationId; + friend class AnimatorManager; AnimatorManager mAnimatorManager; diff --git a/libs/hwui/TreeInfo.cpp b/libs/hwui/TreeInfo.cpp index 808a12a311e2..cdad20ec6caa 100644 --- a/libs/hwui/TreeInfo.cpp +++ b/libs/hwui/TreeInfo.cpp @@ -24,6 +24,7 @@ TreeInfo::TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContex : mode(mode) , prepareTextures(mode == MODE_FULL) , canvasContext(canvasContext) + , damageGenerationId(canvasContext.getFrameNumber()) , disableForceDark(canvasContext.useForceDark() ? 0 : 1) {} } // namespace android::uirenderer diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index a0d960527ca6..04eabac395f0 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -87,6 +87,7 @@ public: // Must not be null during actual usage DamageAccumulator* damageAccumulator = nullptr; + int64_t damageGenerationId = 0; LayerUpdateQueue* layerUpdateQueue = nullptr; ErrorHandler* errorHandler = nullptr; diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java index fece8babb400..5ad7fb9027a2 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java @@ -16,6 +16,7 @@ package com.android.test.hwui; +import android.animation.ObjectAnimator; import android.app.Activity; import android.graphics.Color; import android.graphics.HardwareRenderer; @@ -23,12 +24,15 @@ import android.graphics.Paint; import android.graphics.RecordingCanvas; import android.graphics.RenderNode; import android.os.Bundle; -import android.util.Log; +import android.os.Handler; import android.view.SurfaceHolder; public class CustomRenderer extends Activity { - private RenderNode mContent = new RenderNode("CustomRenderer"); + private RenderNode mRootNode = new RenderNode("CustomRenderer"); + private RenderNode mChildNode = new RenderNode("RedBox"); private HardwareRenderer mRenderer = new HardwareRenderer(); + private ObjectAnimator mAnimator; + private Handler mRedrawHandler = new Handler(true); @Override protected void onCreate(Bundle savedInstanceState) { @@ -36,6 +40,64 @@ public class CustomRenderer extends Activity { getWindow().takeSurface(mSurfaceCallbacks); } + @Override + protected void onStart() { + super.onStart(); + mAnimator = ObjectAnimator.ofFloat(mChildNode, "translationY", 0, 300); + mAnimator.setRepeatMode(ObjectAnimator.REVERSE); + mAnimator.setRepeatCount(ObjectAnimator.INFINITE); + final Runnable redraw = this::draw; + mAnimator.addUpdateListener(animation -> { + mRedrawHandler.post(redraw); + }); + } + + @Override + protected void onStop() { + super.onStop(); + mAnimator.end(); + mAnimator = null; + } + + private void setupRoot(int width, int height) { + mRootNode.setPosition(0, 0, width, height); + + RecordingCanvas canvas = mRootNode.beginRecording(); + canvas.drawColor(Color.WHITE); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(Color.BLACK); + paint.setTextAlign(Paint.Align.CENTER); + float textSize = Math.min(width, height) * .05f; + paint.setTextSize(textSize); + canvas.drawText("Hello custom renderer!", width / 2, textSize * 2, paint); + + canvas.translate(0, height / 4); + canvas.drawRenderNode(mChildNode); + canvas.translate(width / 2, 0); + canvas.drawRenderNode(mChildNode); + mRootNode.endRecording(); + + setupChild(width / 2, height / 2); + } + + private void setupChild(int width, int height) { + mChildNode.setPosition(0, 0, width, height); + mChildNode.setScaleX(.5f); + mChildNode.setScaleY(.5f); + + RecordingCanvas canvas = mChildNode.beginRecording(); + canvas.drawColor(Color.RED); + mChildNode.endRecording(); + } + + private void draw() { + // Since we are constantly pumping frames between onStart & onStop we don't really + // care about any errors that may happen. They will self-correct. + mRenderer.createRenderRequest() + .setVsyncTime(System.nanoTime()) + .syncAndDraw(); + } + private SurfaceHolder.Callback2 mSurfaceCallbacks = new SurfaceHolder.Callback2() { @Override @@ -48,24 +110,14 @@ public class CustomRenderer extends Activity { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - mContent.setLeftTopRightBottom(0, 0, width, height); - RecordingCanvas canvas = mContent.beginRecording(); - canvas.drawColor(Color.WHITE); - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setColor(Color.BLACK); - paint.setTextAlign(Paint.Align.CENTER); - paint.setTextSize(Math.min(width, height) * .05f); - canvas.drawText("Hello custom renderer!", width / 2, height / 2, paint); - mContent.endRecording(); - - mRenderer.setContentRoot(mContent); + setupRoot(width, height); + + mRenderer.setContentRoot(mRootNode); mRenderer.setSurface(holder.getSurface()); - mRenderer.createRenderRequest() - .setVsyncTime(System.nanoTime()) - .setFrameCommitCallback(Runnable::run, () -> { - Log.d("CustomRenderer", "Frame committed!"); - }) - .syncAndDraw(); + draw(); + if (!mAnimator.isStarted()) { + mAnimator.start(); + } } @Override |