• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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/gm.h"
9 #include "include/core/SkBlendMode.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkSize.h"
16 #include "include/core/SkString.h"
17 #include "include/core/SkVertices.h"
18 
19 #include <stdint.h>
20 
21 using namespace skiagm;
22 
23 static const int kCellSize = 60;
24 static const int kColumnSize = 36;
25 
26 static const int kBoneCount = 7;
27 static const SkVertices::Bone kBones[] = {
28     {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},   // SkMatrix::I()
29     {{ 1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 0.0f }},  // SkMatrix::MakeTrans(10, 0)
30     {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 10.0f }},  // SkMatrix::MakeTrans(0, 10)
31     {{ 1.0f, 0.0f, 0.0f, 1.0f, -10.0f, 0.0f }}, // SkMatrix::MakeTrans(-10, 0)
32     {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -10.0f }}, // SkMatrix::MakeTrans(0, -10)
33     {{ 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f }},   // SkMatrix::MakeScale(0.5)
34     {{ 1.5f, 0.0f, 0.0f, 1.5f, 0.0f, 0.0f }},   // SkMatrix::MakeScale(1.5)
35 };
36 
37 static const int kVertexCount = 4;
38 static const SkPoint kPositions[] = {
39     { 0, 0 },
40     { 0, 30 },
41     { 30, 30 },
42     { 30, 0 },
43 };
44 static const SkColor kColors[] = {
45     0xFFFF0000,
46     0xFF00FF00,
47     0xFF0000FF,
48     0xFFFFFF00,
49 };
50 static const SkVertices::BoneIndices kBoneIndices[] = {
51     {{ 1, 0, 0, 0 }},
52     {{ 2, 1, 0, 0 }},
53     {{ 3, 2, 1, 0 }},
54     {{ 4, 3, 2, 1 }},
55 };
56 static const SkVertices::BoneWeights kBoneWeights[] = {
57     {{ 1.0f,  0.0f,  0.0f,  0.0f  }},
58     {{ 0.5f,  0.5f,  0.0f,  0.0f  }},
59     {{ 0.34f, 0.33f, 0.33f, 0.0f  }},
60     {{ 0.25f, 0.25f, 0.25f, 0.25f }},
61 };
62 
63 static const int kIndexCount = 6;
64 static const uint16_t kIndices[] = {
65     0, 1, 2,
66     2, 3, 0,
67 };
68 
69 // Swap two SkVertices::Bone pointers in place.
swap(const SkVertices::Bone ** x,const SkVertices::Bone ** y)70 static void swap(const SkVertices::Bone** x, const SkVertices::Bone** y) {
71     const SkVertices::Bone* temp = *x;
72     *x = *y;
73     *y = temp;
74 }
75 
76 class SkinningGM : public GM {
77 
78 public:
SkinningGM(bool deformUsingCPU,bool cache)79     SkinningGM(bool deformUsingCPU, bool cache)
80             : fPaint()
81             , fVertices(nullptr)
82             , fDeformUsingCPU(deformUsingCPU)
83             , fCache(cache)
84     {}
85 
86 protected:
runAsBench() const87     bool runAsBench() const override {
88         return true;
89     }
90 
onShortName()91     SkString onShortName() override {
92         SkString name("skinning");
93         if (fDeformUsingCPU) {
94             name.append("_cpu");
95         }
96         if (fCache) {
97             name.append("_cached");
98         }
99         return name;
100     }
101 
onISize()102     SkISize onISize() override {
103         return SkISize::Make(2400, 2400);
104     }
105 
onOnceBeforeDraw()106     void onOnceBeforeDraw() override {
107         fVertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
108                                          kVertexCount,
109                                          kPositions,
110                                          nullptr,
111                                          kColors,
112                                          kBoneIndices,
113                                          kBoneWeights,
114                                          kIndexCount,
115                                          kIndices,
116                                          !fCache);
117     }
118 
onDraw(SkCanvas * canvas)119     void onDraw(SkCanvas* canvas) override {
120         // Set the initial position.
121         int xpos = kCellSize;
122         int ypos = kCellSize;
123 
124         // Create the mutable set of bones.
125         const SkVertices::Bone* bones[kBoneCount];
126         for (int i = 0; i < kBoneCount; i ++) {
127             bones[i] = &kBones[i];
128         }
129 
130         // Draw the vertices.
131         drawPermutations(canvas, xpos, ypos, bones, 1);
132     }
133 
134 private:
drawPermutations(SkCanvas * canvas,int & xpos,int & ypos,const SkVertices::Bone ** bones,int start)135     void drawPermutations(SkCanvas* canvas,
136                           int& xpos,
137                           int& ypos,
138                           const SkVertices::Bone** bones,
139                           int start) {
140         if (start == kBoneCount) {
141             // Reached the end of the permutations, so draw.
142             canvas->save();
143 
144             // Copy the bones.
145             SkVertices::Bone copiedBones[kBoneCount];
146             for (int i = 0; i < kBoneCount; i ++) {
147                 copiedBones[i] = *bones[i];
148             }
149 
150             // Set the position.
151             canvas->translate(xpos, ypos);
152 
153             // Draw the vertices.
154             if (fDeformUsingCPU) {
155                 // Apply the bones.
156                 sk_sp<SkVertices> vertices = fVertices->applyBones(copiedBones,
157                                                                    kBoneCount);
158 
159                 // Deform with CPU.
160                 canvas->drawVertices(vertices.get(),
161                                      SkBlendMode::kSrc,
162                                      fPaint);
163             } else {
164                 // Deform with GPU.
165                 canvas->drawVertices(fVertices.get(),
166                                      copiedBones,
167                                      kBoneCount,
168                                      SkBlendMode::kSrc,
169                                      fPaint);
170             }
171 
172             canvas->restore();
173 
174             // Get a new position to draw the vertices.
175             xpos += kCellSize;
176             if (xpos > kCellSize * kColumnSize) {
177                 xpos = kCellSize;
178                 ypos += kCellSize;
179             }
180 
181             return;
182         }
183 
184         // Find all possible permutations within the given range.
185         for (int i = start; i < kBoneCount; i ++) {
186             // Swap the start and i-th elements.
187             swap(bones + start, bones + i);
188 
189             // Find permutations of the sub array.
190             drawPermutations(canvas, xpos, ypos, bones, start + 1);
191 
192             // Swap the elements back.
193             swap(bones + i, bones + start);
194         }
195     }
196 
197 private:
198     SkPaint fPaint;
199     sk_sp<SkVertices> fVertices;
200     bool fDeformUsingCPU;
201     bool fCache;
202 
203     typedef GM INHERITED;
204 };
205 
206 /////////////////////////////////////////////////////////////////////////////////////
207 
208 DEF_GM(return new SkinningGM(true, true);)
209 DEF_GM(return new SkinningGM(false, true);)
210 DEF_GM(return new SkinningGM(true, false);)
211 DEF_GM(return new SkinningGM(false, false);)
212