Updated HWUI to calculate the stretch bounds for a surface
Added logic to StretchEffect to be able to calculate the
stretched position of a pixel on an input texture based
on the current stretch parameters.
Updated shader to leverage linear easing instead of
cubic in order to have a reversible method that
can be used to map input textures to the corresponding
stretch position.
Bug: 179047472
Test: manual
Change-Id: Id32afcf0df1cca03e68ac0c594d307a1090264f2
diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp
index 1519d69..0599bfa 100644
--- a/libs/hwui/effects/StretchEffect.cpp
+++ b/libs/hwui/effects/StretchEffect.cpp
@@ -68,9 +68,8 @@
// and the other way around.
uniform float uInterpolationStrength;
- float easeInCubic(float t, float d) {
- float tmp = t * d;
- return tmp * tmp * tmp;
+ float easeIn(float t, float d) {
+ return t * d;
}
float computeOverscrollStart(
@@ -83,7 +82,7 @@
) {
float offsetPos = uStretchAffectedDist - inPos;
float posBasedVariation = mix(
- 1. ,easeInCubic(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
+ 1. ,easeIn(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
float stretchIntensity = overscroll * posBasedVariation;
return distanceStretched - (offsetPos / (1. + stretchIntensity));
}
@@ -99,7 +98,7 @@
) {
float offsetPos = inPos - reverseStretchDist;
float posBasedVariation = mix(
- 1. ,easeInCubic(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
+ 1. ,easeIn(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
float stretchIntensity = (-overscroll) * posBasedVariation;
return 1 - (distanceStretched - (offsetPos / (1. + stretchIntensity)));
}
@@ -234,4 +233,80 @@
return instance.effect;
}
+/**
+ * Helper method that maps the input texture position to the stretch position
+ * based on the given overscroll value that represents an overscroll from
+ * either the top or left
+ * @param overscroll current overscroll value
+ * @param input normalized input position (can be x or y) on the input texture
+ * @return stretched position of the input normalized from 0 to 1
+ */
+float reverseMapStart(float overscroll, float input) {
+ float numerator = (-input * overscroll * overscroll) -
+ (2 * input * overscroll) - input;
+ float denominator = 1.f + (.3f * overscroll) +
+ (.7f * input * overscroll * overscroll) + (.7f * input * overscroll);
+ return -(numerator / denominator);
+}
+
+/**
+ * Helper method that maps the input texture position to the stretch position
+ * based on the given overscroll value that represents an overscroll from
+ * either the bottom or right
+ * @param overscroll current overscroll value
+ * @param input normalized input position (can be x or y) on the input texture
+ * @return stretched position of the input normalized from 0 to 1
+ */
+float reverseMapEnd(float overscroll, float input) {
+ float numerator = (.3f * overscroll * overscroll) -
+ (.3f * input * overscroll * overscroll) +
+ (1.3f * input * overscroll) - overscroll - input;
+ float denominator = (.7f * input * overscroll * overscroll) -
+ (.7f * input * overscroll) - (.7f * overscroll * overscroll) +
+ overscroll - 1.f;
+ return numerator / denominator;
+}
+
+/**
+ * Calculates the normalized stretch position given the normalized input
+ * position. This handles calculating the overscroll from either the
+ * top or left vs bottom or right depending on the sign of the given overscroll
+ * value
+ *
+ * @param overscroll unit vector of overscroll from -1 to 1 indicating overscroll
+ * from the bottom or right vs top or left respectively
+ * @param normalizedInput the
+ * @return
+ */
+float computeReverseOverscroll(float overscroll, float normalizedInput) {
+ float distanceStretched = 1.f / (1.f + abs(overscroll));
+ float distanceDiff = distanceStretched - 1.f;
+ if (overscroll > 0) {
+ float output = reverseMapStart(overscroll, normalizedInput);
+ if (output <= 1.0f) {
+ return output;
+ } else if (output >= distanceStretched){
+ return output - distanceDiff;
+ }
+ }
+
+ if (overscroll < 0) {
+ float output = reverseMapEnd(overscroll, normalizedInput);
+ if (output >= 0.f) {
+ return output;
+ } else if (output < 0.f){
+ return output + distanceDiff;
+ }
+ }
+ return normalizedInput;
+}
+
+float StretchEffect::computeStretchedPositionX(float normalizedX) const {
+ return computeReverseOverscroll(mStretchDirection.x(), normalizedX);
+}
+
+float StretchEffect::computeStretchedPositionY(float normalizedY) const {
+ return computeReverseOverscroll(mStretchDirection.y(), normalizedY);
+}
+
} // namespace android::uirenderer
\ No newline at end of file