--wip-- [skip ci]
diff --git a/issue-repro/src/main/java/com/airbnb/lottie/issues/IssueReproActivity.kt b/issue-repro/src/main/java/com/airbnb/lottie/issues/IssueReproActivity.kt
index 495438c..8cd1885 100755
--- a/issue-repro/src/main/java/com/airbnb/lottie/issues/IssueReproActivity.kt
+++ b/issue-repro/src/main/java/com/airbnb/lottie/issues/IssueReproActivity.kt
@@ -1,7 +1,12 @@
 package com.airbnb.lottie.issues
 
+import android.animation.Animator
+import android.animation.Animator.AnimatorListener
+import android.animation.AnimatorListenerAdapter
 import android.os.Bundle
+import android.util.Log
 import androidx.appcompat.app.AppCompatActivity
+import com.airbnb.lottie.L
 import com.airbnb.lottie.issues.databinding.IssueReproActivityBinding
 
 class IssueReproActivity : AppCompatActivity() {
@@ -10,5 +15,13 @@
         val binding = IssueReproActivityBinding.inflate(layoutInflater)
         setContentView(binding.root)
         // Reproduce any issues here.
+        binding.animationView.addAnimatorListener(object : AnimatorListenerAdapter() {
+            override fun onAnimationRepeat(animation: Animator) {
+                Log.d("Gabe", "Draw %.1f".format(
+                    L.drawTimeNs.getAndSet(0L) / 1_000_000f,
+                ))
+            }
+        })
+
     }
 }
diff --git a/issue-repro/src/main/res/layout/issue_repro_activity.xml b/issue-repro/src/main/res/layout/issue_repro_activity.xml
index 05ea4fb..9e29817 100755
--- a/issue-repro/src/main/res/layout/issue_repro_activity.xml
+++ b/issue-repro/src/main/res/layout/issue_repro_activity.xml
@@ -9,7 +9,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        app:lottie_rawRes="@raw/heart"
+        app:lottie_rawRes="@raw/matte"
         app:lottie_autoPlay="true"
         app:lottie_loop="true"/>
 </FrameLayout>
\ No newline at end of file
diff --git a/issue-repro/src/main/res/raw/matte.json b/issue-repro/src/main/res/raw/matte.json
new file mode 100644
index 0000000..e094c12
--- /dev/null
+++ b/issue-repro/src/main/res/raw/matte.json
@@ -0,0 +1 @@
+{"v":"5.10.2","fr":60,"ip":0,"op":60,"w":756,"h":756,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[372,358,0],"to":[56.833,58.167,0],"ti":[-56.833,-58.167,0]},{"t":59,"s":[713,707,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[381.742,381.742],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-164.035,-154.496],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":1,"nm":"Purple Solid 1","tt":1,"tp":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[378,378,0],"ix":2,"l":2},"a":{"a":0,"k":[378,378,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"sw":756,"sh":756,"sc":"#a100ff","ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/lottie/src/main/java/com/airbnb/lottie/L.java b/lottie/src/main/java/com/airbnb/lottie/L.java
index a27d7da..861348b 100644
--- a/lottie/src/main/java/com/airbnb/lottie/L.java
+++ b/lottie/src/main/java/com/airbnb/lottie/L.java
@@ -15,6 +15,7 @@
 import com.airbnb.lottie.utils.LottieTrace;
 
 import java.io.File;
+import java.util.concurrent.atomic.AtomicLong;
 
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public class L {
@@ -33,6 +34,10 @@
   private static volatile NetworkCache networkCache;
   private static ThreadLocal<LottieTrace> lottieTrace;
 
+  public static boolean renderNode = true;
+
+  public static AtomicLong drawTimeNs = new AtomicLong(0L);
+
   private L() {
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
index e493288..2d39708 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
@@ -680,7 +680,10 @@
         renderAndDrawAsBitmap(canvas, compositionLayer);
         canvas.restore();
       } else {
+        long start = System.nanoTime();
         compositionLayer.draw(canvas, matrix, alpha);
+        long end = System.nanoTime();
+        L.drawTimeNs.getAndAdd(end - start);
       }
       isDirty = false;
     } catch (InterruptedException e) {
@@ -1560,6 +1563,7 @@
       return;
     }
 
+    long start = System.nanoTime();
     renderingMatrix.reset();
     Rect bounds = getBounds();
     if (!bounds.isEmpty()) {
@@ -1571,6 +1575,8 @@
       renderingMatrix.preTranslate(bounds.left, bounds.top);
     }
     compositionLayer.draw(canvas, renderingMatrix, alpha);
+    long end = System.nanoTime();
+    L.drawTimeNs.getAndAdd(end - start);
   }
 
   /**
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
index 5775c18..fa8327d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
@@ -1,5 +1,6 @@
 package com.airbnb.lottie.model.layer;
 
+import android.annotation.SuppressLint;
 import android.graphics.BlurMaskFilter;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -8,7 +9,9 @@
 import android.graphics.Path;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
+import android.graphics.RecordingCanvas;
 import android.graphics.RectF;
+import android.graphics.RenderNode;
 import android.os.Build;
 
 import androidx.annotation.CallSuper;
@@ -110,6 +113,9 @@
   final TransformKeyframeAnimation transform;
   private boolean visible = true;
 
+  @SuppressLint("NewApi")
+  private final RenderNode renderNode = new RenderNode("BaseLayer");
+
   private boolean outlineMasksAndMattes;
   @Nullable private Paint outlineMasksAndMattesPaint;
 
@@ -290,38 +296,46 @@
     // On older devices, drawing to an offscreen buffer of <1px would draw back as a black bar.
     // https://github.com/airbnb/lottie-android/issues/1625
     if (rect.width() >= 1f && rect.height() >= 1f) {
-      L.beginSection("Layer#saveLayer");
-      contentPaint.setAlpha(255);
-      Utils.saveLayerCompat(canvas, rect, contentPaint);
-      L.endSection("Layer#saveLayer");
-
-      // Clear the off screen buffer. This is necessary for some phones.
-      clearCanvas(canvas);
-      L.beginSection("Layer#drawLayer");
-      drawLayer(canvas, matrix, alpha);
-      L.endSection("Layer#drawLayer");
-
-      if (hasMasksOnThisLayer()) {
-        applyMasks(canvas, matrix);
-      }
-
-      if (hasMatteOnThisLayer()) {
-        L.beginSection("Layer#drawMatte");
+      if (renderNode.hasDisplayList()) {
+        canvas.drawRenderNode(renderNode);
+      } else {
+        renderNode.setPosition(0, 0, canvas.getWidth(), canvas.getHeight());
+        RecordingCanvas recordingCanvas = renderNode.beginRecording();
+        Canvas canvas2 = L.renderNode ? recordingCanvas : canvas;
         L.beginSection("Layer#saveLayer");
-        Utils.saveLayerCompat(canvas, rect, mattePaint, SAVE_FLAGS);
+        contentPaint.setAlpha(255);
+        Utils.saveLayerCompat(canvas2, rect, contentPaint);
         L.endSection("Layer#saveLayer");
-        clearCanvas(canvas);
-        //noinspection ConstantConditions
-        matteLayer.draw(canvas, parentMatrix, alpha);
-        L.beginSection("Layer#restoreLayer");
-        canvas.restore();
-        L.endSection("Layer#restoreLayer");
-        L.endSection("Layer#drawMatte");
-      }
 
-      L.beginSection("Layer#restoreLayer");
-      canvas.restore();
-      L.endSection("Layer#restoreLayer");
+        // Clear the off screen buffer. This is necessary for some phones.
+        clearCanvas(canvas2);
+        L.beginSection("Layer#drawLayer");
+        drawLayer(canvas2, matrix, alpha);
+        L.endSection("Layer#drawLayer");
+
+        if (hasMasksOnThisLayer()) {
+          applyMasks(canvas2, matrix);
+        }
+
+        if (hasMatteOnThisLayer()) {
+          L.beginSection("Layer#drawMatte");
+          L.beginSection("Layer#saveLayer");
+          Utils.saveLayerCompat(canvas2, rect, mattePaint, SAVE_FLAGS);
+          L.endSection("Layer#saveLayer");
+          clearCanvas(canvas2);
+          //noinspection ConstantConditions
+          matteLayer.draw(canvas2, parentMatrix, alpha);
+          L.beginSection("Layer#restoreLayer");
+          canvas2.restore();
+          L.endSection("Layer#restoreLayer");
+          L.endSection("Layer#drawMatte");
+        }
+
+        L.beginSection("Layer#restoreLayer");
+        canvas2.restore();
+        L.endSection("Layer#restoreLayer");
+        renderNode.endRecording();
+      }
     }
 
     if (outlineMasksAndMattes && outlineMasksAndMattesPaint != null) {