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

Commit b78a3dee authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Use CompositingStrategy.Offscreen in Modifier.punchHole (1/2)

This CL optimizes Modifier.punchHole by using an Offscreen composition
strategy (so that the layer can be blended against) rather than using
Canvas.withSaveLayer {} that reallocates an offscreen buffer every
frame.

Bug: 305195729
Test: PunchHoleTest
Flag: N/A
Change-Id: If26804247f36f763c812b007ecb114259c836e3b
parent f312646d
Loading
Loading
Loading
Loading
+21 −12
Original line number Diff line number Diff line
@@ -20,24 +20,26 @@ import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.geometry.toRect
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawOutline
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.withSaveLayer
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.node.DelegatingNode
import androidx.compose.ui.node.DrawModifierNode
import androidx.compose.ui.node.GlobalPositionAwareModifierNode
import androidx.compose.ui.node.LayoutModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.toSize

@@ -88,11 +90,22 @@ private class PunchHoleNode(
    var size: () -> Size,
    var offset: () -> Offset,
    var shape: () -> Shape,
) : Modifier.Node(), DrawModifierNode {
) : Modifier.Node(), DrawModifierNode, LayoutModifierNode {
    private var lastSize: Size = Size.Unspecified
    private var lastLayoutDirection: LayoutDirection = LayoutDirection.Ltr
    private var lastOutline: Outline? = null

    override fun MeasureScope.measure(
        measurable: Measurable,
        constraints: Constraints
    ): MeasureResult {
        return measurable.measure(constraints).run {
            layout(width, height) {
                placeWithLayer(0, 0) { compositingStrategy = CompositingStrategy.Offscreen }
            }
        }
    }

    override fun ContentDrawScope.draw() {
        val holeSize = size()
        if (holeSize == Size.Zero) {
@@ -100,15 +113,11 @@ private class PunchHoleNode(
            return
        }

        drawIntoCanvas { canvas ->
            canvas.withSaveLayer(size.toRect(), Paint()) {
        drawContent()

        val offset = offset()
        translate(offset.x, offset.y) { drawHole(holeSize) }
    }
        }
    }

    private fun DrawScope.drawHole(size: Size) {
        if (shape == RectangleShape) {