Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit d38f5e5

Browse files
[Impeller] generate mipmaps for toImage. (#55655)
Fixes flutter/flutter#156161 Mips must be eagerly generated for Picture.toImage and friends so that filter quality (mip sampling) works as expected.
1 parent 449df25 commit d38f5e5

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

impeller/display_list/dl_dispatcher.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,7 +1368,12 @@ std::shared_ptr<Texture> DisplayListToTexture(
13681368
const sk_sp<flutter::DisplayList>& display_list,
13691369
ISize size,
13701370
AiksContext& context,
1371-
bool reset_host_buffer) {
1371+
bool reset_host_buffer,
1372+
bool generate_mips) {
1373+
int mip_count = 1;
1374+
if (generate_mips) {
1375+
mip_count = size.MipCount();
1376+
}
13721377
// Do not use the render target cache as the lifecycle of this texture
13731378
// will outlive a particular frame.
13741379
impeller::RenderTargetAllocator render_target_allocator =
@@ -1379,7 +1384,7 @@ std::shared_ptr<Texture> DisplayListToTexture(
13791384
target = render_target_allocator.CreateOffscreenMSAA(
13801385
*context.GetContext(), // context
13811386
size, // size
1382-
/*mip_count=*/1,
1387+
/*mip_count=*/mip_count,
13831388
"Picture Snapshot MSAA", // label
13841389
impeller::RenderTarget::
13851390
kDefaultColorAttachmentConfigMSAA // color_attachment_config
@@ -1388,7 +1393,7 @@ std::shared_ptr<Texture> DisplayListToTexture(
13881393
target = render_target_allocator.CreateOffscreen(
13891394
*context.GetContext(), // context
13901395
size, // size
1391-
/*mip_count=*/1,
1396+
/*mip_count=*/mip_count,
13921397
"Picture Snapshot", // label
13931398
impeller::RenderTarget::
13941399
kDefaultColorAttachmentConfig // color_attachment_config

impeller/display_list/dl_dispatcher.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ std::shared_ptr<Texture> DisplayListToTexture(
370370
const sk_sp<flutter::DisplayList>& display_list,
371371
ISize size,
372372
AiksContext& context,
373-
bool reset_host_buffer = true);
373+
bool reset_host_buffer = true,
374+
bool generate_mips = false);
374375

375376
/// Render the provided display list to the render target.
376377
bool RenderToOnscreen(ContentContext& context, RenderTarget render_target,

shell/common/snapshot_controller_impeller.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "flutter/impeller/geometry/size.h"
1515
#include "flutter/shell/common/snapshot_controller.h"
1616
#include "impeller/entity/contents/runtime_effect_contents.h"
17-
#include "impeller/renderer/render_target.h"
1817

1918
namespace flutter {
2019

@@ -49,7 +48,8 @@ sk_sp<DlImage> DoMakeRasterSnapshot(
4948

5049
return impeller::DlImageImpeller::Make(
5150
impeller::DisplayListToTexture(display_list, render_target_size, *context,
52-
/*reset_host_buffer=*/false),
51+
/*reset_host_buffer=*/false,
52+
/*generate_mips=*/true),
5353
DlImage::OwningContext::kRaster);
5454
}
5555

testing/dart/painting_test.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,41 @@ void main() {
114114
'ImageFilter.matrix($data, FilterQuality.medium)',
115115
);
116116
});
117+
118+
test('Picture.toImage generates mip maps', () async {
119+
// Draw a grid of red and blue squares. When averaged together via
120+
// mip maps, this should result in a purplish color. If there are no
121+
// mip maps, the original red and blue colors will be preserved regardless
122+
// of scale or number of pixels.
123+
late final Image image;
124+
{
125+
final PictureRecorder recorder = PictureRecorder();
126+
final Canvas canvas = Canvas(recorder);
127+
for (int i = 0; i < 20; i++) {
128+
for (int j = 0; j < 20; j++) {
129+
final Color color = (i + j).isEven ? const Color(0xFFFF0000) : const Color(0xFF0000FF);
130+
canvas.drawRect(Rect.fromLTWH(i * 5, j * 5, 5, 5), Paint()..color = color);
131+
}
132+
}
133+
final Picture picture = recorder.endRecording();
134+
image = await picture.toImage(100, 100);
135+
}
136+
137+
final PictureRecorder recorder = PictureRecorder();
138+
final Canvas canvas = Canvas(recorder);
139+
canvas.save();
140+
canvas.scale(0.25, 0.25);
141+
canvas.drawImage(image, Offset.zero, Paint()..filterQuality = FilterQuality.medium);
142+
canvas.restore();
143+
144+
final Picture picture = recorder.endRecording();
145+
final Image resultImage = await picture.toImage(10, 10);
146+
final ByteData data = (await resultImage.toByteData())!;
147+
148+
final Int32List colors = data.buffer.asInt32List();
149+
for (int i = 0; i < colors.length; i++) {
150+
expect(colors[i], isNot(const Color(0xFFFF0000)));
151+
expect(colors[i], isNot(const Color(0xFF0000FF)));
152+
}
153+
});
117154
}

0 commit comments

Comments
 (0)