[Shadows] Add shadow radius to sf layer state (2/n)
Bug: 136561771
Test: atest SurfaceFlinger_Test
Change-Id: Icafe852eaad195163b48b802db2a4b092aa30926
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e004e95..e392bc5 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -406,6 +406,12 @@
what |= eMetadataChanged;
metadata.merge(other.metadata);
}
+
+ if (other.what & eShadowRadiusChanged) {
+ what |= eShadowRadiusChanged;
+ shadowRadius = other.shadowRadius;
+ }
+
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e9079ef..14f47c3 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1335,6 +1335,18 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setShadowRadius(
+ const sp<SurfaceControl>& sc, float shadowRadius) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eShadowRadiusChanged;
+ s->shadowRadius = shadowRadius;
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index a49ed52..c2b5119 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -72,7 +72,7 @@
eCropChanged_legacy = 0x00000100,
eDeferTransaction_legacy = 0x00000200,
eOverrideScalingModeChanged = 0x00000400,
- // AVAILABLE 0x00000800,
+ eShadowRadiusChanged = 0x00000800,
eReparentChildren = 0x00001000,
eDetachChildren = 0x00002000,
eRelativeLayerChanged = 0x00004000,
@@ -126,7 +126,8 @@
colorTransform(mat4()),
bgColorAlpha(0),
bgColorDataspace(ui::Dataspace::UNKNOWN),
- colorSpaceAgnostic(false) {
+ colorSpaceAgnostic(false),
+ shadowRadius(0.0f) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -204,6 +205,9 @@
bool colorSpaceAgnostic;
std::vector<ListenerCallbacks> listeners;
+
+ // Draws a shadow around the surface.
+ float shadowRadius;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 08f4e9e..a140142 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -474,6 +474,7 @@
Transaction& setGeometry(const sp<SurfaceControl>& sc,
const Rect& source, const Rect& dst, int transform);
+ Transaction& setShadowRadius(const sp<SurfaceControl>& sc, float cornerRadius);
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
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;
}