Bug 1803375. Use different coordinates when running on AMD. r=lsalzman,jgilbert

This updates the version wpf-gpu-raster which adds support for
GPUs/drivers that use truncation instead of rounding when converting
vertices to fixed point.

It also adds the GL vendor to InitContextResult so that we can detect
AMD on macOS and tell wpf-gpu-raster that truncation is going to happen.

Differential Revision: https://phabricator.services.mozilla.com/D167503
This commit is contained in:
Jeff Muizelaar 2023-01-27 01:45:17 +00:00
parent b0f364de62
commit 3a46da3d80
17 changed files with 93 additions and 34 deletions

View file

@ -12,7 +12,7 @@ replace-with = "vendored-sources"
[source."https://github.com/FirefoxGraphics/wpf-gpu-raster"] [source."https://github.com/FirefoxGraphics/wpf-gpu-raster"]
git = "https://github.com/FirefoxGraphics/wpf-gpu-raster" git = "https://github.com/FirefoxGraphics/wpf-gpu-raster"
rev = "e07e3741d1613b1b7ddb85a1120ed4071b3d6a56" rev = "a6514854d4518b02f2805719ff6cd74dae7dfde6"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."https://github.com/chris-zen/coremidi.git"] [source."https://github.com/chris-zen/coremidi.git"]

2
Cargo.lock generated
View file

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

View file

@ -758,6 +758,7 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
public: public:
const auto& Limits() const { return mNotLost->info.limits; } const auto& Limits() const { return mNotLost->info.limits; }
const auto& Vendor() const { return mNotLost->info.vendor; }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#actual-context-parameters // https://www.khronos.org/registry/webgl/specs/latest/1.0/#actual-context-parameters
const WebGLContextOptions& ActualContextParameters() const { const WebGLContextOptions& ActualContextParameters() const {
MOZ_ASSERT(mNotLost != nullptr); MOZ_ASSERT(mNotLost != nullptr);

View file

@ -429,6 +429,10 @@ bool DrawTargetWebgl::SharedContext::Initialize() {
mMaxTextureSize = mWebgl->Limits().maxTex2dSize; mMaxTextureSize = mWebgl->Limits().maxTex2dSize;
if (kIsMacOS) {
mRasterizationTruncates = mWebgl->Vendor() == gl::GLVendor::ATI;
}
CachePrefs(); CachePrefs();
if (!CreateShaders()) { if (!CreateShaders()) {
@ -2547,7 +2551,7 @@ static Maybe<WGR::VertexBuffer> GeneratePathVertexBuffer(
WGR::OutputVertex* aBuffer, size_t aBufferCapacity) { WGR::OutputVertex* aBuffer, size_t aBufferCapacity) {
WGR::VertexBuffer vb = WGR::wgr_path_rasterize_to_tri_list( WGR::VertexBuffer vb = WGR::wgr_path_rasterize_to_tri_list(
&aPath.mPath, aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height, &aPath.mPath, aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height,
true, false, aBuffer, aBufferCapacity); true, false, false, aBuffer, aBufferCapacity);
if (!vb.len || (aBuffer && vb.len > aBufferCapacity)) { if (!vb.len || (aBuffer && vb.len > aBufferCapacity)) {
WGR::wgr_vertex_buffer_release(vb); WGR::wgr_vertex_buffer_release(vb);
return Nothing(); return Nothing();

View file

@ -212,6 +212,7 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
RefPtr<WebGLTextureJS> mNoClipMask; RefPtr<WebGLTextureJS> mNoClipMask;
uint32_t mMaxTextureSize = 0; uint32_t mMaxTextureSize = 0;
bool mRasterizationTruncates = false;
// The current blending operation. // The current blending operation.
CompositionOp mLastCompositionOp = CompositionOp::OP_SOURCE; CompositionOp mLastCompositionOp = CompositionOp::OP_SOURCE;

View file

@ -623,6 +623,7 @@ RefPtr<WebGLContext> WebGLContext::Create(HostWebGLContext& host,
out->options = webgl->mOptions; out->options = webgl->mOptions;
out->limits = *webgl->mLimits; out->limits = *webgl->mLimits;
out->uploadableSdTypes = UploadableSdTypes(); out->uploadableSdTypes = UploadableSdTypes();
out->vendor = webgl->gl->Vendor();
return webgl; return webgl;
} }

View file

@ -286,6 +286,13 @@ struct ParamTraits<mozilla::webgl::OpaqueFramebufferOptions> final
// - // -
template <>
struct ParamTraits<mozilla::gl::GLVendor>
: public ContiguousEnumSerializerInclusive<mozilla::gl::GLVendor,
mozilla::gl::GLVendor::Intel,
mozilla::gl::kHighestGLVendor> {
};
template <typename T> template <typename T>
struct ParamTraits<mozilla::webgl::EnumMask<T>> final struct ParamTraits<mozilla::webgl::EnumMask<T>> final
: public PlainOldDataSerializer<mozilla::webgl::EnumMask<T>> {}; : public PlainOldDataSerializer<mozilla::webgl::EnumMask<T>> {};
@ -299,12 +306,14 @@ struct ParamTraits<mozilla::webgl::InitContextResult> final {
WriteParam(writer, in.options); WriteParam(writer, in.options);
WriteParam(writer, in.limits); WriteParam(writer, in.limits);
WriteParam(writer, in.uploadableSdTypes); WriteParam(writer, in.uploadableSdTypes);
WriteParam(writer, in.vendor);
} }
static bool Read(MessageReader* const reader, T* const out) { static bool Read(MessageReader* const reader, T* const out) {
return ReadParam(reader, &out->error) && ReadParam(reader, &out->options) && return ReadParam(reader, &out->error) && ReadParam(reader, &out->options) &&
ReadParam(reader, &out->limits) && ReadParam(reader, &out->limits) &&
ReadParam(reader, &out->uploadableSdTypes); ReadParam(reader, &out->uploadableSdTypes) &&
ReadParam(reader, &out->vendor);
} }
}; };

View file

@ -15,6 +15,7 @@
#include <vector> #include <vector>
#include "GLDefs.h" #include "GLDefs.h"
#include "GLVendor.h"
#include "ImageContainer.h" #include "ImageContainer.h"
#include "mozilla/Casting.h" #include "mozilla/Casting.h"
#include "mozilla/CheckedInt.h" #include "mozilla/CheckedInt.h"
@ -676,6 +677,7 @@ struct InitContextResult final {
WebGLContextOptions options; WebGLContextOptions options;
webgl::Limits limits; webgl::Limits limits;
EnumMask<layers::SurfaceDescriptor::Type> uploadableSdTypes; EnumMask<layers::SurfaceDescriptor::Type> uploadableSdTypes;
gl::GLVendor vendor;
}; };
// - // -

View file

@ -37,6 +37,7 @@
#include "GLConsts.h" #include "GLConsts.h"
#include "GLDefs.h" #include "GLDefs.h"
#include "GLTypes.h" #include "GLTypes.h"
#include "GLVendor.h"
#include "nsRegionFwd.h" #include "nsRegionFwd.h"
#include "nsString.h" #include "nsString.h"
#include "GLContextTypes.h" #include "GLContextTypes.h"
@ -151,19 +152,6 @@ enum class ContextProfile : uint8_t {
OpenGLES OpenGLES
}; };
enum class GLVendor {
Intel,
NVIDIA,
ATI,
Qualcomm,
Imagination,
Nouveau,
Vivante,
VMware,
ARM,
Other
};
enum class GLRenderer { enum class GLRenderer {
Adreno200, Adreno200,
Adreno205, Adreno205,

20
gfx/gl/GLVendor.h Normal file
View file

@ -0,0 +1,20 @@
/* -*- mode: c++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* this source code form is subject to the terms of the mozilla public
* license, v. 2.0. if a copy of the mpl was not distributed with this
* file, you can obtain one at http://mozilla.org/mpl/2.0/. */
#ifndef GLVENDOR_H_
#define GLVENDOR_H_
#include "mozilla/DefineEnum.h"
namespace mozilla {
namespace gl {
MOZ_DEFINE_ENUM(GLVendor, (Intel, NVIDIA, ATI, Qualcomm, Imagination, Nouveau,
Vivante, VMware, ARM, Other));
}
} // namespace mozilla
#endif /* GLVENDOR_H_ */

View file

@ -42,6 +42,7 @@ EXPORTS += [
"GLTextureImage.h", "GLTextureImage.h",
"GLTypes.h", "GLTypes.h",
"GLUploadHelpers.h", "GLUploadHelpers.h",
"GLVendor.h",
"HeapCopyOfStackArray.h", "HeapCopyOfStackArray.h",
"MozFramebuffer.h", "MozFramebuffer.h",
"ScopedGLHelpers.h", "ScopedGLHelpers.h",

View file

@ -53,7 +53,8 @@ Path wgr_builder_get_path(PathBuilder* pb);
VertexBuffer wgr_path_rasterize_to_tri_list( VertexBuffer wgr_path_rasterize_to_tri_list(
const Path* p, int32_t clip_x, int32_t clip_y, int32_t clip_width, 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, int32_t clip_height, bool need_inside = true, bool need_outside = false,
OutputVertex* output_ptr = nullptr, size_t output_capacity = 0); bool rasterization_truncates = false, OutputVertex* output_ptr = nullptr,
size_t output_capacity = 0);
void wgr_path_release(Path p); void wgr_path_release(Path p);
void wgr_vertex_buffer_release(VertexBuffer vb); void wgr_vertex_buffer_release(VertexBuffer vb);
void wgr_builder_release(PathBuilder* pb); void wgr_builder_release(PathBuilder* pb);

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":"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} {"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":"9c5ab638cf0a14220d93528e37cdc0f6d83277eaa10acf9ce36f32a28e30c02b","src/fix.rs":"7ccf63db5bab4ab0135d92691f7c2272a27866b9792dd55ec98b2d1c1b7c0358","src/geometry_sink.rs":"9025569f77f475a1e47fd470e8f53dcdf88ef57e3a5b8a51268fff892da8b1a7","src/helpers.rs":"220294dac335943518f249c4a27ad803f8226ed62cd780f517e95be6343a1f2f","src/hwrasterizer.rs":"82b2d6d35488a6ad7de4d82f3ee38c6f09f4b6de06b4f98eea61b3abdd72eb62","src/hwvertexbuffer.rs":"f3dd54f17570eb530c9c827b24a53b755a2dfa6028e9b83f9d7a4ba9945c2ecf","src/lib.rs":"6b3ec96d3efeed723af68d663465c04cebdb54764c137f698195880c9dd8c5fd","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,6 +102,7 @@ pub extern "C" fn wgr_path_rasterize_to_tri_list(
clip_height: i32, clip_height: i32,
need_inside: bool, need_inside: bool,
need_outside: bool, need_outside: bool,
rasterization_truncates: bool,
output_ptr: *mut OutputVertex, output_ptr: *mut OutputVertex,
output_capacity: usize, output_capacity: usize,
) -> VertexBuffer { ) -> VertexBuffer {
@ -115,7 +116,9 @@ pub extern "C" fn wgr_path_rasterize_to_tri_list(
unsafe { std::slice::from_raw_parts(path.types, path.num_types) }, unsafe { std::slice::from_raw_parts(path.types, path.num_types) },
unsafe { std::slice::from_raw_parts(path.points, path.num_points) }, unsafe { std::slice::from_raw_parts(path.points, path.num_points) },
clip_x, clip_y, clip_width, clip_height, clip_x, clip_y, clip_width, clip_height,
need_inside, need_outside, output_buffer, need_inside, need_outside,
rasterization_truncates,
output_buffer
); );
if let Some(output_buffer_size) = result.get_output_buffer_size() { if let Some(output_buffer_size) = result.get_output_buffer_size() {
VertexBuffer { VertexBuffer {

View file

@ -638,12 +638,19 @@ protected:
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
// In debug make a note if we add a triangle strip that doesn't have 6 vertices // 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. // so that we can ensure that we only waffle 6-vertex tri strips.
m_fDbgNonLineSegmentTriangleStrip: bool m_fDbgNonLineSegmentTriangleStrip: bool,
subpixel_bias: f32,
} }
impl<'z, TVertex: Default> CHwTVertexBuffer<'z, TVertex> { impl<'z, TVertex: Default> CHwTVertexBuffer<'z, TVertex> {
pub fn new(output_buffer: Option<&'z mut [TVertex]>) -> Self { pub fn new(rasterization_truncates: bool, output_buffer: Option<&'z mut [TVertex]>) -> Self {
CHwTVertexBuffer::<TVertex> { CHwTVertexBuffer::<TVertex> {
subpixel_bias: if rasterization_truncates {
// 1/512 is 0.5 of a subpixel when using 8 bits of subpixel precision.
1./512.
} else {
0.
},
m_rgVerticesBuffer: output_buffer, m_rgVerticesBuffer: output_buffer,
m_rgVerticesBufferOffset: 0, m_rgVerticesBufferOffset: 0,
..Default::default() ..Default::default()
@ -715,6 +722,7 @@ public:
*/ */
m_vStatic: TVertex, m_vStatic: TVertex,
subpixel_bias: f32,
} }
impl<TVertex> CHwTVertexBuffer<'_, TVertex> { impl<TVertex> CHwTVertexBuffer<'_, TVertex> {
@ -2315,11 +2323,21 @@ impl CHwVertexBuffer<'_> {
// Add the vertices // Add the vertices
// //
// OpenGL doesn't specify how vertex positions are converted to fixed point prior to rasterization. On macOS, with AMD GPUs,
// the GPU appears to truncate to fixed point instead of rounding. This behaviour is controlled by PA_SU_VTX_CNTL
// register. To handle this we'll add a 1./512. subpixel bias to the center vertex to cause the coordinates to round instead
// of truncate.
//
// D3D11 requires the fixed point integer result to be within 0.6ULP which implicitly disallows the truncate behaviour above.
// This means that D2D doesn't need to deal with this problem.
let subpixel_bias = self.subpixel_bias;
// Use a single triangle to cover the entire line // Use a single triangle to cover the entire line
self.AddTriVertices( self.AddTriVertices(
OutputVertex{ x: x0, y: y - 0.5, coverage: dwDiffuse }, OutputVertex{ x: x0, y: y - 0.5, coverage: dwDiffuse },
OutputVertex{ x: x0, y: y + 0.5, coverage: dwDiffuse }, OutputVertex{ x: x0, y: y + 0.5, coverage: dwDiffuse },
OutputVertex{ x: x1, y, coverage: dwDiffuse }, OutputVertex{ x: x1, y: y + subpixel_bias, coverage: dwDiffuse },
); );
self.AddedNonLineSegment(); self.AddedNonLineSegment();

View file

@ -96,6 +96,7 @@ pub struct PathBuilder {
outside_bounds: Option<CMILSurfaceRect>, outside_bounds: Option<CMILSurfaceRect>,
need_inside: bool, need_inside: bool,
valid_range: bool, valid_range: bool,
rasterization_truncates: bool,
} }
impl PathBuilder { impl PathBuilder {
@ -110,6 +111,7 @@ impl PathBuilder {
outside_bounds: None, outside_bounds: None,
need_inside: true, need_inside: true,
valid_range: true, valid_range: true,
rasterization_truncates: false,
} }
} }
fn add_point(&mut self, x: f32, y: f32) { fn add_point(&mut self, x: f32, y: f32) {
@ -199,6 +201,12 @@ impl PathBuilder {
self.need_inside = need_inside; self.need_inside = need_inside;
} }
/// Set this to true if post vertex shader coordinates are converted to fixed point
/// via truncation. This has been observed with OpenGL on AMD GPUs on macOS.
pub fn set_rasterization_truncates(&mut self, rasterization_truncates: bool) {
self.rasterization_truncates = rasterization_truncates;
}
/// Note: trapezoidal areas won't necessarily be clipped to the clip rect /// Note: trapezoidal areas won't necessarily be clipped to the clip rect
pub fn rasterize_to_tri_list(&self, clip_x: i32, clip_y: i32, clip_width: i32, clip_height: i32) -> Box<[OutputVertex]> { pub fn rasterize_to_tri_list(&self, clip_x: i32, clip_y: i32, clip_width: i32, clip_height: i32) -> Box<[OutputVertex]> {
if !self.valid_range { if !self.valid_range {
@ -214,7 +222,7 @@ impl PathBuilder {
} else { } else {
(clip_x, clip_y, clip_width, clip_height, false) (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, None) rasterize_to_tri_list(self.fill_mode, &self.types, &self.points, x, y, width, height, self.need_inside, need_outside, self.rasterization_truncates, None)
.flush_output() .flush_output()
} }
@ -247,6 +255,7 @@ pub fn rasterize_to_tri_list<'a>(
clip_height: i32, clip_height: i32,
need_inside: bool, need_inside: bool,
need_outside: bool, need_outside: bool,
rasterization_truncates: bool,
output_buffer: Option<&'a mut [OutputVertex]>, output_buffer: Option<&'a mut [OutputVertex]>,
) -> CHwVertexBuffer<'a> { ) -> CHwVertexBuffer<'a> {
let clipRect = MilPointAndSizeL { let clipRect = MilPointAndSizeL {
@ -255,6 +264,7 @@ pub fn rasterize_to_tri_list<'a>(
Width: clip_width, Width: clip_width,
Height: clip_height, Height: clip_height,
}; };
let mil_fill_mode = match fill_mode { let mil_fill_mode = match fill_mode {
FillMode::EvenOdd => MilFillMode::Alternate, FillMode::EvenOdd => MilFillMode::Alternate,
FillMode::Winding => MilFillMode::Winding, FillMode::Winding => MilFillMode::Winding,
@ -277,7 +287,7 @@ pub fn rasterize_to_tri_list<'a>(
None None
}; };
let mut vertexBuffer = CHwVertexBuffer::new(output_buffer); let mut vertexBuffer = CHwVertexBuffer::new(rasterization_truncates, output_buffer);
{ {
let mut vertexBuilder = CHwVertexBufferBuilder::Create( let mut vertexBuilder = CHwVertexBufferBuilder::Create(
m_mvfIn, m_mvfIn | m_mvfGenerated, mvfaAALocation, &mut vertexBuffer); m_mvfIn, m_mvfIn | m_mvfGenerated, mvfaAALocation, &mut vertexBuffer);
@ -415,8 +425,8 @@ mod tests {
p.curve_to(40., 10., 40., 10., 40., 40.); p.curve_to(40., 10., 40., 10., 40., 40.);
p.close(); p.close();
let result = p.rasterize_to_tri_list(0, 0, 100, 100); let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(dbg!(calculate_hash(&result)), 0x8dbc4d23f9bba38d);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0xa92aae8dba7b8cd4); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0xa92aae8dba7b8cd4);
assert_eq!(dbg!(calculate_hash(&result)), 0x8dbc4d23f9bba38d);
} }
#[test] #[test]
@ -430,8 +440,8 @@ mod tests {
let result = p.rasterize_to_tri_list(0, 0, 100, 100); let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(result.len(), 21); assert_eq!(result.len(), 21);
assert_eq!(dbg!(calculate_hash(&result)), 0xf90cb6afaadfb559);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0xfa200c3bae144952); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0xfa200c3bae144952);
assert_eq!(dbg!(calculate_hash(&result)), 0xf90cb6afaadfb559);
} }
#[test] #[test]
@ -445,8 +455,8 @@ mod tests {
let result = p.rasterize_to_tri_list(0, 0, 400, 400); let result = p.rasterize_to_tri_list(0, 0, 400, 400);
assert_eq!(result.len(), 429); assert_eq!(result.len(), 429);
assert_eq!(dbg!(calculate_hash(&result)), 0x52d52992e249587a);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x5e82d98fdb47a796); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x5e82d98fdb47a796);
assert_eq!(dbg!(calculate_hash(&result)), 0x52d52992e249587a);
} }
@ -459,8 +469,8 @@ mod tests {
p.line_to(40., 40.); p.line_to(40., 40.);
p.close(); p.close();
let result = p.rasterize_to_tri_list(0, 0, 100, 100); let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(dbg!(calculate_hash(&result)), 0xf10babef5c619d19);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x49ecc769e1d4ec01); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x49ecc769e1d4ec01);
assert_eq!(dbg!(calculate_hash(&result)), 0xf10babef5c619d19);
} }
#[test] #[test]
@ -490,14 +500,14 @@ mod tests {
p.close(); p.close();
p.set_outside_bounds(Some((0, 0, 50, 50)), false); p.set_outside_bounds(Some((0, 0, 50, 50)), false);
let result = p.rasterize_to_tri_list(0, 0, 100, 100); let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(dbg!(calculate_hash(&result)), 0x805fd385e47e6f2);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x59403ddbb7e1d09a); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x59403ddbb7e1d09a);
assert_eq!(dbg!(calculate_hash(&result)), 0x805fd385e47e6f2);
// ensure that adjusting the outside bounds changes the results // ensure that adjusting the outside bounds changes the results
p.set_outside_bounds(Some((5, 5, 50, 50)), false); p.set_outside_bounds(Some((5, 5, 50, 50)), false);
let result = p.rasterize_to_tri_list(0, 0, 100, 100); let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(dbg!(calculate_hash(&result)), 0xcec2ed688999c966);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x59403ddbb7e1d09a); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x59403ddbb7e1d09a);
assert_eq!(dbg!(calculate_hash(&result)), 0xcec2ed688999c966);
} }
#[test] #[test]
@ -510,8 +520,8 @@ mod tests {
p.close(); p.close();
p.set_outside_bounds(Some((0, 0, 50, 50)), true); p.set_outside_bounds(Some((0, 0, 50, 50)), true);
let result = p.rasterize_to_tri_list(0, 0, 100, 100); let result = p.rasterize_to_tri_list(0, 0, 100, 100);
assert_eq!(dbg!(calculate_hash(&result)), 0xaf76b42a5244d1ec);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x49ecc769e1d4ec01); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x49ecc769e1d4ec01);
assert_eq!(dbg!(calculate_hash(&result)), 0xaf76b42a5244d1ec);
} }
#[test] #[test]
@ -524,8 +534,8 @@ mod tests {
p.close(); p.close();
p.set_outside_bounds(Some((0, 0, 50, 50)), false); p.set_outside_bounds(Some((0, 0, 50, 50)), false);
let result = p.rasterize_to_tri_list(0, 0, 50, 50); let result = p.rasterize_to_tri_list(0, 0, 50, 50);
assert_eq!(dbg!(calculate_hash(&result)), 0xbd42b934ab52be39);
assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x3d2a08f5d0bac999); assert_eq!(calculate_hash(&rasterize_to_mask(&result, 100, 100)), 0x3d2a08f5d0bac999);
assert_eq!(dbg!(calculate_hash(&result)), 0xbd42b934ab52be39);
} }
#[test] #[test]

View file

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