Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b7a3053 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix damage tracking for RenderNode drawn twice"

parents 49c1069c f1aa7909
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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) {
+2 −0
Original line number Diff line number Diff line
@@ -255,6 +255,8 @@ private:
    DisplayList* mDisplayList;
    DisplayList* mStagingDisplayList;

    int64_t mDamageGenerationId;

    friend class AnimatorManager;
    AnimatorManager mAnimatorManager;

+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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;
+71 −19
Original line number Diff line number Diff line
@@ -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,38 +40,86 @@ public class CustomRenderer extends Activity {
        getWindow().takeSurface(mSurfaceCallbacks);
    }

    private SurfaceHolder.Callback2 mSurfaceCallbacks = new SurfaceHolder.Callback2() {

    @Override
        public void surfaceRedrawNeeded(SurfaceHolder holder) {
    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
        public void surfaceCreated(SurfaceHolder holder) {
    protected void onStop() {
        super.onStop();
        mAnimator.end();
        mAnimator = null;
    }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            mContent.setLeftTopRightBottom(0, 0, width, height);
            RecordingCanvas canvas = mContent.beginRecording();
    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);
            paint.setTextSize(Math.min(width, height) * .05f);
            canvas.drawText("Hello custom renderer!", width / 2, height / 2, paint);
            mContent.endRecording();
        float textSize = Math.min(width, height) * .05f;
        paint.setTextSize(textSize);
        canvas.drawText("Hello custom renderer!", width / 2, textSize * 2, paint);

            mRenderer.setContentRoot(mContent);
            mRenderer.setSurface(holder.getSurface());
        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())
                    .setFrameCommitCallback(Runnable::run, () -> {
                        Log.d("CustomRenderer", "Frame committed!");
                    })
                .syncAndDraw();
    }

    private SurfaceHolder.Callback2 mSurfaceCallbacks = new SurfaceHolder.Callback2() {

        @Override
        public void surfaceRedrawNeeded(SurfaceHolder holder) {
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            setupRoot(width, height);

            mRenderer.setContentRoot(mRootNode);
            mRenderer.setSurface(holder.getSurface());
            draw();
            if (!mAnimator.isStarted()) {
                mAnimator.start();
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            mRenderer.destroy();