Bug 1560853 - Fix picture cache tiles with fractional origins. r=kvark

Gecko layouts typically produce a picture cache where the origin
of the picture rect is an integer. However, it can occasionally
be a fractional origin.

In these cases, we need to ensure the content origin is floored,
to maintain consistent snapping. When this case occurs, the UV
rect for the tile also needs adjusting, to ensure the exact
1:1 texel:pixel mapping when drawing the tile.

Differential Revision: https://phabricator.services.mozilla.com/D35761

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Glenn Watson 2019-06-25 20:28:16 +00:00
Родитель 2424ebfd74
Коммит 632715284a
4 изменённых файлов: 38 добавлений и 15 удалений

Просмотреть файл

@ -122,15 +122,7 @@ void brush_vs(
vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
#ifdef WR_FEATURE_ALPHA_PASS
int color_mode = prim_user_data.x & 0xffff;
int blend_mode = prim_user_data.x >> 16;
int raster_space = prim_user_data.y;
if (color_mode == COLOR_MODE_FROM_PASS) {
color_mode = uMode;
}
// Derive the texture coordinates for this image, based on
// whether the source image is a local-space or screen-space
// image.
@ -145,6 +137,14 @@ void brush_vs(
default:
break;
}
#ifdef WR_FEATURE_ALPHA_PASS
int color_mode = prim_user_data.x & 0xffff;
int blend_mode = prim_user_data.x >> 16;
if (color_mode == COLOR_MODE_FROM_PASS) {
color_mode = uMode;
}
#endif
// Offset and scale vUv here to avoid doing it in the fragment shader.

Просмотреть файл

@ -1204,7 +1204,7 @@ impl BatchBuilder {
textures,
[
ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
RasterizationSpace::Local as i32,
RasterizationSpace::Screen as i32,
get_shader_opacity(1.0),
0,
],

Просмотреть файл

@ -1234,9 +1234,29 @@ impl TileCacheInstance {
TILE_SIZE_WIDTH,
TILE_SIZE_HEIGHT,
);
let content_origin_f = tile.world_rect.origin * frame_context.global_device_pixel_scale;
let content_origin_i = content_origin_f.floor();
// Calculate the UV coords for this tile. These are generally 0-1, but if the
// local rect of the cache has fractional coordinates, then the content origin
// of the tile is floor'ed, and so we need to adjust the UV rect in order to
// ensure a correct 1:1 texel:pixel mapping and correct snapping.
let s0 = (content_origin_f.x - content_origin_i.x) / tile.world_rect.size.width;
let t0 = (content_origin_f.y - content_origin_i.y) / tile.world_rect.size.height;
let s1 = 1.0;
let t1 = 1.0;
let uv_rect_kind = UvRectKind::Quad {
top_left: DeviceHomogeneousVector::new(s0, t0, 0.0, 1.0),
top_right: DeviceHomogeneousVector::new(s1, t0, 0.0, 1.0),
bottom_left: DeviceHomogeneousVector::new(s0, t1, 0.0, 1.0),
bottom_right: DeviceHomogeneousVector::new(s1, t1, 0.0, 1.0),
};
resource_cache.texture_cache.update_picture_cache(
tile_size,
&mut tile.handle,
uv_rect_kind,
gpu_cache,
);
}
@ -2340,9 +2360,10 @@ impl PicturePrimitive {
continue;
}
// TODO(gw): Is this ever fractional? Can that cause seams?
let content_origin = (tile.world_rect.origin * device_pixel_scale)
.round().to_i32();
// The content origin for surfaces is always an integer value (this preserves
// the same snapping on a surface as would occur if drawn directly to parent).
let content_origin_f = tile.world_rect.origin * device_pixel_scale;
let content_origin = content_origin_f.floor().to_i32();
let cache_item = frame_state.resource_cache.texture_cache.get(&tile.handle);

Просмотреть файл

@ -1308,6 +1308,7 @@ impl TextureCache {
&mut self,
tile_size: DeviceIntSize,
handle: &mut TextureCacheHandle,
uv_rect_kind: UvRectKind,
gpu_cache: &mut GpuCache,
) {
debug_assert!(self.now.is_valid());
@ -1339,10 +1340,11 @@ impl TextureCache {
}
// Upload the resource rect and texture array layer.
self.entries
let entry = self.entries
.get_opt_mut(handle)
.expect("BUG: handle must be valid now")
.update_gpu_cache(gpu_cache);
.expect("BUG: handle must be valid now");
entry.uv_rect_kind = uv_rect_kind;
entry.update_gpu_cache(gpu_cache);
}
}