Merge "Updated HWUI to calculate the stretch bounds for a surface" into sc-dev

This commit is contained in:
Nader Jawad
2021-05-10 17:30:30 +00:00
committed by Android (Google) Code Review
4 changed files with 133 additions and 11 deletions

View File

@@ -272,18 +272,21 @@ void DamageAccumulator::finish(SkRect* totalDirty) {
DamageAccumulator::StretchResult DamageAccumulator::findNearestStretchEffect() const {
DirtyStack* frame = mHead;
const auto& headProperties = mHead->renderNode->properties();
float startWidth = headProperties.getWidth();
float startHeight = headProperties.getHeight();
while (frame->prev != frame) {
if (frame->type == TransformRenderNode) {
const auto& renderNode = frame->renderNode;
const auto& frameRenderNodeProperties = renderNode->properties();
const auto& effect =
frameRenderNodeProperties.layerProperties().getStretchEffect();
const float width = (float) renderNode->getWidth();
const float height = (float) renderNode->getHeight();
const float width = (float) frameRenderNodeProperties.getWidth();
const float height = (float) frameRenderNodeProperties.getHeight();
if (!effect.isEmpty()) {
Matrix4 stretchMatrix;
computeTransformImpl(mHead, frame, &stretchMatrix);
Rect stretchRect = Rect(0.f, 0.f, width, height);
Rect stretchRect = Rect(0.f, 0.f, startWidth, startHeight);
stretchMatrix.mapRect(stretchRect);
return StretchResult{

View File

@@ -68,9 +68,8 @@ static const SkString stretchShader = SkString(R"(
// 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 @@ static const SkString stretchShader = SkString(R"(
) {
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 @@ static const SkString stretchShader = SkString(R"(
) {
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 @@ sk_sp<SkRuntimeEffect> StretchEffect::getStretchEffect() {
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

View File

@@ -75,6 +75,22 @@ public:
maxStretchAmountY = std::max(maxStretchAmountY, other.maxStretchAmountY);
}
/**
* Return the stretched x position given the normalized x position with
* the current horizontal stretch direction
* @param normalizedX x position on the input texture from 0 to 1
* @return x position when the horizontal stretch direction applied
*/
float computeStretchedPositionX(float normalizedX) const;
/**
* Return the stretched y position given the normalized y position with
* the current horizontal stretch direction
* @param normalizedX y position on the input texture from 0 to 1
* @return y position when the horizontal stretch direction applied
*/
float computeStretchedPositionY(float normalizedY) const;
sk_sp<SkShader> getShader(float width, float height,
const sk_sp<SkImage>& snapshotImage) const;

View File

@@ -572,11 +572,11 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
info.damageAccumulator->computeCurrentTransform(&transform);
const RenderProperties& props = node.properties();
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
if (info.stretchEffectCount) {
handleStretchEffect(info, transform);
handleStretchEffect(info, bounds);
}
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
transform.mapRect(bounds);
if (CC_LIKELY(transform.isPureTranslate())) {
@@ -639,7 +639,33 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
return env;
}
void handleStretchEffect(const TreeInfo& info, const Matrix4& transform) {
void stretchTargetBounds(const StretchEffect& stretchEffect,
float width, float height,
const SkRect& childRelativeBounds,
uirenderer::Rect& bounds) {
float normalizedLeft = childRelativeBounds.left() / width;
float normalizedTop = childRelativeBounds.top() / height;
float normalizedRight = childRelativeBounds.right() / width;
float normalizedBottom = childRelativeBounds.bottom() / height;
float reverseLeft = width *
(stretchEffect.computeStretchedPositionX(normalizedLeft) -
normalizedLeft);
float reverseTop = height *
(stretchEffect.computeStretchedPositionY(normalizedTop) -
normalizedTop);
float reverseRight = width *
(stretchEffect.computeStretchedPositionX(normalizedRight) -
normalizedLeft);
float reverseBottom = height *
(stretchEffect.computeStretchedPositionY(normalizedBottom) -
normalizedTop);
bounds.left = reverseLeft;
bounds.top = reverseTop;
bounds.right = reverseRight;
bounds.bottom = reverseBottom;
}
void handleStretchEffect(const TreeInfo& info, uirenderer::Rect& targetBounds) {
// Search up to find the nearest stretcheffect parent
const DamageAccumulator::StretchResult result =
info.damageAccumulator->findNearestStretchEffect();
@@ -649,6 +675,8 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
}
const auto& childRelativeBounds = result.childRelativeBounds;
stretchTargetBounds(*effect, result.width, result.height,
childRelativeBounds,targetBounds);
JNIEnv* env = jnienv();