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