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 
17 // This slide visualizes the various GrRectanizer-derived classes behavior
18 // for various input sets
19 //  'j' will cycle through the various rectanizers
20 //          Pow2 -> GrRectanizerPow2
21 //          Skyline -> GrRectanizerSkyline
22 //  'h' will cycle through the various rect sets
23 //          Rand -> random rects from 2-256
24 //          Pow2Rand -> random power of 2 sized rects from 2-256
25 //          SmallPow2 -> 128x128 rects
26 class RectanizerView : public SampleView {
27 public:
RectanizerView()28     RectanizerView()
29         : fCurRandRect(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[0] = new GrRectanizerPow2(kWidth, kHeight);
49         fRectanizers[1] = new GrRectanizerSkyline(kWidth, kHeight);
50         fCurRectanizer = fRectanizers[0];
51     }
52 
53 protected:
onQuery(SkEvent * evt)54     bool onQuery(SkEvent* evt) override {
55         if (SampleCode::TitleQ(*evt)) {
56             SampleCode::TitleR(evt, "Rectanizer");
57             return true;
58         }
59         SkUnichar uni;
60         if (SampleCode::CharQ(*evt, &uni)) {
61             char utf8[kMaxBytesInUTF8Sequence];
62             size_t size = SkUTF8_FromUnichar(uni, utf8);
63             // Only consider events for single char keys
64             if (1 == size) {
65                 switch (utf8[0]) {
66                 case kCycleRectanizerKey:
67                     this->cycleRectanizer();
68                     return true;
69                 case kCycleRectsKey:
70                     this->cycleRects();
71                     return true;
72                 default:
73                     break;
74                 }
75             }
76         }
77         return this->INHERITED::onQuery(evt);
78     }
79 
onDrawContent(SkCanvas * canvas)80     void onDrawContent(SkCanvas* canvas) override {
81         if (fCurRandRect < kNumRandRects) {
82             if (fCurRectanizer->addRect((*fCurRects)[fCurRandRect].fWidth,
83                                         (*fCurRects)[fCurRandRect].fHeight,
84                                         &fRectLocations[fCurRandRect])) {
85                 ++fCurRandRect;
86             }
87         }
88 
89         SkPaint blackBigFont;
90         blackBigFont.setTextSize(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 * fCurRectanizer->percentFull(),
119                    100.0f * totArea / ((float)kWidth*kHeight),
120                    fCurRandRect,
121                    kNumRandRects);
122         canvas->drawText(str.c_str(), str.size(), 50, kHeight + 50, blackBigFont);
123 
124         str.printf("Press \'j\' to toggle rectanizer");
125         canvas->drawText(str.c_str(), str.size(), 50, kHeight + 100, blackBigFont);
126 
127         str.printf("Press \'h\' to toggle rects");
128         canvas->drawText(str.c_str(), str.size(), 50, kHeight + 150, blackBigFont);
129 
130         this->inval(nullptr);
131     }
132 
133 private:
134     static const int kWidth = 1024;
135     static const int kHeight = 1024;
136     static const int kNumRandRects = 200;
137     static const char kCycleRectanizerKey = 'j';
138     static const char kCycleRectsKey = 'h';
139     static const int kMinRectSize = 2;
140     static const int kMaxRectSize = 256;
141 
142     int                   fCurRandRect;
143     SkTDArray<SkISize>    fRects[3];
144     SkTDArray<SkISize>*   fCurRects;
145     SkTDArray<SkIPoint16> fRectLocations;
146     GrRectanizer*         fRectanizers[2];
147     GrRectanizer*         fCurRectanizer;
148 
getRectanizerName() const149     const char* getRectanizerName() const {
150         if (fCurRectanizer == fRectanizers[0]) {
151             return "Pow2";
152         } else {
153             return "Skyline";
154         }
155     }
156 
cycleRectanizer()157     void cycleRectanizer() {
158         if (fCurRectanizer == fRectanizers[0]) {
159             fCurRectanizer = fRectanizers[1];
160         } else {
161             fCurRectanizer = fRectanizers[0];
162         }
163 
164         fCurRectanizer->reset();
165         fCurRandRect = 0;
166     }
167 
getRectsName() const168     const char* getRectsName() const {
169         if (fCurRects == &fRects[0]) {
170             return "Rand";
171         } else if (fCurRects == &fRects[1]) {
172             return "Pow2Rand";
173         } else {
174             return "SmallPow2";
175         }
176     }
177 
cycleRects()178     void cycleRects() {
179         if (fCurRects == &fRects[0]) {
180             fCurRects = &fRects[1];
181         } else if (fCurRects == &fRects[1]) {
182             fCurRects = &fRects[2];
183         } else {
184             fCurRects = &fRects[0];
185         }
186 
187         fCurRectanizer->reset();
188         fCurRandRect = 0;
189     }
190 
191     typedef SampleView INHERITED;
192 };
193 
194 //////////////////////////////////////////////////////////////////////////////
MyFactory()195 static SkView* MyFactory() { return new RectanizerView; }
196 static SkViewRegister reg(MyFactory);
197 
198 #endif
199