blob: a3eb71ba6d50780517d4d3e7d8c92b53a8c2ea85 [file] [log] [blame]
Ruiqi Maob609e6d2018-07-17 10:19:38 -04001/*
2 * Copyright 2018 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 "gm.h"
9#include "SkCanvas.h"
10#include "SkVertices.h"
11#include "SkPoint.h"
Hal Canary8a001442018-09-19 11:31:27 -040012
Ruiqi Maob609e6d2018-07-17 10:19:38 -040013#include <iostream>
14#include <vector>
15
16using namespace skiagm;
17
18static const int kCellSize = 60;
19static const int kColumnSize = 36;
20
21static const int kBoneCount = 7;
Ruiqi Maoc97a3392018-08-15 10:44:19 -040022static const SkVertices::Bone kBones[] = {
23 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }}, // SkMatrix::I()
24 {{ 1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 0.0f }}, // SkMatrix::MakeTrans(10, 0)
25 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 10.0f }}, // SkMatrix::MakeTrans(0, 10)
26 {{ 1.0f, 0.0f, 0.0f, 1.0f, -10.0f, 0.0f }}, // SkMatrix::MakeTrans(-10, 0)
27 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -10.0f }}, // SkMatrix::MakeTrans(0, -10)
28 {{ 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f }}, // SkMatrix::MakeScale(0.5)
29 {{ 1.5f, 0.0f, 0.0f, 1.5f, 0.0f, 0.0f }}, // SkMatrix::MakeScale(1.5)
Ruiqi Maob609e6d2018-07-17 10:19:38 -040030};
31
32static const int kVertexCount = 4;
33static const SkPoint kPositions[] = {
34 { 0, 0 },
35 { 0, 30 },
36 { 30, 30 },
37 { 30, 0 },
38};
39static const SkColor kColors[] = {
40 0xFFFF0000,
41 0xFF00FF00,
42 0xFF0000FF,
43 0xFFFFFF00,
44};
45static const SkVertices::BoneIndices kBoneIndices[] = {
46 {{ 1, 0, 0, 0 }},
47 {{ 2, 1, 0, 0 }},
48 {{ 3, 2, 1, 0 }},
49 {{ 4, 3, 2, 1 }},
50};
51static const SkVertices::BoneWeights kBoneWeights[] = {
52 {{ 1.0f, 0.0f, 0.0f, 0.0f }},
53 {{ 0.5f, 0.5f, 0.0f, 0.0f }},
54 {{ 0.34f, 0.33f, 0.33f, 0.0f }},
55 {{ 0.25f, 0.25f, 0.25f, 0.25f }},
56};
57
58static const int kIndexCount = 6;
59static const uint16_t kIndices[] = {
60 0, 1, 2,
61 2, 3, 0,
62};
63
Ruiqi Maoc97a3392018-08-15 10:44:19 -040064// Swap two SkVertices::Bone pointers in place.
65static void swap(const SkVertices::Bone** x, const SkVertices::Bone** y) {
66 const SkVertices::Bone* temp = *x;
Ruiqi Maob609e6d2018-07-17 10:19:38 -040067 *x = *y;
68 *y = temp;
69}
70
71class SkinningGM : public GM {
72
73public:
Ruiqi Mao363402d2018-07-18 10:53:44 -040074 SkinningGM(bool deformUsingCPU, bool cache)
Ruiqi Maob609e6d2018-07-17 10:19:38 -040075 : fPaint()
76 , fVertices(nullptr)
77 , fDeformUsingCPU(deformUsingCPU)
Ruiqi Mao363402d2018-07-18 10:53:44 -040078 , fCache(cache)
Ruiqi Maob609e6d2018-07-17 10:19:38 -040079 {}
80
81protected:
82 bool runAsBench() const override {
83 return true;
84 }
85
86 SkString onShortName() override {
87 SkString name("skinning");
88 if (fDeformUsingCPU) {
89 name.append("_cpu");
90 }
Ruiqi Mao363402d2018-07-18 10:53:44 -040091 if (fCache) {
92 name.append("_cached");
93 }
Ruiqi Maob609e6d2018-07-17 10:19:38 -040094 return name;
95 }
96
97 SkISize onISize() override {
98 return SkISize::Make(2400, 2400);
99 }
100
101 void onOnceBeforeDraw() override {
102 fVertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
103 kVertexCount,
104 kPositions,
105 nullptr,
106 kColors,
107 kBoneIndices,
108 kBoneWeights,
109 kIndexCount,
110 kIndices,
Ruiqi Mao363402d2018-07-18 10:53:44 -0400111 !fCache);
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400112 }
113
114 void onDraw(SkCanvas* canvas) override {
115 // Set the initial position.
116 int xpos = kCellSize;
117 int ypos = kCellSize;
118
119 // Create the mutable set of bones.
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400120 const SkVertices::Bone* bones[kBoneCount];
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400121 for (int i = 0; i < kBoneCount; i ++) {
122 bones[i] = &kBones[i];
123 }
124
125 // Draw the vertices.
126 drawPermutations(canvas, xpos, ypos, bones, 1);
127 }
128
129private:
130 void drawPermutations(SkCanvas* canvas,
131 int& xpos,
132 int& ypos,
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400133 const SkVertices::Bone** bones,
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400134 int start) {
135 if (start == kBoneCount) {
136 // Reached the end of the permutations, so draw.
137 canvas->save();
138
139 // Copy the bones.
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400140 SkVertices::Bone copiedBones[kBoneCount];
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400141 for (int i = 0; i < kBoneCount; i ++) {
142 copiedBones[i] = *bones[i];
143 }
144
145 // Set the position.
146 canvas->translate(xpos, ypos);
147
148 // Draw the vertices.
149 if (fDeformUsingCPU) {
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400150 // Apply the bones.
151 sk_sp<SkVertices> vertices = fVertices->applyBones(copiedBones,
152 kBoneCount);
153
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400154 // Deform with CPU.
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400155 canvas->drawVertices(vertices.get(),
156 SkBlendMode::kSrc,
157 fPaint);
158 } else {
159 // Deform with GPU.
160 canvas->drawVertices(fVertices.get(),
161 copiedBones,
162 kBoneCount,
163 SkBlendMode::kSrc,
164 fPaint);
165 }
166
167 canvas->restore();
168
169 // Get a new position to draw the vertices.
170 xpos += kCellSize;
171 if (xpos > kCellSize * kColumnSize) {
172 xpos = kCellSize;
173 ypos += kCellSize;
174 }
175
176 return;
177 }
178
179 // Find all possible permutations within the given range.
180 for (int i = start; i < kBoneCount; i ++) {
181 // Swap the start and i-th elements.
182 swap(bones + start, bones + i);
183
184 // Find permutations of the sub array.
185 drawPermutations(canvas, xpos, ypos, bones, start + 1);
186
187 // Swap the elements back.
188 swap(bones + i, bones + start);
189 }
190 }
191
192private:
193 SkPaint fPaint;
194 sk_sp<SkVertices> fVertices;
195 bool fDeformUsingCPU;
Ruiqi Mao363402d2018-07-18 10:53:44 -0400196 bool fCache;
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400197
198 typedef GM INHERITED;
199};
200
201/////////////////////////////////////////////////////////////////////////////////////
202
Ruiqi Mao363402d2018-07-18 10:53:44 -0400203DEF_GM(return new SkinningGM(true, true);)
204DEF_GM(return new SkinningGM(false, true);)
205DEF_GM(return new SkinningGM(true, false);)
206DEF_GM(return new SkinningGM(false, false);)