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