Add plumbing for sending stretch effect to SF
Bug: 179047472
Test: builds & boots, doesn't do anything yet
Change-Id: Ib8cccdde518f0591c2f2ee3416684442f37a1e06
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index fff3305..f053372 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -167,6 +167,9 @@
SAFE_PARCEL(output.writeInt32, region.right);
SAFE_PARCEL(output.writeInt32, region.bottom);
}
+
+ SAFE_PARCEL(output.write, stretchEffect);
+
return NO_ERROR;
}
@@ -290,6 +293,9 @@
SAFE_PARCEL(input.readInt32, ®ion.bottom);
blurRegions.push_back(region);
}
+
+ SAFE_PARCEL(input.read, stretchEffect);
+
return NO_ERROR;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 550803d..73807c4 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1569,6 +1569,23 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setStretchEffect(
+ const sp<SurfaceControl>& sc, float left, float top, float right, float bottom, float vecX,
+ float vecY, float maxAmount) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::eStretchChanged;
+ s->stretchEffect = StretchEffect{.area = {left, top, right, bottom},
+ .vectorX = vecX,
+ .vectorY = vecY,
+ .maxAmount = maxAmount};
+ 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 2f9a0c0..b273805 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -56,6 +56,7 @@
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Rotation.h>
+#include <ui/StretchEffect.h>
#include <ui/Transform.h>
#include <utils/Errors.h>
@@ -135,6 +136,7 @@
eFrameTimelineInfoChanged = 0x800'00000000,
eBlurRegionsChanged = 0x1000'00000000,
eAutoRefreshChanged = 0x2000'00000000,
+ eStretchChanged = 0x4000'00000000,
};
layer_state_t();
@@ -244,6 +246,9 @@
// can and not wait for a frame to become available. This is only relevant
// in shared buffer mode.
bool autoRefresh;
+
+ // Stretch effect to be applied to this layer
+ StretchEffect stretchEffect;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index e7abfe6..61c0ab6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -551,6 +551,10 @@
// transactions from blocking each other.
Transaction& setApplyToken(const sp<IBinder>& token);
+ Transaction& setStretchEffect(const sp<SurfaceControl>& sc, float left, float top,
+ float right, float bottom, float vecX, float vecY,
+ float maxAmount);
+
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 3a727c9..7661233 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -28,6 +28,7 @@
#include <ui/GraphicTypes.h>
#include <ui/Rect.h>
#include <ui/Region.h>
+#include <ui/StretchEffect.h>
#include <ui/Transform.h>
namespace android {
@@ -155,6 +156,8 @@
std::vector<BlurRegion> blurRegions;
+ StretchEffect stretchEffect;
+
// Name associated with the layer for debugging purposes.
std::string name;
};
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index dd26b17..1eb8da9 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -491,6 +491,9 @@
const LayerSettings* layer,
const DisplaySettings& display,
bool undoPremultipliedAlpha) {
+ if (layer->stretchEffect.hasEffect()) {
+ // TODO: Implement
+ }
if (mUseColorManagement &&
needsLinearEffect(layer->colorTransform, layer->sourceDataspace, display.outputDataspace)) {
LinearEffect effect = LinearEffect{.inputDataspace = layer->sourceDataspace,
diff --git a/libs/ui/include/ui/StretchEffect.h b/libs/ui/include/ui/StretchEffect.h
new file mode 100644
index 0000000..1d2460c
--- /dev/null
+++ b/libs/ui/include/ui/StretchEffect.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/Flattenable.h>
+#include "FloatRect.h"
+
+#include <type_traits>
+
+namespace android {
+
+struct StretchEffect : public LightFlattenablePod<StretchEffect> {
+ FloatRect area = {0, 0, 0, 0};
+ float vectorX = 0;
+ float vectorY = 0;
+ float maxAmount = 0;
+
+ bool operator==(const StretchEffect& other) const {
+ return area == other.area && vectorX == other.vectorX && vectorY == other.vectorY &&
+ maxAmount == other.maxAmount;
+ }
+
+ static bool isZero(float value) {
+ constexpr float NON_ZERO_EPSILON = 0.001f;
+ return fabsf(value) <= NON_ZERO_EPSILON;
+ }
+
+ bool isNoOp() const { return isZero(vectorX) && isZero(vectorY); }
+
+ bool hasEffect() const { return !isNoOp(); }
+
+ void sanitize() {
+ // If the area is empty, or the max amount is zero, then reset back to defaults
+ if (area.bottom >= area.top || area.left >= area.right || isZero(maxAmount)) {
+ *this = StretchEffect{};
+ }
+ }
+};
+
+static_assert(std::is_trivially_copyable<StretchEffect>::value,
+ "StretchEffect must be trivially copyable to be flattenable");
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index c445d5b..8402149 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -34,6 +34,7 @@
#include <gui/BufferQueue.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
+#include <ui/StretchEffect.h>
#include "DisplayHardware/Hal.h"
@@ -123,6 +124,8 @@
// List of regions that require blur
std::vector<BlurRegion> blurRegions;
+ StretchEffect stretchEffect;
+
/*
* Geometry state
*/
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index df14003..1fe0e26 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -488,6 +488,7 @@
compositionState->alpha = alpha;
compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
compositionState->blurRegions = drawingState.blurRegions;
+ compositionState->stretchEffect = drawingState.stretchEffect;
}
void Layer::prepareGeometryCompositionState() {
@@ -556,8 +557,8 @@
isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf;
// Force client composition for special cases known only to the front-end.
- if (isHdrY410() || usesRoundedCorners || drawShadows() ||
- getDrawingState().blurRegions.size() > 0) {
+ if (isHdrY410() || usesRoundedCorners || drawShadows() || drawingState.blurRegions.size() > 0 ||
+ drawingState.stretchEffect.hasEffect()) {
compositionState->forceClientComposition = true;
}
}
@@ -656,6 +657,7 @@
layerSettings.backgroundBlurRadius = getBackgroundBlurRadius();
layerSettings.blurRegions = getBlurRegions();
}
+ layerSettings.stretchEffect = getDrawingState().stretchEffect;
// Record the name of the layer for debugging further down the stack.
layerSettings.name = getName();
return layerSettings;
@@ -1423,6 +1425,19 @@
return true;
}
+bool Layer::setStretchEffect(const StretchEffect& effect) {
+ StretchEffect temp = effect;
+ temp.sanitize();
+ if (mCurrentState.stretchEffect == temp) {
+ return false;
+ }
+ mCurrentState.sequence++;
+ mCurrentState.stretchEffect = temp;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
void Layer::updateTreeHasFrameRateVote() {
const auto traverseTree = [&](const LayerVector::Visitor& visitor) {
auto parent = getParent();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9cd15e8..7d70d91 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -32,6 +32,7 @@
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
#include <ui/Region.h>
+#include <ui/StretchEffect.h>
#include <ui/Transform.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
@@ -323,6 +324,9 @@
// An arbitrary threshold for the number of BufferlessSurfaceFrames in the state. Used to
// trigger a warning if the number of SurfaceFrames crosses the threshold.
static constexpr uint32_t kStateSurfaceFramesThreshold = 25;
+
+ // Stretch effect to apply to this layer
+ StretchEffect stretchEffect;
};
/*
@@ -938,6 +942,8 @@
bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; }
+ bool setStretchEffect(const StretchEffect& effect);
+
protected:
class SyncPoint {
public:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 689a302..bbbb003 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3953,6 +3953,11 @@
if (what & layer_state_t::eAutoRefreshChanged) {
layer->setAutoRefresh(s.autoRefresh);
}
+ if (what & layer_state_t::eStretchChanged) {
+ if (layer->setStretchEffect(s.stretchEffect)) {
+ 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