tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 3c1b634086934ed630c7e4058a7559681010148e
parent 21bf65b55f3997385820ca4015eee74b607e06fa
Author: pstanciu <pstanciu@mozilla.com>
Date:   Mon, 15 Dec 2025 01:30:03 +0200

Revert "Bug 2005618 - Pack subpixel positioned glyphs in to one atlas alloc r=gfx-reviewers,lsalzman" for causing wr failures @highlight-text-across-elements.html

This reverts commit ea7162586cdb9856bf687054064de252ad955730.

Diffstat:
Mgfx/wr/webrender/res/ps_text_run.glsl | 17++---------------
Mgfx/wr/webrender/src/batch.rs | 3---
Mgfx/wr/webrender/src/glyph_cache.rs | 7+++----
Mgfx/wr/webrender/src/gpu_types.rs | 17+++--------------
Mgfx/wr/webrender/src/resource_cache.rs | 21+++++----------------
Mgfx/wr/wr_glyph_rasterizer/src/platform/macos/font.rs | 1-
Mgfx/wr/wr_glyph_rasterizer/src/platform/unix/font.rs | 1-
Mgfx/wr/wr_glyph_rasterizer/src/platform/windows/font.rs | 1-
Mgfx/wr/wr_glyph_rasterizer/src/rasterizer.rs | 158++++---------------------------------------------------------------------------
Mgfx/wr/wrench/reftests/text/reftest.list | 6+++---
10 files changed, 23 insertions(+), 209 deletions(-)

diff --git a/gfx/wr/webrender/res/ps_text_run.glsl b/gfx/wr/webrender/res/ps_text_run.glsl @@ -101,11 +101,8 @@ void main() { PictureTask task = fetch_picture_task(ph.picture_task_address); int glyph_index = instance.segment_index; - int color_mode = instance.flags & 0xF; - int subpx_offset_x = (instance.flags >> 4) & 0x3; - int subpx_offset_y = (instance.flags >> 6) & 0x3; - int subpx_dir = (instance.flags >> 8) & 0x3; - int is_packed_glyph = (instance.flags >> 10) & 0x1; + int subpx_dir = (instance.flags >> 8) & 0xff; + int color_mode = instance.flags & 0xff; // Note that the reference frame relative offset is stored in the prim local // rect size during batching, instead of the actual size of the primitive. @@ -121,16 +118,6 @@ void main() { GlyphResource res = fetch_glyph_resource(instance.resource_address); - // For multi-variant glyphs, adjust the UV rect to select the correct quarter - // of the packed texture based on subpixel offset. - // This must happen before geometry calculations since the glyph rect size depends on the UV rect. - if (is_packed_glyph != 0) { - int variant_index = (subpx_dir == SUBPX_DIR_HORIZONTAL) ? subpx_offset_x : subpx_offset_y; - float quarter_width = (res.uv_rect.z - res.uv_rect.x) * 0.25; - res.uv_rect.x = res.uv_rect.x + float(variant_index) * quarter_width; - res.uv_rect.z = res.uv_rect.x + quarter_width; - } - vec2 snap_bias = get_snap_bias(subpx_dir); // Glyph space refers to the pixel space used by glyph rasterization during frame diff --git a/gfx/wr/webrender/src/batch.rs b/gfx/wr/webrender/src/batch.rs @@ -2015,9 +2015,6 @@ impl BatchBuilder { glyph.index_in_text_run, glyph.uv_rect_address, color_mode, - glyph.subpx_offset_x, - glyph.subpx_offset_y, - glyph.is_packed_glyph, )); } }, diff --git a/gfx/wr/webrender/src/glyph_cache.rs b/gfx/wr/webrender/src/glyph_cache.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{FontKey, FontInstanceKey, IdNamespace}; -use glyph_rasterizer::{FontInstance, GlyphFormat, GlyphCacheKey, GlyphRasterizer}; +use glyph_rasterizer::{FontInstance, GlyphFormat, GlyphKey, GlyphRasterizer}; use crate::internal_types::{FrameId, FrameStamp, FastHashMap}; use crate::resource_cache::ResourceClassCache; use std::sync::Arc; @@ -16,7 +16,6 @@ use crate::texture_cache::TextureCacheHandle; pub struct CachedGlyphInfo { pub format: GlyphFormat, pub texture_cache_handle: TextureCacheHandle, - pub is_packed_glyph: bool, } #[cfg_attr(feature = "capture", derive(Serialize))] @@ -63,7 +62,7 @@ pub struct GlyphKeyCacheInfo { last_frame_used: FrameId, } -pub type GlyphKeyCache = ResourceClassCache<GlyphCacheKey, GlyphCacheEntry, GlyphKeyCacheInfo>; +pub type GlyphKeyCache = ResourceClassCache<GlyphKey, GlyphCacheEntry, GlyphKeyCacheInfo>; impl GlyphKeyCache { pub fn eviction_notice(&self) -> &EvictionNotice { @@ -74,7 +73,7 @@ impl GlyphKeyCache { self.clear(); } - pub fn add_glyph(&mut self, key: GlyphCacheKey, value: GlyphCacheEntry) { + pub fn add_glyph(&mut self, key: GlyphKey, value: GlyphCacheEntry) { self.insert(key, value); } diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs @@ -561,25 +561,14 @@ impl GlyphInstance { glyph_index_in_text_run: i32, glyph_uv_rect: GpuBufferAddress, color_mode: ShaderColorMode, - subpx_offset_x: u8, - subpx_offset_y: u8, - is_packed_glyph: bool, ) -> PrimitiveInstanceData { - // Pack subpixel offsets and multi-variant flag into upper 16 bits of data[2] - // After instance.flags extraction (>> 16), shader sees: - // bits 0-3: color_mode, bits 4-5: subpx_offset_x, bits 6-7: subpx_offset_y, - // bits 8-9: subpx_dir, bit 10: is_packed_glyph - let packed_flags = (((is_packed_glyph as u32) & 0x1) << 26) - | (((subpx_dir as u32) & 0x3) << 24) - | (((subpx_offset_y as u32) & 0x3) << 22) - | (((subpx_offset_x as u32) & 0x3) << 20) - | (((color_mode as u32) & 0xF) << 16); - PrimitiveInstanceData { data: [ self.prim_header_index.0 as i32, clip_task.0 as i32, - packed_flags as i32 | glyph_index_in_text_run, + (subpx_dir as u32 as i32) << 24 + | (color_mode as u32 as i32) << 16 + | glyph_index_in_text_run, glyph_uv_rect.as_int(), ], } diff --git a/gfx/wr/webrender/src/resource_cache.rs b/gfx/wr/webrender/src/resource_cache.rs @@ -67,9 +67,6 @@ pub struct GlyphFetchResult { pub offset: DevicePoint, pub size: DeviceIntSize, pub scale: f32, - pub subpx_offset_x: u8, - pub subpx_offset_y: u8, - pub is_packed_glyph: bool, } // These coordinates are always in texels. @@ -1286,8 +1283,7 @@ impl ResourceCache { font, glyph_keys, |key| { - let cache_key = key.cache_key(); - if let Some(entry) = glyph_key_cache.try_get(&cache_key) { + if let Some(entry) = glyph_key_cache.try_get(key) { match entry { GlyphCacheEntry::Cached(ref glyph) => { if !texture_cache.request(&glyph.texture_cache_handle, gpu_buffer) { @@ -1302,7 +1298,7 @@ impl ResourceCache { } }; - glyph_key_cache.add_glyph(cache_key, GlyphCacheEntry::Pending); + glyph_key_cache.add_glyph(*key, GlyphCacheEntry::Pending); true } @@ -1336,10 +1332,9 @@ impl ResourceCache { debug_assert!(fetch_buffer.is_empty()); for (loop_index, key) in glyph_keys.iter().enumerate() { - let cache_key = key.cache_key(); - let (cache_item, glyph_format, is_packed_glyph) = match *glyph_key_cache.get(&cache_key) { + let (cache_item, glyph_format) = match *glyph_key_cache.get(key) { GlyphCacheEntry::Cached(ref glyph) => { - (self.texture_cache.get(&glyph.texture_cache_handle), glyph.format, glyph.is_packed_glyph) + (self.texture_cache.get(&glyph.texture_cache_handle), glyph.format) } GlyphCacheEntry::Blank | GlyphCacheEntry::Pending => continue, }; @@ -1352,16 +1347,12 @@ impl ResourceCache { current_texture_id = cache_item.texture_id; current_glyph_format = glyph_format; } - let (subpx_offset_x, subpx_offset_y) = key.subpixel_offset(); fetch_buffer.push(GlyphFetchResult { index_in_text_run: loop_index as i32, uv_rect_address: gpu_buffer.resolve_handle(cache_item.uv_rect_handle), offset: DevicePoint::new(cache_item.user_data[0], cache_item.user_data[1]), size: cache_item.uv_rect.size(), scale: cache_item.user_data[2], - subpx_offset_x: subpx_offset_x as u8, - subpx_offset_y: subpx_offset_y as u8, - is_packed_glyph, }); } @@ -1513,7 +1504,6 @@ impl ResourceCache { self.glyph_rasterizer.resolve_glyphs( |job, can_use_r8_format| { let GlyphRasterJob { font, key, result } = job; - let cache_key = key.cache_key(); let glyph_key_cache = cached_glyphs.get_glyph_key_cache_for_font_mut(&*font); let glyph_info = match result { Err(_) => GlyphCacheEntry::Blank, @@ -1546,11 +1536,10 @@ impl ResourceCache { GlyphCacheEntry::Cached(CachedGlyphInfo { texture_cache_handle, format: glyph.format, - is_packed_glyph: glyph.is_packed_glyph, }) } }; - glyph_key_cache.insert(cache_key, glyph_info); + glyph_key_cache.insert(key, glyph_info); }, profile, ); diff --git a/gfx/wr/wr_glyph_rasterizer/src/platform/macos/font.rs b/gfx/wr/wr_glyph_rasterizer/src/platform/macos/font.rs @@ -787,7 +787,6 @@ impl FontContext { GlyphType::Vector => font.get_glyph_format(), }, bytes: rasterized_pixels, - is_packed_glyph: false, })}) } } diff --git a/gfx/wr/wr_glyph_rasterizer/src/platform/unix/font.rs b/gfx/wr/wr_glyph_rasterizer/src/platform/unix/font.rs @@ -1123,7 +1123,6 @@ impl FontContext { scale, format: glyph_format, bytes: final_buffer, - is_packed_glyph: false, }) } } diff --git a/gfx/wr/wr_glyph_rasterizer/src/platform/windows/font.rs b/gfx/wr/wr_glyph_rasterizer/src/platform/windows/font.rs @@ -638,7 +638,6 @@ impl FontContext { scale: (if bitmaps { y_scale.recip() } else { 1.0 }) as f32, format, bytes: bgra_pixels, - is_packed_glyph: false, }) } } diff --git a/gfx/wr/wr_glyph_rasterizer/src/rasterizer.rs b/gfx/wr/wr_glyph_rasterizer/src/rasterizer.rs @@ -1098,27 +1098,11 @@ impl Into<f64> for SubpixelOffset { } } -impl SubpixelOffset { - fn to_f32(self) -> f32 { - match self { - SubpixelOffset::Zero => 0.0, - SubpixelOffset::Quarter => 0.25, - SubpixelOffset::Half => 0.5, - SubpixelOffset::ThreeQuarters => 0.75, - } - } -} - #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GlyphKey(u32); -#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)] -#[cfg_attr(feature = "capture", derive(Serialize))] -#[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct GlyphCacheKey(u32); - impl GlyphKey { pub fn new( index: u32, @@ -1132,49 +1116,22 @@ impl GlyphKey { }; let sox = SubpixelOffset::quantize(dx); let soy = SubpixelOffset::quantize(dy); - assert_eq!(0, index & 0xFC000000); + assert_eq!(0, index & 0xF0000000); - GlyphKey(index | (sox as u32) << 26 | (soy as u32) << 28 | (subpx_dir as u32) << 30) + GlyphKey(index | (sox as u32) << 28 | (soy as u32) << 30) } pub fn index(&self) -> GlyphIndex { - self.0 & 0x03FFFFFF + self.0 & 0x0FFFFFFF } - pub fn subpixel_offset(&self) -> (SubpixelOffset, SubpixelOffset) { - let x = (self.0 >> 26) as u8 & 3; - let y = (self.0 >> 28) as u8 & 3; + fn subpixel_offset(&self) -> (SubpixelOffset, SubpixelOffset) { + let x = (self.0 >> 28) as u8 & 3; + let y = (self.0 >> 30) as u8 & 3; unsafe { (mem::transmute(x), mem::transmute(y)) } } - - pub fn subpixel_dir(&self) -> SubpixelDirection { - let dir = (self.0 >> 30) as u8 & 3; - unsafe { - mem::transmute(dir as u32) - } - } - - pub fn cache_key(&self) -> GlyphCacheKey { - let index = self.index(); - let subpx_dir = self.subpixel_dir(); - assert_eq!(0, index & 0xFC000000); - GlyphCacheKey(index | (subpx_dir as u32) << 30) - } -} - -impl GlyphCacheKey { - pub fn index(&self) -> GlyphIndex { - self.0 & 0x03FFFFFF - } - - pub fn subpixel_dir(&self) -> SubpixelDirection { - let dir = ((self.0 >> 30) & 3) as u32; - unsafe { - mem::transmute(dir) - } - } } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -1333,7 +1290,6 @@ pub struct RasterizedGlyph { pub scale: f32, pub format: GlyphFormat, pub bytes: Vec<u8>, - pub is_packed_glyph: bool, } impl RasterizedGlyph { @@ -1711,69 +1667,6 @@ pub type GlyphRasterResult = Result<RasterizedGlyph, GlyphRasterError>; #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GpuGlyphCacheKey(pub u32); -fn pack_glyph_variants_horizontal(variants: &[RasterizedGlyph]) -> RasterizedGlyph { - // Pack 4 glyph variants horizontally into a single texture. - // Normalize both left and top offsets via padding so all variants can use the same base offsets. - - let min_left = variants.iter().map(|v| v.left.floor()).fold(f32::INFINITY, f32::min); - let max_top = variants.iter().map(|v| v.top.floor()).fold(f32::NEG_INFINITY, f32::max); - - // Slot width must accommodate the widest variant plus left padding - let slot_width = variants.iter() - .map(|v| v.width + (v.left.floor() - min_left) as i32) - .max().unwrap(); - - // Slot height must accommodate the tallest variant plus top padding - let slot_height = variants.iter() - .map(|v| v.height + (max_top - v.top.floor()) as i32) - .max().unwrap(); - - let packed_width = slot_width * 4; - let bpp = 4; - - let mut packed_bytes = vec![0u8; (packed_width * slot_height * bpp) as usize]; - - for (variant_idx, variant) in variants.iter().enumerate() { - // Compute padding needed to normalize both left and top offsets - let left_pad = (variant.left.floor() - min_left) as i32; - let top_pad = (max_top - variant.top.floor()) as i32; - let slot_x = variant_idx as i32 * slot_width; - - for src_y in 0..variant.height { - let dst_y = src_y + top_pad; - if dst_y >= slot_height { - break; - } - - let dst_x = slot_x + left_pad; - if dst_x < 0 { - continue; - } - - let src_row_start = (src_y * variant.width * bpp) as usize; - let src_row_end = src_row_start + (variant.width * bpp) as usize; - let dst_row_start = (dst_y * packed_width * bpp + dst_x * bpp) as usize; - let dst_row_end = dst_row_start + (variant.width * bpp) as usize; - - if dst_row_end <= packed_bytes.len() && src_row_end <= variant.bytes.len() { - packed_bytes[dst_row_start..dst_row_end] - .copy_from_slice(&variant.bytes[src_row_start..src_row_end]); - } - } - } - - RasterizedGlyph { - top: max_top, - left: min_left, - width: packed_width, - height: slot_height, - scale: variants[0].scale, - format: variants[0].format, - bytes: packed_bytes, - is_packed_glyph: true, - } -} - fn process_glyph( context: &mut FontContext, can_use_r8_format: bool, @@ -1781,44 +1674,7 @@ fn process_glyph( key: GlyphKey, ) -> GlyphRasterJob { profile_scope!("glyph-raster"); - - let subpx_dir = key.subpixel_dir(); - - let result = if subpx_dir == SubpixelDirection::None { - context.rasterize_glyph(&font, &key) - } else { - let offsets = [ - SubpixelOffset::Zero, - SubpixelOffset::Quarter, - SubpixelOffset::Half, - SubpixelOffset::ThreeQuarters, - ]; - - let mut variants = Vec::with_capacity(4); - for offset in &offsets { - let variant_key = GlyphKey::new( - key.index(), - match subpx_dir { - SubpixelDirection::Horizontal => DevicePoint::new(offset.to_f32(), 0.0), - SubpixelDirection::Vertical => DevicePoint::new(0.0, offset.to_f32()), - SubpixelDirection::None => DevicePoint::zero(), - }, - subpx_dir, - ); - - match context.rasterize_glyph(&font, &variant_key) { - Ok(glyph) => variants.push(glyph), - Err(e) => return GlyphRasterJob { - font: font, - key: key.clone(), - result: Err(e), - }, - } - } - - Ok(pack_glyph_variants_horizontal(&variants)) - }; - + let result = context.rasterize_glyph(&font, &key); let mut job = GlyphRasterJob { font: font, key: key.clone(), diff --git a/gfx/wr/wrench/reftests/text/reftest.list b/gfx/wr/wrench/reftests/text/reftest.list @@ -19,8 +19,8 @@ skip_on(android,device) fuzzy(1,3692) fuzzy-if(platform(win),2,5585) fuzzy-if(pl fuzzy(2,405) fuzzy-if(platform(swgl),2,1510) == split-batch.yaml split-batch-ref.yaml # Next 3 tests affected by bug 1548099 on Android skip_on(android) == shadow-red.yaml shadow-red-ref.yaml -skip_on(android) fuzzy(1,999) fuzzy-if(platform(swgl),2,1331) == shadow-grey.yaml shadow-grey-ref.yaml -skip_on(android) fuzzy(1,834) fuzzy-if(platform(swgl),2,1549) == shadow-grey-transparent.yaml shadow-grey-ref.yaml +skip_on(android) fuzzy(1,999) fuzzy-if(platform(swgl),2,1324) == shadow-grey.yaml shadow-grey-ref.yaml +skip_on(android) fuzzy(1,834) fuzzy-if(platform(swgl),2,1538) == shadow-grey-transparent.yaml shadow-grey-ref.yaml == subtle-shadow.yaml subtle-shadow-ref.yaml fuzzy(1,64) == shadow-atomic.yaml shadow-atomic-ref.yaml fuzzy(1,64) == shadow-clip-rect.yaml shadow-atomic-ref.yaml @@ -57,7 +57,7 @@ fuzzy(1,1) platform(linux) == two-shadows.yaml two-shadows.png == shadow-fast-clip.yaml shadow-fast-clip-ref.yaml skip_on(android,device) fuzzy-if(platform(win),1,18) == shadow-partial-glyph.yaml shadow-partial-glyph-ref.yaml # Fails on Pixel2 fuzzy(2,212) platform(linux) == shadow-transforms.yaml shadow-transforms.png -fuzzy(2,372) platform(linux) == raster-space.yaml raster-space.png +fuzzy(2,370) platform(linux) == raster-space.yaml raster-space.png skip_on(android) skip_on(mac,>=10.14) != allow-subpixel.yaml allow-subpixel-ref.yaml # Android: we don't enable sub-px aa on this platform. != large-glyphs.yaml blank.yaml != large-line-decoration.yaml blank.yaml