Flutter Engine
The Flutter Engine
GrQuadBufferTest.cpp
Go to the documentation of this file.
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
13#include "tests/Test.h"
14
15#include <utility>
16#include <vector>
17
18#define ASSERT(cond) REPORTER_ASSERT(r, cond)
19#define ASSERTF(cond, ...) REPORTER_ASSERT(r, cond, __VA_ARGS__)
20#define TEST(name) DEF_TEST(GrQuadBuffer##name, r)
21
22struct TestData {
23 int fItem1;
24 float fItem2;
25};
26
27static void assert_quad_eq(skiatest::Reporter* r, const GrQuad& expected, const GrQuad& actual) {
28 ASSERTF(expected.quadType() == actual.quadType(), "Expected type %d, got %d",
29 (int) expected.quadType(), (int) actual.quadType());
30 for (int i = 0; i < 4; ++i) {
31 ASSERTF(expected.x(i) == actual.x(i), "Expected x(%d) = %f, got %f",
32 i, expected.x(i), actual.x(i));
33 ASSERTF(expected.y(i) == actual.y(i), "Expected y(%d) = %f, got %f",
34 i, expected.y(i), actual.y(i));
35 ASSERTF(expected.w(i) == actual.w(i), "Expected w(%d) = %f, got %f",
36 i, expected.w(i), actual.w(i));
37 }
38}
39
40static void assert_metadata_eq(skiatest::Reporter* r, const TestData& expected,
41 const TestData& actual) {
42 ASSERTF(expected.fItem1 == actual.fItem1 && expected.fItem2 == actual.fItem2,
43 "Expected { %d, %f } for metadata, got: { %d %f }",
44 expected.fItem1, expected.fItem2, actual.fItem1, actual.fItem2);
45}
46
47static std::vector<GrQuad> generate_quads(float seed, int cnt, const GrQuad::Type types[]) {
48 // For convenience use matrix to derive each quad type, rely on different seed values to
49 // differentiate between quads of the same type
51 rotate.setRotate(45.f);
52 SkMatrix skew;
53 skew.setSkew(0.5f, 0.5f);
54 SkMatrix perspective;
55 perspective.setPerspX(0.01f);
56 perspective.setPerspY(0.001f);
57
58 std::vector<GrQuad> quads;
59 SkRect rect = SkRect::MakeXYWH(seed, 2.f * seed, 2.f * seed, seed);
60 for (int i = 0; i < cnt; ++i) {
61 GrQuad quad;
62 switch(types[i]) {
64 quad = GrQuad(rect);
65 break;
68 break;
70 quad = GrQuad::MakeFromRect(rect, skew);
71 break;
72 default:
74 quad = GrQuad::MakeFromRect(rect, perspective);
75 break;
76 }
77
78 SkASSERT(quad.quadType() == types[i]);
79 quads.push_back(quad);
80 }
81 return quads;
82}
83
84TEST(Append) {
85 // Generate test data, which includes all quad types out of enum-order and duplicates
86 static const int kQuadCount = 6;
87 static const GrQuad::Type kDeviceTypes[] = {
90 };
91 // Odd indexed quads will be ignored and not stored in the buffer
92 static const GrQuad::Type kLocalTypes[] = {
95 };
96 static_assert(std::size(kDeviceTypes) == kQuadCount, "device quad count");
97 static_assert(std::size(kLocalTypes) == kQuadCount, "local quad count");
98
99 std::vector<GrQuad> expectedDeviceQuads = generate_quads(1.f, kQuadCount, kDeviceTypes);
100 std::vector<GrQuad> expectedLocalQuads = generate_quads(2.f, kQuadCount, kLocalTypes);
101
102 // Fill in the buffer with the device quads, and a local quad if the index is even
104 for (int i = 0; i < kQuadCount; ++i) {
105 buffer.append(expectedDeviceQuads[i], // device quad
106 { 2 * i, 3.f * i }, // metadata
107 i % 2 == 0 ? &expectedLocalQuads[i] : nullptr); // optional local quad
108 }
109
110 // Confirm the state of the buffer
111 ASSERT(kQuadCount == buffer.count());
112 ASSERT(GrQuad::Type::kPerspective == buffer.deviceQuadType());
113 ASSERT(GrQuad::Type::kGeneral == buffer.localQuadType());
114
115 int i = 0;
116 auto iter = buffer.iterator();
117 while(iter.next()) {
118 // Each entry always has the device quad
119 assert_quad_eq(r, expectedDeviceQuads[i], *iter.deviceQuad());
120 assert_metadata_eq(r, {2 * i, 3.f * i}, iter.metadata());
121
122 if (i % 2 == 0) {
123 // Confirm local quads included on even entries
124 ASSERT(iter.isLocalValid());
125 assert_quad_eq(r, expectedLocalQuads[i], *iter.localQuad());
126 } else {
127 // Should not have locals
128 ASSERT(!iter.isLocalValid());
129 ASSERT(!iter.localQuad());
130 }
131
132 i++;
133 }
134 ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i);
135}
136
138 static const int kQuadCount = 2;
141 static_assert(std::size(kTypesA) == kQuadCount, "quadsA count");
142 static_assert(std::size(kTypesB) == kQuadCount, "quadsB count");
143
144 std::vector<GrQuad> quadsA = generate_quads(1.f, kQuadCount, kTypesA);
145 std::vector<GrQuad> quadsB = generate_quads(2.f, kQuadCount, kTypesB);
146 // Make two buffers, the first uses 'quadsA' for device quads and 'quadsB' for local quads
147 // on even indices. The second uses 'quadsB' for device quads and 'quadsA' for local quads
148 // on odd indices.
151 for (int i = 0; i < kQuadCount; ++i) {
152 buffer1.append(quadsA[i], {i, 2.f * i}, i % 2 == 0 ? &quadsB[i] : nullptr);
153 buffer2.append(quadsB[i], {2 * i, 0.5f * i}, i % 2 == 0 ? nullptr : &quadsA[i]);
154 }
155
156 ASSERT(kQuadCount == buffer1.count());
157 ASSERT(kQuadCount == buffer2.count());
158
159 // Perform the concatenation and then confirm the new state of buffer1
160 buffer1.concat(buffer2);
161
162 ASSERT(2 * kQuadCount == buffer1.count());
163 int i = 0;
164 auto iter = buffer1.iterator();
165 while(iter.next()) {
166 if (i < kQuadCount) {
167 // First half should match original buffer1
168 assert_quad_eq(r, quadsA[i], *iter.deviceQuad());
169 assert_metadata_eq(r, {i, 2.f * i}, iter.metadata());
170 if (i % 2 == 0) {
171 ASSERT(iter.isLocalValid());
172 assert_quad_eq(r, quadsB[i], *iter.localQuad());
173 } else {
174 ASSERT(!iter.isLocalValid());
175 ASSERT(!iter.localQuad());
176 }
177
178 } else {
179 // Second half should match buffer2
180 int j = i - kQuadCount;
181 assert_quad_eq(r, quadsB[j], *iter.deviceQuad());
182 assert_metadata_eq(r, {2 * j, 0.5f * j}, iter.metadata());
183 if (j % 2 == 0) {
184 ASSERT(!iter.isLocalValid());
185 ASSERT(!iter.localQuad());
186 } else {
187 ASSERT(iter.isLocalValid());
188 assert_quad_eq(r, quadsA[j], *iter.localQuad());
189 }
190 }
191
192 i++;
193 }
194 ASSERTF(i == 2 * kQuadCount, "Expected %d iterations, got: %d",2 * kQuadCount, i);
195}
196
197TEST(Metadata) {
198 static const int kQuadCount = 3;
199
200 // This test doesn't really care about the quad coordinates (except that they aren't modified
201 // when mutating the metadata)
202 GrQuad quad(SkRect::MakeLTRB(1.f, 2.f, 3.f, 4.f));
203
205 for (int i = 0; i < kQuadCount; ++i) {
206 buffer.append(quad, {i, 2.f * i}, i % 2 == 0 ? &quad : nullptr);
207 }
208
209 // Iterate once using the metadata iterator, confirm the test data and rewrite
210 int i = 0;
211 auto meta = buffer.metadata();
212 while(meta.next()) {
213 // Confirm initial state
214 assert_metadata_eq(r, {i, 2.f * i}, *meta);
215 // Rewrite
216 *meta = {2 * i, 0.5f * i};
217 i++;
218 }
219 ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i);
220
221 // Now that all metadata has been touched, read with regular iterator and confirm updated state
222 // and that no quad coordinates have been changed.
223 i = 0;
224 auto iter = buffer.iterator();
225 while(iter.next()) {
226 // New metadata
227 assert_metadata_eq(r, {2 * i, 0.5f * i}, iter.metadata());
228
229 // Quad coordinates are unchanged
230 assert_quad_eq(r, quad, *iter.deviceQuad());
231 if (i % 2 == 0) {
232 ASSERT(iter.isLocalValid());
233 assert_quad_eq(r, quad, *iter.localQuad());
234 } else {
235 ASSERT(!iter.isLocalValid());
236 ASSERT(!iter.localQuad());
237 }
238 i++;
239 }
240 ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i);
241}
#define ASSERT(cond)
#define ASSERTF(cond,...)
static void assert_quad_eq(skiatest::Reporter *r, const GrQuad &expected, const GrQuad &actual)
#define TEST(name)
static std::vector< GrQuad > generate_quads(float seed, int cnt, const GrQuad::Type types[])
static void assert_metadata_eq(skiatest::Reporter *r, const TestData &expected, const TestData &actual)
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool rotate(const SkDCubic &cubic, int zero, int index, SkDCubic &rotPath)
void append(const GrQuad &deviceQuad, T &&metadata, const GrQuad *localQuad=nullptr)
Definition: GrQuadBuffer.h:271
Iter iterator() const
Definition: GrQuadBuffer.h:116
int count() const
Definition: GrQuadBuffer.h:44
void concat(const GrQuadBuffer< T > &that)
Definition: GrQuadBuffer.h:308
Definition: GrQuad.h:30
float y(int i) const
Definition: GrQuad.h:109
Type quadType() const
Definition: GrQuad.h:118
static GrQuad MakeFromRect(const SkRect &, const SkMatrix &)
Definition: GrQuad.cpp:107
float w(int i) const
Definition: GrQuad.h:110
float x(int i) const
Definition: GrQuad.h:108
Type
Definition: GrQuad.h:35
SkMatrix & setPerspX(SkScalar v)
Definition: SkMatrix.h:537
SkMatrix & setPerspY(SkScalar v)
Definition: SkMatrix.h:544
SkMatrix & setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:488
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
static const char * Concat(const char *a, const char *b)
Definition: file_test.cc:86
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646