1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google LLC 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tests/Test.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrQuadBuffer.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include <vector> 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci#define ASSERT(cond) REPORTER_ASSERT(r, cond) 15cb93a386Sopenharmony_ci#define ASSERTF(cond, ...) REPORTER_ASSERT(r, cond, __VA_ARGS__) 16cb93a386Sopenharmony_ci#define TEST(name) DEF_TEST(GrQuadBuffer##name, r) 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_cistruct TestData { 19cb93a386Sopenharmony_ci int fItem1; 20cb93a386Sopenharmony_ci float fItem2; 21cb93a386Sopenharmony_ci}; 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cistatic void assert_quad_eq(skiatest::Reporter* r, const GrQuad& expected, const GrQuad& actual) { 24cb93a386Sopenharmony_ci ASSERTF(expected.quadType() == actual.quadType(), "Expected type %d, got %d", 25cb93a386Sopenharmony_ci (int) expected.quadType(), (int) actual.quadType()); 26cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i) { 27cb93a386Sopenharmony_ci ASSERTF(expected.x(i) == actual.x(i), "Expected x(%d) = %f, got %f", 28cb93a386Sopenharmony_ci i, expected.x(i), actual.x(i)); 29cb93a386Sopenharmony_ci ASSERTF(expected.y(i) == actual.y(i), "Expected y(%d) = %f, got %f", 30cb93a386Sopenharmony_ci i, expected.y(i), actual.y(i)); 31cb93a386Sopenharmony_ci ASSERTF(expected.w(i) == actual.w(i), "Expected w(%d) = %f, got %f", 32cb93a386Sopenharmony_ci i, expected.w(i), actual.w(i)); 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_cistatic void assert_metadata_eq(skiatest::Reporter* r, const TestData& expected, 37cb93a386Sopenharmony_ci const TestData& actual) { 38cb93a386Sopenharmony_ci ASSERTF(expected.fItem1 == actual.fItem1 && expected.fItem2 == actual.fItem2, 39cb93a386Sopenharmony_ci "Expected { %d, %f } for metadata, got: { %d %f }", 40cb93a386Sopenharmony_ci expected.fItem1, expected.fItem2, actual.fItem1, actual.fItem2); 41cb93a386Sopenharmony_ci} 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_cistatic std::vector<GrQuad> generate_quads(float seed, int cnt, const GrQuad::Type types[]) { 44cb93a386Sopenharmony_ci // For convenience use matrix to derive each quad type, rely on different seed values to 45cb93a386Sopenharmony_ci // differentiate between quads of the same type 46cb93a386Sopenharmony_ci SkMatrix rotate; 47cb93a386Sopenharmony_ci rotate.setRotate(45.f); 48cb93a386Sopenharmony_ci SkMatrix skew; 49cb93a386Sopenharmony_ci skew.setSkew(0.5f, 0.5f); 50cb93a386Sopenharmony_ci SkMatrix perspective; 51cb93a386Sopenharmony_ci perspective.setPerspX(0.01f); 52cb93a386Sopenharmony_ci perspective.setPerspY(0.001f); 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci std::vector<GrQuad> quads; 55cb93a386Sopenharmony_ci SkRect rect = SkRect::MakeXYWH(seed, 2.f * seed, 2.f * seed, seed); 56cb93a386Sopenharmony_ci for (int i = 0; i < cnt; ++i) { 57cb93a386Sopenharmony_ci GrQuad quad; 58cb93a386Sopenharmony_ci switch(types[i]) { 59cb93a386Sopenharmony_ci case GrQuad::Type::kAxisAligned: 60cb93a386Sopenharmony_ci quad = GrQuad(rect); 61cb93a386Sopenharmony_ci break; 62cb93a386Sopenharmony_ci case GrQuad::Type::kRectilinear: 63cb93a386Sopenharmony_ci quad = GrQuad::MakeFromRect(rect, rotate); 64cb93a386Sopenharmony_ci break; 65cb93a386Sopenharmony_ci case GrQuad::Type::kGeneral: 66cb93a386Sopenharmony_ci quad = GrQuad::MakeFromRect(rect, skew); 67cb93a386Sopenharmony_ci break; 68cb93a386Sopenharmony_ci default: 69cb93a386Sopenharmony_ci SkASSERT(types[i] == GrQuad::Type::kPerspective); 70cb93a386Sopenharmony_ci quad = GrQuad::MakeFromRect(rect, perspective); 71cb93a386Sopenharmony_ci break; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci SkASSERT(quad.quadType() == types[i]); 75cb93a386Sopenharmony_ci quads.push_back(quad); 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci return quads; 78cb93a386Sopenharmony_ci} 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ciTEST(Append) { 81cb93a386Sopenharmony_ci // Generate test data, which includes all quad types out of enum-order and duplicates 82cb93a386Sopenharmony_ci static const int kQuadCount = 6; 83cb93a386Sopenharmony_ci static const GrQuad::Type kDeviceTypes[] = { 84cb93a386Sopenharmony_ci GrQuad::Type::kAxisAligned, GrQuad::Type::kRectilinear, GrQuad::Type::kGeneral, 85cb93a386Sopenharmony_ci GrQuad::Type::kPerspective, GrQuad::Type::kRectilinear, GrQuad::Type::kAxisAligned 86cb93a386Sopenharmony_ci }; 87cb93a386Sopenharmony_ci // Odd indexed quads will be ignored and not stored in the buffer 88cb93a386Sopenharmony_ci static const GrQuad::Type kLocalTypes[] = { 89cb93a386Sopenharmony_ci GrQuad::Type::kGeneral, GrQuad::Type::kGeneral, GrQuad::Type::kRectilinear, 90cb93a386Sopenharmony_ci GrQuad::Type::kRectilinear, GrQuad::Type::kAxisAligned, GrQuad::Type::kAxisAligned 91cb93a386Sopenharmony_ci }; 92cb93a386Sopenharmony_ci static_assert(SK_ARRAY_COUNT(kDeviceTypes) == kQuadCount, "device quad count"); 93cb93a386Sopenharmony_ci static_assert(SK_ARRAY_COUNT(kLocalTypes) == kQuadCount, "local quad count"); 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci std::vector<GrQuad> expectedDeviceQuads = generate_quads(1.f, kQuadCount, kDeviceTypes); 96cb93a386Sopenharmony_ci std::vector<GrQuad> expectedLocalQuads = generate_quads(2.f, kQuadCount, kLocalTypes); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci // Fill in the buffer with the device quads, and a local quad if the index is even 99cb93a386Sopenharmony_ci GrQuadBuffer<TestData> buffer; 100cb93a386Sopenharmony_ci for (int i = 0; i < kQuadCount; ++i) { 101cb93a386Sopenharmony_ci buffer.append(expectedDeviceQuads[i], // device quad 102cb93a386Sopenharmony_ci { 2 * i, 3.f * i }, // metadata 103cb93a386Sopenharmony_ci i % 2 == 0 ? &expectedLocalQuads[i] : nullptr); // optional local quad 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci // Confirm the state of the buffer 107cb93a386Sopenharmony_ci ASSERT(kQuadCount == buffer.count()); 108cb93a386Sopenharmony_ci ASSERT(GrQuad::Type::kPerspective == buffer.deviceQuadType()); 109cb93a386Sopenharmony_ci ASSERT(GrQuad::Type::kGeneral == buffer.localQuadType()); 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci int i = 0; 112cb93a386Sopenharmony_ci auto iter = buffer.iterator(); 113cb93a386Sopenharmony_ci while(iter.next()) { 114cb93a386Sopenharmony_ci // Each entry always has the device quad 115cb93a386Sopenharmony_ci assert_quad_eq(r, expectedDeviceQuads[i], *iter.deviceQuad()); 116cb93a386Sopenharmony_ci assert_metadata_eq(r, {2 * i, 3.f * i}, iter.metadata()); 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci if (i % 2 == 0) { 119cb93a386Sopenharmony_ci // Confirm local quads included on even entries 120cb93a386Sopenharmony_ci ASSERT(iter.isLocalValid()); 121cb93a386Sopenharmony_ci assert_quad_eq(r, expectedLocalQuads[i], *iter.localQuad()); 122cb93a386Sopenharmony_ci } else { 123cb93a386Sopenharmony_ci // Should not have locals 124cb93a386Sopenharmony_ci ASSERT(!iter.isLocalValid()); 125cb93a386Sopenharmony_ci ASSERT(!iter.localQuad()); 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci i++; 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i); 131cb93a386Sopenharmony_ci} 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ciTEST(Concat) { 134cb93a386Sopenharmony_ci static const int kQuadCount = 2; 135cb93a386Sopenharmony_ci static const GrQuad::Type kTypesA[] = { GrQuad::Type::kAxisAligned, GrQuad::Type::kRectilinear }; 136cb93a386Sopenharmony_ci static const GrQuad::Type kTypesB[] = { GrQuad::Type::kGeneral, GrQuad::Type::kPerspective }; 137cb93a386Sopenharmony_ci static_assert(SK_ARRAY_COUNT(kTypesA) == kQuadCount, "quadsA count"); 138cb93a386Sopenharmony_ci static_assert(SK_ARRAY_COUNT(kTypesB) == kQuadCount, "quadsB count"); 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci std::vector<GrQuad> quadsA = generate_quads(1.f, kQuadCount, kTypesA); 141cb93a386Sopenharmony_ci std::vector<GrQuad> quadsB = generate_quads(2.f, kQuadCount, kTypesB); 142cb93a386Sopenharmony_ci // Make two buffers, the first uses 'quadsA' for device quads and 'quadsB' for local quads 143cb93a386Sopenharmony_ci // on even indices. The second uses 'quadsB' for device quads and 'quadsA' for local quads 144cb93a386Sopenharmony_ci // on odd indices. 145cb93a386Sopenharmony_ci GrQuadBuffer<TestData> buffer1; 146cb93a386Sopenharmony_ci GrQuadBuffer<TestData> buffer2; 147cb93a386Sopenharmony_ci for (int i = 0; i < kQuadCount; ++i) { 148cb93a386Sopenharmony_ci buffer1.append(quadsA[i], {i, 2.f * i}, i % 2 == 0 ? &quadsB[i] : nullptr); 149cb93a386Sopenharmony_ci buffer2.append(quadsB[i], {2 * i, 0.5f * i}, i % 2 == 0 ? nullptr : &quadsA[i]); 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci ASSERT(kQuadCount == buffer1.count()); 153cb93a386Sopenharmony_ci ASSERT(kQuadCount == buffer2.count()); 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci // Perform the concatenation and then confirm the new state of buffer1 156cb93a386Sopenharmony_ci buffer1.concat(buffer2); 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci ASSERT(2 * kQuadCount == buffer1.count()); 159cb93a386Sopenharmony_ci int i = 0; 160cb93a386Sopenharmony_ci auto iter = buffer1.iterator(); 161cb93a386Sopenharmony_ci while(iter.next()) { 162cb93a386Sopenharmony_ci if (i < kQuadCount) { 163cb93a386Sopenharmony_ci // First half should match original buffer1 164cb93a386Sopenharmony_ci assert_quad_eq(r, quadsA[i], *iter.deviceQuad()); 165cb93a386Sopenharmony_ci assert_metadata_eq(r, {i, 2.f * i}, iter.metadata()); 166cb93a386Sopenharmony_ci if (i % 2 == 0) { 167cb93a386Sopenharmony_ci ASSERT(iter.isLocalValid()); 168cb93a386Sopenharmony_ci assert_quad_eq(r, quadsB[i], *iter.localQuad()); 169cb93a386Sopenharmony_ci } else { 170cb93a386Sopenharmony_ci ASSERT(!iter.isLocalValid()); 171cb93a386Sopenharmony_ci ASSERT(!iter.localQuad()); 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci } else { 175cb93a386Sopenharmony_ci // Second half should match buffer2 176cb93a386Sopenharmony_ci int j = i - kQuadCount; 177cb93a386Sopenharmony_ci assert_quad_eq(r, quadsB[j], *iter.deviceQuad()); 178cb93a386Sopenharmony_ci assert_metadata_eq(r, {2 * j, 0.5f * j}, iter.metadata()); 179cb93a386Sopenharmony_ci if (j % 2 == 0) { 180cb93a386Sopenharmony_ci ASSERT(!iter.isLocalValid()); 181cb93a386Sopenharmony_ci ASSERT(!iter.localQuad()); 182cb93a386Sopenharmony_ci } else { 183cb93a386Sopenharmony_ci ASSERT(iter.isLocalValid()); 184cb93a386Sopenharmony_ci assert_quad_eq(r, quadsA[j], *iter.localQuad()); 185cb93a386Sopenharmony_ci } 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci i++; 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci ASSERTF(i == 2 * kQuadCount, "Expected %d iterations, got: %d",2 * kQuadCount, i); 191cb93a386Sopenharmony_ci} 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ciTEST(Metadata) { 194cb93a386Sopenharmony_ci static const int kQuadCount = 3; 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_ci // This test doesn't really care about the quad coordinates (except that they aren't modified 197cb93a386Sopenharmony_ci // when mutating the metadata) 198cb93a386Sopenharmony_ci GrQuad quad(SkRect::MakeLTRB(1.f, 2.f, 3.f, 4.f)); 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_ci GrQuadBuffer<TestData> buffer; 201cb93a386Sopenharmony_ci for (int i = 0; i < kQuadCount; ++i) { 202cb93a386Sopenharmony_ci buffer.append(quad, {i, 2.f * i}, i % 2 == 0 ? &quad : nullptr); 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ci // Iterate once using the metadata iterator, confirm the test data and rewrite 206cb93a386Sopenharmony_ci int i = 0; 207cb93a386Sopenharmony_ci auto meta = buffer.metadata(); 208cb93a386Sopenharmony_ci while(meta.next()) { 209cb93a386Sopenharmony_ci // Confirm initial state 210cb93a386Sopenharmony_ci assert_metadata_eq(r, {i, 2.f * i}, *meta); 211cb93a386Sopenharmony_ci // Rewrite 212cb93a386Sopenharmony_ci *meta = {2 * i, 0.5f * i}; 213cb93a386Sopenharmony_ci i++; 214cb93a386Sopenharmony_ci } 215cb93a386Sopenharmony_ci ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i); 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci // Now that all metadata has been touched, read with regular iterator and confirm updated state 218cb93a386Sopenharmony_ci // and that no quad coordinates have been changed. 219cb93a386Sopenharmony_ci i = 0; 220cb93a386Sopenharmony_ci auto iter = buffer.iterator(); 221cb93a386Sopenharmony_ci while(iter.next()) { 222cb93a386Sopenharmony_ci // New metadata 223cb93a386Sopenharmony_ci assert_metadata_eq(r, {2 * i, 0.5f * i}, iter.metadata()); 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ci // Quad coordinates are unchanged 226cb93a386Sopenharmony_ci assert_quad_eq(r, quad, *iter.deviceQuad()); 227cb93a386Sopenharmony_ci if (i % 2 == 0) { 228cb93a386Sopenharmony_ci ASSERT(iter.isLocalValid()); 229cb93a386Sopenharmony_ci assert_quad_eq(r, quad, *iter.localQuad()); 230cb93a386Sopenharmony_ci } else { 231cb93a386Sopenharmony_ci ASSERT(!iter.isLocalValid()); 232cb93a386Sopenharmony_ci ASSERT(!iter.localQuad()); 233cb93a386Sopenharmony_ci } 234cb93a386Sopenharmony_ci i++; 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i); 237cb93a386Sopenharmony_ci} 238