Bug 1804340 - Update wpf-gpu-raster and aa-stroke to support generating into a slice. r=jrmuizel

This adds machinery to wpf-gpu-raster and aa-stroke to support an output buffer specified as
a slice, which they will preferentially use instead of their dynamic Vec to store output
vertexes in.

Differential Revision: https://phabricator.services.mozilla.com/D163989
This commit is contained in:
Lee Salzman 2022-12-07 00:53:55 +00:00
parent 02dc105128
commit c6fc10d232
14 changed files with 415 additions and 595 deletions

View file

@ -105,12 +105,12 @@ rev = "fc68464b5445caf111e41f643a2e69ccce0b4f83"
[source."https://github.com/FirefoxGraphics/wpf-gpu-raster"]
git = "https://github.com/FirefoxGraphics/wpf-gpu-raster"
replace-with = "vendored-sources"
rev = "b6ca51395c56648b50f21f68a1586f94f8b966c4"
rev = "e07e3741d1613b1b7ddb85a1120ed4071b3d6a56"
[source."https://github.com/FirefoxGraphics/aa-stroke"]
git = "https://github.com/FirefoxGraphics/aa-stroke"
replace-with = "vendored-sources"
rev = "5289b0ff5736a6a6b916ef007fcf07ac14a663d5"
rev = "07d3c25322518f294300e96246e09b95e118555d"
[source.crates-io]
replace-with = "vendored-sources"

4
Cargo.lock generated
View file

@ -5,7 +5,7 @@ version = 3
[[package]]
name = "aa-stroke"
version = "0.1.0"
source = "git+https://github.com/FirefoxGraphics/aa-stroke?rev=5289b0ff5736a6a6b916ef007fcf07ac14a663d5#5289b0ff5736a6a6b916ef007fcf07ac14a663d5"
source = "git+https://github.com/FirefoxGraphics/aa-stroke?rev=07d3c25322518f294300e96246e09b95e118555d#07d3c25322518f294300e96246e09b95e118555d"
dependencies = [
"euclid",
]
@ -6462,7 +6462,7 @@ dependencies = [
[[package]]
name = "wpf-gpu-raster"
version = "0.1.0"
source = "git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=b6ca51395c56648b50f21f68a1586f94f8b966c4#b6ca51395c56648b50f21f68a1586f94f8b966c4"
source = "git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=e07e3741d1613b1b7ddb85a1120ed4071b3d6a56#e07e3741d1613b1b7ddb85a1120ed4071b3d6a56"
dependencies = [
"typed-arena-nomut",
]

View file

@ -31,7 +31,9 @@ struct VertexBuffer {
};
extern "C" {
Stroker* aa_stroke_new(const StrokeStyle* style);
Stroker* aa_stroke_new(const StrokeStyle* style,
OutputVertex* output_ptr = nullptr,
size_t output_capacity = 0);
void aa_stroke_move_to(Stroker* s, float x, float y, bool closed);
void aa_stroke_line_to(Stroker* s, float x, float y, bool end);
void aa_stroke_curve_to(Stroker* s, float c1x, float c1y, float c2x, float c2y,

View file

@ -50,11 +50,10 @@ void wgr_builder_quad_to(PathBuilder* pb, float cx, float cy, float x, float y);
void wgr_builder_close(PathBuilder* pb);
void wgr_builder_set_fill_mode(PathBuilder* pb, FillMode fill_mode);
Path wgr_builder_get_path(PathBuilder* pb);
VertexBuffer wgr_path_rasterize_to_tri_list(const Path* p, int32_t clip_x,
int32_t clip_y, int32_t clip_width,
int32_t clip_height,
bool need_inside = true,
bool need_outside = false);
VertexBuffer wgr_path_rasterize_to_tri_list(
const Path* p, int32_t clip_x, int32_t clip_y, int32_t clip_width,
int32_t clip_height, bool need_inside = true, bool need_outside = false,
OutputVertex* output_ptr = nullptr, size_t output_capacity = 0);
void wgr_path_release(Path p);
void wgr_vertex_buffer_release(VertexBuffer vb);
void wgr_builder_release(PathBuilder* pb);

View file

@ -1 +1 @@
{"files":{".github/workflows/rust.yml":"e859b12cfed145b66e4fbf1571dde15880359717ca5b0a9720341229183f2c6f","Cargo.toml":"da37548ce129b1d813f6aeb45f0bdb73afb888497c608e884a6f0b6bdb1d0a4b","README.md":"60b34cfa653114d5054009696df2ed2ea1d4926a6bc312d0cac4b84845c2beff","examples/simple.rs":"c196e79568fe4be31a08374aa451c70c9377db5428aef924a985e069c12ed91e","src/bezierflattener.rs":"4268d18ef80899d4b5d1fdbb0ed23fb4a4f9a6197b0796cb7a5e55194437a67b","src/c_bindings.rs":"6b22f6a0557040fce12f14cc1ac1ce11bf5ca41c64d3f79aba414d30f35d3caa","src/lib.rs":"ac23aa05c069a2818f19d3b2ef7fc4c82da3ace66cea45f1261e3884bd8c9b05","src/tri_rasterize.rs":"fb6f595ab9340d8ea6429b41638c378bbd772c8e4d8f7793e225624c12cd3a21"},"package":null}
{"files":{".github/workflows/rust.yml":"e859b12cfed145b66e4fbf1571dde15880359717ca5b0a9720341229183f2c6f","Cargo.toml":"da37548ce129b1d813f6aeb45f0bdb73afb888497c608e884a6f0b6bdb1d0a4b","README.md":"60b34cfa653114d5054009696df2ed2ea1d4926a6bc312d0cac4b84845c2beff","examples/simple.rs":"c196e79568fe4be31a08374aa451c70c9377db5428aef924a985e069c12ed91e","src/bezierflattener.rs":"4268d18ef80899d4b5d1fdbb0ed23fb4a4f9a6197b0796cb7a5e55194437a67b","src/c_bindings.rs":"23890f7bb5d40d87d72b28842821ada7b2e1509a3b37c9af8ed0055036ceadcc","src/lib.rs":"fb46f09d8ed2a53d4a6770a6f1bb2ff1a9df736c5c6d390ba159fefafbeec308","src/tri_rasterize.rs":"fb6f595ab9340d8ea6429b41638c378bbd772c8e4d8f7793e225624c12cd3a21"},"package":null}

View file

@ -9,8 +9,16 @@ pub struct VertexBuffer {
}
#[no_mangle]
pub extern "C" fn aa_stroke_new(style: &StrokeStyle) -> *mut Stroker {
let s = Stroker::new(style);
pub extern "C" fn aa_stroke_new(
style: &StrokeStyle,
output_ptr: *mut OutputVertex,
output_capacity: usize,
) -> *mut Stroker {
let mut s = Stroker::new(style);
if output_ptr != std::ptr::null_mut() {
let slice = unsafe { std::slice::from_raw_parts_mut(output_ptr, output_capacity) };
s.set_output_buffer(slice);
}
Box::into_raw(Box::new(s))
}
@ -50,16 +58,28 @@ pub extern "C" fn aa_stroke_close(s: &mut Stroker) {
#[no_mangle]
pub extern "C" fn aa_stroke_finish(s: &mut Stroker) -> VertexBuffer {
let result = s.finish();
let vb = VertexBuffer { data: result.as_ptr(), len: result.len() };
std::mem::forget(result);
vb
let stroked_path = s.get_stroked_path();
if let Some(output_buffer_size) = stroked_path.get_output_buffer_size() {
VertexBuffer {
data: std::ptr::null(),
len: output_buffer_size,
}
} else {
let result = stroked_path.finish();
let vb = VertexBuffer { data: result.as_ptr(), len: result.len() };
std::mem::forget(result);
vb
}
}
#[no_mangle]
pub extern "C" fn aa_stroke_vertex_buffer_release(vb: VertexBuffer)
{
unsafe { drop(Box::from_raw(std::slice::from_raw_parts_mut(vb.data as *mut OutputVertex, vb.len))) }
if vb.data != std::ptr::null() {
unsafe {
drop(Box::from_raw(std::slice::from_raw_parts_mut(vb.data as *mut OutputVertex, vb.len)));
}
}
}
#[no_mangle]
@ -71,11 +91,11 @@ pub unsafe extern "C" fn aa_stroke_release(s: *mut Stroker) {
#[test]
fn simple() {
let style = StrokeStyle::default();
let s = unsafe { &mut *aa_stroke_new(&style) } ;
let s = unsafe { &mut *aa_stroke_new(&style, std::ptr::null_mut(), 0) } ;
aa_stroke_move_to(s, 10., 10., false);
aa_stroke_line_to(s, 100., 100., false);
aa_stroke_line_to(s, 100., 10., true);
let vb = aa_stroke_finish(s);
aa_stroke_vertex_buffer_release(vb);
unsafe { aa_stroke_release(s) } ;
}
}

View file

@ -81,7 +81,9 @@ pub struct Vertex {
}
/// A helper struct used for constructing a `Path`.
pub struct PathBuilder {
pub struct PathBuilder<'z> {
output_buffer: Option<&'z mut [Vertex]>,
output_buffer_offset: usize,
vertices: Vec<Vertex>,
coverage: f32,
aa: bool
@ -89,27 +91,49 @@ pub struct PathBuilder {
impl PathBuilder {
pub fn new(coverage: f32) -> PathBuilder {
impl<'z> PathBuilder<'z> {
pub fn new(coverage: f32) -> PathBuilder<'z> {
PathBuilder {
output_buffer: None,
output_buffer_offset: 0,
vertices: Vec::new(),
coverage,
aa: true
}
}
pub fn set_output_buffer(&mut self, output_buffer: &'z mut [Vertex]) {
assert!(self.output_buffer.is_none());
self.output_buffer = Some(output_buffer);
}
pub fn push_tri_with_coverage(&mut self, x1: f32, y1: f32, c1: f32, x2: f32, y2: f32, c2: f32, x3: f32, y3: f32, c3: f32) {
let v1 = Vertex { x: x1, y: y1, coverage: c1 };
let v2 = Vertex { x: x2, y: y2, coverage: c2 };
let v3 = Vertex { x: x3, y: y3, coverage: c3 };
if let Some(output_buffer) = &mut self.output_buffer {
let offset = self.output_buffer_offset;
if offset + 3 <= output_buffer.len() {
output_buffer[offset] = v1;
output_buffer[offset + 1] = v2;
output_buffer[offset + 2] = v3;
}
self.output_buffer_offset = offset + 3;
} else {
self.vertices.push(v1);
self.vertices.push(v2);
self.vertices.push(v3);
}
}
pub fn push_tri(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) {
self.vertices.push(Vertex { x: x1, y: y1, coverage: self.coverage});
self.vertices.push(Vertex { x: x2, y: y2, coverage: self.coverage});
self.vertices.push(Vertex { x: x3, y: y3, coverage: self.coverage});
self.push_tri_with_coverage(x1, y1, self.coverage, x2, y2, self.coverage, x3, y3, self.coverage);
}
// x3, y3 is the full coverage vert
pub fn tri_ramp(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) {
self.vertices.push(Vertex { x: x1, y: y1, coverage: 0.});
self.vertices.push(Vertex { x: x2, y: y2, coverage: 0.});
self.vertices.push(Vertex { x: x3, y: y3, coverage: self.coverage});
self.push_tri_with_coverage(x1, y1, 0., x2, y2, 0., x3, y3, self.coverage);
}
pub fn quad(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32, x4: f32, y4: f32) {
@ -118,13 +142,8 @@ impl PathBuilder {
}
pub fn ramp(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32, x4: f32, y4: f32) {
self.vertices.push(Vertex { x: x1, y: y1, coverage: self.coverage});
self.vertices.push(Vertex { x: x2, y: y2, coverage: 0.});
self.vertices.push(Vertex { x: x3, y: y3, coverage: 0.});
self.vertices.push(Vertex { x: x3, y: y3, coverage: 0.});
self.vertices.push(Vertex { x: x4, y: y4, coverage: self.coverage});
self.vertices.push(Vertex { x: x1, y: y1, coverage: self.coverage});
self.push_tri_with_coverage(x1, y1, self.coverage, x2, y2, 0., x3, y3, 0.);
self.push_tri_with_coverage(x3, y3, 0., x4, y4, self.coverage, x1, y1, self.coverage);
}
// first edge is outside
@ -140,6 +159,14 @@ impl PathBuilder {
pub fn finish(self) -> Vec<Vertex> {
self.vertices
}
pub fn get_output_buffer_size(&self) -> Option<usize> {
if self.output_buffer.is_some() {
Some(self.output_buffer_offset)
} else {
None
}
}
}
@ -207,8 +234,8 @@ fn arc_segment_tri(path: &mut PathBuilder, xc: f32, yc: f32, radius: f32, a: Vec
let initial_normal = GpPointR { x: a.x as f64, y: a.y as f64 };
struct Target<'a> { last_point: GpPointR, last_normal: GpPointR, xc: f32, yc: f32, path: &'a mut PathBuilder }
impl<'a> CFlatteningSink for Target<'a> {
struct Target<'a, 'b> { last_point: GpPointR, last_normal: GpPointR, xc: f32, yc: f32, path: &'a mut PathBuilder<'b> }
impl<'a, 'b> CFlatteningSink for Target<'a, 'b> {
fn AcceptPointAndTangent(&mut self,
pt: &GpPointR,
// The point
@ -585,8 +612,8 @@ fn join_line(
}
}
pub struct Stroker {
stroked_path: PathBuilder,
pub struct Stroker<'z> {
stroked_path: PathBuilder<'z>,
cur_pt: Option<Point>,
last_normal: Vector,
half_width: f32,
@ -595,7 +622,7 @@ pub struct Stroker {
closed_subpath: bool
}
impl Stroker {
impl<'z> Stroker<'z> {
pub fn new(style: &StrokeStyle) -> Self {
let mut style = style.clone();
let mut coverage = 1.;
@ -614,6 +641,10 @@ impl Stroker {
}
}
pub fn set_output_buffer(&mut self, output_buffer: &'z mut [Vertex]) {
self.stroked_path.set_output_buffer(output_buffer);
}
pub fn line_to_capped(&mut self, pt: Point) {
if let Some(cur_pt) = self.cur_pt {
let normal = compute_normal(cur_pt, pt).unwrap_or(self.last_normal);
@ -709,8 +740,8 @@ impl Stroker {
}
pub fn curve_to_internal(&mut self, cx1: Point, cx2: Point, pt: Point, end: bool) {
struct Target<'a> { stroker: &'a mut Stroker, end: bool }
impl<'a> CFlatteningSink for Target<'a> {
struct Target<'a, 'b> { stroker: &'a mut Stroker<'b>, end: bool }
impl<'a, 'b> CFlatteningSink for Target<'a, 'b> {
fn AcceptPointAndTangent(&mut self, _: &GpPointR, _: &GpPointR, _: bool ) -> HRESULT {
panic!()
}
@ -794,16 +825,21 @@ impl Stroker {
self.start_point = None;
}
pub fn finish(&mut self) -> Vec<Vertex> {
pub fn get_stroked_path(&mut self) -> PathBuilder<'z> {
let mut stroked_path = std::mem::replace(&mut self.stroked_path, PathBuilder::new(1.));
if let (Some(cur_pt), Some((point, normal))) = (self.cur_pt, self.start_point) {
// cap end
cap_line(&mut stroked_path, &self.style, cur_pt, self.last_normal);
// cap beginning
cap_line( &mut stroked_path, &self.style, point, flip(normal));
cap_line(&mut stroked_path, &self.style, point, flip(normal));
}
stroked_path.finish()
stroked_path
}
pub fn finish(&mut self) -> Vec<Vertex> {
self.get_stroked_path().finish()
}
}

View file

@ -1 +1 @@
{"files":{".github/workflows/coverage.yml":"90aaa068c16cb778b24badaff78baf2a313637780a723be09596abde0f4c827a",".github/workflows/rust.yml":"905954be896d052ced621eedb9d5b9d35795490f27071ac1147e75ac3b3711ec","CHANGES.md":"5f54e553a1c4ef21c5be6109b25df9d1d63c4547627723fe044c73dbddf0db2f","Cargo.toml":"c4f220ebc481f7b1db1909f32c5e95a94f665b40943713f084547d9df2f8c29c","LICENSE":"ae48df11a335dc1a615f4f938b69cba73bcf4485c4f97af49b38efb0f216353b","README.md":"e14b7ddbd29b6f87d956921999da1cf7bc3add0166cacf21e8b1ac1d9092a90d","examples/draw.rs":"52fee9e2f2c11e1c891b30cb460be2a0ec65974f38dc0c08fd48391caf1e4247","examples/obj-output.rs":"6fc549022aa715eee74ea1cafb89ca33189e9dbe914ea6b2c46160049bda68f3","examples/simple.rs":"99fb566414cbd4a0eb69a2774c9780d7cd17e5cdaa14837b280fba319c053f22","notes":"48e636c646d697e213b3a79e31063e11b6ffc7493592d31f3929b1db495870b8","src/aacoverage.rs":"fdadadd208caa986cc386797f937a976b5a315174c7c0782b87c0334d6474a97","src/aarasterizer.rs":"283bed1e22917118f332b24731cb6bd11334a4f0ba0d88821cfeb6b607de12da","src/bezier.rs":"f089ab04e30077ce4e0fe59dfa602948b989aa53d51ad207fbc30c1edd24086b","src/c_bindings.rs":"e3eadbdb83a0ef3d7a364b4607d1e0469cf97b823d69b4eee578ffec59980315","src/fix.rs":"7ccf63db5bab4ab0135d92691f7c2272a27866b9792dd55ec98b2d1c1b7c0358","src/geometry_sink.rs":"9025569f77f475a1e47fd470e8f53dcdf88ef57e3a5b8a51268fff892da8b1a7","src/helpers.rs":"220294dac335943518f249c4a27ad803f8226ed62cd780f517e95be6343a1f2f","src/hwrasterizer.rs":"55d7771b0f2537bb0ba2cce4006786582759bca4958cb8008822aa4947ac5404","src/hwvertexbuffer.rs":"e80caddb180278545ee95f8d55c667d331460180c886b0b90b43786cedf2e8b9","src/lib.rs":"7a3e5f6873796616cd4da0eb954c89edc465de005fff6335a06ce36824c20349","src/matrix.rs":"1ac44bc5d073f96ab64b1b5c6077fd0d47fe61db8243bd9a55fc91d8eae1dd92","src/notes":"d50d49e0b5660bc6350d8055f25f26700c937558de0af690e1fc4f50ed7e05c9","src/nullable_ref.rs":"789fe0e59b7d4a925faecbf2362be93643ea8382b4424ca0e60866f9bf83c3cd","src/real.rs":"73a2d1a77613364e9514fd7ead4d708a554d2b7343645cdb4cb8a2b3b640e057","src/tri_rasterize.rs":"30821a3465cea3c5ac578590013b530c03ea3010225f580d6cf609e39910c412","src/types.rs":"43a20f23a798858c6be64c1faf42ee9e392cbab323f851653993fcb0d78cdb5e"},"package":null}
{"files":{".github/workflows/coverage.yml":"90aaa068c16cb778b24badaff78baf2a313637780a723be09596abde0f4c827a",".github/workflows/rust.yml":"905954be896d052ced621eedb9d5b9d35795490f27071ac1147e75ac3b3711ec","CHANGES.md":"5f54e553a1c4ef21c5be6109b25df9d1d63c4547627723fe044c73dbddf0db2f","Cargo.toml":"c4f220ebc481f7b1db1909f32c5e95a94f665b40943713f084547d9df2f8c29c","LICENSE":"ae48df11a335dc1a615f4f938b69cba73bcf4485c4f97af49b38efb0f216353b","README.md":"e14b7ddbd29b6f87d956921999da1cf7bc3add0166cacf21e8b1ac1d9092a90d","examples/draw.rs":"52fee9e2f2c11e1c891b30cb460be2a0ec65974f38dc0c08fd48391caf1e4247","examples/obj-output.rs":"6fc549022aa715eee74ea1cafb89ca33189e9dbe914ea6b2c46160049bda68f3","examples/simple.rs":"99fb566414cbd4a0eb69a2774c9780d7cd17e5cdaa14837b280fba319c053f22","notes":"48e636c646d697e213b3a79e31063e11b6ffc7493592d31f3929b1db495870b8","src/aacoverage.rs":"fdadadd208caa986cc386797f937a976b5a315174c7c0782b87c0334d6474a97","src/aarasterizer.rs":"283bed1e22917118f332b24731cb6bd11334a4f0ba0d88821cfeb6b607de12da","src/bezier.rs":"f089ab04e30077ce4e0fe59dfa602948b989aa53d51ad207fbc30c1edd24086b","src/c_bindings.rs":"f0b97c58a83f9a9385001956073b7a00c801c9a304b505949d49999426cd08d0","src/fix.rs":"7ccf63db5bab4ab0135d92691f7c2272a27866b9792dd55ec98b2d1c1b7c0358","src/geometry_sink.rs":"9025569f77f475a1e47fd470e8f53dcdf88ef57e3a5b8a51268fff892da8b1a7","src/helpers.rs":"220294dac335943518f249c4a27ad803f8226ed62cd780f517e95be6343a1f2f","src/hwrasterizer.rs":"82b2d6d35488a6ad7de4d82f3ee38c6f09f4b6de06b4f98eea61b3abdd72eb62","src/hwvertexbuffer.rs":"04badf9a61a6d4b6f5383864d25b5293991862d45e94d94feee17ecb36d29aa1","src/lib.rs":"506485e2fa9686636cf6d217cb9ebed52a41617cef382d1c6681e68105e05f9e","src/matrix.rs":"1ac44bc5d073f96ab64b1b5c6077fd0d47fe61db8243bd9a55fc91d8eae1dd92","src/notes":"d50d49e0b5660bc6350d8055f25f26700c937558de0af690e1fc4f50ed7e05c9","src/nullable_ref.rs":"789fe0e59b7d4a925faecbf2362be93643ea8382b4424ca0e60866f9bf83c3cd","src/real.rs":"73a2d1a77613364e9514fd7ead4d708a554d2b7343645cdb4cb8a2b3b640e057","src/tri_rasterize.rs":"30821a3465cea3c5ac578590013b530c03ea3010225f580d6cf609e39910c412","src/types.rs":"b840212a99a212ef38211aaf1bd801ec83416569541941d15fd95285d1342b99"},"package":null}

View file

@ -102,17 +102,35 @@ pub extern "C" fn wgr_path_rasterize_to_tri_list(
clip_height: i32,
need_inside: bool,
need_outside: bool,
output_ptr: *mut OutputVertex,
output_capacity: usize,
) -> VertexBuffer {
let result = rasterize_to_tri_list(
let output_buffer = if output_ptr != std::ptr::null_mut() {
unsafe { Some(std::slice::from_raw_parts_mut(output_ptr, output_capacity)) }
} else {
None
};
let mut result = rasterize_to_tri_list(
path.fill_mode,
unsafe { std::slice::from_raw_parts(path.types, path.num_types) },
unsafe { std::slice::from_raw_parts(path.points, path.num_points) },
clip_x, clip_y, clip_width, clip_height,
need_inside, need_outside,
need_inside, need_outside, output_buffer,
);
let vb = VertexBuffer { data: result.as_ptr(), len: result.len() };
std::mem::forget(result);
vb
if let Some(output_buffer_size) = result.get_output_buffer_size() {
VertexBuffer {
data: std::ptr::null(),
len: output_buffer_size,
}
} else {
let slice = result.flush_output();
let vb = VertexBuffer {
data: slice.as_ptr(),
len: slice.len(),
};
std::mem::forget(slice);
vb
}
}
#[no_mangle]
@ -124,7 +142,11 @@ pub extern "C" fn wgr_path_release(path: Path) {
#[no_mangle]
pub extern "C" fn wgr_vertex_buffer_release(vb: VertexBuffer)
{
unsafe { drop(Box::from_raw(std::slice::from_raw_parts_mut(vb.data as *mut OutputVertex, vb.len))) }
if vb.data != std::ptr::null() {
unsafe {
drop(Box::from_raw(std::slice::from_raw_parts_mut(vb.data as *mut OutputVertex, vb.len)));
}
}
}
#[no_mangle]

View file

@ -4,10 +4,6 @@
#![allow(unused_parens)]
use std::cell::RefCell;
use std::rc::Rc;
use crate::aacoverage::{CCoverageBuffer, c_rInvShiftSize, c_antiAliasMode, c_nShift, CCoverageInterval, c_nShiftMask, c_nShiftSize, c_nHalfShiftSize};
use crate::hwvertexbuffer::CHwVertexBufferBuilder;
use crate::matrix::{CMILMatrix, CMatrix};
@ -396,10 +392,10 @@ ComputeDistanceLowerBound(
return nSubpixelXDistanceLowerBound;
}
pub struct CHwRasterizer {
pub struct CHwRasterizer<'x, 'y, 'z> {
m_rcClipBounds: MilPointAndSizeL,
m_matWorldToDevice: CMILMatrix,
m_pIGeometrySink: Option<Rc<RefCell<CHwVertexBufferBuilder>>>,
m_pIGeometrySink: &'x mut CHwVertexBufferBuilder<'y, 'z>,
m_fillMode: MilFillMode,
/*
DynArray<MilPoint2F> *m_prgPoints;
@ -454,26 +450,7 @@ fn ConvertSubpixelYToPixel(
return (nSubpixel as f32)*c_rInvShiftSize;
}
impl CHwRasterizer {
//-------------------------------------------------------------------------
//
// Function: CHwRasterizer::CHwRasterizer
//
// Synopsis: ctor
//
//-------------------------------------------------------------------------
pub fn new() -> Self
{
Self {
m_fillMode: MilFillMode::Alternate,
m_rcClipBounds: Default::default(),
m_pIGeometrySink: None,
// State is cleared on the Setup call
m_matWorldToDevice: Default::default(),
}
}
impl<'x, 'y, 'z> CHwRasterizer<'x, 'y, 'z> {
//-------------------------------------------------------------------------
//
// Function: CHwRasterizer::RasterizePath
@ -650,29 +627,20 @@ pub fn RasterizePath(
//-------------------------------------------------------------------------
//
// Function: CHwRasterizer::Setup
// Function: CHwRasterizer::new
//
// Synopsis:
// 1. Ensure clean state
// 2. Convert path to internal format
//
//-------------------------------------------------------------------------
pub fn Setup(&mut self,
pD3DDevice: Rc<CD3DDeviceLevel1>,
pub fn new(
pIGeometrySink: &'x mut CHwVertexBufferBuilder<'y, 'z>,
fillMode: MilFillMode,
pmatWorldToDevice: Option<&CMatrix<CoordinateSpace::Shape,CoordinateSpace::Device>>
) -> HRESULT
pmatWorldToDevice: Option<CMatrix<CoordinateSpace::Shape,CoordinateSpace::Device>>,
clipRect: MilPointAndSizeL,
) -> Self
{
let hr = S_OK;
//
// Initialize our state
//
self.m_rcClipBounds = Default::default();
self.m_pIGeometrySink = None;
//
// PS#856364-2003/07/01-ashrafm Remove pixel center fixup
//
@ -688,15 +656,7 @@ pub fn Setup(&mut self,
// antialiased rendering.
//
let mut matWorldHPCToDeviceIPC;
if let Some(pmatWorldToDevice) = pmatWorldToDevice
{
matWorldHPCToDeviceIPC = pmatWorldToDevice.clone();
}
else
{
matWorldHPCToDeviceIPC = CMatrix::Identity();
}
let mut matWorldHPCToDeviceIPC = pmatWorldToDevice.unwrap_or(CMatrix::Identity());
matWorldHPCToDeviceIPC.SetDx(matWorldHPCToDeviceIPC.GetDx() - 0.5);
matWorldHPCToDeviceIPC.SetDy(matWorldHPCToDeviceIPC.GetDy() - 0.5);
@ -704,17 +664,17 @@ pub fn Setup(&mut self,
// Set local state.
//
pD3DDevice.GetClipRect(&mut self.m_rcClipBounds);
self.m_matWorldToDevice = matWorldHPCToDeviceIPC;
self.m_fillMode = fillMode;
// There's an opportunity for early clipping here
//
// However, since the rasterizer itself does a reasonable job of clipping some
// cases, we don't early clip yet.
return hr;
Self {
m_fillMode: fillMode,
m_rcClipBounds: clipRect,
m_pIGeometrySink: pIGeometrySink,
m_matWorldToDevice: matWorldHPCToDeviceIPC,
}
}
//-------------------------------------------------------------------------
@ -726,20 +686,12 @@ pub fn Setup(&mut self,
//
//-------------------------------------------------------------------------
pub fn SendGeometry(&mut self,
pIGeometrySink: Rc<RefCell<CHwVertexBufferBuilder>>,
points: &[POINT],
types: &[BYTE],
) -> HRESULT
{
let mut hr = S_OK;
//
// It's ok not to addref the geometry sink here since it
// is never used outside the scope of this method.
//
self.m_pIGeometrySink = Some(pIGeometrySink.clone());
//
// Rasterize the path
//
@ -765,13 +717,11 @@ pub fn SendGeometry(&mut self,
// up front, we simply rasterize and see if we generated anything.
//
if (pIGeometrySink.borrow().IsEmpty())
if (self.m_pIGeometrySink.IsEmpty())
{
hr = WGXHR_EMPTYFILL;
}
self.m_pIGeometrySink = None;
RRETURN1!(hr, WGXHR_EMPTYFILL);
}
/*
@ -820,7 +770,7 @@ GenerateOutputAndClearCoverage<'a>(&mut self, coverageBuffer: &'a CCoverageBuffe
let pIntervalSpanStart: Ref<CCoverageInterval> = coverageBuffer.m_pIntervalStart.get();
IFC!(self.m_pIGeometrySink.as_ref().unwrap().borrow_mut().AddComplexScan(nPixelY, pIntervalSpanStart));
IFC!(self.m_pIGeometrySink.AddComplexScan(nPixelY, pIntervalSpanStart));
coverageBuffer.Reset();
@ -1282,7 +1232,7 @@ OutputTrapezoids(&mut self,
// Output the trapezoid
//
IFC!(self.m_pIGeometrySink.as_mut().unwrap().borrow_mut().AddTrapezoid(
IFC!(self.m_pIGeometrySink.AddTrapezoid(
rPixelYTop, // In: y coordinate of top of trapezoid
rPixelXLeft, // In: x coordinate for top left
rPixelXRight, // In: x coordinate for top right
@ -1502,29 +1452,4 @@ RasterizeEdges<'a, 'b>(&mut self,
RRETURN!(hr);
}
//+------------------------------------------------------------------------
//
// Member: GetPerVertexDataType
//
// Synopsis: Return vertex fields that are generated when this generator
// is used
//
//-------------------------------------------------------------------------
pub fn GetPerVertexDataType(&self,
mvfFullyGenerated: &mut MilVertexFormat
)
{
//
// (X,Y) destination coordinate and alpha falloff (in diffuse) are
// generated for each vertex. The diffuse value is a 32 bit float and
// not a fully generated vertex data member. It must be multiplied by
// a color to be ready for HW consumption. Therefore it is not fully
// generated.
//
*mvfFullyGenerated = MilVertexFormatAttribute::MILVFAttrXY as MilVertexFormat;
}
}

View file

@ -106,8 +106,6 @@ const FLOAT_ONE: f32 = 1.;
//
//-----------------------------------------------------------------------------
use std::rc::Rc;
use crate::{types::*, geometry_sink::IGeometrySink, aacoverage::c_nShiftSizeSquared, OutputVertex, nullable_ref::Ref};
@ -245,31 +243,6 @@ public:
{
return FlushInternal(NULL);
}
*/
*/
impl CHwVertexBufferBuilder {
//+------------------------------------------------------------------------
//
// Member: FlushTryGetVertexBuffer
//
// Synopsis: Send pending state and geometry to the device and
// return the vertex buffer if there was not another flush
// (since the last BeginBuilding.)
//
//-------------------------------------------------------------------------
pub fn FlushTryGetVertexBuffer(&mut self,
ppVertexBuffer: Option<&mut CHwVertexBuffer>
) -> HRESULT
{
return self.FlushInternal(ppVertexBuffer);
}
}
/*
/*
//
// Currently all CHwVertexBuffer::Builder are supposed to be allocated via
@ -349,9 +322,9 @@ pub struct CD3DVertexXYZDUV2 {
/*U0: f32, V0: f32,
U1: f32, V1: f32,*/
}
pub type CHwVertexBuffer = CHwTVertexBuffer<OutputVertex>;
pub type CHwVertexBuffer<'z> = CHwTVertexBuffer<'z, OutputVertex>;
#[derive(Default)]
pub struct CHwTVertexBuffer<TVertex>
pub struct CHwTVertexBuffer<'z, TVertex>
{
//m_rgIndices: DynArray<WORD>, // Dynamic array of indices
@ -659,12 +632,37 @@ protected:
m_rgVerticesTriList: DynArray<TVertex>, // Triangle strip vertices
//m_rgVerticesLineList: DynArray<TVertex>, // Linelist vertices
m_rgVerticesBuffer: Option<&'z mut [TVertex]>,
m_rgVerticesBufferOffset: usize,
#[cfg(debug_assertions)]
// In debug make a note if we add a triangle strip that doesn't have 6 vertices
// so that we can ensure that we only waffle 6-vertex tri strips.
m_fDbgNonLineSegmentTriangleStrip: bool
}
impl<'z, TVertex: Default> CHwTVertexBuffer<'z, TVertex> {
pub fn new(output_buffer: Option<&'z mut [TVertex]>) -> Self {
CHwTVertexBuffer::<TVertex> {
m_rgVerticesBuffer: output_buffer,
m_rgVerticesBufferOffset: 0,
..Default::default()
}
}
pub fn flush_output(&mut self) -> Box<[TVertex]> {
std::mem::take(&mut self.m_rgVerticesTriList).into_boxed_slice()
}
pub fn get_output_buffer_size(&self) -> Option<usize> {
if self.m_rgVerticesBuffer.is_some() {
Some(self.m_rgVerticesBufferOffset)
} else {
None
}
}
}
//+----------------------------------------------------------------------------
//
// Class: CHwTVertexMappings<class TVertex>
@ -719,7 +717,7 @@ public:
m_vStatic: TVertex,
}
impl<TVertex> CHwTVertexBuffer<TVertex> {
impl<TVertex> CHwTVertexBuffer<'_, TVertex> {
pub fn Reset(&mut self,
/*pVBB: &mut CHwTVertexBufferBuilder<TVertex>*/
)
@ -732,6 +730,7 @@ impl<TVertex> CHwTVertexBuffer<TVertex> {
//self.m_rgIndices.SetCount(0);
//self.m_rgVerticesTriList.SetCount(0);
self.m_rgVerticesTriList.SetCount(0);
self.m_rgVerticesBufferOffset = 0;
//self.m_rgVerticesLineList.SetCount(0);
//self.m_rgVerticesNonIndexedTriList.SetCount(0);
@ -744,6 +743,7 @@ impl<TVertex> CHwTVertexBuffer<TVertex> {
// && (self.m_rgIndices.GetCount() == 0)
//&& (self.m_rgVerticesLineList.GetCount() == 0)
&& (self.m_rgVerticesTriList.GetCount() == 0)
&& self.m_rgVerticesBufferOffset == 0
//&& (self.m_rgVerticesNonIndexedTriList.GetCount() == 0);
}
@ -758,9 +758,8 @@ impl<TVertex> CHwTVertexBuffer<TVertex> {
//
//-----------------------------------------------------------------------------
pub struct CHwTVertexBufferBuilder<TVertex>
pub struct CHwTVertexBufferBuilder<'y, 'z, TVertex>
{
m_pDeviceNoRef: Rc<CD3DDeviceLevel1>,
m_mvfIn: MilVertexFormat, // Vertex fields that are pre-generated
#[cfg(debug_assertions)]
@ -1076,7 +1075,7 @@ private:
return BuildWafflePipeline(wafflers, fNotUsed);
}*/
m_pVB: Box<CHwTVertexBuffer<TVertex>>,
m_pVB: &'y mut CHwTVertexBuffer<'z, TVertex>,
//m_pfnExpandVertices: PFN_ExpandVertices, // Method for expanding vertices
@ -1205,7 +1204,7 @@ Cleanup:
}
*/
impl CHwVertexBuffer {
impl CHwVertexBuffer<'_> {
//+----------------------------------------------------------------------------
//
// Member: CHwTVertexBuffer<TVertex>::AddLine
@ -1301,40 +1300,61 @@ CHwTVertexBuffer<TVertex>::AddTriListVertices(
RRETURN(hr);
}
*/
//+----------------------------------------------------------------------------
//
// Member: CHwTVertexBuffer<TVertex>::AddTriListVertices
//
// Synopsis: Reserve space for consecutive vertices
//
impl<TVertex: Default> CHwTVertexBuffer<TVertex> {
fn AddTriListVertices(
&mut self,
uCount: UINT,
) -> &mut DynArray<TVertex>
{
impl<TVertex: Clone + Default> CHwTVertexBuffer<'_, TVertex> {
fn AddTriVertices(&mut self, v0: TVertex, v1: TVertex, v2: TVertex) {
if let Some(output_buffer) = &mut self.m_rgVerticesBuffer {
let offset = self.m_rgVerticesBufferOffset;
if offset + 3 <= output_buffer.len() {
output_buffer[offset] = v0;
output_buffer[offset + 1] = v1;
output_buffer[offset + 2] = v2;
}
self.m_rgVerticesBufferOffset = offset + 3;
} else {
self.m_rgVerticesTriList.reserve(3);
self.m_rgVerticesTriList.push(v0);
self.m_rgVerticesTriList.push(v1);
self.m_rgVerticesTriList.push(v2);
}
}
fn AddTrapezoidVertices(&mut self, v0: TVertex, v1: TVertex, v2: TVertex, v3: TVertex) {
if let Some(output_buffer) = &mut self.m_rgVerticesBuffer {
let offset = self.m_rgVerticesBufferOffset;
if offset + 6 <= output_buffer.len() {
output_buffer[offset] = v0;
output_buffer[offset + 1] = v1.clone();
output_buffer[offset + 2] = v2.clone();
output_buffer[offset + 3] = v1;
output_buffer[offset + 4] = v2;
output_buffer[offset + 5] = v3;
}
self.m_rgVerticesBufferOffset = offset + 6;
} else {
self.m_rgVerticesTriList.reserve(6);
self.m_rgVerticesTriList.push(v0);
self.m_rgVerticesTriList.push(v1.clone());
self.m_rgVerticesTriList.push(v2.clone());
self.m_rgVerticesTriList.push(v1);
self.m_rgVerticesTriList.push(v2);
self.m_rgVerticesTriList.push(v3);
}
}
fn AddedNonLineSegment(&mut self) {
#[cfg(debug_assertions)]
if (uCount != 6)
{
// Make a note that we added a tristrip using other than
// 6 elements.
self.m_fDbgNonLineSegmentTriangleStrip = true;
}
self.m_rgVerticesTriList.reserve(uCount as usize);
/*
if (newCount > self.m_rgVerticesTriStrip.GetCapacity())
{
IFC(self.m_rgVerticesTriStrip.ReserveSpace(uCount));
}
self.m_rgVerticesTriStrip.SetCount(newCount);*/
return &mut self.m_rgVerticesTriList;
//Cleanup:
//RRETURN!(hr);
}
}
/*
//+----------------------------------------------------------------------------
//
@ -1457,17 +1477,17 @@ CHwTVertexBuffer<CD3DVertexXYZNDSUV4>::Builder::GetOutVertexFormat()
// matching vertex builder
//
*/
pub type CHwVertexBufferBuilder = CHwTVertexBufferBuilder<OutputVertex>;
impl CHwVertexBufferBuilder {
pub type CHwVertexBufferBuilder<'y, 'z> = CHwTVertexBufferBuilder<'y, 'z, OutputVertex>;
impl<'y, 'z> CHwVertexBufferBuilder<'y, 'z> {
pub fn Create(
vfIn: MilVertexFormat,
vfOut: MilVertexFormat,
mvfaAntiAliasScaleLocation: MilVertexFormatAttribute,
pDevice: Rc<CD3DDeviceLevel1>,
pVertexBuffer: &'y mut CHwVertexBuffer<'z>,
/*pBufferDispenser: &CBufferDispenser*/
) -> CHwVertexBufferBuilder
) -> CHwVertexBufferBuilder<'y, 'z>
{
CHwVertexBufferBuilder::CreateTemplate(pDevice.GetVB_XYZDUV2(), vfIn, vfOut, mvfaAntiAliasScaleLocation, pDevice)
CHwVertexBufferBuilder::CreateTemplate(pVertexBuffer, vfIn, vfOut, mvfaAntiAliasScaleLocation)
//let hr: HRESULT = S_OK;
//assert!(ppVertexBufferBuilder);
@ -1656,7 +1676,7 @@ CHwTVertexMappings<TVertex>::PointToUV(
*/
impl<TVertex: Default> CHwTVertexBufferBuilder<TVertex> {
impl<'y, 'z, TVertex: Default> CHwTVertexBufferBuilder<'y, 'z, TVertex> {
//+----------------------------------------------------------------------------
//
@ -1666,18 +1686,17 @@ impl<TVertex: Default> CHwTVertexBufferBuilder<TVertex> {
//
fn CreateTemplate(
pVertexBuffer: Box<CHwTVertexBuffer<TVertex>>,
pVertexBuffer: &'y mut CHwTVertexBuffer<'z, TVertex>,
mvfIn: MilVertexFormat,
mvfOut: MilVertexFormat,
mvfaAntiAliasScaleLocation: MilVertexFormatAttribute,
/*pBufferDispenser: __inout_ecount(1) CBufferDispenser *,*/
pDevice: Rc<CD3DDeviceLevel1>,
) -> Self
{
let mut pVertexBufferBuilder = CHwTVertexBufferBuilder::<TVertex>::new(pVertexBuffer, pDevice);
let mut pVertexBufferBuilder = CHwTVertexBufferBuilder::<TVertex>::new(pVertexBuffer);
IFC!(pVertexBufferBuilder.SetupConverter(
mvfIn,
@ -1696,7 +1715,7 @@ fn CreateTemplate(
//
//-----------------------------------------------------------------------------
fn new(pVertexBuffer: Box<CHwTVertexBuffer<TVertex>>, device: Rc<CD3DDeviceLevel1>) -> Self
fn new(pVertexBuffer: &'y mut CHwTVertexBuffer<'z, TVertex>) -> Self
{
Self {
m_pVB: pVertexBuffer,
@ -1721,7 +1740,6 @@ fn new(pVertexBuffer: Box<CHwTVertexBuffer<TVertex>>, device: Rc<CD3DDeviceLevel
m_fHasFlushed: false,
//m_map: Default::default(),
m_rcOutsideBounds: Default::default(),
m_pDeviceNoRef: device,
#[cfg(debug_assertions)]
m_mvfDbgOut: MilVertexFormatAttribute::MILVFAttrNone as MilVertexFormat,
m_mvfIn: MilVertexFormatAttribute::MILVFAttrNone as MilVertexFormat,
@ -1848,7 +1866,7 @@ CHwTVertexBuffer<TVertex>::Builder::FinalizeMappings(
RRETURN(hr);
}*/
impl<TVertex> CHwTVertexBufferBuilder<TVertex> {
impl<TVertex> CHwTVertexBufferBuilder<'_, '_, TVertex> {
//+----------------------------------------------------------------------------
//
@ -1900,7 +1918,7 @@ pub fn BeginBuilding(&mut self,
RRETURN!(hr);
}
}
impl IGeometrySink for CHwVertexBufferBuilder {
impl IGeometrySink for CHwVertexBufferBuilder<'_, '_> {
fn AddTrapezoid(&mut self,
rPixelYTop: f32, // In: y coordinate of top of trapezoid
@ -2274,7 +2292,7 @@ Cleanup:
// longer be needed. (Pixel center conventions will also change.)
//
//-----------------------------------------------------------------------------
impl CHwVertexBuffer {
impl CHwVertexBuffer<'_> {
fn AddLineAsTriangleList(&mut self,
pBegin: &CD3DVertexXYZDUV2, // Begin
pEnd: &CD3DVertexXYZDUV2 // End
@ -2297,34 +2315,20 @@ impl CHwVertexBuffer {
// Add the vertices
//
let pVertex = self.AddTriListVertices(3);
// Use a single triangle to cover the entire line
pVertex.push(OutputVertex{ x: x0, y: y - 0.5, coverage: dwDiffuse });
pVertex.push(OutputVertex{ x: x0, y: y + 0.5, coverage: dwDiffuse });
pVertex.push(OutputVertex{ x: x1, y, coverage: dwDiffuse });
self.AddTriVertices(
OutputVertex{ x: x0, y: y - 0.5, coverage: dwDiffuse },
OutputVertex{ x: x0, y: y + 0.5, coverage: dwDiffuse },
OutputVertex{ x: x1, y, coverage: dwDiffuse },
);
self.AddedNonLineSegment();
//Cleanup:
RRETURN!(hr);
}
//+------------------------------------------------------------------------
//
// Member: DrawPrimitive
//
// Synopsis: Send the geometry data to the device and execute rendering
//
//-------------------------------------------------------------------------
fn DrawPrimitive(&mut self,
pDevice: &CD3DDeviceLevel1
) -> HRESULT {
pDevice.output.replace(std::mem::replace(&mut self.m_rgVerticesTriList, Vec::new()));
return S_OK;
}
}
/*
//+----------------------------------------------------------------------------
//
@ -2518,7 +2522,7 @@ CHwTVertexBuffer<TVertex>::Builder::IsEmpty()
// + ^^ +
// delta
//
impl CHwVertexBufferBuilder {
impl CHwVertexBufferBuilder<'_, '_> {
//+----------------------------------------------------------------------------
//
@ -2560,125 +2564,82 @@ fn AddTrapezoidStandard(&mut self,
fNeedOutsideGeometry = self.NeedOutsideGeometry();
fNeedInsideGeometry = self.NeedInsideGeometry();
let pVertex = self.m_pVB.AddTriListVertices(18);
//
// Fill in the vertices
//
pVertex.push(OutputVertex{
x: rPixelXTopLeft - rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rPixelXBottomLeft - rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rPixelXTopLeft + rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXBottomLeft - rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rPixelXTopLeft + rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXBottomLeft + rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
if (fNeedInsideGeometry)
{
pVertex.push(OutputVertex{
self.m_pVB.AddTrapezoidVertices(
OutputVertex{
x: rPixelXTopLeft - rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rPixelXBottomLeft - rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rPixelXTopLeft + rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
},
OutputVertex{
x: rPixelXBottomLeft + rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
}
);
pVertex.push(OutputVertex{
if (fNeedInsideGeometry)
{
self.m_pVB.AddTrapezoidVertices(
OutputVertex{
x: rPixelXTopLeft + rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
},
OutputVertex{
x: rPixelXBottomLeft + rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
},
OutputVertex{
x: rPixelXTopRight - rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
},
OutputVertex{
x: rPixelXBottomRight - rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
}
);
}
self.m_pVB.AddTrapezoidVertices(
OutputVertex{
x: rPixelXTopRight - rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXBottomLeft + rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXTopRight - rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
},
OutputVertex{
x: rPixelXBottomRight - rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
}
pVertex.push(OutputVertex{
x: rPixelXTopRight - rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXBottomRight - rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXTopRight + rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rPixelXBottomRight - rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXTopRight + rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rPixelXBottomRight + rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
});
},
OutputVertex{
x: rPixelXTopRight + rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rPixelXBottomRight + rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
}
);
if (!fNeedOutsideGeometry)
{
@ -2695,6 +2656,8 @@ fn AddTrapezoidStandard(&mut self,
//});
}
self.m_pVB.AddedNonLineSegment();
//Cleanup:
RRETURN!(hr);
}
@ -2779,7 +2742,7 @@ Cleanup:
RRETURN(hr);
}
*/
impl CHwVertexBufferBuilder {
impl CHwVertexBufferBuilder<'_, '_> {
//+----------------------------------------------------------------------------
//
@ -2933,44 +2896,28 @@ fn PrepareStratumSlow(&mut self,
// End current trapezoid stratum.
let pVertex = self.m_pVB.AddTriListVertices(6);
pVertex.push(OutputVertex{
x: self.m_rLastTrapezoidTopRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: self.m_rLastTrapezoidBottomRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: self.m_rLastTrapezoidBottomRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
});
self.m_pVB.AddTrapezoidVertices(
OutputVertex{
x: self.m_rLastTrapezoidTopRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: self.m_rLastTrapezoidBottomRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
}
);
}
// Compute the gap between where the last stratum ended and where
// this one begins.
@ -2992,45 +2939,30 @@ fn PrepareStratumSlow(&mut self,
let outside_left = self.OutsideLeft();
let outside_right = self.OutsideRight();
let pVertex = self.m_pVB.AddTriListVertices(6);
// Duplicate first vertex.
pVertex.push(OutputVertex{
x: outside_left,
y: flRectTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: outside_left,
y: flRectBot,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: outside_right,
y: flRectTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: outside_left,
y: flRectBot,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: outside_right,
y: flRectTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: outside_right,
y: flRectBot,
coverage: FLOAT_ZERO,
});
self.m_pVB.AddTrapezoidVertices(
OutputVertex{
x: outside_left,
y: flRectTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: outside_left,
y: flRectBot,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: outside_right,
y: flRectTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: outside_right,
y: flRectBot,
coverage: FLOAT_ZERO,
}
);
}
if (fTrapezoid)
@ -3043,44 +2975,28 @@ fn PrepareStratumSlow(&mut self,
// Begin new trapezoid stratum.
let pVertex = self.m_pVB.AddTriListVertices(6);
pVertex.push(OutputVertex{
x: rOutsideLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rOutsideLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rTrapezoidTopLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rOutsideLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rTrapezoidTopLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rTrapezoidBottomLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
});
self.m_pVB.AddTrapezoidVertices(
OutputVertex{
x: rOutsideLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rOutsideLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rTrapezoidTopLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
},
OutputVertex{
x: rTrapezoidBottomLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
}
);
}
}
@ -3128,89 +3044,14 @@ fn EndBuildingOutside(&mut self) -> HRESULT
// vertex buffer.
//
//-----------------------------------------------------------------------------
fn EndBuilding(&mut self,
ppVertexBuffer: *const *const CHwVertexBuffer
) -> HRESULT
pub fn EndBuilding(&mut self) -> HRESULT
{
let hr = S_OK;
IFC!(self.EndBuildingOutside());
if (ppVertexBuffer != NULL())
{
todo!();
//*ppVertexBuffer = m_pVB;
}
//Cleanup:
RRETURN!(hr);
}
//+----------------------------------------------------------------------------
//
// Member: CHwTVertexBuffer<TVertex>::Builder::FlushInternal
//
// Synopsis: Send any pending state and geometry to the device.
// If the optional argument is NULL then reset the
// vertex buffer.
// If the optional argument is non-NULL AND we have
// not yet flushed the vertex buffer return the vertex
// buffer.
//
// These semantics allow the VB to be re-used for multipass
// rendering if a single buffer sufficed for all of the geometry.
// Otherwise multipass has to use a slower algorithm.
//
//-----------------------------------------------------------------------------
fn FlushInternal(&mut self,
ppVertexBuffer: Option<&mut CHwVertexBuffer> ) -> HRESULT
{
let hr: HRESULT = S_OK;
/*
if (self.m_pPipelineNoRef)
{
// We use the pointer to the pipeline to ask it to send
// the state if it hasn't been sent already. Therefore after sending
// we null it.
IFC(self.m_pPipelineNoRef->RealizeColorSourcesAndSendState(m_pVB));
self.m_pPipelineNoRef = NULL();
}
*/
IFC!(self.EndBuilding(NULL()));
if (false/*self.m_rgoPrecomputedTriListVertices != NULL()*/)
{
panic!();
}
else
{
IFC!(self.m_pVB.DrawPrimitive(&self.m_pDeviceNoRef));
}
//Cleanup:
if let Some(_ppVertexBuffer) = (ppVertexBuffer)
{
if (!self.m_fHasFlushed)
{
todo!();
//*ppVertexBuffer = self.m_pVB;
}
}
else
{
self.m_fHasFlushed = true;
self.m_pVB.Reset();
//self.m_rgoPrecomputedTriListVertices = NULL();
//self.m_cPrecomputedTriListVertices = 0;
//self.m_rguPrecomputedTriListIndices = NULL();
//self.m_cPrecomputedTriListIndices = 0;
}
RRETURN!(hr);
}
}

View file

@ -44,17 +44,14 @@ pub mod c_bindings;
#[cfg(test)]
mod tri_rasterize;
use std::{rc::Rc, cell::RefCell};
use aarasterizer::CheckValidRange28_4;
use hwrasterizer::CHwRasterizer;
use hwvertexbuffer::CHwVertexBufferBuilder;
use matrix::CMatrix;
use hwvertexbuffer::{CHwVertexBuffer, CHwVertexBufferBuilder};
use real::CFloatFPU;
use types::{CoordinateSpace, CD3DDeviceLevel1, MilFillMode, PathPointTypeStart, MilPoint2F, PathPointTypeLine, MilVertexFormat, MilVertexFormatAttribute, DynArray, BYTE, PathPointTypeBezier, PathPointTypeCloseSubpath, CMILSurfaceRect, POINT};
use types::{MilFillMode, PathPointTypeStart, MilPoint2F, MilPointAndSizeL, PathPointTypeLine, MilVertexFormat, MilVertexFormatAttribute, DynArray, BYTE, PathPointTypeBezier, PathPointTypeCloseSubpath, CMILSurfaceRect, POINT};
#[repr(C)]
#[derive(Debug, Default)]
#[derive(Clone, Debug, Default)]
pub struct OutputVertex {
pub x: f32,
pub y: f32,
@ -217,7 +214,8 @@ impl PathBuilder {
} else {
(clip_x, clip_y, clip_width, clip_height, false)
};
rasterize_to_tri_list(self.fill_mode, &self.types, &self.points, x, y, width, height, self.need_inside, need_outside)
rasterize_to_tri_list(self.fill_mode, &self.types, &self.points, x, y, width, height, self.need_inside, need_outside, None)
.flush_output()
}
pub fn get_path(&mut self) -> Option<OutputPath> {
@ -239,7 +237,7 @@ impl PathBuilder {
// fill the inside of the path excluding the outside. It may alternatively be desirable to fill the
// outside the path out to the clip boundary, optionally keeping the inside. PathBuilder may be
// used instead as a simpler interface to this function that handles building the path arrays.
pub fn rasterize_to_tri_list(
pub fn rasterize_to_tri_list<'a>(
fill_mode: FillMode,
types: &[BYTE],
points: &[POINT],
@ -249,38 +247,25 @@ pub fn rasterize_to_tri_list(
clip_height: i32,
need_inside: bool,
need_outside: bool,
) -> Box<[OutputVertex]> {
let mut rasterizer = CHwRasterizer::new();
let mut device = CD3DDeviceLevel1::new();
device.clipRect.X = clip_x;
device.clipRect.Y = clip_y;
device.clipRect.Width = clip_width;
device.clipRect.Height = clip_height;
let device = Rc::new(device);
/*
device.m_rcViewport = device.clipRect;
*/
let worldToDevice: CMatrix<CoordinateSpace::Shape, CoordinateSpace::Device> = CMatrix::Identity();
output_buffer: Option<&'a mut [OutputVertex]>,
) -> CHwVertexBuffer<'a> {
let clipRect = MilPointAndSizeL {
X: clip_x,
Y: clip_y,
Width: clip_width,
Height: clip_height,
};
let mil_fill_mode = match fill_mode {
FillMode::EvenOdd => MilFillMode::Alternate,
FillMode::Winding => MilFillMode::Winding,
};
rasterizer.Setup(device.clone(), mil_fill_mode, Some(&worldToDevice));
let mut m_mvfIn: MilVertexFormat = MilVertexFormatAttribute::MILVFAttrNone as MilVertexFormat;
let m_mvfIn: MilVertexFormat = MilVertexFormatAttribute::MILVFAttrXY as MilVertexFormat;
let m_mvfGenerated: MilVertexFormat = MilVertexFormatAttribute::MILVFAttrNone as MilVertexFormat;
//let mvfaAALocation = MILVFAttrNone;
const HWPIPELINE_ANTIALIAS_LOCATION: MilVertexFormatAttribute = MilVertexFormatAttribute::MILVFAttrDiffuse;
let mvfaAALocation = HWPIPELINE_ANTIALIAS_LOCATION;
rasterizer.GetPerVertexDataType(&mut m_mvfIn);
let vertexBuilder= Rc::new(RefCell::new(CHwVertexBufferBuilder::Create(m_mvfIn, m_mvfIn | m_mvfGenerated,
mvfaAALocation,
device.clone())));
let outside_bounds = if need_outside {
Some(CMILSurfaceRect {
left: clip_x,
@ -291,12 +276,22 @@ pub fn rasterize_to_tri_list(
} else {
None
};
vertexBuilder.borrow_mut().SetOutsideBounds(outside_bounds.as_ref(), need_inside);
vertexBuilder.borrow_mut().BeginBuilding();
rasterizer.SendGeometry(vertexBuilder.clone(), points, types);
vertexBuilder.borrow_mut().FlushTryGetVertexBuffer(None);
device.output.replace(Vec::new()).into_boxed_slice()
let mut vertexBuffer = CHwVertexBuffer::new(output_buffer);
{
let mut vertexBuilder = CHwVertexBufferBuilder::Create(
m_mvfIn, m_mvfIn | m_mvfGenerated, mvfaAALocation, &mut vertexBuffer);
vertexBuilder.SetOutsideBounds(outside_bounds.as_ref(), need_inside);
vertexBuilder.BeginBuilding();
{
let mut rasterizer = CHwRasterizer::new(
&mut vertexBuilder, mil_fill_mode, None, clipRect);
rasterizer.SendGeometry(points, types);
}
vertexBuilder.EndBuilding();
}
vertexBuffer
}
#[cfg(test)]

View file

@ -107,10 +107,6 @@ pub const PathPointTypeBezier: u8 = 3; // default Bezier (= cubic
pub const PathPointTypePathTypeMask: u8 = 0x07; // type mask (lowest 3 bits).
pub const PathPointTypeCloseSubpath: u8 = 0x80; // closed flag
use std::cell::RefCell;
use crate::{hwvertexbuffer::CHwVertexBuffer, OutputVertex};
pub type DynArray<T> = Vec<T>;
@ -141,22 +137,6 @@ impl<T> DynArrayExts<T> for DynArray<T> {
}
}
#[derive(Default)]
pub struct CD3DDeviceLevel1 {
pub clipRect: MilPointAndSizeL,
pub output: RefCell<Vec<OutputVertex>>
}
impl CD3DDeviceLevel1 {
pub fn new() -> Self { Default::default() }
pub fn GetClipRect(&self, rect: &mut MilPointAndSizeL) {
*rect = self.clipRect.clone();
}
pub fn GetViewport(&self) -> MilPointAndSizeL { self.clipRect.clone() }
pub fn GetVB_XYZDUV2(&self) -> Box<CHwVertexBuffer> {
Box::new(Default::default())
}
}
pub struct CHwPipelineBuilder;
pub mod CoordinateSpace {

View file

@ -100,8 +100,8 @@ localization-ffi = { path = "../../../../intl/l10n/rust/localization-ffi" }
processtools = { path = "../../../components/processtools" }
qcms = { path = "../../../../gfx/qcms", features = ["c_bindings", "neon"], default-features = false }
wpf-gpu-raster = { git = "https://github.com/FirefoxGraphics/wpf-gpu-raster", rev = "b6ca51395c56648b50f21f68a1586f94f8b966c4" }
aa-stroke = { git = "https://github.com/FirefoxGraphics/aa-stroke", rev = "5289b0ff5736a6a6b916ef007fcf07ac14a663d5" }
wpf-gpu-raster = { git = "https://github.com/FirefoxGraphics/wpf-gpu-raster", rev = "e07e3741d1613b1b7ddb85a1120ed4071b3d6a56" }
aa-stroke = { git = "https://github.com/FirefoxGraphics/aa-stroke", rev = "07d3c25322518f294300e96246e09b95e118555d" }
# Force url to stay at 2.1.0. See bug 1734538.
url = "=2.1.0"