diff options
Diffstat (limited to 'gfx/wr/webrender/src/quad.rs')
-rw-r--r-- | gfx/wr/webrender/src/quad.rs | 284 |
1 files changed, 182 insertions, 102 deletions
diff --git a/gfx/wr/webrender/src/quad.rs b/gfx/wr/webrender/src/quad.rs index 5455611f3f..4e83b0c425 100644 --- a/gfx/wr/webrender/src/quad.rs +++ b/gfx/wr/webrender/src/quad.rs @@ -88,6 +88,7 @@ pub fn push_quad( frame_state.clip_store, interned_clips, prim_is_2d_scale_translation, + pattern, frame_context.spatial_tree, ); @@ -161,10 +162,10 @@ pub fn push_quad( match strategy { QuadRenderStrategy::Direct => {} QuadRenderStrategy::Indirect => { - let segment = add_segment( + let task_id = add_render_task_with_mask( pattern, - &clipped_surface_rect, - true, + clipped_surface_rect.size(), + clipped_surface_rect.min.to_f32(), clip_chain, prim_spatial_node_index, pic_context.raster_spatial_node_index, @@ -177,21 +178,23 @@ pub fn push_quad( frame_state, ); + let rect = clipped_surface_rect.to_f32().cast_unit(); + let is_masked = true; add_composite_prim( pattern, + is_masked, prim_instance_index, - segment.rect, - quad_flags, + rect, frame_state, targets, - &[segment], + &[QuadSegment { rect, task_id }], ); } QuadRenderStrategy::Tiled { x_tiles, y_tiles } => { let unclipped_surface_rect = surface .map_to_device_rect(&clip_chain.pic_coverage_rect, frame_context.spatial_tree); - scratch.quad_segments.clear(); + scratch.quad_indirect_segments.clear(); let mut x_coords = vec![clipped_surface_rect.min.x]; let mut y_coords = vec![clipped_surface_rect.min.y]; @@ -225,16 +228,17 @@ pub fn push_quad( continue; } - let create_task = true; - let rect = DeviceIntRect { + let int_rect = DeviceIntRect { min: point2(x0, y0), max: point2(x1, y1), }; - let segment = add_segment( + let rect = int_rect.to_f32(); + + let task_id = add_render_task_with_mask( pattern, - &rect, - create_task, + int_rect.size(), + rect.min, clip_chain, prim_spatial_node_index, pic_context.raster_spatial_node_index, @@ -246,18 +250,20 @@ pub fn push_quad( needs_scissor, frame_state, ); - scratch.quad_segments.push(segment); + + scratch.quad_indirect_segments.push(QuadSegment { rect: rect.cast_unit(), task_id }); } } + let is_masked = true; add_composite_prim( pattern, + is_masked, prim_instance_index, unclipped_surface_rect.cast_unit(), - quad_flags, frame_state, targets, - &scratch.quad_segments, + &scratch.quad_indirect_segments, ); } QuadRenderStrategy::NinePatch { clip_rect, radius } => { @@ -298,7 +304,21 @@ pub fn push_quad( x_coords.sort_by(|a, b| a.partial_cmp(b).unwrap()); y_coords.sort_by(|a, b| a.partial_cmp(b).unwrap()); - scratch.quad_segments.clear(); + scratch.quad_direct_segments.clear(); + scratch.quad_indirect_segments.clear(); + + // TODO: re-land clip-out mode. + let mode = ClipMode::Clip; + + fn should_create_task(mode: ClipMode, x: usize, y: usize) -> bool { + match mode { + // Only create render tasks for the corners. + ClipMode::Clip => x != 1 && y != 1, + // Create render tasks for all segments (the + // center will be skipped). + ClipMode::ClipOut => true, + } + } for y in 0 .. y_coords.len()-1 { let y0 = y_coords[y]; @@ -309,6 +329,10 @@ pub fn push_quad( } for x in 0 .. x_coords.len()-1 { + if mode == ClipMode::ClipOut && x == 1 && y == 1 { + continue; + } + let x0 = x_coords[x]; let x1 = x_coords[x+1]; @@ -316,46 +340,68 @@ pub fn push_quad( continue; } - // Only create render tasks for the corners. - let create_task = x != 1 && y != 1; - let rect = DeviceIntRect::new(point2(x0, y0), point2(x1, y1)); - let rect = match rect.intersection(&clipped_surface_rect) { + let device_rect = match rect.intersection(&clipped_surface_rect) { Some(rect) => rect, None => { continue; } }; - let segment = add_segment( - pattern, - &rect, - create_task, - clip_chain, - prim_spatial_node_index, - pic_context.raster_spatial_node_index, - main_prim_address, - transform_id, - aa_flags, - quad_flags, - device_pixel_scale, - false, - frame_state, - ); - scratch.quad_segments.push(segment); + if should_create_task(mode, x, y) { + let task_id = add_render_task_with_mask( + pattern, + device_rect.size(), + device_rect.min.to_f32(), + clip_chain, + prim_spatial_node_index, + pic_context.raster_spatial_node_index, + main_prim_address, + transform_id, + aa_flags, + quad_flags, + device_pixel_scale, + false, + frame_state, + ); + scratch.quad_indirect_segments.push(QuadSegment { + rect: device_rect.to_f32().cast_unit(), + task_id, + }); + } else { + scratch.quad_direct_segments.push(QuadSegment { + rect: device_rect.to_f32().cast_unit(), + task_id: RenderTaskId::INVALID, + }); + }; } } - add_composite_prim( - pattern, - prim_instance_index, - unclipped_surface_rect.cast_unit(), - quad_flags, - frame_state, - targets, - &scratch.quad_segments, - ); + if !scratch.quad_direct_segments.is_empty() { + add_pattern_prim( + pattern, + prim_instance_index, + unclipped_surface_rect.cast_unit(), + pattern.is_opaque, + frame_state, + targets, + &scratch.quad_direct_segments, + ); + } + + if !scratch.quad_indirect_segments.is_empty() { + let is_masked = true; + add_composite_prim( + pattern, + is_masked, + prim_instance_index, + unclipped_surface_rect.cast_unit(), + frame_state, + targets, + &scratch.quad_indirect_segments, + ); + } } } } @@ -366,6 +412,7 @@ fn get_prim_render_strategy( clip_store: &ClipStore, interned_clips: &DataStore<ClipIntern>, can_use_nine_patch: bool, + pattern: &Pattern, spatial_tree: &SpatialTree, ) -> QuadRenderStrategy { if !clip_chain.needs_mask { @@ -385,6 +432,10 @@ fn get_prim_render_strategy( return QuadRenderStrategy::Indirect; } + if !pattern.supports_segmented_rendering() { + return QuadRenderStrategy::Indirect; + } + if can_use_nine_patch && clip_chain.clips_range.count == 1 { let clip_instance = clip_store.get_instance_from_range(&clip_chain.clips_range, 0); let clip_node = &interned_clips[clip_instance.handle]; @@ -432,10 +483,10 @@ fn get_prim_render_strategy( } } -fn add_segment( +fn add_render_task_with_mask( pattern: &Pattern, - rect: &DeviceIntRect, - create_task: bool, + task_size: DeviceIntSize, + content_origin: DevicePoint, clip_chain: &ClipChainInstance, prim_spatial_node_index: SpatialNodeIndex, raster_spatial_node_index: SpatialNodeIndex, @@ -446,56 +497,86 @@ fn add_segment( device_pixel_scale: DevicePixelScale, needs_scissor_rect: bool, frame_state: &mut FrameBuildingState, -) -> QuadSegment { - let task_size = rect.size(); - let rect = rect.to_f32(); - let content_origin = rect.min; - - let task_id = if create_task { - let task_id = frame_state.rg_builder.add().init(RenderTask::new_dynamic( - task_size, - RenderTaskKind::new_prim( - pattern.kind, - pattern.shader_input, - prim_spatial_node_index, - raster_spatial_node_index, - device_pixel_scale, - content_origin, - prim_address_f, - transform_id, - aa_flags, - quad_flags, - clip_chain.clips_range, - needs_scissor_rect, - ), - )); - - let masks = MaskSubPass { - clip_node_range: clip_chain.clips_range, - prim_spatial_node_index, +) -> RenderTaskId { + let task_id = frame_state.rg_builder.add().init(RenderTask::new_dynamic( + task_size, + RenderTaskKind::new_prim( + pattern.kind, + pattern.shader_input, + raster_spatial_node_index, + device_pixel_scale, + content_origin, prim_address_f, - }; + transform_id, + aa_flags, + quad_flags, + clip_chain.clips_range, + needs_scissor_rect, + ), + )); - let task = frame_state.rg_builder.get_task_mut(task_id); - task.add_sub_pass(SubPass::Masks { masks }); + let masks = MaskSubPass { + clip_node_range: clip_chain.clips_range, + prim_spatial_node_index, + prim_address_f, + }; - frame_state - .surface_builder - .add_child_render_task(task_id, frame_state.rg_builder); + let task = frame_state.rg_builder.get_task_mut(task_id); + task.add_sub_pass(SubPass::Masks { masks }); - task_id - } else { - RenderTaskId::INVALID - }; + frame_state + .surface_builder + .add_child_render_task(task_id, frame_state.rg_builder); - QuadSegment { rect: rect.cast_unit(), task_id } + task_id +} + +fn add_pattern_prim( + pattern: &Pattern, + prim_instance_index: PrimitiveInstanceIndex, + rect: LayoutRect, + is_opaque: bool, + frame_state: &mut FrameBuildingState, + targets: &[CommandBufferIndex], + segments: &[QuadSegment], +) { + let prim_address = write_prim_blocks( + &mut frame_state.frame_gpu_data.f32, + rect, + rect, + pattern.base_color, + segments, + ); + + frame_state.set_segments(segments, targets); + + let mut quad_flags = QuadFlags::IGNORE_DEVICE_PIXEL_SCALE + | QuadFlags::APPLY_DEVICE_CLIP; + + if is_opaque { + quad_flags |= QuadFlags::IS_OPAQUE; + } + + frame_state.push_cmd( + &PrimitiveCommand::quad( + pattern.kind, + pattern.shader_input, + prim_instance_index, + prim_address, + TransformPaletteId::IDENTITY, + quad_flags, + // TODO(gw): No AA on composite, unless we use it to apply 2d clips + EdgeAaSegmentMask::empty(), + ), + targets, + ); } fn add_composite_prim( pattern: &Pattern, + is_masked: bool, prim_instance_index: PrimitiveInstanceIndex, rect: LayoutRect, - quad_flags: QuadFlags, frame_state: &mut FrameBuildingState, targets: &[CommandBufferIndex], segments: &[QuadSegment], @@ -504,16 +585,17 @@ fn add_composite_prim( &mut frame_state.frame_gpu_data.f32, rect, rect, - pattern.base_color, + PremultipliedColorF::WHITE, segments, ); frame_state.set_segments(segments, targets); - let mut composite_quad_flags = - QuadFlags::IGNORE_DEVICE_PIXEL_SCALE | QuadFlags::APPLY_DEVICE_CLIP; - if quad_flags.contains(QuadFlags::IS_OPAQUE) { - composite_quad_flags |= QuadFlags::IS_OPAQUE; + let mut quad_flags = QuadFlags::IGNORE_DEVICE_PIXEL_SCALE + | QuadFlags::APPLY_DEVICE_CLIP; + + if pattern.is_opaque && !is_masked { + quad_flags |= QuadFlags::IS_OPAQUE; } frame_state.push_cmd( @@ -523,7 +605,7 @@ fn add_composite_prim( prim_instance_index, composite_prim_address, TransformPaletteId::IDENTITY, - composite_quad_flags, + quad_flags, // TODO(gw): No AA on composite, unless we use it to apply 2d clips EdgeAaSegmentMask::empty(), ), @@ -562,13 +644,13 @@ pub fn write_prim_blocks( pub fn add_to_batch<F>( kind: PatternKind, pattern_input: PatternShaderInput, - render_task_address: RenderTaskAddress, + dst_task_address: RenderTaskAddress, transform_id: TransformPaletteId, prim_address_f: GpuBufferAddress, quad_flags: QuadFlags, edge_flags: EdgeAaSegmentMask, segment_index: u8, - task_id: RenderTaskId, + src_task_id: RenderTaskId, z_id: ZBufferId, render_tasks: &RenderTaskGraph, gpu_buffer_builder: &mut GpuBufferBuilder, @@ -596,13 +678,11 @@ pub fn add_to_batch<F>( ]); let prim_address_i = writer.finish(); - let texture = match task_id { - RenderTaskId::INVALID => { - TextureSource::Invalid - } + let texture = match src_task_id { + RenderTaskId::INVALID => TextureSource::Invalid, _ => { let texture = render_tasks - .resolve_texture(task_id) + .resolve_texture(src_task_id) .expect("bug: valid task id must be resolvable"); texture @@ -614,7 +694,7 @@ pub fn add_to_batch<F>( TextureSource::Invalid, ); - let default_blend_mode = if quad_flags.contains(QuadFlags::IS_OPAQUE) && task_id == RenderTaskId::INVALID { + let default_blend_mode = if quad_flags.contains(QuadFlags::IS_OPAQUE) { BlendMode::None } else { BlendMode::PremultipliedAlpha @@ -635,7 +715,7 @@ pub fn add_to_batch<F>( }; let mut instance = QuadInstance { - render_task_address, + dst_task_address, prim_address_i, prim_address_f, z_id, |