webgl/wgpu: Omit strokes when drawing a mask stencil
Adjust `common_tess` to add an additional `mask_index_count` to draws. This is used to not render strokes when drawing a shape as a mask stencil. Fixes #7027.
This commit is contained in:
parent
b39d54de2c
commit
d3c64d4eb7
|
@ -13,6 +13,8 @@ pub struct ShapeTessellator {
|
|||
stroke_tess: StrokeTessellator,
|
||||
mesh: Vec<Draw>,
|
||||
lyon_mesh: VertexBuffers<Vertex, u32>,
|
||||
mask_index_count: Option<u32>,
|
||||
is_stroke: bool,
|
||||
}
|
||||
|
||||
impl ShapeTessellator {
|
||||
|
@ -22,6 +24,8 @@ impl ShapeTessellator {
|
|||
stroke_tess: StrokeTessellator::new(),
|
||||
mesh: Vec::new(),
|
||||
lyon_mesh: VertexBuffers::new(),
|
||||
mask_index_count: None,
|
||||
is_stroke: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,9 +37,9 @@ impl ShapeTessellator {
|
|||
self.mesh = Vec::new();
|
||||
self.lyon_mesh = VertexBuffers::new();
|
||||
for path in shape.paths {
|
||||
let (fill_style, lyon_path) = match &path {
|
||||
let (fill_style, lyon_path, next_is_stroke) = match &path {
|
||||
DrawPath::Fill { style, commands } => {
|
||||
(*style, ruffle_path_to_lyon_path(commands, true))
|
||||
(*style, ruffle_path_to_lyon_path(commands, true), false)
|
||||
}
|
||||
DrawPath::Stroke {
|
||||
style,
|
||||
|
@ -44,6 +48,7 @@ impl ShapeTessellator {
|
|||
} => (
|
||||
style.fill_style(),
|
||||
ruffle_path_to_lyon_path(&commands, *is_closed),
|
||||
true,
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -107,10 +112,19 @@ impl ShapeTessellator {
|
|||
}
|
||||
};
|
||||
|
||||
if needs_flush {
|
||||
// Non-solid color fills are isolated draw calls, so flush any pending color fill.
|
||||
if needs_flush || (self.is_stroke && !next_is_stroke) {
|
||||
// We flush separate draw calls in these cases:
|
||||
// * Non-solid color fills which require their own shader.
|
||||
// * Strokes followed by fills, because strokes need to be omitted
|
||||
// when using this shape as a mask.
|
||||
self.flush_draw(DrawType::Color);
|
||||
} else if !self.is_stroke && next_is_stroke {
|
||||
// Bake solid color fills followed by strokes into a single draw call, and adjust
|
||||
// the index count to omit the strokes when rendering this shape as a mask.
|
||||
debug_assert!(self.mask_index_count.is_none());
|
||||
self.mask_index_count = Some(self.lyon_mesh.indices.len() as u32);
|
||||
}
|
||||
self.is_stroke = next_is_stroke;
|
||||
|
||||
let mut buffers_builder =
|
||||
BuffersBuilder::new(&mut self.lyon_mesh, RuffleVertexCtor { color });
|
||||
|
@ -187,9 +201,13 @@ impl ShapeTessellator {
|
|||
let draw_mesh = std::mem::replace(&mut self.lyon_mesh, VertexBuffers::new());
|
||||
self.mesh.push(Draw {
|
||||
draw_type: draw,
|
||||
mask_index_count: self
|
||||
.mask_index_count
|
||||
.unwrap_or(draw_mesh.indices.len() as u32),
|
||||
vertices: draw_mesh.vertices,
|
||||
indices: draw_mesh.indices,
|
||||
});
|
||||
self.mask_index_count = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,6 +223,7 @@ pub struct Draw {
|
|||
pub draw_type: DrawType,
|
||||
pub vertices: Vec<Vertex>,
|
||||
pub indices: Vec<u32>,
|
||||
pub mask_index_count: u32,
|
||||
}
|
||||
|
||||
pub enum DrawType {
|
||||
|
|
|
@ -348,6 +348,7 @@ impl WebGlRenderBackend {
|
|||
vertex_buffer,
|
||||
index_buffer,
|
||||
num_indices: 6,
|
||||
num_mask_indices: 6,
|
||||
}],
|
||||
};
|
||||
Ok(quad_mesh)
|
||||
|
@ -501,6 +502,7 @@ impl WebGlRenderBackend {
|
|||
let mut draws = Vec::with_capacity(lyon_mesh.len());
|
||||
for draw in lyon_mesh {
|
||||
let num_indices = draw.indices.len() as i32;
|
||||
let num_mask_indices = draw.mask_index_count as i32;
|
||||
|
||||
let vao = self.create_vertex_array().unwrap();
|
||||
let vertex_buffer = self.gl.create_buffer().unwrap();
|
||||
|
@ -565,6 +567,7 @@ impl WebGlRenderBackend {
|
|||
vertex_buffer,
|
||||
index_buffer,
|
||||
num_indices,
|
||||
num_mask_indices,
|
||||
},
|
||||
TessDrawType::Gradient(gradient) => Draw {
|
||||
draw_type: DrawType::Gradient(Box::new(Gradient::from(gradient))),
|
||||
|
@ -572,6 +575,7 @@ impl WebGlRenderBackend {
|
|||
vertex_buffer,
|
||||
index_buffer,
|
||||
num_indices,
|
||||
num_mask_indices,
|
||||
},
|
||||
TessDrawType::Bitmap(bitmap) => Draw {
|
||||
draw_type: DrawType::Bitmap(BitmapDraw {
|
||||
|
@ -584,6 +588,7 @@ impl WebGlRenderBackend {
|
|||
vertex_buffer,
|
||||
index_buffer,
|
||||
num_indices,
|
||||
num_mask_indices,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -947,6 +952,18 @@ impl RenderBackend for WebGlRenderBackend {
|
|||
|
||||
let mesh = &self.meshes[shape.0];
|
||||
for draw in &mesh.draws {
|
||||
// Ignore strokes when drawing a mask stencil.
|
||||
let num_indices = if self.mask_state != MaskState::DrawMaskStencil
|
||||
&& self.mask_state != MaskState::ClearMaskStencil
|
||||
{
|
||||
draw.num_indices
|
||||
} else {
|
||||
draw.num_mask_indices
|
||||
};
|
||||
if num_indices == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
self.bind_vertex_array(Some(&draw.vao));
|
||||
|
||||
let (program, src_blend, dst_blend) = match &draw.draw_type {
|
||||
|
@ -1068,7 +1085,7 @@ impl RenderBackend for WebGlRenderBackend {
|
|||
|
||||
// Draw the triangles.
|
||||
self.gl
|
||||
.draw_elements_with_i32(Gl::TRIANGLES, draw.num_indices, Gl::UNSIGNED_INT, 0);
|
||||
.draw_elements_with_i32(Gl::TRIANGLES, num_indices, Gl::UNSIGNED_INT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1336,6 +1353,7 @@ struct Draw {
|
|||
index_buffer: WebGlBuffer,
|
||||
vao: WebGlVertexArrayObject,
|
||||
num_indices: i32,
|
||||
num_mask_indices: i32,
|
||||
}
|
||||
|
||||
enum DrawType {
|
||||
|
|
|
@ -283,7 +283,8 @@ struct Draw {
|
|||
draw_type: DrawType,
|
||||
vertex_buffer: wgpu::Buffer,
|
||||
index_buffer: wgpu::Buffer,
|
||||
index_count: u32,
|
||||
num_indices: u32,
|
||||
num_mask_indices: u32,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -590,7 +591,8 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
|||
draw_type: DrawType::Color,
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
index_count,
|
||||
num_indices: index_count,
|
||||
num_mask_indices: draw.mask_index_count,
|
||||
},
|
||||
TessDrawType::Gradient(gradient) => {
|
||||
// TODO: Extract to function?
|
||||
|
@ -672,7 +674,8 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
|||
},
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
index_count,
|
||||
num_indices: index_count,
|
||||
num_mask_indices: draw.mask_index_count,
|
||||
}
|
||||
}
|
||||
TessDrawType::Bitmap(bitmap) => {
|
||||
|
@ -742,7 +745,8 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
|||
},
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
index_count,
|
||||
num_indices: index_count,
|
||||
num_mask_indices: draw.mask_index_count,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1086,6 +1090,18 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
|||
);
|
||||
|
||||
for draw in &mesh.draws {
|
||||
let num_indices = if self.mask_state != MaskState::DrawMaskStencil
|
||||
&& self.mask_state != MaskState::ClearMaskStencil
|
||||
{
|
||||
draw.num_indices
|
||||
} else {
|
||||
// Omit strokes when drawing a mask stencil.
|
||||
draw.num_mask_indices
|
||||
};
|
||||
if num_indices == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
match &draw.draw_type {
|
||||
DrawType::Color => {
|
||||
frame.render_pass.set_pipeline(
|
||||
|
@ -1146,7 +1162,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
|||
}
|
||||
};
|
||||
|
||||
frame.render_pass.draw_indexed(0..draw.index_count, 0, 0..1);
|
||||
frame.render_pass.draw_indexed(0..num_indices, 0, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue