blob: 2b2d8497cfd48fef600c7104849e3032c80281eb [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"
robertphillips@google.comb7061172013-09-06 14:16:12 +00009#include "SkBlurMask.h"
robertphillips@google.com2cc0b472013-08-20 16:51:20 +000010#include "SkBlurMaskFilter.h"
robertphillips@google.comb7061172013-09-06 14:16:12 +000011#include "SkCanvas.h"
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000012
13#if SK_SUPPORT_GPU
14#include "GrContext.h"
15
16namespace skiagm {
17extern GrContext* GetGr();
18};
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000019#endif
20
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000021// Create a black&white checked texture with a 1-pixel red ring
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000022// around the outside edge
23static void make_red_ringed_bitmap(SkBitmap* result, int width, int height) {
24 SkASSERT(0 == width % 2 && 0 == width % 2);
25
26 result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
27 result->allocPixels();
28 SkAutoLockPixels lock(*result);
29
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000030 SkPMColor* scanline = result->getAddr32(0, 0);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000031 for (int x = 0; x < width; ++x) {
32 scanline[x] = SK_ColorRED;
33 }
34
35 for (int y = 1; y < height/2; ++y) {
36 scanline = result->getAddr32(0, y);
37 scanline[0] = SK_ColorRED;
38 for (int x = 1; x < width/2; ++x) {
39 scanline[x] = SK_ColorBLACK;
40 }
41 for (int x = width/2; x < width-1; ++x) {
42 scanline[x] = SK_ColorWHITE;
43 }
44 scanline[width-1] = SK_ColorRED;
45 }
46
47 for (int y = height/2; y < height-1; ++y) {
48 scanline = result->getAddr32(0, y);
49 scanline[0] = SK_ColorRED;
50 for (int x = 1; x < width/2; ++x) {
51 scanline[x] = SK_ColorWHITE;
52 }
53 for (int x = width/2; x < width-1; ++x) {
54 scanline[x] = SK_ColorBLACK;
55 }
56 scanline[width-1] = SK_ColorRED;
57 }
58
59 scanline = result->getAddr32(0, height-1);
60 for (int x = 0; x < width; ++x) {
61 scanline[x] = SK_ColorRED;
62 }
63 result->setIsOpaque(true);
64 result->setImmutable();
65}
66
67// This GM exercises the drawBitmapRectToRect "bleed" flag
68class BleedGM : public skiagm::GM {
69public:
70 BleedGM() {}
71
72protected:
73 virtual SkString onShortName() SK_OVERRIDE {
74 return SkString("bleed");
75 }
76
77 virtual SkISize onISize() SK_OVERRIDE {
78 return SkISize::Make(kWidth, kHeight);
79 }
80
81 virtual void onOnceBeforeDraw() SK_OVERRIDE {
82 make_red_ringed_bitmap(&fBitmapSmall, kSmallTextureSize, kSmallTextureSize);
83
84 // To exercise the GPU's tiling path we need a texture
85 // too big for the GPU to handle in one go
86 make_red_ringed_bitmap(&fBitmapBig, 2*kMaxTextureSize, 2*kMaxTextureSize);
87 }
88
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000089 // Draw only the center of the small bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +000090 void drawCase1(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000091 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
92 SkRect src = SkRect::MakeXYWH(1, 1,
93 kSmallTextureSize-2,
94 kSmallTextureSize-2);
95 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
96
97 SkPaint paint;
98 paint.setFilterBitmap(filter);
99
100 canvas->save();
101 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
102 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
103 canvas->restore();
104 }
105
106 // Draw almost all of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000107 void drawCase2(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000108 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
109 SkRect src = SkRect::MakeXYWH(1, 1,
110 SkIntToScalar(fBitmapBig.width()-2),
111 SkIntToScalar(fBitmapBig.height()-2));
112 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
113
114 SkPaint paint;
115 paint.setFilterBitmap(filter);
116
117 canvas->save();
118 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
119 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
120 canvas->restore();
121 }
122
123 // Draw ~1/4 of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000124 void drawCase3(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000125 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
126 SkRect src = SkRect::MakeXYWH(1, 1,
127 SkIntToScalar(fBitmapBig.width()/2-1),
128 SkIntToScalar(fBitmapBig.height()/2-1));
129 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
130
131 SkPaint paint;
132 paint.setFilterBitmap(filter);
133
134 canvas->save();
135 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
136 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
137 canvas->restore();
138 }
139
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000140 // Draw the center of the small bitmap with a mask filter
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000141 void drawCase4(SkCanvas* canvas, int transX, int transY,
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000142 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
143 SkRect src = SkRect::MakeXYWH(1, 1,
144 kSmallTextureSize-2,
145 kSmallTextureSize-2);
146 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
147
148 SkPaint paint;
149 paint.setFilterBitmap(filter);
robertphillips@google.comb7061172013-09-06 14:16:12 +0000150 SkMaskFilter* mf = SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
151 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)));
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000152 paint.setMaskFilter(mf)->unref();
153
154 canvas->save();
155 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
156 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
157 canvas->restore();
158 }
159
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000160 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000161
162 canvas->clear(SK_ColorGRAY);
163
164 // First draw a column with no bleeding, tiling, or filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000165 this->drawCase1(canvas, kCol0X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
166 this->drawCase2(canvas, kCol0X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
167 this->drawCase3(canvas, kCol0X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000168 this->drawCase4(canvas, kCol0X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000169
170 // Then draw a column with no bleeding or tiling but with filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000171 this->drawCase1(canvas, kCol1X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
172 this->drawCase2(canvas, kCol1X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
173 this->drawCase3(canvas, kCol1X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000174 this->drawCase4(canvas, kCol1X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000175
176
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000177#if SK_SUPPORT_GPU
178 GrContext* ctx = skiagm::GetGr();
179 int oldMaxTextureSize = 0;
180 if (NULL != ctx) {
181 // shrink the max texture size so all our textures can be reasonably sized
182 oldMaxTextureSize = ctx->getMaxTextureSize();
183 ctx->setMaxTextureSizeOverride(kMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000184 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000185#endif
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000186
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000187 // Then draw a column with no bleeding but with tiling and filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000188 this->drawCase1(canvas, kCol2X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
189 this->drawCase2(canvas, kCol2X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
190 this->drawCase3(canvas, kCol2X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000191 this->drawCase4(canvas, kCol2X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000192
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000193 // Finally draw a column with all three (bleeding, tiling, and filtering)
194 this->drawCase1(canvas, kCol3X, kRow0Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
195 this->drawCase2(canvas, kCol3X, kRow1Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
196 this->drawCase3(canvas, kCol3X, kRow2Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000197 this->drawCase4(canvas, kCol3X, kRow3Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000198
199#if SK_SUPPORT_GPU
200 if (NULL != ctx) {
201 ctx->setMaxTextureSizeOverride(oldMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000202 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000203#endif
204 }
205
206private:
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000207 static const int kBlockSize = 90;
208 static const int kBlockSpacing = 10;
209
210 static const int kCol0X = kBlockSpacing;
211 static const int kCol1X = 2*kBlockSpacing + kBlockSize;
212 static const int kCol2X = 3*kBlockSpacing + 2*kBlockSize;
213 static const int kCol3X = 4*kBlockSpacing + 3*kBlockSize;
214 static const int kWidth = 5*kBlockSpacing + 4*kBlockSize;
215
216 static const int kRow0Y = kBlockSpacing;
217 static const int kRow1Y = 2*kBlockSpacing + kBlockSize;
218 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize;
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000219 static const int kRow3Y = 4*kBlockSpacing + 3*kBlockSize;
220 static const int kHeight = 5*kBlockSpacing + 4*kBlockSize;
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000221
222 static const int kSmallTextureSize = 4;
223 static const int kMaxTextureSize = 32;
224
225 SkBitmap fBitmapSmall;
226 SkBitmap fBitmapBig;
227
228 typedef GM INHERITED;
229};
230
231DEF_GM( return new BleedGM(); )