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 {
|
DamageAccumulator::StretchResult DamageAccumulator::findNearestStretchEffect() const {
|
||||||
DirtyStack* frame = mHead;
|
DirtyStack* frame = mHead;
|
||||||
|
const auto& headProperties = mHead->renderNode->properties();
|
||||||
|
float startWidth = headProperties.getWidth();
|
||||||
|
float startHeight = headProperties.getHeight();
|
||||||
while (frame->prev != frame) {
|
while (frame->prev != frame) {
|
||||||
if (frame->type == TransformRenderNode) {
|
if (frame->type == TransformRenderNode) {
|
||||||
const auto& renderNode = frame->renderNode;
|
const auto& renderNode = frame->renderNode;
|
||||||
const auto& frameRenderNodeProperties = renderNode->properties();
|
const auto& frameRenderNodeProperties = renderNode->properties();
|
||||||
const auto& effect =
|
const auto& effect =
|
||||||
frameRenderNodeProperties.layerProperties().getStretchEffect();
|
frameRenderNodeProperties.layerProperties().getStretchEffect();
|
||||||
const float width = (float) renderNode->getWidth();
|
const float width = (float) frameRenderNodeProperties.getWidth();
|
||||||
const float height = (float) renderNode->getHeight();
|
const float height = (float) frameRenderNodeProperties.getHeight();
|
||||||
if (!effect.isEmpty()) {
|
if (!effect.isEmpty()) {
|
||||||
Matrix4 stretchMatrix;
|
Matrix4 stretchMatrix;
|
||||||
computeTransformImpl(mHead, frame, &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);
|
stretchMatrix.mapRect(stretchRect);
|
||||||
|
|
||||||
return StretchResult{
|
return StretchResult{
|
||||||
|
|||||||
@@ -68,9 +68,8 @@ static const SkString stretchShader = SkString(R"(
|
|||||||
// and the other way around.
|
// and the other way around.
|
||||||
uniform float uInterpolationStrength;
|
uniform float uInterpolationStrength;
|
||||||
|
|
||||||
float easeInCubic(float t, float d) {
|
float easeIn(float t, float d) {
|
||||||
float tmp = t * d;
|
return t * d;
|
||||||
return tmp * tmp * tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float computeOverscrollStart(
|
float computeOverscrollStart(
|
||||||
@@ -83,7 +82,7 @@ static const SkString stretchShader = SkString(R"(
|
|||||||
) {
|
) {
|
||||||
float offsetPos = uStretchAffectedDist - inPos;
|
float offsetPos = uStretchAffectedDist - inPos;
|
||||||
float posBasedVariation = mix(
|
float posBasedVariation = mix(
|
||||||
1. ,easeInCubic(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
|
1. ,easeIn(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
|
||||||
float stretchIntensity = overscroll * posBasedVariation;
|
float stretchIntensity = overscroll * posBasedVariation;
|
||||||
return distanceStretched - (offsetPos / (1. + stretchIntensity));
|
return distanceStretched - (offsetPos / (1. + stretchIntensity));
|
||||||
}
|
}
|
||||||
@@ -99,7 +98,7 @@ static const SkString stretchShader = SkString(R"(
|
|||||||
) {
|
) {
|
||||||
float offsetPos = inPos - reverseStretchDist;
|
float offsetPos = inPos - reverseStretchDist;
|
||||||
float posBasedVariation = mix(
|
float posBasedVariation = mix(
|
||||||
1. ,easeInCubic(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
|
1. ,easeIn(offsetPos, uInverseStretchAffectedDist), interpolationStrength);
|
||||||
float stretchIntensity = (-overscroll) * posBasedVariation;
|
float stretchIntensity = (-overscroll) * posBasedVariation;
|
||||||
return 1 - (distanceStretched - (offsetPos / (1. + stretchIntensity)));
|
return 1 - (distanceStretched - (offsetPos / (1. + stretchIntensity)));
|
||||||
}
|
}
|
||||||
@@ -234,4 +233,80 @@ sk_sp<SkRuntimeEffect> StretchEffect::getStretchEffect() {
|
|||||||
return instance.effect;
|
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
|
} // namespace android::uirenderer
|
||||||
@@ -75,6 +75,22 @@ public:
|
|||||||
maxStretchAmountY = std::max(maxStretchAmountY, other.maxStretchAmountY);
|
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,
|
sk_sp<SkShader> getShader(float width, float height,
|
||||||
const sk_sp<SkImage>& snapshotImage) const;
|
const sk_sp<SkImage>& snapshotImage) const;
|
||||||
|
|
||||||
|
|||||||
@@ -572,11 +572,11 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
|
|||||||
info.damageAccumulator->computeCurrentTransform(&transform);
|
info.damageAccumulator->computeCurrentTransform(&transform);
|
||||||
const RenderProperties& props = node.properties();
|
const RenderProperties& props = node.properties();
|
||||||
|
|
||||||
|
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
|
||||||
if (info.stretchEffectCount) {
|
if (info.stretchEffectCount) {
|
||||||
handleStretchEffect(info, transform);
|
handleStretchEffect(info, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
|
|
||||||
transform.mapRect(bounds);
|
transform.mapRect(bounds);
|
||||||
|
|
||||||
if (CC_LIKELY(transform.isPureTranslate())) {
|
if (CC_LIKELY(transform.isPureTranslate())) {
|
||||||
@@ -639,7 +639,33 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
|
|||||||
return env;
|
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
|
// Search up to find the nearest stretcheffect parent
|
||||||
const DamageAccumulator::StretchResult result =
|
const DamageAccumulator::StretchResult result =
|
||||||
info.damageAccumulator->findNearestStretchEffect();
|
info.damageAccumulator->findNearestStretchEffect();
|
||||||
@@ -649,6 +675,8 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto& childRelativeBounds = result.childRelativeBounds;
|
const auto& childRelativeBounds = result.childRelativeBounds;
|
||||||
|
stretchTargetBounds(*effect, result.width, result.height,
|
||||||
|
childRelativeBounds,targetBounds);
|
||||||
|
|
||||||
JNIEnv* env = jnienv();
|
JNIEnv* env = jnienv();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user