Bug 1685563 - Store non-subpixel-AA glyphs in R8 texture rather than BGRA8. r=lsalzman

Add a new texture type alpha8_glyphs to the texture cache and store
alpha glyphs in it. Because the opengl texture format is R8 but the
shader requires to read the texture's alpha channel, we must swizzle
the components. We cannot rely on texture swizzling due to driver
bugs, so add the necessary code to the shader to do so manually.

Differential Revision: https://phabricator.services.mozilla.com/D101643
This commit is contained in:
Jamie Nicol 2021-01-13 22:51:07 +00:00
Родитель d9f36dce53
Коммит 3591b6e8cb
4 изменённых файлов: 61 добавлений и 14 удалений

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

@ -1604,6 +1604,7 @@ pub extern "C" fn wr_window_new(
color8_nearest_texture_size: 512,
color8_glyph_texture_size: 512,
alpha8_texture_size: 512,
alpha8_glyph_texture_size: 512,
alpha16_texture_size: 512,
}
};

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

@ -5,7 +5,7 @@
#include shared,prim_shared
flat varying vec4 v_color;
flat varying vec2 v_mask_swizzle;
flat varying vec3 v_mask_swizzle;
// Normalized bounds of the source image in the texture.
flat varying vec4 v_uv_bounds;
@ -226,27 +226,30 @@ void main() {
switch (color_mode) {
case COLOR_MODE_ALPHA:
v_mask_swizzle = vec3(0.0, 1.0, 1.0);
v_color = text.color;
break;
case COLOR_MODE_BITMAP:
v_mask_swizzle = vec2(0.0, 1.0);
v_mask_swizzle = vec3(0.0, 1.0, 0.0);
v_color = text.color;
break;
case COLOR_MODE_SUBPX_BG_PASS2:
case COLOR_MODE_SUBPX_DUAL_SOURCE:
v_mask_swizzle = vec2(1.0, 0.0);
v_mask_swizzle = vec3(1.0, 0.0, 0.0);
v_color = text.color;
break;
case COLOR_MODE_SUBPX_CONST_COLOR:
case COLOR_MODE_SUBPX_BG_PASS0:
case COLOR_MODE_COLOR_BITMAP:
v_mask_swizzle = vec2(1.0, 0.0);
v_mask_swizzle = vec3(1.0, 0.0, 0.0);
v_color = vec4(text.color.a);
break;
case COLOR_MODE_SUBPX_BG_PASS1:
v_mask_swizzle = vec2(-1.0, 1.0);
v_mask_swizzle = vec3(-1.0, 1.0, 0.0);
v_color = vec4(text.color.a) * text.bg_color;
break;
default:
v_mask_swizzle = vec2(0.0);
v_mask_swizzle = vec3(0.0, 0.0, 0.0);
v_color = vec4(1.0);
}
@ -267,6 +270,7 @@ Fragment text_fs(void) {
vec2 tc = clamp(v_uv, v_uv_bounds.xy, v_uv_bounds.zw);
vec4 mask = texture(sColor0, tc);
mask = v_mask_swizzle.z != 0.0 ? vec4(mask.r) : mask;
mask.rgb = mask.rgb * v_mask_swizzle.x + mask.aaa * v_mask_swizzle.y;
#ifdef WR_FEATURE_GLYPH_TRANSFORM

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

@ -181,6 +181,16 @@ impl GlyphRasterizer {
// Check if the glyph has a bitmap that needs to be downscaled.
glyph.downscale_bitmap_if_required(&font);
// Convert from BGRA8 to R8 if required. In the future we can make it the
// backends' responsibility to output glyphs in the desired format,
// potentially reducing the number of copies.
if glyph.format.image_format().bytes_per_pixel() == 1 {
glyph.bytes = glyph.bytes
.chunks_mut(4)
.map(|pixel| pixel[3])
.collect::<Vec<_>>();
}
}
job
@ -283,7 +293,7 @@ impl GlyphRasterizer {
ImageDescriptor {
size: size2(glyph.width, glyph.height),
stride: None,
format: FORMAT,
format: glyph.format.image_format(),
flags: ImageDescriptorFlags::empty(),
offset: 0,
},
@ -315,9 +325,6 @@ impl GlyphRasterizer {
}
}
#[allow(dead_code)]
pub const FORMAT: ImageFormat = ImageFormat::BGRA8;
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
@ -756,6 +763,20 @@ impl GlyphFormat {
_ => self,
}
}
/// Returns the ImageFormat that a glyph should be stored as in the texture cache.
pub fn image_format(&self) -> ImageFormat {
match *self {
// GlyphFormat::Bitmap glyphs could be stored in an R8 texture. However, we currently
// support drawing ColorBitmap glyphs (stored in a BGRA8 texture) in Bitmap mode, and
// currently the text shader cannot differentiate between the two cases.
GlyphFormat::Alpha | GlyphFormat::TransformedAlpha => ImageFormat::R8,
GlyphFormat::Subpixel |
GlyphFormat::TransformedSubpixel |
GlyphFormat::Bitmap |
GlyphFormat::ColorBitmap => ImageFormat::BGRA8,
}
}
}
pub struct RasterizedGlyph {
@ -1119,6 +1140,8 @@ struct GlyphRasterJobs {
#[cfg(test)]
mod test_glyph_rasterizer {
pub const FORMAT: api::ImageFormat = api::ImageFormat::BGRA8;
#[test]
fn rasterize_200_glyphs() {
// This test loads a font from disc, the renders 4 requests containing
@ -1135,7 +1158,7 @@ mod test_glyph_rasterizer {
IdNamespace, ColorU};
use api::units::DevicePoint;
use std::sync::Arc;
use crate::glyph_rasterizer::{FORMAT, FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
use crate::glyph_rasterizer::{FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
let worker = ThreadPoolBuilder::new()
.thread_name(|idx|{ format!("WRWorker#{}", idx) })
@ -1213,7 +1236,7 @@ mod test_glyph_rasterizer {
IdNamespace, ColorU};
use api::units::DevicePoint;
use std::sync::Arc;
use crate::glyph_rasterizer::{FORMAT, FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
use crate::glyph_rasterizer::{FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
let worker = ThreadPoolBuilder::new()
.thread_name(|idx|{ format!("WRWorker#{}", idx) })

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

@ -245,6 +245,7 @@ impl EvictionNotice {
struct SharedTextures {
color8_nearest: AllocatorList<ShelfAllocator, TextureParameters>,
alpha8_linear: AllocatorList<ShelfAllocator, TextureParameters>,
alpha8_glyphs: AllocatorList<ShelfAllocator, TextureParameters>,
alpha16_linear: AllocatorList<SlabAllocator, TextureParameters>,
color8_linear: AllocatorList<ShelfAllocator, TextureParameters>,
color8_glyphs: AllocatorList<ShelfAllocator, TextureParameters>,
@ -274,6 +275,19 @@ impl SharedTextures {
filter: TextureFilter::Linear,
},
),
// The cache for alpha glyphs (separate to help with batching).
alpha8_glyphs: AllocatorList::new(
config.alpha8_glyph_texture_size,
ShelfAllocatorOptions {
num_columns: if config.alpha8_glyph_texture_size >= 1024 { 2 } else { 1 },
alignment: size2(4, 8),
.. ShelfAllocatorOptions::default()
},
TextureParameters {
formats: TextureFormatPair::from(ImageFormat::R8),
filter: TextureFilter::Linear,
},
),
// Used for experimental hdr yuv texture support, but not used in
// production Firefox.
alpha16_linear: AllocatorList::new(
@ -299,7 +313,7 @@ impl SharedTextures {
filter: TextureFilter::Linear,
},
),
// The cache for glyphs (separate to help with batching).
// The cache for subpixel-AA and bitmap glyphs (separate to help with batching).
color8_glyphs: AllocatorList::new(
config.color8_glyph_texture_size,
ShelfAllocatorOptions {
@ -346,7 +360,10 @@ impl SharedTextures {
match external_format {
ImageFormat::R8 => {
assert_eq!(filter, TextureFilter::Linear);
&mut self.alpha8_linear
match shader {
TargetShader::Text => &mut self.alpha8_glyphs,
_ => &mut self.alpha8_linear,
}
}
ImageFormat::R16 => {
assert_eq!(filter, TextureFilter::Linear);
@ -573,6 +590,7 @@ pub struct TextureCacheConfig {
pub color8_nearest_texture_size: i32,
pub color8_glyph_texture_size: i32,
pub alpha8_texture_size: i32,
pub alpha8_glyph_texture_size: i32,
pub alpha16_texture_size: i32,
}
@ -582,6 +600,7 @@ impl TextureCacheConfig {
color8_nearest_texture_size: 512,
color8_glyph_texture_size: 2048,
alpha8_texture_size: 1024,
alpha8_glyph_texture_size: 2048,
alpha16_texture_size: 512,
};
}