Allocate textures in multiples of LAYER_SIZE.
This matches the behavior of the old HWUI renderer and avoids
jank when trying to release a series of small textures.
Test: UiBenchJankTests #testResizeHwLayer
Bug: 69566781
Change-Id: Idc01f8438e85d4810032fd30a141132a6cdd47a1
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 845acc0..e2f02df 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -205,7 +205,13 @@
if (layerNeedsPaint(layerProperties, alphaMultiplier, &tmpPaint)) {
paint = &tmpPaint;
}
- renderNode->getLayerSurface()->draw(canvas, 0, 0, paint);
+
+ // surfaces for layers are created on LAYER_SIZE boundaries (which are >= layer size) so
+ // we need to restrict the portion of the surface drawn to the size of the renderNode.
+ SkASSERT(renderNode->getLayerSurface()->width() >= bounds.width());
+ SkASSERT(renderNode->getLayerSurface()->height() >= bounds.height());
+ canvas->drawImageRect(renderNode->getLayerSurface()->makeImageSnapshot().get(),
+ bounds, bounds, paint);
if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) {
renderNode->getSkiaLayer()->hasRenderedSinceRepaint = true;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index d5fe7f4..4ba368f 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -161,14 +161,18 @@
bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
bool wideColorGamut) {
+ // compute the size of the surface (i.e. texture) to be allocated for this layer
+ const int surfaceWidth = ceilf(node->getWidth() / float(LAYER_SIZE)) * LAYER_SIZE;
+ const int surfaceHeight = ceilf(node->getHeight() / float(LAYER_SIZE)) * LAYER_SIZE;
+
SkSurface* layer = node->getLayerSurface();
- if (!layer || layer->width() != node->getWidth() || layer->height() != node->getHeight()) {
+ if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
SkImageInfo info;
if (wideColorGamut) {
- info = SkImageInfo::Make(node->getWidth(), node->getHeight(), kRGBA_F16_SkColorType,
+ info = SkImageInfo::Make(surfaceWidth, surfaceHeight, kRGBA_F16_SkColorType,
kPremul_SkAlphaType);
} else {
- info = SkImageInfo::MakeN32Premul(node->getWidth(), node->getHeight());
+ info = SkImageInfo::MakeN32Premul(surfaceWidth, surfaceHeight);
}
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkASSERT(mRenderThread.getGrContext() != nullptr);
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 7dd271f..c7f57fe 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -460,15 +460,15 @@
ProjectionLayer(int* drawCounter)
: SkSurface_Base(SkImageInfo::MakeN32Premul(LAYER_WIDTH, LAYER_HEIGHT), nullptr)
, mDrawCounter(drawCounter) {}
- void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {
+ virtual sk_sp<SkImage> onNewImageSnapshot() override {
EXPECT_EQ(3, (*mDrawCounter)++);
EXPECT_EQ(SkRect::MakeLTRB(100 - SCROLL_X, 100 - SCROLL_Y, 300 - SCROLL_X,
300 - SCROLL_Y),
TestUtils::getClipBounds(this->getCanvas()));
+ return nullptr;
}
SkCanvas* onNewCanvas() override { return new ProjectionTestCanvas(mDrawCounter); }
sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
- sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
void onCopyOnWrite(ContentChangeMode) override {}
int* mDrawCounter;
};