Home | History | Annotate | Download | only in gm
      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.h"
      9 #include "SkCanvas.h"
     10 #include "SkVertices.h"
     11 #include "SkPoint.h"
     12 
     13 #include <iostream>
     14 #include <vector>
     15 
     16 using namespace skiagm;
     17 
     18 static const int kCellSize = 60;
     19 static const int kColumnSize = 36;
     20 
     21 static const int kBoneCount = 7;
     22 static 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)
     30 };
     31 
     32 static const int kVertexCount = 4;
     33 static const SkPoint kPositions[] = {
     34     { 0, 0 },
     35     { 0, 30 },
     36     { 30, 30 },
     37     { 30, 0 },
     38 };
     39 static const SkColor kColors[] = {
     40     0xFFFF0000,
     41     0xFF00FF00,
     42     0xFF0000FF,
     43     0xFFFFFF00,
     44 };
     45 static 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 };
     51 static 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 
     58 static const int kIndexCount = 6;
     59 static const uint16_t kIndices[] = {
     60     0, 1, 2,
     61     2, 3, 0,
     62 };
     63 
     64 // Swap two SkVertices::Bone pointers in place.
     65 static void swap(const SkVertices::Bone** x, const SkVertices::Bone** y) {
     66     const SkVertices::Bone* temp = *x;
     67     *x = *y;
     68     *y = temp;
     69 }
     70 
     71 class SkinningGM : public GM {
     72 
     73 public:
     74     SkinningGM(bool deformUsingCPU, bool cache)
     75             : fPaint()
     76             , fVertices(nullptr)
     77             , fDeformUsingCPU(deformUsingCPU)
     78             , fCache(cache)
     79     {}
     80 
     81 protected:
     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         }
     91         if (fCache) {
     92             name.append("_cached");
     93         }
     94         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,
    111                                          !fCache);
    112     }
    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.
    120         const SkVertices::Bone* bones[kBoneCount];
    121         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 
    129 private:
    130     void drawPermutations(SkCanvas* canvas,
    131                           int& xpos,
    132                           int& ypos,
    133                           const SkVertices::Bone** bones,
    134                           int start) {
    135         if (start == kBoneCount) {
    136             // Reached the end of the permutations, so draw.
    137             canvas->save();
    138 
    139             // Copy the bones.
    140             SkVertices::Bone copiedBones[kBoneCount];
    141             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) {
    150                 // Apply the bones.
    151                 sk_sp<SkVertices> vertices = fVertices->applyBones(copiedBones,
    152                                                                    kBoneCount);
    153 
    154                 // Deform with CPU.
    155                 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 
    192 private:
    193     SkPaint fPaint;
    194     sk_sp<SkVertices> fVertices;
    195     bool fDeformUsingCPU;
    196     bool fCache;
    197 
    198     typedef GM INHERITED;
    199 };
    200 
    201 /////////////////////////////////////////////////////////////////////////////////////
    202 
    203 DEF_GM(return new SkinningGM(true, true);)
    204 DEF_GM(return new SkinningGM(false, true);)
    205 DEF_GM(return new SkinningGM(true, false);)
    206 DEF_GM(return new SkinningGM(false, false);)
    207