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