[Shadows] Add shadow radius to sf layer state (2/n)

Bug: 136561771
Test: atest SurfaceFlinger_Test
Change-Id: Icafe852eaad195163b48b802db2a4b092aa30926
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index b48d471..9b7bab1 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -34,6 +34,7 @@
     bool isCreatedFromMainThread() const override { return true; }
 
 protected:
+    bool canDrawShadows() const override { return false; }
     sp<Layer> createClone() override;
 };
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index e19b79b..b51653d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -339,7 +339,8 @@
     return bufferScaleTransform.inverse().transform(mBounds);
 }
 
-void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform) {
+void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform,
+                          float parentShadowRadius) {
     const State& s(getDrawingState());
 
     // Calculate effective layer transform
@@ -362,11 +363,23 @@
     mBounds = bounds;
     mScreenBounds = mEffectiveTransform.transform(mBounds);
 
+    // Use the layer's own shadow radius if set. Otherwise get the radius from
+    // parent.
+    if (s.shadowRadius > 0.f) {
+        mEffectiveShadowRadius = s.shadowRadius;
+    } else {
+        mEffectiveShadowRadius = parentShadowRadius;
+    }
+
+    // Shadow radius is passed down to only one layer so if the layer can draw shadows,
+    // don't pass it to its children.
+    const float childShadowRadius = canDrawShadows() ? 0.f : mEffectiveShadowRadius;
+
     // Add any buffer scaling to the layer's children.
     ui::Transform bufferScaleTransform = getBufferScaleTransform();
     for (const sp<Layer>& child : mDrawingChildren) {
         child->computeBounds(getBoundsPreScaling(bufferScaleTransform),
-                             getTransformWithScale(bufferScaleTransform));
+                             getTransformWithScale(bufferScaleTransform), childShadowRadius);
     }
 }
 
@@ -466,11 +479,13 @@
     compositionState.hasProtectedContent = isProtected();
 
     const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
+    const bool drawsShadows = mEffectiveShadowRadius != 0.f;
+
     compositionState.isOpaque =
             isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf;
 
     // Force client composition for special cases known only to the front-end.
-    if (isHdrY410() || usesRoundedCorners) {
+    if (isHdrY410() || usesRoundedCorners || drawsShadows) {
         compositionState.forceClientComposition = true;
     }
 }
@@ -1116,6 +1131,18 @@
     return p->getLayerStack();
 }
 
+bool Layer::setShadowRadius(float shadowRadius) {
+    if (mCurrentState.shadowRadius == shadowRadius) {
+        return false;
+    }
+
+    mCurrentState.sequence++;
+    mCurrentState.shadowRadius = shadowRadius;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
 void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
     ATRACE_CALL();
     mCurrentState.barrierLayer_legacy = barrierLayer;
@@ -1410,8 +1437,8 @@
     for (const sp<Layer>& child : mDrawingChildren) {
         child->mDrawingParent = newParent;
         child->computeBounds(newParent->mBounds,
-                             newParent->getTransformWithScale(
-                                     newParent->getBufferScaleTransform()));
+                             newParent->getTransformWithScale(newParent->getBufferScaleTransform()),
+                             newParent->mEffectiveShadowRadius);
     }
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index fdac98f..648be3e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -216,6 +216,7 @@
         std::deque<sp<CallbackHandle>> callbackHandles;
         bool colorSpaceAgnostic;
         nsecs_t desiredPresentTime = -1;
+        float shadowRadius;
     };
 
     explicit Layer(const LayerCreationArgs& args);
@@ -329,6 +330,7 @@
     };
     virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
     virtual bool setColorSpaceAgnostic(const bool agnostic);
+    bool setShadowRadius(float shadowRadius);
 
     virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; }
 
@@ -362,7 +364,7 @@
     FloatRect getBounds() const;
 
     // Compute bounds for the layer and cache the results.
-    void computeBounds(FloatRect parentBounds, ui::Transform parentTransform);
+    void computeBounds(FloatRect parentBounds, ui::Transform parentTransform, float shadowRadius);
 
     // Returns the buffer scale transform if a scaling mode is set.
     ui::Transform getBufferScaleTransform() const;
@@ -942,6 +944,14 @@
     // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children,
     // and relatives, this layer will update as well.
     wp<Layer> mClonedFrom;
+
+    // The inherited shadow radius after taking into account the layer hierarchy. This is the
+    // final shadow radius for this layer. If a shadow is specified for a layer, then effective
+    // shadow radius is the set shadow radius, otherwise its the parent's shadow radius.
+    float mEffectiveShadowRadius;
+
+    // Returns true if the layer can draw shadows on its border.
+    virtual bool canDrawShadows() const { return true; }
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1acb2da..953cb99 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2011,7 +2011,8 @@
                 continue;
             }
 
-            layer->computeBounds(displayDevice->getViewport().toFloatRect(), ui::Transform());
+            layer->computeBounds(displayDevice->getViewport().toFloatRect(), ui::Transform(),
+                                 0.f /* shadowRadius */);
         }
     }
 }
@@ -3335,6 +3336,9 @@
             flags |= eTraversalNeeded;
         }
     }
+    if (what & layer_state_t::eShadowRadiusChanged) {
+        if (layer->setShadowRadius(s.shadowRadius)) flags |= eTraversalNeeded;
+    }
     // This has to happen after we reparent children because when we reparent to null we remove
     // child layers from current state and remove its relative z. If the children are reparented in
     // the same transaction, then we have to make sure we reparent the children first so we do not
@@ -5010,7 +5014,8 @@
                                const Rect& drawingBounds)
                   : oldParent(oldParent), newParent(newParent) {
                 // Compute and cache the bounds for the new parent layer.
-                newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform());
+                newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform(),
+                                         0.f /* shadowRadius */);
                 oldParent->setChildrenDrawingParent(newParent);
             }
             ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); }
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 60da70f..143a7a0 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -803,7 +803,7 @@
         layerDrawingState.active.h = 100;
         layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
                                         LayerProperties::COLOR[2], LayerProperties::COLOR[3]);
-        layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform());
+        layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform(), 0.f /* shadowRadius */);
 
         return layer;
     }