Merge "Updated HWUI to calculate the stretch bounds for a surface" into sc-dev
This commit is contained in:
@@ -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{
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user