aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/VerticesTest.cpp
blob: b38a9de8bab86b4e0fe68930e224ac40034cedd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCanvas.h"
#include "SkSurface.h"
#include "SkVertices.h"
#include "sk_pixel_iter.h"
#include "Test.h"

static bool equal(const SkVertices* v0, const SkVertices* v1) {
    if (v0->mode() != v1->mode()) {
        return false;
    }
    if (v0->vertexCount() != v1->vertexCount()) {
        return false;
    }
    if (v0->indexCount() != v1->indexCount()) {
        return false;
    }

    if (!!v0->texCoords() != !!v1->texCoords()) {
        return false;
    }
    if (!!v0->colors() != !!v1->colors()) {
        return false;
    }

    for (int i = 0; i < v0->vertexCount(); ++i) {
        if (v0->positions()[i] != v1->positions()[i]) {
            return false;
        }
        if (v0->texCoords()) {
            if (v0->texCoords()[i] != v1->texCoords()[i]) {
                return false;
            }
        }
        if (v0->colors()) {
            if (v0->colors()[i] != v1->colors()[i]) {
                return false;
            }
        }
    }
    for (int i = 0; i < v0->indexCount(); ++i) {
        if (v0->indices()[i] != v1->indices()[i]) {
            return false;
        }
    }
    return true;
}

DEF_TEST(Vertices, reporter) {
    int vCount = 5;
    int iCount = 9; // odd value exercises padding logic in encode()

    const uint32_t texFlags[] = { 0, SkVertices::kHasTexCoords_BuilderFlag };
    const uint32_t colFlags[] = { 0, SkVertices::kHasColors_BuilderFlag };
    for (auto texF : texFlags) {
        for (auto colF : colFlags) {
            uint32_t flags = texF | colF;

            SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, vCount, iCount, flags);

            for (int i = 0; i < vCount; ++i) {
                float x = (float)i;
                builder.positions()[i].set(x, 1);
                if (builder.texCoords()) {
                    builder.texCoords()[i].set(x, 2);
                }
                if (builder.colors()) {
                    builder.colors()[i] = SkColorSetARGB(0xFF, i, 0x80, 0);
                }
            }
            for (int i = 0; i < builder.indexCount(); ++i) {
                builder.indices()[i] = i % vCount;
            }

            sk_sp<SkVertices> v0 = builder.detach();
            sk_sp<SkData> data = v0->encode();
            sk_sp<SkVertices> v1 = SkVertices::Decode(data->data(), data->size());

            REPORTER_ASSERT(reporter, v0->uniqueID() != 0);
            REPORTER_ASSERT(reporter, v1->uniqueID() != 0);
            REPORTER_ASSERT(reporter, v0->uniqueID() != v1->uniqueID());
            REPORTER_ASSERT(reporter, equal(v0.get(), v1.get()));
        }
    }
    {
        // This has the maximum number of vertices to be rewritten as indexed triangles without
        // overflowing a 16bit index.
        SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, UINT16_MAX + 1, 0,
                                    SkVertices::kHasColors_BuilderFlag);
        REPORTER_ASSERT(reporter, builder.isValid());
    }
    {
        // This has too many to be rewritten.
        SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, UINT16_MAX + 2, 0,
                                    SkVertices::kHasColors_BuilderFlag);
        REPORTER_ASSERT(reporter, !builder.isValid());
    }
    {
        // Only two vertices - can't be rewritten.
        SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, 2, 0,
                                    SkVertices::kHasColors_BuilderFlag);
        REPORTER_ASSERT(reporter, !builder.isValid());
    }
    {
        // Minimum number of indices to be rewritten.
        SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, 10, 3,
                                    SkVertices::kHasColors_BuilderFlag);
        REPORTER_ASSERT(reporter, builder.isValid());
    }
    {
        // Too few indices to be rewritten.
        SkVertices::Builder builder(SkVertices::kTriangleFan_VertexMode, 10, 2,
                                    SkVertices::kHasColors_BuilderFlag);
        REPORTER_ASSERT(reporter, !builder.isValid());
    }
}

static void fill_triangle(SkCanvas* canvas, const SkPoint pts[], SkColor c) {
    SkColor colors[] = { c, c, c };
    auto verts = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts, nullptr, colors);
    canvas->drawVertices(verts, SkBlendMode::kSrc, SkPaint());
}

DEF_TEST(Vertices_clipping, reporter) {
    // A very large triangle has to be geometrically clipped (since its "fast" clipping is
    // normally done in after building SkFixed coordinates). Check that we handle this.
    // (and don't assert).
    auto surf = SkSurface::MakeRasterN32Premul(3, 3);

    SkPoint pts[] = { { -10, 1 }, { -10, 2 }, { 1e9f, 1.5f } };
    fill_triangle(surf->getCanvas(), pts, SK_ColorBLACK);

    sk_tool_utils::PixelIter iter(surf.get());
    SkIPoint loc;
    while (void* addr = iter.next(&loc)) {
        SkPMColor c = *(SkPMColor*)addr;
        if (loc.fY == 1) {
            REPORTER_ASSERT(reporter, c == 0xFF000000);
        } else {
            REPORTER_ASSERT(reporter, c == 0);
        }
    }
}