xref: /aosp_15_r20/external/skia/tests/VerticesTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2017 Google Inc.
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 
8 #include "include/core/SkBlendMode.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkSurface.h"
16 #include "include/core/SkVertices.h"
17 #include "src/base/SkAutoMalloc.h"
18 #include "src/core/SkReadBuffer.h"
19 #include "src/core/SkVerticesPriv.h"
20 #include "src/core/SkWriteBuffer.h"
21 #include "tests/Test.h"
22 #include "tools/ToolUtils.h"
23 
24 #include <cstdint>
25 
equal(const SkVertices * vert0,const SkVertices * vert1)26 static bool equal(const SkVertices* vert0, const SkVertices* vert1) {
27     SkVerticesPriv v0(vert0->priv()), v1(vert1->priv());
28 
29     if (v0.mode() != v1.mode()) {
30         return false;
31     }
32     if (v0.vertexCount() != v1.vertexCount()) {
33         return false;
34     }
35     if (v0.indexCount() != v1.indexCount()) {
36         return false;
37     }
38 
39     if (!!v0.texCoords() != !!v1.texCoords()) {
40         return false;
41     }
42     if (!!v0.colors() != !!v1.colors()) {
43         return false;
44     }
45 
46     for (int i = 0; i < v0.vertexCount(); ++i) {
47         if (v0.positions()[i] != v1.positions()[i]) {
48             return false;
49         }
50         if (v0.texCoords()) {
51             if (v0.texCoords()[i] != v1.texCoords()[i]) {
52                 return false;
53             }
54         }
55         if (v0.colors()) {
56             if (v0.colors()[i] != v1.colors()[i]) {
57                 return false;
58             }
59         }
60     }
61     for (int i = 0; i < v0.indexCount(); ++i) {
62         if (v0.indices()[i] != v1.indices()[i]) {
63             return false;
64         }
65     }
66     return true;
67 }
68 
self_test(const sk_sp<SkVertices> & v0,skiatest::Reporter * reporter)69 static void self_test(const sk_sp<SkVertices>& v0, skiatest::Reporter* reporter) {
70     SkBinaryWriteBuffer writer({});
71     v0->priv().encode(writer);
72 
73     SkAutoMalloc buf(writer.bytesWritten());
74     writer.writeToMemory(buf.get());
75     SkReadBuffer reader(buf.get(), writer.bytesWritten());
76 
77     sk_sp<SkVertices> v1 = SkVerticesPriv::Decode(reader);
78 
79     REPORTER_ASSERT(reporter, v1 != nullptr);
80     REPORTER_ASSERT(reporter, v0->uniqueID() != 0);
81     REPORTER_ASSERT(reporter, v1->uniqueID() != 0);
82     REPORTER_ASSERT(reporter, v0->uniqueID() != v1->uniqueID());
83     REPORTER_ASSERT(reporter, equal(v0.get(), v1.get()));
84 }
85 
DEF_TEST(Vertices,reporter)86 DEF_TEST(Vertices, reporter) {
87     int vCount = 5;
88     int iCount = 9; // odd value exercises padding logic in encode()
89 
90     // color-tex tests
91     const uint32_t texFlags[] = { 0, SkVertices::kHasTexCoords_BuilderFlag };
92     const uint32_t colFlags[] = { 0, SkVertices::kHasColors_BuilderFlag };
93     for (auto texF : texFlags) {
94         for (auto colF : colFlags) {
95             uint32_t flags = texF | colF;
96 
97             SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, vCount, iCount, flags);
98 
99             for (int i = 0; i < vCount; ++i) {
100                 float x = (float)i;
101                 builder.positions()[i].set(x, 1);
102                 if (builder.texCoords()) {
103                     builder.texCoords()[i].set(x, 2);
104                 }
105                 if (builder.colors()) {
106                     builder.colors()[i] = SkColorSetARGB(0xFF, i, 0x80, 0);
107                 }
108             }
109             for (int i = 0; i < iCount; ++i) {
110                 builder.indices()[i] = i % vCount;
111             }
112             self_test(builder.detach(), reporter);
113         }
114     }
115 
116     {
117         // This has the maximum number of vertices to be rewritten as indexed triangles without
118         // overflowing a 16bit index.
119         SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, UINT16_MAX + 1, 0,
120                                     SkVertices::kHasColors_BuilderFlag);
121         REPORTER_ASSERT(reporter, builder.isValid());
122     }
123     {
124         // This has too many to be rewritten.
125         SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, UINT16_MAX + 2, 0,
126                                     SkVertices::kHasColors_BuilderFlag);
127         REPORTER_ASSERT(reporter, !builder.isValid());
128     }
129     {
130         // Only two vertices - can't be rewritten.
131         SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, 2, 0,
132                                     SkVertices::kHasColors_BuilderFlag);
133         REPORTER_ASSERT(reporter, !builder.isValid());
134     }
135     {
136         // Minimum number of indices to be rewritten.
137         SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, 10, 3,
138                                     SkVertices::kHasColors_BuilderFlag);
139         REPORTER_ASSERT(reporter, builder.isValid());
140     }
141     {
142         // Too few indices to be rewritten.
143         SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, 10, 2,
144                                     SkVertices::kHasColors_BuilderFlag);
145         REPORTER_ASSERT(reporter, !builder.isValid());
146     }
147 }
148 
fill_triangle(SkCanvas * canvas,const SkPoint pts[],SkColor c)149 static void fill_triangle(SkCanvas* canvas, const SkPoint pts[], SkColor c) {
150     SkColor colors[] = { c, c, c };
151     auto verts = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts, nullptr, colors);
152     canvas->drawVertices(verts, SkBlendMode::kSrc, SkPaint());
153 }
154 
DEF_TEST(Vertices_clipping,reporter)155 DEF_TEST(Vertices_clipping, reporter) {
156     // A very large triangle has to be geometrically clipped (since its "fast" clipping is
157     // normally done in after building SkFixed coordinates). Check that we handle this.
158     // (and don't assert).
159     auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(3, 3));
160 
161     SkPoint pts[] = { { -10, 1 }, { -10, 2 }, { 1e9f, 1.5f } };
162     fill_triangle(surf->getCanvas(), pts, SK_ColorBLACK);
163 
164     ToolUtils::PixelIter iter(surf.get());
165     SkIPoint loc;
166     while (void* addr = iter.next(&loc)) {
167         SkPMColor c = *(SkPMColor*)addr;
168         if (loc.fY == 1) {
169             REPORTER_ASSERT(reporter, c == 0xFF000000);
170         } else {
171             REPORTER_ASSERT(reporter, c == 0);
172         }
173     }
174 }
175