-
Notifications
You must be signed in to change notification settings - Fork 6k
dont pixel snap raster cache if SUPPORT_FRACTIONAL_TRANSLATION is enabled #34002
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
dnfield
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but I'd give @flar a chance to look at this too before landing.
|
I think this is the last piece before we can start opting in the desktop targets, after the next flutter roll allows me to "fix" the last google3 test that fails without pixel snapping |
flow/raster_cache.h
Outdated
| return bounds; | ||
| return SkRect::MakeLTRB(bounds.fLeft, bounds.fTop, bounds.fRight, | ||
| bounds.fBottom); | ||
| #else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 2 branches share a few lines of code so the ifndef could be reduced a bit.
Even more because I believe that SkRect has a "round out to SkRect" method which can be executed on "itself" which means only 1 line of code needs to be inside the ifndef.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the math isn't really complete here.
When computing the size of the cache image we need something along the lines of roundOut, but it isn't being done. More comments in the Rasterize method...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this method should perform no roundOut in any case and let the calling method figure out the right way to handle non-integer bounds?
flow/raster_cache.cc
Outdated
| TRACE_EVENT0("flutter", "RasterCachePopulate"); | ||
| SkIRect cache_rect = RasterCache::GetDeviceBounds(logical_rect, ctm); | ||
|
|
||
| SkRect cache_rect = RasterCache::GetDeviceBounds(logical_rect, ctm); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below we pass width/height to MakeN32Premul. That method takes an integer width/height. I'm not sure why that is compiling, is it performing a silent conversion? Using what method? floor? round? ceil?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a couple of options here:
- roundOut and use those bounds and offset
- ceil the width and height and use the sub-pixel offset to render into that cache image
- something where we store the sub-pixel rounding that was used for the offset so that we can adjust the location of the cache image properly in Draw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh shoot, I didn't check and assumed this took an SkScalar. Its probably just truncating?
I think we should probably round out to get the size of the texture, and then when drawing it use the original float offset, right?
flow/raster_cache.h
Outdated
| SkIRect bounds; | ||
| device_rect.roundOut(&bounds); | ||
| return SkRect::MakeLTRB(bounds.fLeft, bounds.fTop, bounds.fRight, | ||
| bounds.fBottom); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is equivalent to device_rect.roundOut(&deviceRect); return device_rect; which makes the return statements the same in both cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, I believe that the only modification to this method needed is:
#ifndef ...
device_rect.roundOut(&device_rect);
#endif
flar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this change is now compatible with our current implementation, but I mention a few opportunities for improvement.
One suggestion is simply reducing the lines of code.
The other suggestion is just pointing out that the existing code (and this patch) both do the rounding inaccurately in the case of IntCTM, but since that isn't a regression from the current code, that potential change should probably be left to its own PR so that it can be reverted separately from this change if we get it wrong.
| SkCanvas* canvas = surface->getCanvas(); | ||
| canvas->clear(SK_ColorTRANSPARENT); | ||
| canvas->translate(-cache_rect.left(), -cache_rect.top()); | ||
| canvas->translate(-dest_rect.left(), -dest_rect.top()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still have a rounding problem when using ICTMs, but it is the same rounding problem that we are already living with.
I describe the current rounding problem here: #33981 (comment)
flow/raster_cache.cc
Outdated
| SkRect dest_rect = RasterCache::GetDeviceBounds(logical_rect, ctm); | ||
| // we always round out here so that the texture is integer sized. | ||
| SkIRect cache_rect; | ||
| dest_rect.roundOut(&cache_rect); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can choose a cache image size that is 1 pixel larger than needed in the non-ICTM case because our translation will be by dest_rect.left/top which may move it closer to the origin of the cache image by enough to not need that last pixel on the right and bottom. A minor issue, but could be fixed by using the ceil of the dest_rect width and height instead of the height of the cache_rect.
With ICTM, dest_rect is all integers anyway so the ceil of its w/h are just the w/h.
Without ICTM, the w/h indicate the number of pixels from the left/topmost coordinate in the drawing which are mapped to 0,0 in the cache image by the translate below and so the ceil of the w/h represent the number of whole pixels which it will take up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh good point, fixed
Required to support flutter/flutter#103909
When drawing from the raster cache, the engine unconditionally snaps to physical pixels. If we want to enable SUPPORT_FRACTIONAL_TRANSLATION , this will be incorrect.
Remove the round out when SUPPORT_FRACTIONAL_TRANSLATION , change several APIs that accept SKIRect to SkRect