blob: 1a7e188ec1ad9e2c9140686b0ebde3daa342d55a [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"
10
11#if SK_SUPPORT_GPU
12#include "GrContext.h"
13
14namespace skiagm {
15extern GrContext* GetGr();
16};
17
18void GrContext::setMaxTextureSizeOverride(int maxTextureSizeOverride) {
19 fMaxTextureSizeOverride = maxTextureSizeOverride;
20}
21#endif
22
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000023// Create a black&white checked texture with a 1-pixel red ring
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000024// around the outside edge
25static void make_red_ringed_bitmap(SkBitmap* result, int width, int height) {
26 SkASSERT(0 == width % 2 && 0 == width % 2);
27
28 result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
29 result->allocPixels();
30 SkAutoLockPixels lock(*result);
31
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000032 SkPMColor* scanline = result->getAddr32(0, 0);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000033 for (int x = 0; x < width; ++x) {
34 scanline[x] = SK_ColorRED;
35 }
36
37 for (int y = 1; y < height/2; ++y) {
38 scanline = result->getAddr32(0, y);
39 scanline[0] = SK_ColorRED;
40 for (int x = 1; x < width/2; ++x) {
41 scanline[x] = SK_ColorBLACK;
42 }
43 for (int x = width/2; x < width-1; ++x) {
44 scanline[x] = SK_ColorWHITE;
45 }
46 scanline[width-1] = SK_ColorRED;
47 }
48
49 for (int y = height/2; y < height-1; ++y) {
50 scanline = result->getAddr32(0, y);
51 scanline[0] = SK_ColorRED;
52 for (int x = 1; x < width/2; ++x) {
53 scanline[x] = SK_ColorWHITE;
54 }
55 for (int x = width/2; x < width-1; ++x) {
56 scanline[x] = SK_ColorBLACK;
57 }
58 scanline[width-1] = SK_ColorRED;
59 }
60
61 scanline = result->getAddr32(0, height-1);
62 for (int x = 0; x < width; ++x) {
63 scanline[x] = SK_ColorRED;
64 }
65 result->setIsOpaque(true);
66 result->setImmutable();
67}
68
69// This GM exercises the drawBitmapRectToRect "bleed" flag
70class BleedGM : public skiagm::GM {
71public:
72 BleedGM() {}
73
74protected:
75 virtual SkString onShortName() SK_OVERRIDE {
76 return SkString("bleed");
77 }
78
79 virtual SkISize onISize() SK_OVERRIDE {
80 return SkISize::Make(kWidth, kHeight);
81 }
82
83 virtual void onOnceBeforeDraw() SK_OVERRIDE {
84 make_red_ringed_bitmap(&fBitmapSmall, kSmallTextureSize, kSmallTextureSize);
85
86 // To exercise the GPU's tiling path we need a texture
87 // too big for the GPU to handle in one go
88 make_red_ringed_bitmap(&fBitmapBig, 2*kMaxTextureSize, 2*kMaxTextureSize);
89 }
90
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000091 // Draw only the center of the small bitmap
92 void drawCase1(SkCanvas* canvas, int transX, int transY,
93 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
94 SkRect src = SkRect::MakeXYWH(1, 1,
95 kSmallTextureSize-2,
96 kSmallTextureSize-2);
97 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
98
99 SkPaint paint;
100 paint.setFilterBitmap(filter);
101
102 canvas->save();
103 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
104 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
105 canvas->restore();
106 }
107
108 // Draw almost all of the large bitmap
109 void drawCase2(SkCanvas* canvas, int transX, int transY,
110 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
111 SkRect src = SkRect::MakeXYWH(1, 1,
112 SkIntToScalar(fBitmapBig.width()-2),
113 SkIntToScalar(fBitmapBig.height()-2));
114 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
115
116 SkPaint paint;
117 paint.setFilterBitmap(filter);
118
119 canvas->save();
120 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
121 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
122 canvas->restore();
123 }
124
125 // Draw ~1/4 of the large bitmap
126 void drawCase3(SkCanvas* canvas, int transX, int transY,
127 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
128 SkRect src = SkRect::MakeXYWH(1, 1,
129 SkIntToScalar(fBitmapBig.width()/2-1),
130 SkIntToScalar(fBitmapBig.height()/2-1));
131 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
132
133 SkPaint paint;
134 paint.setFilterBitmap(filter);
135
136 canvas->save();
137 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
138 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
139 canvas->restore();
140 }
141
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000142 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000143
144 canvas->clear(SK_ColorGRAY);
145
146 // First draw a column with no bleeding, tiling, or filtering
147 this->drawCase1(canvas, kCol0X, kRow0Y, SkCanvas::kNone_DrawBitmapRectflag, false);
148 this->drawCase2(canvas, kCol0X, kRow1Y, SkCanvas::kNone_DrawBitmapRectflag, false);
149 this->drawCase3(canvas, kCol0X, kRow2Y, SkCanvas::kNone_DrawBitmapRectflag, false);
150
151 // Then draw a column with no bleeding or tiling but with filtering
152 this->drawCase1(canvas, kCol1X, kRow0Y, SkCanvas::kNone_DrawBitmapRectflag, true);
153 this->drawCase2(canvas, kCol1X, kRow1Y, SkCanvas::kNone_DrawBitmapRectflag, true);
154 this->drawCase3(canvas, kCol1X, kRow2Y, SkCanvas::kNone_DrawBitmapRectflag, true);
155
156
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000157#if SK_SUPPORT_GPU
158 GrContext* ctx = skiagm::GetGr();
159 int oldMaxTextureSize = 0;
160 if (NULL != ctx) {
161 // shrink the max texture size so all our textures can be reasonably sized
162 oldMaxTextureSize = ctx->getMaxTextureSize();
163 ctx->setMaxTextureSizeOverride(kMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000164 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000165#endif
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000166
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000167 // Then draw a column with no bleeding but with tiling and filtering
168 this->drawCase1(canvas, kCol2X, kRow0Y, SkCanvas::kNone_DrawBitmapRectflag, true);
169 this->drawCase2(canvas, kCol2X, kRow1Y, SkCanvas::kNone_DrawBitmapRectflag, true);
170 this->drawCase3(canvas, kCol2X, kRow2Y, SkCanvas::kNone_DrawBitmapRectflag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000171
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000172 // Finally draw a column with all three (bleeding, tiling, and filtering)
173 this->drawCase1(canvas, kCol3X, kRow0Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
174 this->drawCase2(canvas, kCol3X, kRow1Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
175 this->drawCase3(canvas, kCol3X, kRow2Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000176
177#if SK_SUPPORT_GPU
178 if (NULL != ctx) {
179 ctx->setMaxTextureSizeOverride(oldMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000180 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000181#endif
182 }
183
184private:
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000185 static const int kBlockSize = 90;
186 static const int kBlockSpacing = 10;
187
188 static const int kCol0X = kBlockSpacing;
189 static const int kCol1X = 2*kBlockSpacing + kBlockSize;
190 static const int kCol2X = 3*kBlockSpacing + 2*kBlockSize;
191 static const int kCol3X = 4*kBlockSpacing + 3*kBlockSize;
192 static const int kWidth = 5*kBlockSpacing + 4*kBlockSize;
193
194 static const int kRow0Y = kBlockSpacing;
195 static const int kRow1Y = 2*kBlockSpacing + kBlockSize;
196 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize;
197 static const int kHeight = 4*kBlockSpacing + 3*kBlockSize;
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000198
199 static const int kSmallTextureSize = 4;
200 static const int kMaxTextureSize = 32;
201
202 SkBitmap fBitmapSmall;
203 SkBitmap fBitmapBig;
204
205 typedef GM INHERITED;
206};
207
208DEF_GM( return new BleedGM(); )