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 "Sample.h" 9 #include "SkCanvas.h" 10 #include "SkFont.h" 11 #include "SkRandom.h" 12 #include "SkPaint.h" 13 #include "SkUTF.h" 14 #if SK_SUPPORT_GPU 15 #include "GrRectanizer_pow2.h" 16 #include "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: onQuery(Sample::Event * evt)57 bool onQuery(Sample::Event* evt) override { 58 if (Sample::TitleQ(*evt)) { 59 Sample::TitleR(evt, "Rectanizer"); 60 return true; 61 } 62 SkUnichar uni; 63 if (Sample::CharQ(*evt, &uni)) { 64 char utf8[SkUTF::kMaxBytesInUTF8Sequence]; 65 size_t size = SkUTF::ToUTF8(uni, utf8); 66 // Only consider events for single char keys 67 if (1 == size) { 68 switch (utf8[0]) { 69 case kCycleRectanizerKey: 70 this->cycleRectanizer(); 71 return true; 72 case kCycleRectsKey: 73 this->cycleRects(); 74 return true; 75 default: 76 break; 77 } 78 } 79 } 80 return this->INHERITED::onQuery(evt); 81 } 82 onDrawContent(SkCanvas * canvas)83 void onDrawContent(SkCanvas* canvas) override { 84 if (fCurRandRect < kNumRandRects) { 85 if (fRectanizers[fCurRectanizer]->addRect((*fCurRects)[fCurRandRect].fWidth, 86 (*fCurRects)[fCurRandRect].fHeight, 87 &fRectLocations[fCurRandRect])) { 88 ++fCurRandRect; 89 } 90 } 91 92 SkFont blackBigFont; 93 blackBigFont.setSize(20); 94 SkPaint blackStroke; 95 blackStroke.setStyle(SkPaint::kStroke_Style); 96 SkPaint redFill; 97 redFill.setColor(SK_ColorRED); 98 99 SkRect r = SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); 100 101 canvas->clear(SK_ColorWHITE); 102 canvas->drawRect(r, blackStroke); 103 104 long totArea = 0; 105 for (int i = 0; i < fCurRandRect; ++i) { 106 r = SkRect::MakeXYWH(SkIntToScalar(fRectLocations[i].fX), 107 SkIntToScalar(fRectLocations[i].fY), 108 SkIntToScalar((*fCurRects)[i].fWidth), 109 SkIntToScalar((*fCurRects)[i].fHeight)); 110 canvas->drawRect(r, redFill); 111 canvas->drawRect(r, blackStroke); 112 totArea += (*fCurRects)[i].fWidth * (*fCurRects)[i].fHeight; 113 } 114 115 SkString str; 116 117 str.printf("%s-%s: tot Area: %ld %%full: %.2f (%.2f) numTextures: %d/%d", 118 this->getRectanizerName(), 119 this->getRectsName(), 120 totArea, 121 100.0f * fRectanizers[fCurRectanizer]->percentFull(), 122 100.0f * totArea / ((float)kWidth*kHeight), 123 fCurRandRect, 124 kNumRandRects); 125 canvas->drawString(str, 50, kHeight + 50, blackBigFont, SkPaint()); 126 127 str.printf("Press \'j\' to toggle rectanizer"); 128 canvas->drawString(str, 50, kHeight + 100, blackBigFont, SkPaint()); 129 130 str.printf("Press \'h\' to toggle rects"); 131 canvas->drawString(str, 50, kHeight + 150, blackBigFont, SkPaint()); 132 } 133 134 private: 135 static const int kWidth = 1024; 136 static const int kHeight = 1024; 137 static const int kNumRandRects = 200; 138 static const char kCycleRectanizerKey = 'j'; 139 static const char kCycleRectsKey = 'h'; 140 static const int kMinRectSize = 2; 141 static const int kMaxRectSize = 256; 142 143 int fCurRandRect; 144 SkTDArray<SkISize> fRects[3]; 145 SkTDArray<SkISize>* fCurRects; 146 SkTDArray<SkIPoint16> fRectLocations; 147 SkTArray<std::unique_ptr<GrRectanizer>> fRectanizers; 148 int fCurRectanizer; 149 getRectanizerName() const150 const char* getRectanizerName() const { 151 if (!fCurRectanizer) { 152 return "Pow2"; 153 } else { 154 return "Skyline"; 155 } 156 } 157 cycleRectanizer()158 void cycleRectanizer() { 159 fCurRectanizer = (fCurRectanizer + 1) % fRectanizers.count(); 160 161 fRectanizers[fCurRectanizer]->reset(); 162 fCurRandRect = 0; 163 } 164 getRectsName() const165 const char* getRectsName() const { 166 if (fCurRects == &fRects[0]) { 167 return "Rand"; 168 } else if (fCurRects == &fRects[1]) { 169 return "Pow2Rand"; 170 } else { 171 return "SmallPow2"; 172 } 173 } 174 cycleRects()175 void cycleRects() { 176 if (fCurRects == &fRects[0]) { 177 fCurRects = &fRects[1]; 178 } else if (fCurRects == &fRects[1]) { 179 fCurRects = &fRects[2]; 180 } else { 181 fCurRects = &fRects[0]; 182 } 183 184 fRectanizers[fCurRectanizer]->reset(); 185 fCurRandRect = 0; 186 } 187 188 typedef Sample INHERITED; 189 }; 190 191 ////////////////////////////////////////////////////////////////////////////// 192 193 DEF_SAMPLE( return new RectanizerView(); ) 194 195 #endif 196