Do not use SkImageFilter for Stretch
Refactor stretch implementation to manually
draw the shader as a rect instead of using
SkImageFilter
Bug: 184184033
Test: Re-ran stretch tests
Change-Id: I6263f5474b185b3f81ef9fd1bec3e43e86da49f2
diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp
index d7162b9..de14beb 100644
--- a/libs/hwui/effects/StretchEffect.cpp
+++ b/libs/hwui/effects/StretchEffect.cpp
@@ -171,13 +171,13 @@
static const float ZERO = 0.f;
static const float CONTENT_DISTANCE_STRETCHED = 1.f;
-sk_sp<SkImageFilter> StretchEffect::getImageFilter(const sk_sp<SkImage>& snapshotImage) const {
+sk_sp<SkShader> StretchEffect::getShader(const sk_sp<SkImage>& snapshotImage) const {
if (isEmpty()) {
return nullptr;
}
- if (mStretchFilter != nullptr) {
- return mStretchFilter;
+ if (mStretchShader != nullptr) {
+ return mStretchShader;
}
float viewportWidth = stretchArea.width();
@@ -212,10 +212,9 @@
mBuilder->uniform("viewportWidth").set(&viewportWidth, 1);
mBuilder->uniform("viewportHeight").set(&viewportHeight, 1);
- mStretchFilter = SkImageFilters::Shader(mBuilder->makeShader(nullptr, false),
- SkRect{0, 0, viewportWidth, viewportHeight});
+ mStretchShader = mBuilder->makeShader(nullptr, false);
- return mStretchFilter;
+ return mStretchShader;
}
sk_sp<SkRuntimeEffect> StretchEffect::getStretchEffect() {
diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h
index 8221b41..546d53b 100644
--- a/libs/hwui/effects/StretchEffect.h
+++ b/libs/hwui/effects/StretchEffect.h
@@ -53,7 +53,7 @@
StretchEffect& operator=(const StretchEffect& other) {
this->stretchArea = other.stretchArea;
this->mStretchDirection = other.mStretchDirection;
- this->mStretchFilter = nullptr;
+ this->mStretchShader = other.mStretchShader;
this->maxStretchAmountX = other.maxStretchAmountX;
this->maxStretchAmountY = other.maxStretchAmountY;
return *this;
@@ -76,14 +76,14 @@
maxStretchAmountY = std::max(maxStretchAmountY, other.maxStretchAmountY);
}
- sk_sp<SkImageFilter> getImageFilter(const sk_sp<SkImage>& snapshotImage) const;
+ sk_sp<SkShader> getShader(const sk_sp<SkImage>& snapshotImage) const;
SkRect stretchArea {0, 0, 0, 0};
float maxStretchAmountX = 0;
float maxStretchAmountY = 0;
void setStretchDirection(const SkVector& direction) {
- mStretchFilter = nullptr;
+ mStretchShader = nullptr;
mStretchDirection = direction;
}
@@ -93,7 +93,7 @@
static sk_sp<SkRuntimeEffect> getStretchEffect();
mutable SkVector mStretchDirection{0, 0};
mutable std::unique_ptr<SkRuntimeShaderBuilder> mBuilder;
- mutable sk_sp<SkImageFilter> mStretchFilter;
+ mutable sk_sp<SkShader> mStretchShader;
};
} // namespace android::uirenderer
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 5627a7e..77d99a6 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -180,20 +180,7 @@
paint->setColorFilter(sk_ref_sp(properties.getColorFilter()));
sk_sp<SkImageFilter> imageFilter = sk_ref_sp(properties.getImageFilter());
- sk_sp<SkImageFilter> stretchFilter =
- properties.getStretchEffect().getImageFilter(snapshotImage);
- sk_sp<SkImageFilter> filter;
- if (imageFilter && stretchFilter) {
- filter = SkImageFilters::Compose(
- std::move(stretchFilter),
- std::move(imageFilter)
- );
- } else if (stretchFilter) {
- filter = std::move(stretchFilter);
- } else {
- filter = std::move(imageFilter);
- }
- paint->setImageFilter(std::move(filter));
+ paint->setImageFilter(std::move(imageFilter));
return true;
}
return false;
@@ -262,8 +249,16 @@
TransformCanvas transformCanvas(canvas);
displayList->draw(&transformCanvas);
}
- canvas->drawImageRect(snapshotImage, bounds, bounds, sampling, &paint,
- SkCanvas::kStrict_SrcRectConstraint);
+
+ const StretchEffect& stretch = properties.layerProperties().getStretchEffect();
+ if (stretch.isEmpty()) {
+ canvas->drawImageRect(snapshotImage, bounds, bounds, sampling, &paint,
+ SkCanvas::kStrict_SrcRectConstraint);
+ } else {
+ sk_sp<SkShader> stretchShader = stretch.getShader(snapshotImage);
+ paint.setShader(stretchShader);
+ canvas->drawRect(bounds, paint);
+ }
if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) {
renderNode->getSkiaLayer()->hasRenderedSinceRepaint = true;