| /* | |
| * Copyright 2026 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_graphite_sparse_strips_FastValidator_DEFINED | |
| #define skgpu_graphite_sparse_strips_FastValidator_DEFINED | |
| #include "src/gpu/graphite/sparse_strips/SparseStripsConfig.h" | |
| #include "src/gpu/graphite/sparse_strips/SparseStripsTypes.h" | |
| #include "tests/Test.h" | |
| #include <array> | |
| #include <cstdint> | |
| class SkMatrix; | |
| class SkPath; | |
| enum class SkPathFillType : uint8_t; | |
| struct SkIRect; | |
| template <typename T> class SkTDArray; | |
| namespace skgpu::graphite { | |
| class AlphaAtlasManager; | |
| class EndCaps; | |
| class Polyline; | |
| class Recorder; | |
| class WideTiles; | |
| class WindingHistogram; | |
| template <uint16_t kTileWidth, uint16_t kTileHeight> class Tiles; | |
| // The FastValidator is a faster alternative to the Oracle that is intended to run on CQ. Like the | |
| // Oracle, it validates subpixel winding by naively carrying the scanline across the viewport. | |
| // Unlike the Oracle, the FastValidator implicitly assumes that the flattenning and tiling are | |
| // correct; it calculates winding by consuming the polyline produced by flattenning and therefore | |
| // does not root solve. It only validates the condensed geometric tiles produced by the | |
| // StripProcessors: the EndCaps per subsample, and every other tile of the viewport, which must be | |
| // covered by exactly one WideTile if all of its subsamples are inside the path, or else be empty. | |
| template <uint16_t kTileWidth, uint16_t kTileHeight> class FastValidator { | |
| public: | |
| static constexpr float kTileWidthF = static_cast<float>(kTileWidth); | |
| static constexpr float kTileHeightF = static_cast<float>(kTileHeight); | |
| using StripFunc = void (*)(const Tiles<kTileWidth, kTileHeight>&, | |
| WideTiles* wides, | |
| EndCaps* ends, | |
| AlphaAtlasManager* atlasManager, | |
| SkPathFillType fillType, | |
| const Polyline& polyline, | |
| const SparseStripConfig::LUTArray& msaaLut, | |
| bool isCulled, | |
| const WindingHistogram& windingHistogram, | |
| const SkIRect& clipRect, | |
| MsaaExactMaskObserver observer); | |
| static void RunScalarWinding(const Tiles<kTileWidth, kTileHeight>& tileContainer, | |
| WideTiles* wides, | |
| EndCaps* ends, | |
| AlphaAtlasManager* atlasManager, | |
| SkPathFillType fillType, | |
| const Polyline& polyline, | |
| const SparseStripConfig::LUTArray& maskLut, | |
| bool isCulled, | |
| const WindingHistogram& windingHistogram, | |
| const SkIRect& clipRect, | |
| MsaaExactMaskObserver observer); | |
| static void RunSimdWinding(const Tiles<kTileWidth, kTileHeight>& tileContainer, | |
| WideTiles* wides, | |
| EndCaps* ends, | |
| AlphaAtlasManager* atlasManager, | |
| SkPathFillType fillType, | |
| const Polyline& polyline, | |
| const SparseStripConfig::LUTArray& maskLut, | |
| bool isCulled, | |
| const WindingHistogram& windingHistogram, | |
| const SkIRect& clipRect, | |
| MsaaExactMaskObserver observer); | |
| // Validates a single path end-to-end: | |
| // 1. Flattens using unculled Flatten::processPathsSimdTest to get ground-truth polyline. | |
| // 2. Runs the production pipeline under test (culled Flatten -> Tiler -> MakeStrips). | |
| // 3. Evaluates 8-subsample winding across the tiles of interest (ends.caps()). | |
| // 4. Verifies actual masks and alpha reduction against expected ground truth. | |
| // 5. Verifies that every other tile of the viewport is covered by exactly one WideTile if it is | |
| // inside the path, and is empty if it is outside. | |
| static bool ValidatePath(skiatest::Reporter* reporter, | |
| Recorder* recorder, | |
| const SkPath& path, | |
| const SkMatrix& ctm, | |
| uint16_t viewportWidth, | |
| uint16_t viewportHeight, | |
| const char* testName, | |
| const SparseStripConfig::LUTArray& maskLut, | |
| StripFunc stripFunc = nullptr, | |
| std::array<uint32_t, 3>* minorErrorCount = nullptr); | |
| // As above, but for a draw restricted to `clipRect` rather than a viewport anchored at the | |
| // origin. Like the clips passed by StripGenerator, `clipRect` must have a tile aligned left and | |
| // top. Only the pixels inside of `clipRect` are validated, and every tile outside of it must be | |
| // empty. | |
| static bool ValidatePath(skiatest::Reporter* reporter, | |
| Recorder* recorder, | |
| const SkPath& path, | |
| const SkMatrix& ctm, | |
| const SkIRect& clipRect, | |
| const char* testName, | |
| const SparseStripConfig::LUTArray& maskLut, | |
| StripFunc stripFunc = nullptr, | |
| std::array<uint32_t, 3>* minorErrorCount = nullptr); | |
| // Validates precomputed strip output against an unculled reference polyline. | |
| static bool ValidateStripOutput(skiatest::Reporter* reporter, | |
| const SkPath& path, | |
| const Polyline& polyline, | |
| const Polyline& unculledPolyline, | |
| const Tiles<kTileWidth, kTileHeight>& tiler, | |
| const WideTiles& wides, | |
| const EndCaps& ends, | |
| const AlphaAtlasManager& atlasManager, | |
| const SkTDArray<uint8_t>& exactMasks, | |
| const SkIRect& clip, | |
| SkPathFillType fillType, | |
| const char* testName, | |
| std::array<uint32_t, 3>* minorErrorCount = nullptr); | |
| }; | |
| } // namespace skgpu::graphite | |
| #endif // skgpu_graphite_sparse_strips_FastValidator_DEFINED |