Bug 1801307 - Remember last interval to speed up insertion search. r=jrmuizel

This modifies AddInterval in wpf-gpu-raster to try to remember the last interval
it searched for so that it doesn't have to search the entire interval list for
every interval added. This should take us down from O(n^2) to closer to O(n) for
this phase of rasterization.

Differential Revision: https://phabricator.services.mozilla.com/D163795
This commit is contained in:
Lee Salzman 2022-12-05 04:40:45 +00:00
parent e82ecbadae
commit 2ad13433da
9 changed files with 245 additions and 186 deletions

View File

@ -105,7 +105,7 @@ rev = "fc68464b5445caf111e41f643a2e69ccce0b4f83"
[source."https://github.com/FirefoxGraphics/wpf-gpu-raster"]
git = "https://github.com/FirefoxGraphics/wpf-gpu-raster"
replace-with = "vendored-sources"
rev = "f0d95ce14af8a8de74f469dbad715c4064fca2e1"
rev = "b6ca51395c56648b50f21f68a1586f94f8b966c4"
[source."https://github.com/FirefoxGraphics/aa-stroke"]
git = "https://github.com/FirefoxGraphics/aa-stroke"

2
Cargo.lock generated
View File

@ -6390,7 +6390,7 @@ dependencies = [
[[package]]
name = "wpf-gpu-raster"
version = "0.1.0"
source = "git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=f0d95ce14af8a8de74f469dbad715c4064fca2e1#f0d95ce14af8a8de74f469dbad715c4064fca2e1"
source = "git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=b6ca51395c56648b50f21f68a1586f94f8b966c4#b6ca51395c56648b50f21f68a1586f94f8b966c4"
dependencies = [
"typed-arena-nomut",
]

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":"45f9e20ee7a50ca4b4b55918976b3218667d63ebc3075952f8b0ea1d6a6d22f8","examples/draw.rs":"52fee9e2f2c11e1c891b30cb460be2a0ec65974f38dc0c08fd48391caf1e4247","examples/obj-output.rs":"6fc549022aa715eee74ea1cafb89ca33189e9dbe914ea6b2c46160049bda68f3","examples/simple.rs":"99fb566414cbd4a0eb69a2774c9780d7cd17e5cdaa14837b280fba319c053f22","notes":"48e636c646d697e213b3a79e31063e11b6ffc7493592d31f3929b1db495870b8","src/aacoverage.rs":"1f9ebe8db75bd80b6b347e3734b3c5bdb35c6fa984e142271bfcc0c286e0cb45","src/aarasterizer.rs":"d02939c0de5ad1c134543e0e91e89f3d86f6ff718c52a6f40df4db5fb1c4a714","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":"51f884dda5f91e30a70fb6486673967b216dee295521539d1a4806fcdbf4cf94","src/lib.rs":"bc496e7d4e6827198997a5c5a099000405ac590daece785ca94b4a31e2351c55","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":"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}

View File

@ -6,10 +6,6 @@ Target Independent Rasterization.
Design
======
Bezier flattening is done using an approach that uses forward differencing
of the error metric to compute a flattened version that would match a traditional
adaptive recursive flattening.
The general algorithm used for rasterization is a vertical sweep of
the shape that maintains an active edge list. The sweep is done
at a sub-scanline resolution and results in either:
@ -18,3 +14,9 @@ at a sub-scanline resolution and results in either:
of triangle strips.
2. Simple trapezoids being recognized in the active edge list
and output using a faster simple trapezoid path.
Bezier flattening is done using an approach that uses forward differencing
of the error metric to compute a flattened version that would match a traditional
adaptive recursive flattening.

View File

@ -178,6 +178,9 @@ public:*/
m_pIntervalEndMinus4: Cell<Ref<'a, CCoverageInterval<'a>>>,
// Cache the next-to-last added interval to accelerate insertion.
m_pIntervalLast: Cell<Ref<'a, CCoverageInterval<'a>>>,
m_pIntervalBufferBuiltin: CCoverageIntervalBuffer<'a>,
m_pIntervalBufferCurrent: Cell<Ref<'a, CCoverageIntervalBuffer<'a>>>,
@ -193,6 +196,7 @@ impl<'a> Default for CCoverageBuffer<'a> {
m_pIntervalStart: Cell::new(unsafe { Ref::null() }),
m_pIntervalNew: Cell::new(unsafe { Ref::null() }),
m_pIntervalEndMinus4: Cell::new(unsafe { Ref::null() }),
m_pIntervalLast: Cell::new(unsafe { Ref::null() }),
m_pIntervalBufferBuiltin: Default::default(),
m_pIntervalBufferCurrent: unsafe { Cell::new(Ref::null()) },
arena: Arena::new(),
@ -242,15 +246,24 @@ pub fn AddInterval(&'a self, nSubpixelXLeft: INT, nSubpixelXRight: INT) -> HRESU
nPixelXLeft = nSubpixelXLeft >> c_nShift;
nPixelXRight = nSubpixelXRight >> c_nShift;
// Try to resume searching from the last searched interval.
if self.m_pIntervalLast.get().m_nPixelX.get() < nPixelXLeft {
pInterval = self.m_pIntervalLast.get();
}
// Skip any intervals less than 'nPixelLeft':
loop {
nPixelXNext = pInterval.m_pNext.get().m_nPixelX.get();
let nextInterval = pInterval.m_pNext.get();
nPixelXNext = nextInterval.m_nPixelX.get();
if !(nPixelXNext < nPixelXLeft) { break }
pInterval = pInterval.m_pNext.get();
pInterval = nextInterval;
}
// Remember the found interval.
self.m_pIntervalLast.set(pInterval);
// Insert a new interval if necessary:
if (nPixelXNext != nPixelXLeft)
@ -329,16 +342,20 @@ pub fn AddInterval(&'a self, nSubpixelXLeft: INT, nSubpixelXRight: INT) -> HRESU
// and 'nPixelXRight':
loop {
(nPixelXNext = pInterval.m_pNext.get().m_nPixelX.get());
let nextInterval = pInterval.m_pNext.get();
(nPixelXNext = nextInterval.m_nPixelX.get());
if !(nPixelXNext < nPixelXRight) {
break;
}
pInterval = pInterval.m_pNext.get();
pInterval = nextInterval;
pInterval.m_nCoverage.set(pInterval.m_nCoverage.get() + c_nShiftSize);
debug_assert!(pInterval.m_nCoverage.get() <= c_nShiftSize*c_nShiftSize);
}
// Remember the found interval.
self.m_pIntervalLast.set(pInterval);
// Insert another new interval if necessary:
if (nPixelXNext != nPixelXRight)
@ -392,7 +409,6 @@ pub fn AddInterval(&'a self, nSubpixelXLeft: INT, nSubpixelXRight: INT) -> HRESU
self.interval_new_index.set(interval_new_index);
self.m_pIntervalNew.set(pIntervalNew);
return hr;
}
@ -543,6 +559,7 @@ pub fn Initialize(&'a self)
self.m_pIntervalNew.set(Ref::new(&self.m_pIntervalBufferBuiltin.m_interval[2]));
self.interval_new_index.set(2);
self.m_pIntervalEndMinus4.set(Ref::new(&self.m_pIntervalBufferBuiltin.m_interval[INTERVAL_BUFFER_NUMBER - 4]));
self.m_pIntervalLast.set(Ref::new(&self.m_pIntervalBufferBuiltin.m_interval[1]));
}
//-------------------------------------------------------------------------
@ -579,6 +596,7 @@ pub fn Reset(&'a self)
self.m_pIntervalNew.set(Ref::new(&self.m_pIntervalBufferBuiltin.m_interval[2]));
self.interval_new_index.set(2);
self.m_pIntervalEndMinus4.set(Ref::new(&self.m_pIntervalBufferBuiltin.m_interval[INTERVAL_BUFFER_NUMBER - 4]));
self.m_pIntervalLast.set(Ref::new(&self.m_pIntervalBufferBuiltin.m_interval[1]));
}
//-------------------------------------------------------------------------

View File

@ -112,10 +112,10 @@ macro_rules! ASSERTACTIVELISTORDER {
*
\**************************************************************************/
pub fn AdvanceDDAAndUpdateActiveEdgeList(nSubpixelYCurrent: INT, pEdgeActiveList: Ref<CEdge>) {
let mut nOutOfOrderCount: INT = 0;
let mut outOfOrder = false;
let mut pEdgePrevious: Ref<CEdge> = pEdgeActiveList;
let mut pEdgeCurrent: Ref<CEdge> = pEdgeActiveList.Next.get();
let mut prevX = pEdgePrevious.X.get();
// Advance DDA and update edge list
@ -135,21 +135,23 @@ pub fn AdvanceDDAAndUpdateActiveEdgeList(nSubpixelYCurrent: INT, pEdgeActiveList
// Advance the DDA:
pEdgeCurrent.X.set(pEdgeCurrent.X.get() + pEdgeCurrent.Dx);
pEdgeCurrent.Error.set(pEdgeCurrent.Error.get()+ pEdgeCurrent.ErrorUp);
if (pEdgeCurrent.Error.get() >= 0) {
pEdgeCurrent.Error.set(pEdgeCurrent.Error.get() - pEdgeCurrent.ErrorDown);
pEdgeCurrent.X.set(pEdgeCurrent.X.get() + 1);
let mut x = pEdgeCurrent.X.get() + pEdgeCurrent.Dx;
let mut error = pEdgeCurrent.Error.get() + pEdgeCurrent.ErrorUp;
if (error >= 0) {
error -= pEdgeCurrent.ErrorDown;
x += 1;
}
pEdgeCurrent.X.set(x);
pEdgeCurrent.Error.set(error);
// Is this entry out-of-order with respect to the previous one?
nOutOfOrderCount += (pEdgePrevious.X > pEdgeCurrent.X) as i32;
outOfOrder |= (prevX > x);
// Advance:
pEdgePrevious = pEdgeCurrent;
pEdgeCurrent = pEdgeCurrent.Next.get();
prevX = x;
}
// It turns out that having any out-of-order edges at this point
@ -162,7 +164,7 @@ pub fn AdvanceDDAAndUpdateActiveEdgeList(nSubpixelYCurrent: INT, pEdgeActiveList
// Instead, figure out what caused our 'outOfOrder' logic
// above to get messed up.
if (nOutOfOrderCount != 0) {
if (outOfOrder) {
SortActiveEdges(pEdgeActiveList);
}
ASSERTACTIVELISTORDER!(pEdgeActiveList);

View File

@ -1311,7 +1311,7 @@ impl<TVertex: Default> CHwTVertexBuffer<TVertex> {
fn AddTriListVertices(
&mut self,
uCount: UINT,
) -> &mut [TVertex]
) -> &mut DynArray<TVertex>
{
#[cfg(debug_assertions)]
if (uCount != 6)
@ -1321,10 +1321,7 @@ fn AddTriListVertices(
self.m_fDbgNonLineSegmentTriangleStrip = true;
}
let Count = (self.m_rgVerticesTriList.GetCount() as UINT);
let newCount = Count + uCount;
self.m_rgVerticesTriList.resize_with(newCount as usize, Default::default);
self.m_rgVerticesTriList.reserve(uCount as usize);
/*
if (newCount > self.m_rgVerticesTriStrip.GetCapacity())
{
@ -1332,7 +1329,7 @@ fn AddTriListVertices(
}
self.m_rgVerticesTriStrip.SetCount(newCount);*/
return &mut self.m_rgVerticesTriList[Count as usize..];
return &mut self.m_rgVerticesTriList;
//Cleanup:
//RRETURN!(hr);
@ -2303,15 +2300,9 @@ impl CHwVertexBuffer {
let pVertex = self.AddTriListVertices(3);
// Use a single triangle to cover the entire line
pVertex[0].x = x0;
pVertex[0].y = y - 0.5;
pVertex[0].coverage = dwDiffuse;
pVertex[1].x = x0;
pVertex[1].y = y + 0.5;
pVertex[1].coverage = dwDiffuse;
pVertex[2].x = x1;
pVertex[2].y = y;
pVertex[2].coverage = dwDiffuse;
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 });
//Cleanup:
RRETURN!(hr);
@ -2571,109 +2562,123 @@ fn AddTrapezoidStandard(&mut self,
let pVertex = self.m_pVB.AddTriListVertices(18);
let mut i = 0;
//
// Fill in the vertices
//
pVertex[i].x = rPixelXTopLeft - rPixelXLeftDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ZERO;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopLeft - rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
});
pVertex[i].x = rPixelXBottomLeft - rPixelXLeftDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ZERO;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXBottomLeft - rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
});
pVertex[i].x = rPixelXTopLeft + rPixelXLeftDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopLeft + rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXBottomLeft - rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
});
pVertex[i].x = rPixelXBottomLeft - rPixelXLeftDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ZERO;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopLeft + rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXTopLeft + rPixelXLeftDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex[i].x = rPixelXBottomLeft + rPixelXLeftDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXBottomLeft + rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
if (fNeedInsideGeometry)
{
pVertex[i].x = rPixelXTopLeft + rPixelXLeftDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopLeft + rPixelXLeftDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXBottomLeft + rPixelXLeftDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXBottomLeft + rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXTopRight - rPixelXRightDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopRight - rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex.push(OutputVertex{
x: rPixelXBottomLeft + rPixelXLeftDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXBottomLeft + rPixelXLeftDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopRight - rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXTopRight - rPixelXRightDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex[i].x = rPixelXBottomRight - rPixelXRightDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXBottomRight - rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
}
pVertex[i].x = rPixelXTopRight - rPixelXRightDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopRight - rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXBottomRight - rPixelXRightDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXBottomRight - rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXTopRight + rPixelXRightDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ZERO;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopRight + rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
});
pVertex.push(OutputVertex{
x: rPixelXBottomRight - rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ONE,
});
pVertex[i].x = rPixelXBottomRight - rPixelXRightDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ONE;
i += 1;
pVertex.push(OutputVertex{
x: rPixelXTopRight + rPixelXRightDelta,
y: rPixelYTop,
coverage: FLOAT_ZERO,
});
pVertex[i].x = rPixelXTopRight + rPixelXRightDelta;
pVertex[i].y = rPixelYTop;
pVertex[i].coverage = FLOAT_ZERO;
i += 1;
pVertex[i].x = rPixelXBottomRight + rPixelXRightDelta;
pVertex[i].y = rPixelYBottom;
pVertex[i].coverage = FLOAT_ZERO;
// i += 1;
pVertex.push(OutputVertex{
x: rPixelXBottomRight + rPixelXRightDelta,
y: rPixelYBottom,
coverage: FLOAT_ZERO,
});
if (!fNeedOutsideGeometry)
{
@ -2683,10 +2688,11 @@ fn AddTrapezoidStandard(&mut self,
// next one.
//
//pVertex[i].X = rPixelXBottomRight + rPixelXRightDelta;
//pVertex[i].Y = rPixelYBottom;
//pVertex[i].Diffuse = FLOAT_ZERO;
// i += 1;
//pVertex.push(OutputVertex{
// x: rPixelXBottomRight + rPixelXRightDelta,
// y: rPixelYBottom,
// coverage: FLOAT_ZERO,
//});
}
//Cleanup:
@ -2927,32 +2933,44 @@ fn PrepareStratumSlow(&mut self,
// End current trapezoid stratum.
let pVertex: &mut [OutputVertex] = self.m_pVB.AddTriListVertices(6);
let pVertex = self.m_pVB.AddTriListVertices(6);
pVertex[0].x = self.m_rLastTrapezoidTopRight;
pVertex[0].y = self.m_rCurStratumTop;
pVertex[0].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: self.m_rLastTrapezoidTopRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
});
pVertex[1].x = self.m_rLastTrapezoidBottomRight;
pVertex[1].y = self.m_rCurStratumBottom;
pVertex[1].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: self.m_rLastTrapezoidBottomRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex[2].x = rOutsideRight;
pVertex[2].y = self.m_rCurStratumTop;
pVertex[2].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
});
pVertex[3].x = self.m_rLastTrapezoidBottomRight;
pVertex[3].y = self.m_rCurStratumBottom;
pVertex[3].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: self.m_rLastTrapezoidBottomRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex[4].x = rOutsideRight;
pVertex[4].y = self.m_rCurStratumTop;
pVertex[4].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumTop,
coverage: FLOAT_ZERO,
});
pVertex[5].x = rOutsideRight;
pVertex[5].y = self.m_rCurStratumBottom;
pVertex[5].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rOutsideRight,
y: self.m_rCurStratumBottom,
coverage: FLOAT_ZERO,
});
}
// Compute the gap between where the last stratum ended and where
// this one begins.
@ -2977,30 +2995,42 @@ fn PrepareStratumSlow(&mut self,
let pVertex = self.m_pVB.AddTriListVertices(6);
// Duplicate first vertex.
pVertex[0].x = outside_left;
pVertex[0].y = flRectTop;
pVertex[0].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: outside_left,
y: flRectTop,
coverage: FLOAT_ZERO,
});
pVertex[1].x = outside_left;
pVertex[1].y = flRectBot;
pVertex[1].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: outside_left,
y: flRectBot,
coverage: FLOAT_ZERO,
});
pVertex[2].x = outside_right;
pVertex[2].y = flRectTop;
pVertex[2].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: outside_right,
y: flRectTop,
coverage: FLOAT_ZERO,
});
pVertex[3].x = outside_left;
pVertex[3].y = flRectBot;
pVertex[3].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: outside_left,
y: flRectBot,
coverage: FLOAT_ZERO,
});
pVertex[4].x = outside_right;
pVertex[4].y = flRectTop;
pVertex[4].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: outside_right,
y: flRectTop,
coverage: FLOAT_ZERO,
});
pVertex[5].x = outside_right;
pVertex[5].y = flRectBot;
pVertex[5].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: outside_right,
y: flRectBot,
coverage: FLOAT_ZERO,
});
}
if (fTrapezoid)
@ -3013,32 +3043,44 @@ fn PrepareStratumSlow(&mut self,
// Begin new trapezoid stratum.
let mut pVertex: &mut [TVertex] = self.m_pVB.AddTriListVertices(6);
let pVertex = self.m_pVB.AddTriListVertices(6);
pVertex[0].x = rOutsideLeft;
pVertex[0].y = rStratumTop;
pVertex[0].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rOutsideLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
});
pVertex[1].x = rOutsideLeft;
pVertex[1].y = rStratumBottom;
pVertex[1].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rOutsideLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex[2].x = rTrapezoidTopLeft;
pVertex[2].y = rStratumTop;
pVertex[2].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rTrapezoidTopLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
});
pVertex[3].x = rOutsideLeft;
pVertex[3].y = rStratumBottom;
pVertex[3].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rOutsideLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
});
pVertex[4].x = rTrapezoidTopLeft;
pVertex[4].y = rStratumTop;
pVertex[4].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rTrapezoidTopLeft,
y: rStratumTop,
coverage: FLOAT_ZERO,
});
pVertex[5].x = rTrapezoidBottomLeft;
pVertex[5].y = rStratumBottom;
pVertex[5].coverage = FLOAT_ZERO;
pVertex.push(OutputVertex{
x: rTrapezoidBottomLeft,
y: rStratumBottom,
coverage: FLOAT_ZERO,
});
}
}

View File

@ -275,16 +275,11 @@ pub fn rasterize_to_tri_list(
//let mvfaAALocation = MILVFAttrNone;
const HWPIPELINE_ANTIALIAS_LOCATION: MilVertexFormatAttribute = MilVertexFormatAttribute::MILVFAttrDiffuse;
let mvfaAALocation = HWPIPELINE_ANTIALIAS_LOCATION;
struct CHwPipeline {
m_pDevice: Rc<CD3DDeviceLevel1>
}
let pipeline = CHwPipeline { m_pDevice: device.clone() };
let m_pHP = &pipeline;
rasterizer.GetPerVertexDataType(&mut m_mvfIn);
let vertexBuilder= Rc::new(RefCell::new(CHwVertexBufferBuilder::Create(m_mvfIn, m_mvfIn | m_mvfGenerated,
mvfaAALocation,
m_pHP.m_pDevice.clone())));
device.clone())));
let outside_bounds = if need_outside {
Some(CMILSurfaceRect {
@ -500,13 +495,13 @@ mod tests {
p.close();
p.set_outside_bounds(Some((0, 0, 50, 50)), false);
let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(dbg!(calculate_hash(&result)), 0x7c5750ee536ae4ee);
assert_eq!(dbg!(calculate_hash(&result)), 0x805fd385e47e6f2);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x59403ddbb7e1d09a);
// ensure that adjusting the outside bounds changes the results
p.set_outside_bounds(Some((5, 5, 50, 50)), false);
let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(dbg!(calculate_hash(&result)), 0x55441457b28613e0);
assert_eq!(dbg!(calculate_hash(&result)), 0xcec2ed688999c966);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x59403ddbb7e1d09a);
}
@ -534,7 +529,7 @@ mod tests {
p.close();
p.set_outside_bounds(Some((0, 0, 50, 50)), false);
let result = p.rasterize_to_tri_list(0, 0, 50, 50);
assert_eq!(dbg!(calculate_hash(&result)), 0x648a0b7b6aa3b4ed);
assert_eq!(dbg!(calculate_hash(&result)), 0xbd42b934ab52be39);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x3d2a08f5d0bac999);
}

View File

@ -99,7 +99,7 @@ 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 = "f0d95ce14af8a8de74f469dbad715c4064fca2e1" }
wpf-gpu-raster = { git = "https://github.com/FirefoxGraphics/wpf-gpu-raster", rev = "b6ca51395c56648b50f21f68a1586f94f8b966c4" }
aa-stroke = { git = "https://github.com/FirefoxGraphics/aa-stroke", rev = "5289b0ff5736a6a6b916ef007fcf07ac14a663d5" }
# Force url to stay at 2.1.0. See bug 1734538.