1 /* 2 * Copyright 2014 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 "include/core/SkCanvas.h" 9 #include "include/core/SkFont.h" 10 #include "include/core/SkPaint.h" 11 #include "include/utils/SkRandom.h" 12 #include "samplecode/Sample.h" 13 #include "src/utils/SkUTF.h" 14 #if SK_SUPPORT_GPU 15 #include "src/gpu/GrRectanizer_pow2.h" 16 #include "src/gpu/GrRectanizer_skyline.h" 17 18 // This slide visualizes the various GrRectanizer-derived classes behavior 19 // for various input sets 20 // 'j' will cycle through the various rectanizers 21 // Pow2 -> GrRectanizerPow2 22 // Skyline -> GrRectanizerSkyline 23 // 'h' will cycle through the various rect sets 24 // Rand -> random rects from 2-256 25 // Pow2Rand -> random power of 2 sized rects from 2-256 26 // SmallPow2 -> 128x128 rects 27 class RectanizerView : public Sample { 28 public: RectanizerView()29 RectanizerView() 30 : fCurRandRect(0) 31 , fCurRectanizer(0) { 32 for (int i = 0; i < 3; ++i) { 33 fRects[i].setReserve(kNumRandRects); 34 } 35 fRectLocations.setReserve(kNumRandRects); 36 37 SkRandom random; 38 for (int i = 0; i < kNumRandRects; ++i) { 39 *fRects[0].append() = SkISize::Make(random.nextRangeU(kMinRectSize, kMaxRectSize), 40 random.nextRangeU(kMinRectSize, kMaxRectSize)); 41 *fRects[1].append() = SkISize::Make( 42 GrNextPow2(random.nextRangeU(kMinRectSize, kMaxRectSize)), 43 GrNextPow2(random.nextRangeU(kMinRectSize, kMaxRectSize))); 44 *fRects[2].append() = SkISize::Make(128, 128); 45 *fRectLocations.append() = SkIPoint16::Make(0, 0); 46 } 47 48 fCurRects = &fRects[0]; 49 50 fRectanizers.push_back( 51 std::unique_ptr<GrRectanizer>(new GrRectanizerPow2(kWidth, kHeight))); 52 fRectanizers.push_back( 53 std::unique_ptr<GrRectanizer>(new GrRectanizerSkyline(kWidth, kHeight))); 54 } 55 56 protected: name()57 SkString name() override { return SkString("Rectanizer"); } 58 onChar(SkUnichar uni)59 bool onChar(SkUnichar uni) override { 60 char utf8[SkUTF::kMaxBytesInUTF8Sequence]; 61 size_t size = SkUTF::ToUTF8(uni, utf8); 62 // Only consider events for single char keys 63 if (1 == size) { 64 switch (utf8[0]) { 65 case kCycleRectanizerKey: 66 this->cycleRectanizer(); 67 return true; 68 case kCycleRectsKey: 69 this->cycleRects(); 70 return true; 71 default: 72 break; 73 } 74 } 75 return false; 76 } 77 onDrawContent(SkCanvas * canvas)78 void onDrawContent(SkCanvas* canvas) override { 79 if (fCurRandRect < kNumRandRects) { 80 if (fRectanizers[fCurRectanizer]->addRect((*fCurRects)[fCurRandRect].fWidth, 81 (*fCurRects)[fCurRandRect].fHeight, 82 &fRectLocations[fCurRandRect])) { 83 ++fCurRandRect; 84 } 85 } 86 87 SkFont blackBigFont; 88 blackBigFont.setSize(20); 89 SkPaint blackStroke; 90 blackStroke.setStyle(SkPaint::kStroke_Style); 91 SkPaint redFill; 92 redFill.setColor(SK_ColorRED); 93 94 SkRect r = SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); 95 96 canvas->clear(SK_ColorWHITE); 97 canvas->drawRect(r, blackStroke); 98 99 long totArea = 0; 100 for (int i = 0; i < fCurRandRect; ++i) { 101 r = SkRect::MakeXYWH(SkIntToScalar(fRectLocations[i].fX), 102 SkIntToScalar(fRectLocations[i].fY), 103 SkIntToScalar((*fCurRects)[i].fWidth), 104 SkIntToScalar((*fCurRects)[i].fHeight)); 105 canvas->drawRect(r, redFill); 106 canvas->drawRect(r, blackStroke); 107 totArea += (*fCurRects)[i].fWidth * (*fCurRects)[i].fHeight; 108 } 109 110 SkString str; 111 112 str.printf("%s-%s: tot Area: %ld %%full: %.2f (%.2f) numTextures: %d/%d", 113 this->getRectanizerName(), 114 this->getRectsName(), 115 totArea, 116 100.0f * fRectanizers[fCurRectanizer]->percentFull(), 117 100.0f * totArea / ((float)kWidth*kHeight), 118 fCurRandRect, 119 kNumRandRects); 120 canvas->drawString(str, 50, kHeight + 50, blackBigFont, SkPaint()); 121 122 str.printf("Press \'j\' to toggle rectanizer"); 123 canvas->drawString(str, 50, kHeight + 100, blackBigFont, SkPaint()); 124 125 str.printf("Press \'h\' to toggle rects"); 126 canvas->drawString(str, 50, kHeight + 150, blackBigFont, SkPaint()); 127 } 128 129 private: 130 static const int kWidth = 1024; 131 static const int kHeight = 1024; 132 static const int kNumRandRects = 200; 133 static const char kCycleRectanizerKey = 'j'; 134 static const char kCycleRectsKey = 'h'; 135 static const int kMinRectSize = 2; 136 static const int kMaxRectSize = 256; 137 138 int fCurRandRect; 139 SkTDArray<SkISize> fRects[3]; 140 SkTDArray<SkISize>* fCurRects; 141 SkTDArray<SkIPoint16> fRectLocations; 142 SkTArray<std::unique_ptr<GrRectanizer>> fRectanizers; 143 int fCurRectanizer; 144 getRectanizerName() const145 const char* getRectanizerName() const { 146 if (!fCurRectanizer) { 147 return "Pow2"; 148 } else { 149 return "Skyline"; 150 } 151 } 152 cycleRectanizer()153 void cycleRectanizer() { 154 fCurRectanizer = (fCurRectanizer + 1) % fRectanizers.count(); 155 156 fRectanizers[fCurRectanizer]->reset(); 157 fCurRandRect = 0; 158 } 159 getRectsName() const160 const char* getRectsName() const { 161 if (fCurRects == &fRects[0]) { 162 return "Rand"; 163 } else if (fCurRects == &fRects[1]) { 164 return "Pow2Rand"; 165 } else { 166 return "SmallPow2"; 167 } 168 } 169 cycleRects()170 void cycleRects() { 171 if (fCurRects == &fRects[0]) { 172 fCurRects = &fRects[1]; 173 } else if (fCurRects == &fRects[1]) { 174 fCurRects = &fRects[2]; 175 } else { 176 fCurRects = &fRects[0]; 177 } 178 179 fRectanizers[fCurRectanizer]->reset(); 180 fCurRandRect = 0; 181 } 182 183 typedef Sample INHERITED; 184 }; 185 186 ////////////////////////////////////////////////////////////////////////////// 187 188 DEF_SAMPLE( return new RectanizerView(); ) 189 190 #endif 191