blob: 10d375067e5d7a3fc8f4327b94250f43ff93d226 [file]
/*
* Copyright 2026 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/graphite/sparse_strips/Polyline.h"
#include "src/gpu/graphite/sparse_strips/Tiler.h"
#include "tests/Test.h"
#include <cmath>
#include <sstream>
#include <vector>
namespace skgpu::graphite {
namespace {
std::vector<Line> scale_lines(const std::vector<Line>& input, float scale) {
if (scale == 1.0f) {
return input;
}
std::vector<Line> scaled;
scaled.reserve(input.size());
for (const auto& line : input) {
scaled.push_back({{line.p0.fX * scale, line.p0.fY * scale},
{line.p1.fX * scale, line.p1.fY * scale}});
}
return scaled;
}
Polyline make_polyline(const std::vector<Line>& lines) {
Polyline p;
for (const auto& line : lines) {
p.appendPoint({line.p0.fX, line.p0.fY});
p.appendPoint({line.p1.fX, line.p1.fY});
p.appendSentinel();
}
return p;
}
void build_polyline_and_mapping(const std::vector<Line>& lines,
Polyline* outPolyline,
std::vector<uint32_t>* outMapping) {
outMapping->clear();
outPolyline->reset();
outMapping->reserve(lines.size());
outPolyline->reserve(lines.size() * 3);
for (const auto& line : lines) {
outMapping->push_back(outPolyline->count());
outPolyline->appendPoint({line.p0.fX, line.p0.fY});
outPolyline->appendPoint({line.p1.fX, line.p1.fY});
outPolyline->appendSentinel();
}
}
template <uint16_t kTileWidth, uint16_t kTileHeight>
void check_tiles_match(skiatest::Reporter* reporter,
const std::vector<Line>& rawLines,
const SkTDArray<Tile>& expected,
const char* testName,
float scale) {
Polyline polyline;
std::vector<uint32_t> expectedToActualIdx;
const std::vector<Line> lines = scale_lines(rawLines, scale);
build_polyline_and_mapping(lines, &polyline, &expectedToActualIdx);
Tiles<kTileWidth, kTileHeight> tiles;
uint16_t kScaledDim = static_cast<uint16_t>(100.0f * scale);
tiles.makeTilesMSAA(polyline, kScaledDim, kScaledDim);
const SkTDArray<Tile>& actual = tiles.getTiles();
bool hasFailure = (actual.size() != expected.size());
size_t limit = std::min(actual.size(), expected.size());
for (size_t i = 0; i < limit && !hasFailure; ++i) {
const Tile& got = actual[i];
const Tile& want = expected[i];
uint32_t wantLogicalLine = want.lineIdx();
uint32_t wantLine = wantLogicalLine < expectedToActualIdx.size()
? expectedToActualIdx[wantLogicalLine]
: wantLogicalLine;
if (got.x != want.x || got.y != want.y || got.lineIdx() != wantLine ||
got.intersectionMask() != want.intersectionMask()) {
hasFailure = true;
}
}
if (hasFailure) {
SkString dump;
dump.appendf("\n--- [%s] ---\n", testName);
dump.append("Lines:\n{\n");
for (size_t i = 0; i < rawLines.size(); ++i) {
const auto& line = rawLines[i];
dump.appendf(" {{%gf, %gf}, {%gf, %gf}}%s\n",
line.p0.fX,
line.p0.fY,
line.p1.fX,
line.p1.fY,
(i < rawLines.size() - 1) ? "," : "");
}
dump.append("}\n\n");
auto dumpTiles = [&](const SkTDArray<Tile>& tileArray, const char* label, bool isActual) {
dump.appendf("%s:\n", label);
for (int32_t i = 0; i < tileArray.size(); ++i) {
const auto& tile = tileArray[i];
uint32_t rawLine = tile.lineIdx();
uint32_t mask = tile.intersectionMask();
uint32_t logicalLine = rawLine;
if (isActual) {
for (size_t j = 0; j < expectedToActualIdx.size(); ++j) {
if (expectedToActualIdx[j] == rawLine) {
logicalLine = static_cast<uint32_t>(j);
break;
}
}
}
std::string maskStr = IntersectionBits::maskToString(mask);
if (maskStr.empty()) {
maskStr = "0";
}
dump.appendf(" Tile (%u,%u) LineId %u IntersectionMask : %s\n",
tile.x,
tile.y,
logicalLine,
maskStr.c_str());
}
dump.append("\n");
};
dumpTiles(expected, "Expected", false);
dumpTiles(actual, "Actual", true);
dump.append("--- Mismatches ---\n");
if (actual.size() != expected.size()) {
dump.appendf(" Tile count mismatch. Expected %d, got %d\n",
expected.size(),
actual.size());
}
for (size_t i = 0; i < limit; ++i) {
const Tile& got = actual[i];
const Tile& want = expected[i];
uint32_t wantLogicalLine = want.lineIdx();
uint32_t wantLine = wantLogicalLine < expectedToActualIdx.size()
? expectedToActualIdx[wantLogicalLine]
: wantLogicalLine;
if (got.x != want.x) {
dump.appendf(" Tile[%zu] X mismatch. Want %u, Got %u\n", i, want.x, got.x);
}
if (got.y != want.y) {
dump.appendf(" Tile[%zu] Y mismatch. Want %u, Got %u\n", i, want.y, got.y);
}
if (got.lineIdx() != wantLine) {
dump.appendf(" Tile[%zu] Line Index mismatch. Want %u, Got %u\n",
i,
wantLine,
got.lineIdx());
}
uint32_t gotMask = got.intersectionMask();
uint32_t wantMask = want.intersectionMask();
if (gotMask != wantMask) {
dump.appendf(" Tile[%zu] Mask mismatch. Want [%s], Got [%s]\n",
i,
IntersectionBits::maskToString(wantMask).c_str(),
IntersectionBits::maskToString(gotMask).c_str());
}
}
dump.append("---------------------------\n");
INFOF(reporter, "%s", dump.c_str());
}
REPORTER_ASSERT(reporter, !hasFailure, "%s", testName);
}
void check_sorted(skiatest::Reporter* reporter, const SkTDArray<Tile>& buf) {
if (buf.empty()) return;
for (int32_t i = 0; i < buf.size() - 1; ++i) {
const Tile& current = buf[i];
const Tile& next = buf[i + 1];
if (current.y > next.y) {
ERRORF(reporter, "Sort Failure [Y]: Tile[%d] > Tile[%d]", i, i + 1);
}
if (current.y == next.y) {
if (current.x > next.x) {
ERRORF(reporter, "Sort Failure [X]: Tile[%d] > Tile[%d]", i, i + 1);
}
if (current.x == next.x &&
current.fPackedLineIdxIntersectionMask > next.fPackedLineIdxIntersectionMask) {
ERRORF(reporter, "Sort Failure [Payload]: Tile[%d] > Tile[%d]", i, i + 1);
}
}
}
}
} // namespace
template <uint16_t kTileWidth, uint16_t kTileHeight> class TileTestRunner : IntersectionBits {
static_assert(kTileWidth == kTileHeight); // only support square tiles for now
static constexpr float kScale = static_cast<float>(kTileWidth) / 4.0f;
static constexpr float kUnscaledDim = 100.0f;
static constexpr uint16_t kScaledDim = static_cast<uint16_t>(kUnscaledDim * kScale);
static constexpr float kScaledDimF = static_cast<float>(kScaledDim);
public:
static void runAll(skiatest::Reporter* reporter) {
{
const std::vector<Line> lines = {
{{1.0f, -7.0f}, {3.0f, -1.0f}},
{{1.0f, -11.0f}, {3.0f, -1.0f}},
{{kUnscaledDim + 1.0f, 50.0f}, {kUnscaledDim + 3.0f, 70.0f}},
{{1.0f, kUnscaledDim + 1.0f}, {3.0f, kUnscaledDim + 7.0f}},
{{1.0f, kUnscaledDim + 1.0f}, {3.0f, kUnscaledDim + 13.0f}},
};
const SkTDArray<Tile> expected = {};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "CulledLines", kScale);
}
{
const std::vector<Line> lines = {
{{-2.0f, -3.0f}, {2.0f, 1.0f}},
{{6.0f, -1.0f}, {5.0f, 2.0f}},
{{9.0f, -10.0f}, {10.0f, 3.0f}},
{{2.0f, 1.0f}, {-2.0f, -3.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W | T),
Tile(1, 0, 1, W | T),
Tile(2, 0, 2, W | T),
Tile(0, 0, 3, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedLineCrossingTop", kScale);
}
{
const std::vector<Line> lines = {
{{5.0f, kUnscaledDim + 3.0f}, {6.0f, kUnscaledDim - 2.0f}},
{{10.0f, kUnscaledDim + 1.0f}, {9.0f, kUnscaledDim - 1.0f}},
{{2.0f, kUnscaledDim - 2.0f}, {3.0f, kUnscaledDim + 3.0f}},
};
const SkTDArray<Tile> expected = {
Tile(1, 24, 0, B),
Tile(2, 24, 1, B),
Tile(0, 24, 2, B),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedLineCrossingBot", kScale);
}
{
const std::vector<Line> lines = {
{{1.0f, -5.0f}, {6.0f, 7.0f}},
{{2.5f, -10.0f}, {3.5f, 6.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W | T | R),
Tile(1, 0, 0, L | B),
Tile(1, 1, 0, W | T),
Tile(0, 0, 1, W | T | B),
Tile(0, 1, 1, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedLineCrossingTopMultiTile", kScale);
}
{
const std::vector<Line> lines = {
{{12.0f, kUnscaledDim + 10.0f}, {2.0f, 94.0f}},
{{1.5f, kUnscaledDim + 5.0f}, {3.5f, 94.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 23, 0, B),
Tile(0, 24, 0, W | T | R),
Tile(1, 24, 0, B | L),
Tile(0, 23, 1, B),
Tile(0, 24, 1, W | T | B),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedLineCrossingBotMultiTile", kScale);
}
{
const std::vector<Line> lines = {
{{97.0f, 1.0f}, {kUnscaledDim + 1.0f, 2.0f}},
{{93.0f, 1.0f}, {kUnscaledDim + 5.0f, 2.0f}},
};
const SkTDArray<Tile> expected = {
Tile(24, 0, 0, R),
Tile(23, 0, 1, R),
Tile(24, 0, 1, R | L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedLineCrossingRight", kScale);
}
{
const std::vector<Line> lines = {
{{-5.0f, 1.0f}, {1.0f, 2.0f}},
{{-5.0f, 1.0f}, {5.0f, 2.0f}},
{{-5.0f, 1.0f}, {13.0f, 9.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, L),
Tile(0, 0, 1, L | R),
Tile(1, 0, 1, L),
Tile(0, 0, 2, L | B),
Tile(0, 1, 2, W | R | T),
Tile(1, 1, 2, R | L),
Tile(2, 1, 2, L | B),
Tile(2, 2, 2, W | R | T),
Tile(3, 2, 2, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedLineCrossingLeft", kScale);
}
{
const std::vector<Line> lines = {{{10.0f, -5.0f}, {90.0f, -5.0f}}};
const SkTDArray<Tile> expected = {};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "HorizontalLineAboveViewport", kScale);
}
{
const std::vector<Line> lines = {
{{10.0f, kUnscaledDim + 5.0f}, {90.0f, kUnscaledDim + 5.0f}}};
const SkTDArray<Tile> expected = {};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "HorizontalLineBelowViewport", kScale);
}
{
const std::vector<Line> lines = {{{-10.0f, 10.0f}, {10.0f, 10.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 2, 0, L | R),
Tile(1, 2, 0, L | R),
Tile(2, 2, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "HorizontalLineCrossingLeftViewport", kScale);
}
{
const std::vector<Line> lines = {
{{kUnscaledDim - 5.0f, 10.0f}, {kUnscaledDim + 5.0f, 10.0f}}};
const SkTDArray<Tile> expected = {Tile(23, 2, 0, R), Tile(24, 2, 0, L | R)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "HorizontalLineCrossingRightViewport", kScale);
}
{
const std::vector<Line> lines = {
{{1.0f, -5.0f}, {1.0f, -1.0f}},
{{1.0f, kUnscaledDim + 1.0f}, {1.0f, kUnscaledDim + 5.0f}},
};
const SkTDArray<Tile> expected = {};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLinesOutsideViewport", kScale);
}
{
const std::vector<Line> lines = {
{{1.0f, -7.0f}, {1.0f, 3.0f}},
{{1.0f, -7.0f}, {1.0f, 7.0f}},
{{1.0f, -7.0f}, {1.0f, 8.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W | T),
Tile(0, 0, 1, W | B | T),
Tile(0, 1, 1, W | T),
Tile(0, 0, 2, W | B | T),
Tile(0, 1, 2, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineCrossingTopViewport", kScale);
}
{
const std::vector<Line> lines = {
{{1.0f, kUnscaledDim - 1.0f}, {1.0f, kUnscaledDim + 5.0f}},
{{1.0f, kUnscaledDim - 5.0f}, {1.0f, kUnscaledDim + 5.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 24, 0, B),
Tile(0, 23, 1, B),
Tile(0, 24, 1, W | T | B),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineCrossingBotViewport", kScale);
}
{
const std::vector<Line> lines = {{{-1.0f, 2.0f}, {2.0f, -1.0f}}};
const SkTDArray<Tile> expected = {Tile(0, 0, 0, W | L | T)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "ClipTopLeftCorner", kScale);
}
{
const std::vector<Line> lines = {{{kUnscaledDim + 1.0f, kUnscaledDim - 2.0f},
{kUnscaledDim - 2.0f, kUnscaledDim + 1.0f}}};
const SkTDArray<Tile> expected = {Tile(24, 24, 0, R | B)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "ClipBottomRightCorner", kScale);
}
{
{
const std::vector<Line> lines = {{{1.5f, 1.0f}, {8.5f, 1.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, R | L),
Tile(2, 0, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "HorizontalLineLeftToRightThreeTile", kScale);
}
{
const std::vector<Line> lines = {{{8.5f, 1.0f}, {1.5f, 1.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, R | L),
Tile(2, 0, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "HorizontalLineRightToLeftThreeTile", kScale);
}
{
const std::vector<Line> lines = {{{1.5f, 1.0f}, {12.5f, 1.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, R | L),
Tile(2, 0, 0, R | L),
Tile(3, 0, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "HorizontalLineMultiTile", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 1.5f}, {1.0f, 8.5f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, B),
Tile(0, 1, 0, W | T | B),
Tile(0, 2, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineDownThreeTile", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 1.0f}, {1.0f, 13.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, B),
Tile(0, 1, 0, W | T | B),
Tile(0, 2, 0, W | T | B),
Tile(0, 3, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineDownMultiTile", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 13.0f}, {1.0f, 1.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, B),
Tile(0, 1, 0, W | T | B),
Tile(0, 2, 0, W | T | B),
Tile(0, 3, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineUpThreeTile", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 8.5f}, {1.0f, 1.5f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, B),
Tile(0, 1, 0, W | T | B),
Tile(0, 2, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineUpMultiTile", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 1.0f}, {1.0f, 8.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, B),
Tile(0, 1, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineTouchingBot", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 0.0f}, {1.0f, 7.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W | B),
Tile(0, 1, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineTouchingTop", kScale);
}
{
const std::vector<Line> lines = {{{4.0f, 0.0f}, {4.0f, 7.0f}}};
const SkTDArray<Tile> expected = {
Tile(1, 0, 0, W | B),
Tile(1, 1, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "VerticalLineTouchingLeft", kScale);
}
}
{
{
const std::vector<Line> lines = {{{1.0f, 1.0f}, {11.0f, 9.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, L | B),
Tile(1, 1, 0, W | R | T),
Tile(2, 1, 0, L | B),
Tile(2, 2, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "TopLeftToBottomRight", kScale);
}
{
const std::vector<Line> lines = {{{11.0f, 9.0f}, {1.0f, 1.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, L | B),
Tile(1, 1, 0, W | R | T),
Tile(2, 1, 0, L | B),
Tile(2, 2, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "BottomRightToTopLeft", kScale);
}
{
const std::vector<Line> lines = {{{2.0f, 11.0f}, {14.0f, 6.0f}}};
const SkTDArray<Tile> expected = {
Tile(2, 1, 0, R | B),
Tile(3, 1, 0, L),
Tile(0, 2, 0, R),
Tile(1, 2, 0, R | L),
Tile(2, 2, 0, W | L | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "BottomLeftToTopRight", kScale);
}
{
const std::vector<Line> lines = {{{14.0f, 6.0f}, {2.0f, 11.0f}}};
const SkTDArray<Tile> expected = {
Tile(2, 1, 0, R | B),
Tile(3, 1, 0, L),
Tile(0, 2, 0, R),
Tile(1, 2, 0, R | L),
Tile(2, 2, 0, W | L | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "TopRightToBottomLeft", kScale);
}
}
{
{
const std::vector<Line> lines = {
{{1.0f, 3.0f}, {3.0f, 3.0f}},
{{3.0f, 3.0f}, {0.0f, 1.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, 0),
Tile(0, 0, 1, 0),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "TwoLinesInSingleTile", kScale);
}
{
const std::vector<Line> lines = {{{3.0f, 5.0f}, {5.0f, 3.0f}}};
const SkTDArray<Tile> expected = {
Tile(1, 0, 0, L),
Tile(0, 1, 0, R),
Tile(1, 1, 0, W | L | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalCrossCorner", kScale);
}
{
const std::vector<Line> lines = {{{7.9f, 7.9f}, {0.1f, 0.1f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, L),
Tile(1, 1, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalCrossCornerTwo", kScale);
}
{
const std::vector<Line> lines = {{{5.0f, 5.0f}, {9.0f, 9.0f}}};
const SkTDArray<Tile> expected = {
Tile(1, 1, 0, R),
Tile(2, 1, 0, L),
Tile(2, 2, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalDownSlopeTiles", kScale);
}
{
const std::vector<Line> lines = {{{5.0f, 9.0f}, {9.0f, 5.0f}}};
const SkTDArray<Tile> expected = {
Tile(1, 1, 0, R | B),
Tile(2, 1, 0, L),
Tile(1, 2, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalUpSlopeTiles", kScale);
}
{
const std::vector<Line> lines = {{{0.0f, 0.0f}, {4.0f, 4.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W | R),
Tile(1, 0, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalDownOneTile", kScale);
}
{
const std::vector<Line> lines = {{{0.0f, 4.0f}, {4.0f, 0.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, W | L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalUpOneTile", kScale);
}
{
const std::vector<Line> lines = {{{0.0f, 0.0f}, {8.0f, 8.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W | R),
Tile(1, 0, 0, L),
Tile(1, 1, 0, W | R | T),
Tile(2, 1, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalDownTwoTile", kScale);
}
{
const std::vector<Line> lines = {{{0.0f, 8.0f}, {8.0f, 0.0f}}};
const SkTDArray<Tile> expected = {
Tile(1, 0, 0, R | L),
Tile(2, 0, 0, W | L),
Tile(0, 1, 0, R),
Tile(1, 1, 0, W | L | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "DiagonalUpTwoTile", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 1.0f}, {8.0f, 2.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, R | L),
Tile(2, 0, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedEndingRight", kScale);
}
{
const std::vector<Line> lines = {{{0.0f, 8.0f}, {4.0f, 0.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R | B),
Tile(1, 0, 0, W | L),
Tile(0, 1, 0, W | T),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedTouchingTop", kScale);
}
{
const std::vector<Line> lines = {{{0.0f, 0.0f}, {4.0f, 8.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W | B),
Tile(0, 1, 0, W | R | T),
Tile(1, 1, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedTouchingBot", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 1.0f}, {5.0f, 11.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, B),
Tile(0, 1, 0, W | T | B),
Tile(0, 2, 0, W | T | R),
Tile(1, 2, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SlopedDownThree", kScale);
}
}
{
{
const std::vector<Line> lines = {{{1.0f, 1.0f}, {3.0f, 3.0f}}};
const SkTDArray<Tile> expected = {Tile(0, 0, 0, 0)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SameTile", kScale);
}
{
const std::vector<Line> lines = {{{0.0f, 1.0f}, {3.0f, 1.0f}}};
const SkTDArray<Tile> expected = {Tile(0, 0, 0, 0)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SameTileLeft", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 0.0f}, {1.0f, 3.0f}}};
const SkTDArray<Tile> expected = {Tile(0, 0, 0, W)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SameTileTop", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 1.0f}, {4.0f, 1.0f}}};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, R),
Tile(1, 0, 0, L),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SameTileRight", kScale);
}
{
const std::vector<Line> lines = {
{{1.0f, 1.0f}, {1.0f, 4.0f}},
{{1.0f, 1.0f}, {2.0f, 4.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, 0),
Tile(0, 0, 1, 0),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SameTileBottom", kScale);
}
{
const std::vector<Line> lines = {
{{0.0f, 1.0f}, {1.0f, 0.0f}},
{{0.0f, 0.0001f}, {0.0001f, 0.0f}},
};
const SkTDArray<Tile> expected = {
Tile(0, 0, 0, W),
Tile(0, 0, 1, W),
};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "SameTileTopLeft", kScale);
}
{
const std::vector<Line> lines = {{{4.0f, 1.0f}, {4.0f, 3.0f}}};
const SkTDArray<Tile> expected = {Tile(1, 0, 0, 0)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "ExactRightEdgeCoincidence", kScale);
}
{
const std::vector<Line> lines = {{{1.0f, 4.0f}, {3.0f, 4.0f}}};
const SkTDArray<Tile> expected = {};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "ExactBottomEdgeCoincidence", kScale);
}
}
{
const std::vector<Line> lines = {{{0.000000, 15.856406}, {8.000000, 2.000000}}};
const SkTDArray<Tile> expected = {Tile(1, 0, 0, B | R),
Tile(2, 0, 0, L),
Tile(1, 1, 0, W | T | B),
Tile(0, 2, 0, B | R),
Tile(1, 2, 0, W | T | L),
Tile(0, 3, 0, W | T)};
check_tiles_match<kTileWidth, kTileHeight>(
reporter, lines, expected, "Tricky Precision", kScale);
}
{
Polyline polyline;
Tiles<kTileWidth, kTileHeight> tiles;
float step = 4.0f * kScale;
float y = kScaledDimF - (10.0f * kScale);
float limit = 10.0f * kScale;
while (y > limit) {
polyline.appendPoint({kScaledDimF - (10.0f * kScale), y});
polyline.appendPoint({10.0f * kScale, y});
polyline.appendSentinel();
polyline.appendPoint({kScaledDimF - (12.0f * kScale), y});
polyline.appendPoint({12.0f * kScale, y});
polyline.appendSentinel();
y -= step;
}
tiles.makeTilesMSAA(polyline, kScaledDim, kScaledDim);
const auto& buf = tiles.getTiles();
REPORTER_ASSERT(reporter, !buf.empty(), "SortTest produced no tiles");
tiles.sortTiles();
check_sorted(reporter, tiles.getTiles());
}
{
Tiles<kTileWidth, kTileHeight> tiles;
const std::vector<Line> lines = {
{{22.0f * kScale, 552.0f * kScale}, {224.0f * kScale, 388.0f * kScale}}};
tiles.makeTilesMSAA(
make_polyline(lines), (uint16_t)(600 * kScale), (uint16_t)(600 * kScale));
}
{
Tiles<kTileWidth, kTileHeight> tiles;
const std::vector<Line> lines = {{{59.60001f * kScale, 40.78f * kScale},
{520599.6f * kScale, 100.18f * kScale}}};
tiles.makeTilesMSAA(
make_polyline(lines), (uint16_t)(200 * kScale), (uint16_t)(100 * kScale));
}
}
};
DEF_TEST(SparseStrips_Tiler_4x4, reporter) {
skgpu::graphite::TileTestRunner<4, 4>::runAll(reporter);
}
DEF_TEST(SparseStrips_Tiler_8x8, reporter) {
skgpu::graphite::TileTestRunner<8, 8>::runAll(reporter);
}
} // namespace skgpu::graphite