зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1504125 - Update webrender to commit d30fda15ac69d3d421c7307f77f2b5b9c0a1b4ce (WR PR 3260). r=kats
Differential Revision: https://phabricator.services.mozilla.com/D10683 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
366e98d80b
Коммит
fdbcf6db98
|
@ -542,6 +542,116 @@ impl AlphaBatchBuilder {
|
|||
.map_or(OPAQUE_TASK_ADDRESS, |id| render_tasks.get_task_address(id));
|
||||
|
||||
match prim_instance.kind {
|
||||
PrimitiveInstanceKind::TextRun { ref run, .. } => {
|
||||
let subpx_dir = run.used_font.get_subpx_dir();
|
||||
|
||||
// The GPU cache data is stored in the template and reused across
|
||||
// frames and display lists.
|
||||
let prim_data = &ctx
|
||||
.resources
|
||||
.prim_data_store[prim_instance.prim_data_handle];
|
||||
|
||||
let glyph_fetch_buffer = &mut self.glyph_fetch_buffer;
|
||||
let alpha_batch_list = &mut self.batch_list.alpha_batch_list;
|
||||
let prim_cache_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
|
||||
|
||||
let prim_header = PrimitiveHeader {
|
||||
local_rect: prim_data.prim_rect,
|
||||
local_clip_rect: prim_instance.combined_local_clip_rect,
|
||||
task_address,
|
||||
specific_prim_address: prim_cache_address,
|
||||
clip_task_address,
|
||||
transform_id,
|
||||
};
|
||||
|
||||
ctx.resource_cache.fetch_glyphs(
|
||||
run.used_font.clone(),
|
||||
&run.glyph_keys,
|
||||
glyph_fetch_buffer,
|
||||
gpu_cache,
|
||||
|texture_id, mut glyph_format, glyphs| {
|
||||
debug_assert_ne!(texture_id, TextureSource::Invalid);
|
||||
|
||||
// Ignore color and only sample alpha when shadowing.
|
||||
if run.shadow {
|
||||
glyph_format = glyph_format.ignore_color();
|
||||
}
|
||||
|
||||
let subpx_dir = subpx_dir.limit_by(glyph_format);
|
||||
|
||||
let textures = BatchTextures {
|
||||
colors: [
|
||||
texture_id,
|
||||
TextureSource::Invalid,
|
||||
TextureSource::Invalid,
|
||||
],
|
||||
};
|
||||
|
||||
let kind = BatchKind::TextRun(glyph_format);
|
||||
|
||||
let (blend_mode, color_mode) = match glyph_format {
|
||||
GlyphFormat::Subpixel |
|
||||
GlyphFormat::TransformedSubpixel => {
|
||||
if run.used_font.bg_color.a != 0 {
|
||||
(
|
||||
BlendMode::SubpixelWithBgColor,
|
||||
ShaderColorMode::FromRenderPassMode,
|
||||
)
|
||||
} else if ctx.use_dual_source_blending {
|
||||
(
|
||||
BlendMode::SubpixelDualSource,
|
||||
ShaderColorMode::SubpixelDualSource,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
BlendMode::SubpixelConstantTextColor(run.used_font.color.into()),
|
||||
ShaderColorMode::SubpixelConstantTextColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
GlyphFormat::Alpha |
|
||||
GlyphFormat::TransformedAlpha => {
|
||||
(
|
||||
BlendMode::PremultipliedAlpha,
|
||||
ShaderColorMode::Alpha,
|
||||
)
|
||||
}
|
||||
GlyphFormat::Bitmap => {
|
||||
(
|
||||
BlendMode::PremultipliedAlpha,
|
||||
ShaderColorMode::Bitmap,
|
||||
)
|
||||
}
|
||||
GlyphFormat::ColorBitmap => {
|
||||
(
|
||||
BlendMode::PremultipliedAlpha,
|
||||
ShaderColorMode::ColorBitmap,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let prim_header_index = prim_headers.push(&prim_header, z_id, [0; 3]);
|
||||
let key = BatchKey::new(kind, blend_mode, textures);
|
||||
let base_instance = GlyphInstance::new(
|
||||
prim_header_index,
|
||||
);
|
||||
let batch = alpha_batch_list.set_params_and_get_batch(
|
||||
key,
|
||||
bounding_rect,
|
||||
z_id,
|
||||
);
|
||||
|
||||
for glyph in glyphs {
|
||||
batch.push(base_instance.build(
|
||||
glyph.index_in_text_run,
|
||||
glyph.uv_rect_address.as_int(),
|
||||
(subpx_dir as u32 as i32) << 16 |
|
||||
(color_mode as u32 as i32),
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
PrimitiveInstanceKind::LineDecoration { ref cache_handle, .. } => {
|
||||
// The GPU cache data is stored in the template and reused across
|
||||
// frames and display lists.
|
||||
|
@ -654,6 +764,7 @@ impl AlphaBatchBuilder {
|
|||
let pic_index = match prim_instance.kind {
|
||||
PrimitiveInstanceKind::Picture { pic_index } => pic_index,
|
||||
PrimitiveInstanceKind::LineDecoration { .. } |
|
||||
PrimitiveInstanceKind::TextRun { .. } |
|
||||
PrimitiveInstanceKind::LegacyPrimitive { .. } => {
|
||||
unreachable!();
|
||||
}
|
||||
|
@ -1055,7 +1166,6 @@ impl AlphaBatchBuilder {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let prim_cache_address = if is_multiple_primitives {
|
||||
|
@ -1185,102 +1295,7 @@ impl AlphaBatchBuilder {
|
|||
}
|
||||
}
|
||||
}
|
||||
PrimitiveDetails::TextRun(ref text_cpu) => {
|
||||
let subpx_dir = text_cpu.used_font.get_subpx_dir();
|
||||
|
||||
let glyph_fetch_buffer = &mut self.glyph_fetch_buffer;
|
||||
let alpha_batch_list = &mut self.batch_list.alpha_batch_list;
|
||||
|
||||
ctx.resource_cache.fetch_glyphs(
|
||||
text_cpu.used_font.clone(),
|
||||
&text_cpu.glyph_keys,
|
||||
glyph_fetch_buffer,
|
||||
gpu_cache,
|
||||
|texture_id, mut glyph_format, glyphs| {
|
||||
debug_assert_ne!(texture_id, TextureSource::Invalid);
|
||||
|
||||
// Ignore color and only sample alpha when shadowing.
|
||||
if text_cpu.shadow {
|
||||
glyph_format = glyph_format.ignore_color();
|
||||
}
|
||||
|
||||
let subpx_dir = subpx_dir.limit_by(glyph_format);
|
||||
|
||||
let textures = BatchTextures {
|
||||
colors: [
|
||||
texture_id,
|
||||
TextureSource::Invalid,
|
||||
TextureSource::Invalid,
|
||||
],
|
||||
};
|
||||
|
||||
let kind = BatchKind::TextRun(glyph_format);
|
||||
|
||||
let (blend_mode, color_mode) = match glyph_format {
|
||||
GlyphFormat::Subpixel |
|
||||
GlyphFormat::TransformedSubpixel => {
|
||||
if text_cpu.used_font.bg_color.a != 0 {
|
||||
(
|
||||
BlendMode::SubpixelWithBgColor,
|
||||
ShaderColorMode::FromRenderPassMode,
|
||||
)
|
||||
} else if ctx.use_dual_source_blending {
|
||||
(
|
||||
BlendMode::SubpixelDualSource,
|
||||
ShaderColorMode::SubpixelDualSource,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
BlendMode::SubpixelConstantTextColor(text_cpu.used_font.color.into()),
|
||||
ShaderColorMode::SubpixelConstantTextColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
GlyphFormat::Alpha |
|
||||
GlyphFormat::TransformedAlpha => {
|
||||
(
|
||||
BlendMode::PremultipliedAlpha,
|
||||
ShaderColorMode::Alpha,
|
||||
)
|
||||
}
|
||||
GlyphFormat::Bitmap => {
|
||||
(
|
||||
BlendMode::PremultipliedAlpha,
|
||||
ShaderColorMode::Bitmap,
|
||||
)
|
||||
}
|
||||
GlyphFormat::ColorBitmap => {
|
||||
(
|
||||
BlendMode::PremultipliedAlpha,
|
||||
ShaderColorMode::ColorBitmap,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let prim_header_index = prim_headers.push(&prim_header, z_id, [0; 3]);
|
||||
let key = BatchKey::new(kind, blend_mode, textures);
|
||||
let base_instance = GlyphInstance::new(
|
||||
prim_header_index,
|
||||
);
|
||||
let batch = alpha_batch_list.set_params_and_get_batch(
|
||||
key,
|
||||
bounding_rect,
|
||||
z_id,
|
||||
);
|
||||
|
||||
for glyph in glyphs {
|
||||
batch.push(base_instance.build(
|
||||
glyph.index_in_text_run,
|
||||
glyph.uv_rect_address.as_int(),
|
||||
(subpx_dir as u32 as i32) << 16 |
|
||||
(color_mode as u32 as i32),
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1807,11 +1822,6 @@ impl PrimitiveInstance {
|
|||
details: &PrimitiveDetails,
|
||||
) -> BlendMode {
|
||||
match *details {
|
||||
// Can only resolve the TextRun's blend mode once glyphs are fetched.
|
||||
PrimitiveDetails::TextRun(..) => {
|
||||
BlendMode::PremultipliedAlpha
|
||||
}
|
||||
|
||||
PrimitiveDetails::Brush(ref brush) => {
|
||||
match brush.kind {
|
||||
BrushKind::Clear => {
|
||||
|
@ -1847,8 +1857,7 @@ impl PrimitiveInstance {
|
|||
PrimitiveDetails::Brush(BrushPrimitive { kind: BrushKind::YuvImage{ yuv_key, .. }, .. }) => {
|
||||
yuv_key[0]
|
||||
}
|
||||
PrimitiveDetails::Brush(_) |
|
||||
PrimitiveDetails::TextRun(..) => {
|
||||
PrimitiveDetails::Brush(_) => {
|
||||
return true
|
||||
}
|
||||
};
|
||||
|
|
|
@ -27,7 +27,7 @@ use picture::{Picture3DContext, PictureCompositeMode, PictureIdGenerator, Pictur
|
|||
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, PrimitiveInstance, PrimitiveDataInterner, PrimitiveKeyKind};
|
||||
use prim_store::{EdgeAaSegmentMask, ImageSource, PrimitiveOpacity, PrimitiveKey, PrimitiveSceneData, PrimitiveInstanceKind};
|
||||
use prim_store::{BorderSource, BrushSegment, BrushSegmentVec, PrimitiveContainer, PrimitiveDataHandle, PrimitiveStore};
|
||||
use prim_store::{OpacityBinding, ScrollNodeAndClipChain, TextRunPrimitive, PictureIndex, register_prim_chase_id};
|
||||
use prim_store::{OpacityBinding, ScrollNodeAndClipChain, PictureIndex, register_prim_chase_id};
|
||||
use render_backend::{DocumentView};
|
||||
use resource_cache::{FontInstanceMap, ImageRequest};
|
||||
use scene::{Scene, ScenePipeline, StackingContextHelpers};
|
||||
|
@ -553,6 +553,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
&text_info.color,
|
||||
item.glyphs(),
|
||||
text_info.glyph_options,
|
||||
pipeline_id,
|
||||
);
|
||||
}
|
||||
SpecificDisplayItem::Rectangle(ref info) => {
|
||||
|
@ -2062,14 +2063,15 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pub fn add_text(
|
||||
&mut self,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
run_offset: LayoutVector2D,
|
||||
offset: LayoutVector2D,
|
||||
prim_info: &LayoutPrimitiveInfo,
|
||||
font_instance_key: &FontInstanceKey,
|
||||
text_color: &ColorF,
|
||||
glyph_range: ItemRange<GlyphInstance>,
|
||||
glyph_options: Option<GlyphOptions>,
|
||||
pipeline_id: PipelineId,
|
||||
) {
|
||||
let prim = {
|
||||
let container = {
|
||||
let instance_map = self.font_instances.read().unwrap();
|
||||
let font_instance = match instance_map.get(font_instance_key) {
|
||||
Some(instance) => instance,
|
||||
|
@ -2097,7 +2099,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
flags |= options.flags;
|
||||
}
|
||||
|
||||
let prim_font = FontInstance::new(
|
||||
let font = FontInstance::new(
|
||||
font_instance.font_key,
|
||||
font_instance.size,
|
||||
*text_color,
|
||||
|
@ -2108,20 +2110,29 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
font_instance.platform_options,
|
||||
font_instance.variations.clone(),
|
||||
);
|
||||
TextRunPrimitive::new(
|
||||
prim_font,
|
||||
run_offset,
|
||||
glyph_range,
|
||||
Vec::new(),
|
||||
false,
|
||||
)
|
||||
|
||||
// TODO(gw): We can do better than a hash lookup here...
|
||||
let display_list = self.scene.get_display_list_for_pipeline(pipeline_id);
|
||||
|
||||
// TODO(gw): It'd be nice not to have to allocate here for creating
|
||||
// the primitive key, when the common case is that the
|
||||
// hash will match and we won't end up creating a new
|
||||
// primitive template.
|
||||
let glyphs = display_list.get(glyph_range).collect();
|
||||
|
||||
PrimitiveContainer::TextRun {
|
||||
glyphs,
|
||||
font,
|
||||
offset,
|
||||
shadow: false,
|
||||
}
|
||||
};
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
prim_info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::TextRun(prim),
|
||||
container,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -512,10 +512,6 @@ impl<'a> GpuDataRequest<'a> {
|
|||
self.texture.pending_blocks.push(block.into());
|
||||
}
|
||||
|
||||
pub fn extend_from_slice(&mut self, blocks: &[GpuBlockData]) {
|
||||
self.texture.pending_blocks.extend_from_slice(blocks);
|
||||
}
|
||||
|
||||
pub fn current_used_block_num(&self) -> usize {
|
||||
self.texture.pending_blocks.len() - self.start_index
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use api::{FilterOp, GlyphInstance, GradientStop, ImageKey, ImageRendering, ItemR
|
|||
use api::{RasterSpace, LayoutPoint, LayoutRect, LayoutSideOffsets, LayoutSize, LayoutToWorldTransform};
|
||||
use api::{LayoutVector2D, PremultipliedColorF, PropertyBinding, Shadow, YuvColorSpace, YuvFormat, LayoutRectAu};
|
||||
use api::{DeviceIntSideOffsets, WorldPixel, BoxShadowClipMode, NormalBorder, WorldRect, LayoutToWorldScale};
|
||||
use api::{PicturePixel, RasterPixel, ColorDepth, LineStyle, LineOrientation, LayoutSizeAu, AuHelpers};
|
||||
use api::{PicturePixel, RasterPixel, ColorDepth, LineStyle, LineOrientation, LayoutSizeAu, AuHelpers, LayoutVector2DAu};
|
||||
use app_units::Au;
|
||||
use border::{get_max_scale_for_border, build_border_instances, create_normal_border_prim};
|
||||
use clip_scroll_tree::{ClipScrollTree, CoordinateSystemId, SpatialNodeIndex};
|
||||
|
@ -17,8 +17,7 @@ use euclid::{TypedTransform3D, TypedRect, TypedScale};
|
|||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
|
||||
use frame_builder::PrimitiveContext;
|
||||
use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
|
||||
use gpu_cache::{GpuBlockData, GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest,
|
||||
ToGpuBlocks};
|
||||
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpuBlocks};
|
||||
use gpu_types::BrushFlags;
|
||||
use image::{self, Repetition};
|
||||
use intern;
|
||||
|
@ -26,7 +25,7 @@ use picture::{ClusterRange, PictureCompositeMode, PicturePrimitive, PictureUpdat
|
|||
use picture::{PrimitiveList, SurfaceInfo};
|
||||
#[cfg(debug_assertions)]
|
||||
use render_backend::FrameId;
|
||||
use render_task::{BlitSource, RenderTask, RenderTaskCacheKey, to_cache_size};
|
||||
use render_task::{BlitSource, RenderTask, RenderTaskCacheKey, RenderTaskTree, to_cache_size};
|
||||
use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskCacheEntryHandle};
|
||||
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
||||
use resource_cache::{ImageProperties, ImageRequest, ResourceCache};
|
||||
|
@ -34,6 +33,7 @@ use scene::SceneProperties;
|
|||
use std::{cmp, fmt, mem, ops, usize};
|
||||
#[cfg(debug_assertions)]
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use tiling::SpecialRenderPasses;
|
||||
use util::{ScaleOffset, MatrixHelpers, MaxRect};
|
||||
use util::{pack_as_float, project_rect, raster_rect_to_device_pixels};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -314,6 +314,13 @@ pub enum PrimitiveKeyKind {
|
|||
/// to instead have Option<PrimitiveKeyKind>. It should become
|
||||
/// clearer as we port more primitives to be interned.
|
||||
Unused,
|
||||
/// A run of glyphs, with associated font information.
|
||||
TextRun {
|
||||
font: FontInstance,
|
||||
offset: LayoutVector2DAu,
|
||||
glyphs: Vec<GlyphInstance>,
|
||||
shadow: bool,
|
||||
},
|
||||
/// Identifying key for a line decoration.
|
||||
LineDecoration {
|
||||
// If the cache_key is Some(..) it is a line decoration
|
||||
|
@ -359,6 +366,15 @@ impl PrimitiveKey {
|
|||
cache_handle: None,
|
||||
}
|
||||
}
|
||||
PrimitiveKeyKind::TextRun { ref font, shadow, .. } => {
|
||||
PrimitiveInstanceKind::TextRun {
|
||||
run: TextRunPrimitive {
|
||||
used_font: font.clone(),
|
||||
glyph_keys: Vec::new(),
|
||||
shadow,
|
||||
}
|
||||
}
|
||||
}
|
||||
PrimitiveKeyKind::Unused => {
|
||||
// Should never be hit as this method should not be
|
||||
// called for old style primitives.
|
||||
|
@ -377,6 +393,11 @@ pub enum PrimitiveTemplateKind {
|
|||
cache_key: Option<LineDecorationCacheKey>,
|
||||
color: ColorF,
|
||||
},
|
||||
TextRun {
|
||||
font: FontInstance,
|
||||
offset: LayoutVector2DAu,
|
||||
glyphs: Vec<GlyphInstance>,
|
||||
},
|
||||
Unused,
|
||||
}
|
||||
|
||||
|
@ -387,6 +408,13 @@ impl From<PrimitiveKeyKind> for PrimitiveTemplateKind {
|
|||
fn from(item: PrimitiveKeyKind) -> Self {
|
||||
match item {
|
||||
PrimitiveKeyKind::Unused => PrimitiveTemplateKind::Unused,
|
||||
PrimitiveKeyKind::TextRun { glyphs, font, offset, .. } => {
|
||||
PrimitiveTemplateKind::TextRun {
|
||||
font,
|
||||
offset,
|
||||
glyphs,
|
||||
}
|
||||
}
|
||||
PrimitiveKeyKind::LineDecoration { cache_key, color } => {
|
||||
PrimitiveTemplateKind::LineDecoration {
|
||||
cache_key,
|
||||
|
@ -460,6 +488,42 @@ impl PrimitiveTemplate {
|
|||
);
|
||||
}
|
||||
}
|
||||
PrimitiveTemplateKind::TextRun { ref glyphs, ref font, ref offset, .. } => {
|
||||
if let Some(mut request) = gpu_cache.request(&mut self.gpu_cache_handle) {
|
||||
request.push(ColorF::from(font.color).premultiplied());
|
||||
// this is the only case where we need to provide plain color to GPU
|
||||
let bg_color = ColorF::from(font.bg_color);
|
||||
request.push([bg_color.r, bg_color.g, bg_color.b, 1.0]);
|
||||
request.push([
|
||||
offset.x.to_f32_px(),
|
||||
offset.y.to_f32_px(),
|
||||
0.0,
|
||||
0.0,
|
||||
]);
|
||||
|
||||
let mut gpu_block = [0.0; 4];
|
||||
for (i, src) in glyphs.iter().enumerate() {
|
||||
// Two glyphs are packed per GPU block.
|
||||
|
||||
if (i & 1) == 0 {
|
||||
gpu_block[0] = src.point.x;
|
||||
gpu_block[1] = src.point.y;
|
||||
} else {
|
||||
gpu_block[2] = src.point.x;
|
||||
gpu_block[3] = src.point.y;
|
||||
request.push(gpu_block);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the last block is added in the case
|
||||
// of an odd number of glyphs.
|
||||
if (glyphs.len() & 1) != 0 {
|
||||
request.push(gpu_block);
|
||||
}
|
||||
|
||||
assert!(request.current_used_block_num() <= MAX_VERTEX_TEXTURE_WIDTH);
|
||||
}
|
||||
}
|
||||
PrimitiveTemplateKind::Unused => {}
|
||||
}
|
||||
}
|
||||
|
@ -1129,43 +1193,22 @@ impl<'a> GradientGpuBlockBuilder<'a> {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextRunPrimitive {
|
||||
pub specified_font: FontInstance,
|
||||
pub used_font: FontInstance,
|
||||
pub offset: LayoutVector2D,
|
||||
pub glyph_range: ItemRange<GlyphInstance>,
|
||||
pub glyph_keys: Vec<GlyphKey>,
|
||||
pub glyph_gpu_blocks: Vec<GpuBlockData>,
|
||||
pub shadow: bool,
|
||||
}
|
||||
|
||||
impl TextRunPrimitive {
|
||||
pub fn new(
|
||||
font: FontInstance,
|
||||
offset: LayoutVector2D,
|
||||
glyph_range: ItemRange<GlyphInstance>,
|
||||
glyph_keys: Vec<GlyphKey>,
|
||||
shadow: bool,
|
||||
) -> Self {
|
||||
TextRunPrimitive {
|
||||
specified_font: font.clone(),
|
||||
used_font: font,
|
||||
offset,
|
||||
glyph_range,
|
||||
glyph_keys,
|
||||
glyph_gpu_blocks: Vec::new(),
|
||||
shadow,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_font_instance(
|
||||
&mut self,
|
||||
specified_font: &FontInstance,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
transform: &LayoutToWorldTransform,
|
||||
allow_subpixel_aa: bool,
|
||||
raster_space: RasterSpace,
|
||||
) -> bool {
|
||||
// Get the current font size in device pixels
|
||||
let device_font_size = self.specified_font.size.scale_by(device_pixel_scale.0);
|
||||
let device_font_size = specified_font.size.scale_by(device_pixel_scale.0);
|
||||
|
||||
// Determine if rasterizing glyphs in local or screen space.
|
||||
// Only support transforms that can be coerced to simple 2D transforms.
|
||||
|
@ -1198,13 +1241,13 @@ impl TextRunPrimitive {
|
|||
self.used_font = FontInstance {
|
||||
transform: font_transform,
|
||||
size: device_font_size,
|
||||
..self.specified_font.clone()
|
||||
..specified_font.clone()
|
||||
};
|
||||
|
||||
// If subpixel AA is disabled due to the backing surface the glyphs
|
||||
// are being drawn onto, disable it (unless we are using the
|
||||
// specifial subpixel mode that estimates background color).
|
||||
if !allow_subpixel_aa && self.specified_font.bg_color.a == 0 {
|
||||
if !allow_subpixel_aa && self.used_font.bg_color.a == 0 {
|
||||
self.used_font.disable_subpixel_aa();
|
||||
}
|
||||
|
||||
|
@ -1220,79 +1263,43 @@ impl TextRunPrimitive {
|
|||
|
||||
fn prepare_for_render(
|
||||
&mut self,
|
||||
specified_font: &FontInstance,
|
||||
glyphs: &[GlyphInstance],
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
transform: &LayoutToWorldTransform,
|
||||
allow_subpixel_aa: bool,
|
||||
raster_space: RasterSpace,
|
||||
display_list: &BuiltDisplayList,
|
||||
frame_building_state: &mut FrameBuildingState,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
special_render_passes: &mut SpecialRenderPasses,
|
||||
) {
|
||||
let cache_dirty = self.update_font_instance(
|
||||
specified_font,
|
||||
device_pixel_scale,
|
||||
transform,
|
||||
allow_subpixel_aa,
|
||||
raster_space,
|
||||
);
|
||||
|
||||
// Cache the glyph positions, if not in the cache already.
|
||||
// TODO(gw): In the future, remove `glyph_instances`
|
||||
// completely, and just reference the glyphs
|
||||
// directly from the display list.
|
||||
if self.glyph_keys.is_empty() || cache_dirty {
|
||||
let subpx_dir = self.used_font.get_subpx_dir();
|
||||
let src_glyphs = display_list.get(self.glyph_range);
|
||||
|
||||
// TODO(gw): If we support chunks() on AuxIter
|
||||
// in the future, this code below could
|
||||
// be much simpler...
|
||||
let mut gpu_block = [0.0; 4];
|
||||
for (i, src) in src_glyphs.enumerate() {
|
||||
for src in glyphs {
|
||||
let world_offset = self.used_font.transform.transform(&src.point);
|
||||
let device_offset = device_pixel_scale.transform_point(&world_offset);
|
||||
let key = GlyphKey::new(src.index, device_offset, subpx_dir);
|
||||
self.glyph_keys.push(key);
|
||||
|
||||
// Two glyphs are packed per GPU block.
|
||||
|
||||
if (i & 1) == 0 {
|
||||
gpu_block[0] = src.point.x;
|
||||
gpu_block[1] = src.point.y;
|
||||
} else {
|
||||
gpu_block[2] = src.point.x;
|
||||
gpu_block[3] = src.point.y;
|
||||
self.glyph_gpu_blocks.push(gpu_block.into());
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the last block is added in the case
|
||||
// of an odd number of glyphs.
|
||||
if (self.glyph_keys.len() & 1) != 0 {
|
||||
self.glyph_gpu_blocks.push(gpu_block.into());
|
||||
}
|
||||
}
|
||||
|
||||
frame_building_state.resource_cache
|
||||
.request_glyphs(self.used_font.clone(),
|
||||
&self.glyph_keys,
|
||||
frame_building_state.gpu_cache,
|
||||
frame_building_state.render_tasks,
|
||||
frame_building_state.special_render_passes);
|
||||
}
|
||||
|
||||
fn write_gpu_blocks(&self, request: &mut GpuDataRequest) {
|
||||
request.push(ColorF::from(self.used_font.color).premultiplied());
|
||||
// this is the only case where we need to provide plain color to GPU
|
||||
let bg_color = ColorF::from(self.used_font.bg_color);
|
||||
request.push([bg_color.r, bg_color.g, bg_color.b, 1.0]);
|
||||
request.push([
|
||||
self.offset.x,
|
||||
self.offset.y,
|
||||
0.0,
|
||||
0.0,
|
||||
]);
|
||||
request.extend_from_slice(&self.glyph_gpu_blocks);
|
||||
|
||||
assert!(request.current_used_block_num() <= MAX_VERTEX_TEXTURE_WIDTH);
|
||||
resource_cache.request_glyphs(
|
||||
self.used_font.clone(),
|
||||
&self.glyph_keys,
|
||||
gpu_cache,
|
||||
render_tasks,
|
||||
special_render_passes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1484,7 +1491,12 @@ impl ClipData {
|
|||
}
|
||||
|
||||
pub enum PrimitiveContainer {
|
||||
TextRun(TextRunPrimitive),
|
||||
TextRun {
|
||||
font: FontInstance,
|
||||
offset: LayoutVector2D,
|
||||
glyphs: Vec<GlyphInstance>,
|
||||
shadow: bool,
|
||||
},
|
||||
Brush(BrushPrimitive),
|
||||
LineDecoration {
|
||||
color: ColorF,
|
||||
|
@ -1504,8 +1516,8 @@ impl PrimitiveContainer {
|
|||
// primitive types to use this.
|
||||
pub fn is_visible(&self) -> bool {
|
||||
match *self {
|
||||
PrimitiveContainer::TextRun(ref info) => {
|
||||
info.specified_font.color.a > 0
|
||||
PrimitiveContainer::TextRun { ref font, .. } => {
|
||||
font.color.a > 0
|
||||
}
|
||||
PrimitiveContainer::Brush(ref brush) => {
|
||||
match brush.kind {
|
||||
|
@ -1535,8 +1547,15 @@ impl PrimitiveContainer {
|
|||
info: &mut LayoutPrimitiveInfo,
|
||||
) -> (PrimitiveKeyKind, Option<PrimitiveDetails>) {
|
||||
match self {
|
||||
PrimitiveContainer::TextRun(prim) => {
|
||||
(PrimitiveKeyKind::Unused, Some(PrimitiveDetails::TextRun(prim)))
|
||||
PrimitiveContainer::TextRun { font, offset, glyphs, shadow, .. } => {
|
||||
let key = PrimitiveKeyKind::TextRun {
|
||||
font,
|
||||
offset: offset.to_au(),
|
||||
glyphs,
|
||||
shadow,
|
||||
};
|
||||
|
||||
(key, None)
|
||||
}
|
||||
PrimitiveContainer::LineDecoration { color, style, orientation, wavy_line_thickness } => {
|
||||
// For line decorations, we can construct the render task cache key
|
||||
|
@ -1612,22 +1631,21 @@ impl PrimitiveContainer {
|
|||
prim_rect: &LayoutRect,
|
||||
) -> PrimitiveContainer {
|
||||
match *self {
|
||||
PrimitiveContainer::TextRun(ref info) => {
|
||||
PrimitiveContainer::TextRun { ref font, offset, ref glyphs, .. } => {
|
||||
let mut font = FontInstance {
|
||||
color: shadow.color.into(),
|
||||
..info.specified_font.clone()
|
||||
..font.clone()
|
||||
};
|
||||
if shadow.blur_radius > 0.0 {
|
||||
font.disable_subpixel_aa();
|
||||
}
|
||||
|
||||
PrimitiveContainer::TextRun(TextRunPrimitive::new(
|
||||
PrimitiveContainer::TextRun {
|
||||
font,
|
||||
info.offset + shadow.offset,
|
||||
info.glyph_range,
|
||||
info.glyph_keys.clone(),
|
||||
true,
|
||||
))
|
||||
glyphs: glyphs.clone(),
|
||||
offset: offset + shadow.offset,
|
||||
shadow: true,
|
||||
}
|
||||
}
|
||||
PrimitiveContainer::LineDecoration { style, orientation, wavy_line_thickness, .. } => {
|
||||
PrimitiveContainer::LineDecoration {
|
||||
|
@ -1688,7 +1706,6 @@ impl PrimitiveContainer {
|
|||
|
||||
pub enum PrimitiveDetails {
|
||||
Brush(BrushPrimitive),
|
||||
TextRun(TextRunPrimitive),
|
||||
}
|
||||
|
||||
pub struct Primitive {
|
||||
|
@ -1713,6 +1730,10 @@ pub enum PrimitiveInstanceKind {
|
|||
LegacyPrimitive {
|
||||
prim_index: PrimitiveIndex,
|
||||
},
|
||||
/// A run of glyphs, with associated font parameters.
|
||||
TextRun {
|
||||
run: TextRunPrimitive,
|
||||
},
|
||||
/// A line decoration. cache_handle refers to a cached render
|
||||
/// task handle, if this line decoration is not a simple solid.
|
||||
LineDecoration {
|
||||
|
@ -1912,6 +1933,7 @@ impl PrimitiveStore {
|
|||
// handled by this optimization. In the future, we can easily extend
|
||||
// this to other primitives, such as text runs and gradients.
|
||||
match prim_instance.kind {
|
||||
PrimitiveInstanceKind::TextRun { .. } |
|
||||
PrimitiveInstanceKind::LineDecoration { .. } => {
|
||||
// TODO: Once rectangles and/or images are ported
|
||||
// to use interned primitives, we will need
|
||||
|
@ -1944,7 +1966,6 @@ impl PrimitiveStore {
|
|||
BrushKind::Clear => {}
|
||||
}
|
||||
}
|
||||
PrimitiveDetails::TextRun(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1993,9 +2014,6 @@ impl PrimitiveStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
PrimitiveDetails::TextRun(..) => {
|
||||
unreachable!("bug: invalid prim type for opacity collapse");
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -2054,6 +2072,7 @@ impl PrimitiveStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
PrimitiveInstanceKind::TextRun { .. } |
|
||||
PrimitiveInstanceKind::LineDecoration { .. } |
|
||||
PrimitiveInstanceKind::LegacyPrimitive { .. } => {
|
||||
None
|
||||
|
@ -2107,6 +2126,7 @@ impl PrimitiveStore {
|
|||
let pic = &self.pictures[pic_index.0];
|
||||
(pic.local_rect, LayoutRect::max_rect())
|
||||
}
|
||||
PrimitiveInstanceKind::TextRun { .. } |
|
||||
PrimitiveInstanceKind::LineDecoration { .. } => {
|
||||
let prim_data = &frame_state
|
||||
.resources
|
||||
|
@ -2277,8 +2297,11 @@ impl PrimitiveStore {
|
|||
);
|
||||
}
|
||||
}
|
||||
PrimitiveInstanceKind::TextRun { .. } |
|
||||
PrimitiveInstanceKind::LineDecoration { .. } => {
|
||||
prim_instance.prepare_interned_prim_for_render(
|
||||
prim_context,
|
||||
pic_context,
|
||||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
|
@ -2291,7 +2314,6 @@ impl PrimitiveStore {
|
|||
prim_local_rect,
|
||||
prim_details,
|
||||
prim_context,
|
||||
pic_context,
|
||||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
|
@ -2705,6 +2727,7 @@ impl PrimitiveInstance {
|
|||
) -> bool {
|
||||
let brush = match self.kind {
|
||||
PrimitiveInstanceKind::Picture { .. } |
|
||||
PrimitiveInstanceKind::TextRun { .. } |
|
||||
PrimitiveInstanceKind::LineDecoration { .. } => {
|
||||
return false;
|
||||
}
|
||||
|
@ -2712,7 +2735,6 @@ impl PrimitiveInstance {
|
|||
let prim = &mut primitives[prim_index.0];
|
||||
match prim.details {
|
||||
PrimitiveDetails::Brush(ref mut brush) => brush,
|
||||
PrimitiveDetails::TextRun(..) => return false,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -2791,6 +2813,8 @@ impl PrimitiveInstance {
|
|||
/// prepare_prim_for_render_inner call for old style primitives.
|
||||
fn prepare_interned_prim_for_render(
|
||||
&mut self,
|
||||
prim_context: &PrimitiveContext,
|
||||
pic_context: &PictureContext,
|
||||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
|
@ -2805,10 +2829,15 @@ impl PrimitiveInstance {
|
|||
frame_state.gpu_cache,
|
||||
);
|
||||
|
||||
self.opacity = match prim_data.kind {
|
||||
PrimitiveTemplateKind::LineDecoration { ref cache_key, ref color } => {
|
||||
let is_chased = self.is_chased();
|
||||
|
||||
self.opacity = match (&mut self.kind, &mut prim_data.kind) {
|
||||
(
|
||||
PrimitiveInstanceKind::LineDecoration { ref mut cache_handle, .. },
|
||||
PrimitiveTemplateKind::LineDecoration { ref cache_key, ref color }
|
||||
) => {
|
||||
// Work out the device pixel size to be used to cache this line decoration.
|
||||
if self.is_chased() {
|
||||
if is_chased {
|
||||
println!("\tline decoration opaque={}, key={:?}", self.opacity.is_opaque, cache_key);
|
||||
}
|
||||
|
||||
|
@ -2826,36 +2855,28 @@ impl PrimitiveInstance {
|
|||
// once the prepare_prims and batching are unified. When that
|
||||
// happens, we can use the cache handle immediately, and not need
|
||||
// to temporarily store it in the primitive instance.
|
||||
match self.kind {
|
||||
PrimitiveInstanceKind::LineDecoration { ref mut cache_handle, .. } => {
|
||||
*cache_handle = Some(frame_state.resource_cache.request_render_task(
|
||||
RenderTaskCacheKey {
|
||||
size: task_size,
|
||||
kind: RenderTaskCacheKeyKind::LineDecoration(cache_key.clone()),
|
||||
},
|
||||
frame_state.gpu_cache,
|
||||
frame_state.render_tasks,
|
||||
None,
|
||||
false,
|
||||
|render_tasks| {
|
||||
let task = RenderTask::new_line_decoration(
|
||||
task_size,
|
||||
cache_key.style,
|
||||
cache_key.orientation,
|
||||
cache_key.wavy_line_thickness.to_f32_px(),
|
||||
LayoutSize::from_au(cache_key.size),
|
||||
);
|
||||
let task_id = render_tasks.add(task);
|
||||
pic_state.tasks.push(task_id);
|
||||
task_id
|
||||
}
|
||||
));
|
||||
*cache_handle = Some(frame_state.resource_cache.request_render_task(
|
||||
RenderTaskCacheKey {
|
||||
size: task_size,
|
||||
kind: RenderTaskCacheKeyKind::LineDecoration(cache_key.clone()),
|
||||
},
|
||||
frame_state.gpu_cache,
|
||||
frame_state.render_tasks,
|
||||
None,
|
||||
false,
|
||||
|render_tasks| {
|
||||
let task = RenderTask::new_line_decoration(
|
||||
task_size,
|
||||
cache_key.style,
|
||||
cache_key.orientation,
|
||||
cache_key.wavy_line_thickness.to_f32_px(),
|
||||
LayoutSize::from_au(cache_key.size),
|
||||
);
|
||||
let task_id = render_tasks.add(task);
|
||||
pic_state.tasks.push(task_id);
|
||||
task_id
|
||||
}
|
||||
PrimitiveInstanceKind::LegacyPrimitive { .. } |
|
||||
PrimitiveInstanceKind::Picture { .. } => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
PrimitiveOpacity::translucent()
|
||||
}
|
||||
|
@ -2864,7 +2885,33 @@ impl PrimitiveInstance {
|
|||
}
|
||||
}
|
||||
}
|
||||
PrimitiveTemplateKind::Unused => {
|
||||
(
|
||||
PrimitiveInstanceKind::TextRun { ref mut run, .. },
|
||||
PrimitiveTemplateKind::TextRun { ref font, ref glyphs, .. }
|
||||
) => {
|
||||
// The transform only makes sense for screen space rasterization
|
||||
let transform = prim_context.spatial_node.world_content_transform.to_transform();
|
||||
|
||||
// TODO(gw): This match is a bit untidy, but it should disappear completely
|
||||
// once the prepare_prims and batching are unified. When that
|
||||
// happens, we can use the cache handle immediately, and not need
|
||||
// to temporarily store it in the primitive instance.
|
||||
run.prepare_for_render(
|
||||
font,
|
||||
glyphs,
|
||||
frame_context.device_pixel_scale,
|
||||
&transform,
|
||||
pic_context.allow_subpixel_aa,
|
||||
pic_context.raster_space,
|
||||
frame_state.resource_cache,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.render_tasks,
|
||||
frame_state.special_render_passes,
|
||||
);
|
||||
|
||||
PrimitiveOpacity::translucent()
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
@ -2875,7 +2922,6 @@ impl PrimitiveInstance {
|
|||
prim_local_rect: LayoutRect,
|
||||
prim_details: &mut PrimitiveDetails,
|
||||
prim_context: &PrimitiveContext,
|
||||
pic_context: &PictureContext,
|
||||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
|
@ -2889,19 +2935,6 @@ impl PrimitiveInstance {
|
|||
);
|
||||
|
||||
self.opacity = match *prim_details {
|
||||
PrimitiveDetails::TextRun(ref mut text) => {
|
||||
// The transform only makes sense for screen space rasterization
|
||||
let transform = prim_context.spatial_node.world_content_transform.to_transform();
|
||||
text.prepare_for_render(
|
||||
frame_context.device_pixel_scale,
|
||||
&transform,
|
||||
pic_context.allow_subpixel_aa,
|
||||
pic_context.raster_space,
|
||||
display_list,
|
||||
frame_state,
|
||||
);
|
||||
PrimitiveOpacity::translucent()
|
||||
}
|
||||
PrimitiveDetails::Brush(ref mut brush) => {
|
||||
match brush.kind {
|
||||
BrushKind::Image {
|
||||
|
@ -3329,9 +3362,6 @@ impl PrimitiveInstance {
|
|||
let is_chased = self.is_chased();
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.gpu_location) {
|
||||
match *prim_details {
|
||||
PrimitiveDetails::TextRun(ref mut text) => {
|
||||
text.write_gpu_blocks(&mut request);
|
||||
}
|
||||
PrimitiveDetails::Brush(ref mut brush) => {
|
||||
brush.write_gpu_blocks(&mut request, prim_local_rect);
|
||||
|
||||
|
|
|
@ -376,3 +376,13 @@ pub struct GlyphInstance {
|
|||
pub point: LayoutPoint,
|
||||
}
|
||||
|
||||
impl Eq for GlyphInstance {}
|
||||
|
||||
impl Hash for GlyphInstance {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
// Note: this is inconsistent with the Eq impl for -0.0 (don't care).
|
||||
self.index.hash(state);
|
||||
self.point.x.to_bits().hash(state);
|
||||
self.point.y.to_bits().hash(state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
347e66c2aa117724ac6b0f391b346f9c6898ad11
|
||||
d30fda15ac69d3d421c7307f77f2b5b9c0a1b4ce
|
||||
|
|
Загрузка…
Ссылка в новой задаче