Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate brush segment descriptors from clip mask instances. #3289

Merged
merged 2 commits into from
Nov 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 67 additions & 16 deletions webrender/src/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ use gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance};
use gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette};
use internal_types::{FastHashMap, SavedTargetIndex, TextureSource};
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureSurface};
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentTaskId, DeferredResolve};
use prim_store::{BrushKind, BrushPrimitive, DeferredResolve};
use prim_store::{EdgeAaSegmentMask, ImageSource, PrimitiveInstanceKind};
use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity};
use prim_store::{BrushSegment, BorderSource, PrimitiveDetails};
use prim_store::{BrushSegment, BorderSource, ClipMaskKind, ClipTaskIndex, PrimitiveDetails};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree};
use renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
use renderer::BLOCKS_PER_UV_RECT;
Expand Down Expand Up @@ -537,9 +537,13 @@ impl AlphaBatchBuilder {
.expect("bug");
let z_id = z_generator.next();

let clip_task_address = prim_instance
.clip_task_id
.map_or(OPAQUE_TASK_ADDRESS, |id| render_tasks.get_task_address(id));
// Get the clip task address for the global primitive, if one was set.
let clip_task_address = get_clip_task_address(
&ctx.prim_store.clip_mask_instances,
prim_instance.clip_task_index,
0,
render_tasks,
).unwrap_or(OPAQUE_TASK_ADDRESS);

match prim_instance.kind {
PrimitiveInstanceKind::Clear => {
Expand Down Expand Up @@ -745,7 +749,7 @@ impl AlphaBatchBuilder {
// helper methods, as we port more primitives to make
// use of interning.
let blend_mode = if !prim_data.opacity.is_opaque ||
prim_instance.clip_task_id.is_some() ||
prim_instance.clip_task_index != ClipTaskIndex::INVALID ||
transform_kind == TransformedRectKind::Complex
{
BlendMode::PremultipliedAlpha
Expand Down Expand Up @@ -820,9 +824,13 @@ impl AlphaBatchBuilder {
};
let pic = &ctx.prim_store.pictures[pic_index.0];

let clip_task_address = prim_instance
.clip_task_id
.map_or(OPAQUE_TASK_ADDRESS, |id| render_tasks.get_task_address(id));
// Get clip task, if set, for the picture primitive.
let clip_task_address = get_clip_task_address(
&ctx.prim_store.clip_mask_instances,
prim_instance.clip_task_index,
0,
render_tasks,
).unwrap_or(OPAQUE_TASK_ADDRESS);

let prim_header = PrimitiveHeader {
local_rect: pic.local_rect,
Expand Down Expand Up @@ -1242,7 +1250,7 @@ impl AlphaBatchBuilder {
match prim.details {
PrimitiveDetails::Brush(ref brush) => {
let non_segmented_blend_mode = if !brush.opacity.is_opaque ||
prim_instance.clip_task_id.is_some() ||
prim_instance.clip_task_index != ClipTaskIndex::INVALID ||
transform_kind == TransformedRectKind::Complex
{
specified_blend_mode
Expand Down Expand Up @@ -1338,6 +1346,8 @@ impl AlphaBatchBuilder {
transform_kind,
render_tasks,
z_id,
prim_instance.clip_task_index,
ctx,
);
}
}
Expand Down Expand Up @@ -1396,17 +1406,27 @@ impl AlphaBatchBuilder {
render_tasks: &RenderTaskTree,
z_id: ZBufferId,
prim_opacity: PrimitiveOpacity,
clip_task_index: ClipTaskIndex,
ctx: &RenderTargetContext,
) {
let clip_task_address = match segment.clip_task_id {
BrushSegmentTaskId::RenderTaskId(id) =>
render_tasks.get_task_address(id),
BrushSegmentTaskId::Opaque => OPAQUE_TASK_ADDRESS,
BrushSegmentTaskId::Empty => return,
debug_assert!(clip_task_index != ClipTaskIndex::INVALID);

// Get GPU address of clip task for this segment, or None if
// the entire segment is clipped out.
let clip_task_address = match get_clip_task_address(
&ctx.prim_store.clip_mask_instances,
clip_task_index,
segment_index,
render_tasks,
) {
Some(clip_task_address) => clip_task_address,
None => return,
};

// If a got a valid (or OPAQUE) clip task address, add the segment.
let is_inner = segment.edge_flags.is_empty();
let needs_blending = !prim_opacity.is_opaque ||
segment.clip_task_id.needs_blending() ||
clip_task_address != OPAQUE_TASK_ADDRESS ||
(!is_inner && transform_kind == TransformedRectKind::Complex);

let instance = PrimitiveInstanceData::from(BrushInstance {
Expand Down Expand Up @@ -1445,6 +1465,8 @@ impl AlphaBatchBuilder {
transform_kind: TransformedRectKind,
render_tasks: &RenderTaskTree,
z_id: ZBufferId,
clip_task_index: ClipTaskIndex,
ctx: &RenderTargetContext,
) {
match (&brush.segment_desc, &params.segment_data) {
(Some(ref segment_desc), SegmentDataKind::Instanced(ref segment_data)) => {
Expand All @@ -1468,6 +1490,8 @@ impl AlphaBatchBuilder {
render_tasks,
z_id,
brush.opacity,
clip_task_index,
ctx,
);
}
}
Expand All @@ -1490,6 +1514,8 @@ impl AlphaBatchBuilder {
render_tasks,
z_id,
brush.opacity,
clip_task_index,
ctx,
);
}
}
Expand Down Expand Up @@ -2185,3 +2211,28 @@ fn get_buffer_kind(texture: TextureSource) -> ImageBufferKind {
fn get_shader_opacity(opacity: f32) -> i32 {
(opacity * 65535.0).round() as i32
}

/// Retrieve the GPU task address for a given clip task instance.
/// Returns None if the segment was completely clipped out.
/// Returns Some(OPAQUE_TASK_ADDRESS) if no clip mask is needed.
/// Returns Some(task_address) if there was a valid clip mask.
fn get_clip_task_address(
clip_mask_instances: &[ClipMaskKind],
clip_task_index: ClipTaskIndex,
offset: i32,
render_tasks: &RenderTaskTree,
) -> Option<RenderTaskAddress> {
let address = match clip_mask_instances[clip_task_index.0 as usize + offset as usize] {
ClipMaskKind::Mask(task_id) => {
render_tasks.get_task_address(task_id)
}
ClipMaskKind::None => {
OPAQUE_TASK_ADDRESS
}
ClipMaskKind::Clipped => {
return None;
}
};

Some(address)
}
2 changes: 2 additions & 0 deletions webrender/src/frame_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ impl FrameBuilder {
return None
}

self.prim_store.reset_clip_instances();

let root_spatial_node_index = clip_scroll_tree.root_reference_frame_index();

const MAX_CLIP_COORD: f32 = 1.0e9;
Expand Down
2 changes: 1 addition & 1 deletion webrender/src/glyph_rasterizer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ mod test_glyph_rasterizer {
let mut gpu_cache = GpuCache::new();
let mut texture_cache = TextureCache::new(2048, 1024);
let mut render_task_cache = RenderTaskCache::new();
let mut render_task_tree = RenderTaskTree::new(FrameId::invalid());
let mut render_task_tree = RenderTaskTree::new(FrameId::INVALID);
let mut special_render_passes = SpecialRenderPasses::new(&DeviceIntSize::new(1366, 768));

let mut font_file =
Expand Down
2 changes: 1 addition & 1 deletion webrender/src/gpu_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ pub struct GpuCache {
impl GpuCache {
pub fn new() -> Self {
GpuCache {
frame_id: FrameId::invalid(),
frame_id: FrameId::INVALID,
texture: Texture::new(),
saved_block_count: 0,
in_debug: false,
Expand Down