SurfaceFlinger: Inherit Alpha for child surfaces.
Necessary for various animations to work correctly and
for the general goal of treating child surfaces like
pixels in the parent surface.
Test: Includes new test in SurfaceFlinger_test
Bug: None yet ;)
Change-Id: Ic8309518bd327bbba6ad2f79f265e24cf37898e7
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index adfff96..ac7e083 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -595,7 +595,7 @@
const State& s(getDrawingState());
#ifdef USE_HWC2
auto blendMode = HWC2::BlendMode::None;
- if (!isOpaque(s) || s.alpha != 1.0f) {
+ if (!isOpaque(s) || getAlpha() != 1.0f) {
blendMode = mPremultipliedAlpha ?
HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
}
@@ -604,7 +604,7 @@
" %s (%d)", mName.string(), to_string(blendMode).c_str(),
to_string(error).c_str(), static_cast<int32_t>(error));
#else
- if (!isOpaque(s) || s.alpha != 0xFF) {
+ if (!isOpaque(s) || getAlpha() != 0xFF) {
layer.setBlending(mPremultipliedAlpha ?
HWC_BLENDING_PREMULT :
HWC_BLENDING_COVERAGE);
@@ -678,9 +678,10 @@
hwcInfo.sourceCrop = sourceCrop;
}
- error = hwcLayer->setPlaneAlpha(s.alpha);
+ float alpha = getAlpha();
+ error = hwcLayer->setPlaneAlpha(alpha);
ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
- "%s (%d)", mName.string(), s.alpha, to_string(error).c_str(),
+ "%s (%d)", mName.string(), alpha, to_string(error).c_str(),
static_cast<int32_t>(error));
error = hwcLayer->setZOrder(z);
@@ -698,7 +699,7 @@
const Transform& tr(hw->getTransform());
layer.setFrame(tr.transform(frame));
layer.setCrop(computeCrop(hw));
- layer.setPlaneAlpha(s.alpha);
+ layer.setPlaneAlpha(getAlpha());
#endif
/*
@@ -1147,7 +1148,7 @@
texCoords[3] = vec2(right, 1.0f - top);
RenderEngine& engine(mFlinger->getRenderEngine());
- engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
+ engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
engine.drawMesh(mMesh);
engine.disableBlending();
}
@@ -1961,12 +1962,11 @@
}
bool Layer::isVisible() const {
- const Layer::State& s(mDrawingState);
#ifdef USE_HWC2
- return !(isHiddenByPolicy()) && s.alpha > 0.0f
+ return !(isHiddenByPolicy()) && getAlpha() > 0.0f
&& (mActiveBuffer != NULL || mSidebandStream != NULL);
#else
- return !(isHiddenByPolicy()) && s.alpha
+ return !(isHiddenByPolicy()) && getAlpha()
&& (mActiveBuffer != NULL || mSidebandStream != NULL);
#endif
}
@@ -2523,6 +2523,24 @@
return t * getDrawingState().active.transform;
}
+#ifdef USE_HWC2
+float Layer::getAlpha() const {
+ const auto& p = getParent();
+
+ float parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0;
+ return parentAlpha * getDrawingState().alpha;
+}
+#else
+uint8_t Layer::getAlpha() const {
+ const auto& p = getParent();
+
+ float parentAlpha = (p != nullptr) ? (p->getAlpha() / 255.0f) : 1.0;
+ float drawingAlpha = getDrawingState().alpha / 255.0f;
+ drawingAlpha = drawingAlpha * parentAlpha;
+ return static_cast<uint8_t>(std::round(drawingAlpha * 255));
+}
+#endif
+
void Layer::commitChildList() {
for (size_t i = 0; i < mCurrentChildren.size(); i++) {
const auto& child = mCurrentChildren[i];