| /* |
| * 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_OracleValidator_DEFINED |
| #define skgpu_graphite_sparse_strips_OracleValidator_DEFINED |
| |
| #include "include/core/SkPath.h" |
| #include "include/core/SkPoint.h" |
| #include "include/private/SkTDArray.h" |
| #include "src/core/SkVx.h" |
| #include "src/gpu/graphite/sparse_strips/Flatten.h" |
| #include "src/gpu/graphite/sparse_strips/MSAA_LUT.h" |
| #include "src/gpu/graphite/sparse_strips/Polyline.h" |
| #include "src/gpu/graphite/sparse_strips/Strip.h" |
| #include "src/gpu/graphite/sparse_strips/Tiler.h" |
| #include "tests/Test.h" |
| #include "tests/graphite/sparse_strips/Oracle.h" |
| |
| #include <array> |
| #include <cstdint> |
| #include <unordered_map> |
| #include <vector> |
| |
| namespace skgpu::graphite { |
| |
| // Zero-copy reference validator that evaluates the SparseStrips stream against the analytical |
| // ScanlineOracle8x ground truth row by row, pixel by pixel, and subsample by subsample. |
| template <uint16_t kTileWidth, uint16_t kTileHeight> class OracleValidator { |
| public: |
| enum class Strictness { |
| kStrict, // Exact sample matching against oracle |
| kNonStrict, // Ignore winding errors on subsamples within flattening tolerance of any |
| // chord in tile |
| }; |
| |
| OracleValidator(const SkPath& path, |
| const SkTDArray<Strip>& stripBuf, |
| const SkTDArray<uint8_t>& alphaBuf, |
| const SkTDArray<skvx::int8>& exactWindings, |
| const Polyline* polyline = nullptr, |
| const Tiles<kTileWidth, kTileHeight>* tiler = nullptr, |
| const char* testName = "OracleValidator", |
| Strictness strictness = Strictness::kStrict); |
| |
| static skvx::int8 GetOracleWinding( |
| int px, const std::vector<ScanlineOracle8x::RowWindingInterval>& intervals); |
| |
| bool validate(skiatest::Reporter* reporter, |
| uint16_t viewportWidth, |
| uint16_t viewportHeight, |
| uint32_t* maxSampleDiffOut = nullptr) const; |
| |
| private: |
| bool validateStreamInvariants(skiatest::Reporter* reporter, |
| uint16_t viewportWidth, |
| uint16_t viewportHeight) const; |
| |
| bool validateBoundaryColumn( |
| skiatest::Reporter* reporter, |
| uint16_t px, |
| uint16_t py, |
| const std::vector<ScanlineOracle8x::RowWindingInterval>& oracleIntervals, |
| bool expectedFill) const; |
| |
| bool validateGapSpan(skiatest::Reporter* reporter, |
| int startPx, |
| int endPx, |
| uint16_t py, |
| const std::vector<ScanlineOracle8x::RowWindingInterval>& oracleIntervals, |
| bool expectedFill) const; |
| |
| bool validateAlphaTileSpan( |
| skiatest::Reporter* reporter, |
| const Strip& strip, |
| uint32_t startAlphaIdx, |
| uint16_t spannedTiles, |
| uint16_t py, |
| const std::vector<ScanlineOracle8x::RowWindingInterval>& oracleIntervals, |
| uint32_t* maxSampleDiffOut) const; |
| |
| static float DistanceSqToSegment(SkPoint p, SkPoint a, SkPoint b); |
| void buildTileLineMap(); |
| bool isWithinTolerance(SkPoint subPt, uint16_t tileX, uint16_t tileY) const; |
| |
| const SkPath fPath; |
| const SkTDArray<Strip>& fStrips; |
| const SkTDArray<uint8_t>& fAlphaBuf; |
| const SkTDArray<skvx::int8>& fExactWindings; |
| const Polyline* fPolyline; |
| const Tiles<kTileWidth, kTileHeight>* fTiler; |
| const char* fTestName; |
| const Strictness fStrictness; |
| const float fToleranceSq = static_cast<float>(Flatten::kQuadTolerance2); |
| std::unordered_map<uint32_t, std::vector<Line>> fTileLineMap; |
| mutable ScanlineOracle8x fOracle; |
| |
| // We only explicitly instantiate 4 and 8 |
| static_assert(kTileWidth == kTileHeight && (kTileWidth == 4 || kTileWidth == 8)); |
| }; |
| |
| } // namespace skgpu::graphite |
| |
| #endif // skgpu_graphite_sparse_strips_OracleValidator_DEFINED |