Merge "Fixed issue where SurfaceView transforms were applied twice" into udc-dev

This commit is contained in:
Nader Jawad
2023-04-19 17:10:07 +00:00
committed by Android (Google) Code Review
3 changed files with 45 additions and 76 deletions

View File

@@ -207,27 +207,6 @@ static void applyTransforms(DirtyStack* frame, DirtyStack* end) {
}
}
static void computeTransformImpl(const DirtyStack* frame, const DirtyStack* end,
Matrix4* outMatrix) {
while (frame != end) {
switch (frame->type) {
case TransformRenderNode:
frame->renderNode->applyViewPropertyTransforms(*outMatrix);
break;
case TransformMatrix4:
outMatrix->multiply(*frame->matrix4);
break;
case TransformNone:
// nothing to be done
break;
default:
LOG_ALWAYS_FATAL("Tried to compute transform with an invalid type: %d",
frame->type);
}
frame = frame->prev;
}
}
void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) {
if (frame->pendingDirty.isEmpty()) {
return;
@@ -282,9 +261,6 @@ 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;
@@ -295,21 +271,16 @@ DamageAccumulator::StretchResult DamageAccumulator::findNearestStretchEffect() c
const float height = (float) frameRenderNodeProperties.getHeight();
if (!effect.isEmpty()) {
Matrix4 stretchMatrix;
computeTransformImpl(mHead, frame, &stretchMatrix);
Rect stretchRect = Rect(0.f, 0.f, startWidth, startHeight);
computeTransformImpl(frame, &stretchMatrix);
Rect stretchRect = Rect(0.f, 0.f, width, height);
stretchMatrix.mapRect(stretchRect);
return StretchResult{
.stretchEffect = &effect,
.childRelativeBounds = SkRect::MakeLTRB(
stretchRect.left,
stretchRect.top,
stretchRect.right,
stretchRect.bottom
),
.width = width,
.height = height
};
.stretchEffect = &effect,
.parentBounds = SkRect::MakeLTRB(stretchRect.left, stretchRect.top,
stretchRect.right, stretchRect.bottom),
.width = width,
.height = height};
}
}
frame = frame->prev;

View File

@@ -70,9 +70,9 @@ public:
const StretchEffect* stretchEffect;
/**
* Bounds of the child relative to the stretch container
* Bounds of the stretching container
*/
const SkRect childRelativeBounds;
const SkRect parentBounds;
/**
* Width of the stretch container

View File

@@ -584,13 +584,15 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
bool useStretchShader =
Properties::getStretchEffectBehavior() != StretchEffectBehavior::UniformScale;
if (useStretchShader && info.stretchEffectCount) {
// Compute the transform bounds first before calculating the stretch
transform.mapRect(bounds);
bool hasStretch = useStretchShader && info.stretchEffectCount;
if (hasStretch) {
handleStretchEffect(info, bounds);
}
transform.mapRect(bounds);
if (CC_LIKELY(transform.isPureTranslate())) {
if (CC_LIKELY(transform.isPureTranslate()) && !hasStretch) {
// snap/round the computed bounds, so they match the rounding behavior
// of the clear done in SurfaceView#draw().
bounds.snapGeometryToPixelBoundaries(false);
@@ -665,45 +667,42 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
return env;
}
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();
const StretchEffect* effect = result.stretchEffect;
if (!effect) {
if (effect) {
// Compute the number of pixels that the stretching container
// scales by.
// Then compute the scale factor that the child would need
// to scale in order to occupy the same pixel bounds.
auto& parentBounds = result.parentBounds;
auto parentWidth = parentBounds.width();
auto parentHeight = parentBounds.height();
auto& stretchDirection = effect->getStretchDirection();
auto stretchX = stretchDirection.x();
auto stretchY = stretchDirection.y();
auto stretchXPixels = parentWidth * std::abs(stretchX);
auto stretchYPixels = parentHeight * std::abs(stretchY);
SkMatrix stretchMatrix;
auto childScaleX = 1 + (stretchXPixels / targetBounds.getWidth());
auto childScaleY = 1 + (stretchYPixels / targetBounds.getHeight());
auto pivotX = stretchX > 0 ? targetBounds.left : targetBounds.right;
auto pivotY = stretchY > 0 ? targetBounds.top : targetBounds.bottom;
stretchMatrix.setScale(childScaleX, childScaleY, pivotX, pivotY);
SkRect rect = SkRect::MakeLTRB(targetBounds.left, targetBounds.top,
targetBounds.right, targetBounds.bottom);
SkRect dst = stretchMatrix.mapRect(rect);
targetBounds.left = dst.left();
targetBounds.top = dst.top();
targetBounds.right = dst.right();
targetBounds.bottom = dst.bottom();
} else {
return;
}
const auto& childRelativeBounds = result.childRelativeBounds;
stretchTargetBounds(*effect, result.width, result.height,
childRelativeBounds,targetBounds);
if (Properties::getStretchEffectBehavior() ==
StretchEffectBehavior::Shader) {
JNIEnv* env = jnienv();
@@ -714,9 +713,8 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
gPositionListener.clazz, gPositionListener.callApplyStretch, mListener,
info.canvasContext.getFrameNumber(), result.width, result.height,
stretchDirection.fX, stretchDirection.fY, effect->maxStretchAmountX,
effect->maxStretchAmountY, childRelativeBounds.left(),
childRelativeBounds.top(), childRelativeBounds.right(),
childRelativeBounds.bottom());
effect->maxStretchAmountY, targetBounds.left, targetBounds.top,
targetBounds.right, targetBounds.bottom);
if (!keepListening) {
env->DeleteGlobalRef(mListener);
mListener = nullptr;