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