blob: b61284122b969347133e4bf8ccc17eb893248f02 [file] [log] [blame]
robertphillips@google.comaaa9b292013-07-25 21:34:00 +00001/*
2 * Copyright 2013 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 "SkCanvas.h"
robertphillips@google.com2cc0b472013-08-20 16:51:20 +000010#include "SkBlurMaskFilter.h"
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000011
12#if SK_SUPPORT_GPU
13#include "GrContext.h"
14
15namespace skiagm {
16extern GrContext* GetGr();
17};
18
19void GrContext::setMaxTextureSizeOverride(int maxTextureSizeOverride) {
20 fMaxTextureSizeOverride = maxTextureSizeOverride;
21}
22#endif
23
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000024// Create a black&white checked texture with a 1-pixel red ring
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000025// around the outside edge
26static void make_red_ringed_bitmap(SkBitmap* result, int width, int height) {
27 SkASSERT(0 == width % 2 && 0 == width % 2);
28
29 result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
30 result->allocPixels();
31 SkAutoLockPixels lock(*result);
32
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000033 SkPMColor* scanline = result->getAddr32(0, 0);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000034 for (int x = 0; x < width; ++x) {
35 scanline[x] = SK_ColorRED;
36 }
37
38 for (int y = 1; y < height/2; ++y) {
39 scanline = result->getAddr32(0, y);
40 scanline[0] = SK_ColorRED;
41 for (int x = 1; x < width/2; ++x) {
42 scanline[x] = SK_ColorBLACK;
43 }
44 for (int x = width/2; x < width-1; ++x) {
45 scanline[x] = SK_ColorWHITE;
46 }
47 scanline[width-1] = SK_ColorRED;
48 }
49
50 for (int y = height/2; y < height-1; ++y) {
51 scanline = result->getAddr32(0, y);
52 scanline[0] = SK_ColorRED;
53 for (int x = 1; x < width/2; ++x) {
54 scanline[x] = SK_ColorWHITE;
55 }
56 for (int x = width/2; x < width-1; ++x) {
57 scanline[x] = SK_ColorBLACK;
58 }
59 scanline[width-1] = SK_ColorRED;
60 }
61
62 scanline = result->getAddr32(0, height-1);
63 for (int x = 0; x < width; ++x) {
64 scanline[x] = SK_ColorRED;
65 }
66 result->setIsOpaque(true);
67 result->setImmutable();
68}
69
70// This GM exercises the drawBitmapRectToRect "bleed" flag
71class BleedGM : public skiagm::GM {
72public:
73 BleedGM() {}
74
75protected:
76 virtual SkString onShortName() SK_OVERRIDE {
77 return SkString("bleed");
78 }
79
80 virtual SkISize onISize() SK_OVERRIDE {
81 return SkISize::Make(kWidth, kHeight);
82 }
83
84 virtual void onOnceBeforeDraw() SK_OVERRIDE {
85 make_red_ringed_bitmap(&fBitmapSmall, kSmallTextureSize, kSmallTextureSize);
86
87 // To exercise the GPU's tiling path we need a texture
88 // too big for the GPU to handle in one go
89 make_red_ringed_bitmap(&fBitmapBig, 2*kMaxTextureSize, 2*kMaxTextureSize);
90 }
91
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000092 // Draw only the center of the small bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +000093 void drawCase1(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000094 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
95 SkRect src = SkRect::MakeXYWH(1, 1,
96 kSmallTextureSize-2,
97 kSmallTextureSize-2);
98 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
99
100 SkPaint paint;
101 paint.setFilterBitmap(filter);
102
103 canvas->save();
104 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
105 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
106 canvas->restore();
107 }
108
109 // Draw almost all of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000110 void drawCase2(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000111 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
112 SkRect src = SkRect::MakeXYWH(1, 1,
113 SkIntToScalar(fBitmapBig.width()-2),
114 SkIntToScalar(fBitmapBig.height()-2));
115 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
116
117 SkPaint paint;
118 paint.setFilterBitmap(filter);
119
120 canvas->save();
121 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
122 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
123 canvas->restore();
124 }
125
126 // Draw ~1/4 of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000127 void drawCase3(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000128 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
129 SkRect src = SkRect::MakeXYWH(1, 1,
130 SkIntToScalar(fBitmapBig.width()/2-1),
131 SkIntToScalar(fBitmapBig.height()/2-1));
132 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
133
134 SkPaint paint;
135 paint.setFilterBitmap(filter);
136
137 canvas->save();
138 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
139 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
140 canvas->restore();
141 }
142
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000143 // Draw the center of the small bitmap with a mask filter
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000144 void drawCase4(SkCanvas* canvas, int transX, int transY,
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000145 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
146 SkRect src = SkRect::MakeXYWH(1, 1,
147 kSmallTextureSize-2,
148 kSmallTextureSize-2);
149 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
150
151 SkPaint paint;
152 paint.setFilterBitmap(filter);
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000153 SkMaskFilter* mf = SkBlurMaskFilter::Create(SkIntToScalar(3),
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000154 SkBlurMaskFilter::kNormal_BlurStyle);
155 paint.setMaskFilter(mf)->unref();
156
157 canvas->save();
158 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
159 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
160 canvas->restore();
161 }
162
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000163 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000164
165 canvas->clear(SK_ColorGRAY);
166
167 // First draw a column with no bleeding, tiling, or filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000168 this->drawCase1(canvas, kCol0X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
169 this->drawCase2(canvas, kCol0X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
170 this->drawCase3(canvas, kCol0X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000171 this->drawCase4(canvas, kCol0X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000172
173 // Then draw a column with no bleeding or tiling but with filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000174 this->drawCase1(canvas, kCol1X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
175 this->drawCase2(canvas, kCol1X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
176 this->drawCase3(canvas, kCol1X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000177 this->drawCase4(canvas, kCol1X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000178
179
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000180#if SK_SUPPORT_GPU
181 GrContext* ctx = skiagm::GetGr();
182 int oldMaxTextureSize = 0;
183 if (NULL != ctx) {
184 // shrink the max texture size so all our textures can be reasonably sized
185 oldMaxTextureSize = ctx->getMaxTextureSize();
186 ctx->setMaxTextureSizeOverride(kMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000187 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000188#endif
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000189
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000190 // Then draw a column with no bleeding but with tiling and filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000191 this->drawCase1(canvas, kCol2X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
192 this->drawCase2(canvas, kCol2X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
193 this->drawCase3(canvas, kCol2X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000194 this->drawCase4(canvas, kCol2X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000195
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000196 // Finally draw a column with all three (bleeding, tiling, and filtering)
197 this->drawCase1(canvas, kCol3X, kRow0Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
198 this->drawCase2(canvas, kCol3X, kRow1Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
199 this->drawCase3(canvas, kCol3X, kRow2Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000200 this->drawCase4(canvas, kCol3X, kRow3Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000201
202#if SK_SUPPORT_GPU
203 if (NULL != ctx) {
204 ctx->setMaxTextureSizeOverride(oldMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000205 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000206#endif
207 }
208
209private:
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000210 static const int kBlockSize = 90;
211 static const int kBlockSpacing = 10;
212
213 static const int kCol0X = kBlockSpacing;
214 static const int kCol1X = 2*kBlockSpacing + kBlockSize;
215 static const int kCol2X = 3*kBlockSpacing + 2*kBlockSize;
216 static const int kCol3X = 4*kBlockSpacing + 3*kBlockSize;
217 static const int kWidth = 5*kBlockSpacing + 4*kBlockSize;
218
219 static const int kRow0Y = kBlockSpacing;
220 static const int kRow1Y = 2*kBlockSpacing + kBlockSize;
221 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize;
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000222 static const int kRow3Y = 4*kBlockSpacing + 3*kBlockSize;
223 static const int kHeight = 5*kBlockSpacing + 4*kBlockSize;
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000224
225 static const int kSmallTextureSize = 4;
226 static const int kMaxTextureSize = 32;
227
228 SkBitmap fBitmapSmall;
229 SkBitmap fBitmapBig;
230
231 typedef GM INHERITED;
232};
233
234DEF_GM( return new BleedGM(); )