GrQuadBufferTest.cpp 8.8 KB

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