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,
|
stroke_tess: StrokeTessellator,
|
||||||
mesh: Vec<Draw>,
|
mesh: Vec<Draw>,
|
||||||
lyon_mesh: VertexBuffers<Vertex, u32>,
|
lyon_mesh: VertexBuffers<Vertex, u32>,
|
||||||
|
mask_index_count: Option<u32>,
|
||||||
|
is_stroke: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShapeTessellator {
|
impl ShapeTessellator {
|
||||||
|
@ -22,6 +24,8 @@ impl ShapeTessellator {
|
||||||
stroke_tess: StrokeTessellator::new(),
|
stroke_tess: StrokeTessellator::new(),
|
||||||
mesh: Vec::new(),
|
mesh: Vec::new(),
|
||||||
lyon_mesh: VertexBuffers::new(),
|
lyon_mesh: VertexBuffers::new(),
|
||||||
|
mask_index_count: None,
|
||||||
|
is_stroke: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +37,9 @@ impl ShapeTessellator {
|
||||||
self.mesh = Vec::new();
|
self.mesh = Vec::new();
|
||||||
self.lyon_mesh = VertexBuffers::new();
|
self.lyon_mesh = VertexBuffers::new();
|
||||||
for path in shape.paths {
|
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 } => {
|
DrawPath::Fill { style, commands } => {
|
||||||
(*style, ruffle_path_to_lyon_path(commands, true))
|
(*style, ruffle_path_to_lyon_path(commands, true), false)
|
||||||
}
|
}
|
||||||
DrawPath::Stroke {
|
DrawPath::Stroke {
|
||||||
style,
|
style,
|
||||||
|
@ -44,6 +48,7 @@ impl ShapeTessellator {
|
||||||
} => (
|
} => (
|
||||||
style.fill_style(),
|
style.fill_style(),
|
||||||
ruffle_path_to_lyon_path(&commands, *is_closed),
|
ruffle_path_to_lyon_path(&commands, *is_closed),
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,10 +112,19 @@ impl ShapeTessellator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if needs_flush {
|
if needs_flush || (self.is_stroke && !next_is_stroke) {
|
||||||
// Non-solid color fills are isolated draw calls, so flush any pending color fill.
|
// 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);
|
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 =
|
let mut buffers_builder =
|
||||||
BuffersBuilder::new(&mut self.lyon_mesh, RuffleVertexCtor { color });
|
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());
|
let draw_mesh = std::mem::replace(&mut self.lyon_mesh, VertexBuffers::new());
|
||||||
self.mesh.push(Draw {
|
self.mesh.push(Draw {
|
||||||
draw_type: draw,
|
draw_type: draw,
|
||||||
|
mask_index_count: self
|
||||||
|
.mask_index_count
|
||||||
|
.unwrap_or(draw_mesh.indices.len() as u32),
|
||||||
vertices: draw_mesh.vertices,
|
vertices: draw_mesh.vertices,
|
||||||
indices: draw_mesh.indices,
|
indices: draw_mesh.indices,
|
||||||
});
|
});
|
||||||
|
self.mask_index_count = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +223,7 @@ pub struct Draw {
|
||||||
pub draw_type: DrawType,
|
pub draw_type: DrawType,
|
||||||
pub vertices: Vec<Vertex>,
|
pub vertices: Vec<Vertex>,
|
||||||
pub indices: Vec<u32>,
|
pub indices: Vec<u32>,
|
||||||
|
pub mask_index_count: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DrawType {
|
pub enum DrawType {
|
||||||
|
|
|
@ -348,6 +348,7 @@ impl WebGlRenderBackend {
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
num_indices: 6,
|
num_indices: 6,
|
||||||
|
num_mask_indices: 6,
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
Ok(quad_mesh)
|
Ok(quad_mesh)
|
||||||
|
@ -501,6 +502,7 @@ impl WebGlRenderBackend {
|
||||||
let mut draws = Vec::with_capacity(lyon_mesh.len());
|
let mut draws = Vec::with_capacity(lyon_mesh.len());
|
||||||
for draw in lyon_mesh {
|
for draw in lyon_mesh {
|
||||||
let num_indices = draw.indices.len() as i32;
|
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 vao = self.create_vertex_array().unwrap();
|
||||||
let vertex_buffer = self.gl.create_buffer().unwrap();
|
let vertex_buffer = self.gl.create_buffer().unwrap();
|
||||||
|
@ -565,6 +567,7 @@ impl WebGlRenderBackend {
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
num_indices,
|
num_indices,
|
||||||
|
num_mask_indices,
|
||||||
},
|
},
|
||||||
TessDrawType::Gradient(gradient) => Draw {
|
TessDrawType::Gradient(gradient) => Draw {
|
||||||
draw_type: DrawType::Gradient(Box::new(Gradient::from(gradient))),
|
draw_type: DrawType::Gradient(Box::new(Gradient::from(gradient))),
|
||||||
|
@ -572,6 +575,7 @@ impl WebGlRenderBackend {
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
num_indices,
|
num_indices,
|
||||||
|
num_mask_indices,
|
||||||
},
|
},
|
||||||
TessDrawType::Bitmap(bitmap) => Draw {
|
TessDrawType::Bitmap(bitmap) => Draw {
|
||||||
draw_type: DrawType::Bitmap(BitmapDraw {
|
draw_type: DrawType::Bitmap(BitmapDraw {
|
||||||
|
@ -584,6 +588,7 @@ impl WebGlRenderBackend {
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
num_indices,
|
num_indices,
|
||||||
|
num_mask_indices,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -947,6 +952,18 @@ impl RenderBackend for WebGlRenderBackend {
|
||||||
|
|
||||||
let mesh = &self.meshes[shape.0];
|
let mesh = &self.meshes[shape.0];
|
||||||
for draw in &mesh.draws {
|
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));
|
self.bind_vertex_array(Some(&draw.vao));
|
||||||
|
|
||||||
let (program, src_blend, dst_blend) = match &draw.draw_type {
|
let (program, src_blend, dst_blend) = match &draw.draw_type {
|
||||||
|
@ -1068,7 +1085,7 @@ impl RenderBackend for WebGlRenderBackend {
|
||||||
|
|
||||||
// Draw the triangles.
|
// Draw the triangles.
|
||||||
self.gl
|
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,
|
index_buffer: WebGlBuffer,
|
||||||
vao: WebGlVertexArrayObject,
|
vao: WebGlVertexArrayObject,
|
||||||
num_indices: i32,
|
num_indices: i32,
|
||||||
|
num_mask_indices: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DrawType {
|
enum DrawType {
|
||||||
|
|
|
@ -283,7 +283,8 @@ struct Draw {
|
||||||
draw_type: DrawType,
|
draw_type: DrawType,
|
||||||
vertex_buffer: wgpu::Buffer,
|
vertex_buffer: wgpu::Buffer,
|
||||||
index_buffer: wgpu::Buffer,
|
index_buffer: wgpu::Buffer,
|
||||||
index_count: u32,
|
num_indices: u32,
|
||||||
|
num_mask_indices: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -590,7 +591,8 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
||||||
draw_type: DrawType::Color,
|
draw_type: DrawType::Color,
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
index_count,
|
num_indices: index_count,
|
||||||
|
num_mask_indices: draw.mask_index_count,
|
||||||
},
|
},
|
||||||
TessDrawType::Gradient(gradient) => {
|
TessDrawType::Gradient(gradient) => {
|
||||||
// TODO: Extract to function?
|
// TODO: Extract to function?
|
||||||
|
@ -672,7 +674,8 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
||||||
},
|
},
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
index_count,
|
num_indices: index_count,
|
||||||
|
num_mask_indices: draw.mask_index_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TessDrawType::Bitmap(bitmap) => {
|
TessDrawType::Bitmap(bitmap) => {
|
||||||
|
@ -742,7 +745,8 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
||||||
},
|
},
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
index_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 {
|
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 {
|
match &draw.draw_type {
|
||||||
DrawType::Color => {
|
DrawType::Color => {
|
||||||
frame.render_pass.set_pipeline(
|
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