OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
9 #include "SkBlurMask.h" | 9 #include "SkBlurMask.h" |
10 #include "SkBlurMaskFilter.h" | 10 #include "SkBlurMaskFilter.h" |
11 #include "SkCanvas.h" | 11 #include "SkCanvas.h" |
12 #include "SkGradientShader.h" | 12 #include "SkGradientShader.h" |
13 #include "SkImage.h" | 13 #include "SkImage.h" |
14 #include "SkUtils.h" | 14 #include "SkUtils.h" |
15 | 15 |
16 #if SK_SUPPORT_GPU | 16 #if SK_SUPPORT_GPU |
17 #include "GrContext.h" | 17 #include "GrContext.h" |
18 #include "GrContextOptions.h" | 18 #include "GrContextOptions.h" |
19 #include "SkGr.h" | 19 #include "SkGr.h" |
20 #endif | 20 #endif |
21 | 21 |
22 static void draw_bitmap_rect(SkCanvas* canvas, const SkBitmap& bitmap, const SkI mage*, | 22 /** Holds either a bitmap or image to be rendered and a rect that indicates what part of the bitmap |
23 const SkRect& src, const SkRect& dst, | 23 or image should be tested by the GM. The area outside of the rect is present to check |
24 const SkPaint* paint, SkCanvas::SrcRectConstraint c onstraint) { | 24 for bleed due to filtering/blurring. */ |
25 canvas->drawBitmapRect(bitmap, src, dst, paint, constraint); | 25 struct TestPixels { |
26 } | 26 enum Type { |
27 | 27 kBitmap, |
28 static void draw_image_rect(SkCanvas* canvas, const SkBitmap&, const SkImage* im age, | 28 kImage |
29 const SkRect& src, const SkRect& dst, | 29 }; |
30 const SkPaint* paint, SkCanvas::SrcRectConstraint co nstraint) { | 30 Type fType; |
31 canvas->drawImageRect(image, src, dst, paint, constraint); | 31 SkBitmap fBitmap; |
32 } | 32 SkAutoTUnref<SkImage> fImage; |
33 | 33 SkIRect fRect; // The region of the bitmap/image that should be rendered. |
34 // Upload the tight-fitting sw-backed bitmap to a loose-fitting gpu-backed textu re before drawing | 34 }; |
35 static void draw_texture_bitmap_rect(SkCanvas* canvas, const SkBitmap& bitmap, c onst SkImage*, | 35 |
36 const SkRect& src, const SkRect& dst, | 36 /** Creates a bitmap with two one-pixel rings around a checkerboard. The checker board is 2x2 |
37 const SkPaint* paint, | 37 logically where each check has as many pixels as is necessary to fill the in terior. The rect |
38 SkCanvas::SrcRectConstraint constraint) { | 38 to draw is set to the checkerboard portion. */ |
39 GrContext* context = canvas->getGrContext(); | 39 template<typename PIXEL_TYPE> |
40 if (!context) { | 40 bool make_ringed_bitmap(GrContext*, TestPixels* result, int width, int height, |
41 // For non-GPU canvases fallback to drawing the bitmap directly. | 41 SkColorType ct, SkAlphaType at, |
42 canvas->drawBitmapRect(bitmap, src, dst, paint, constraint); | 42 PIXEL_TYPE outerRingColor, PIXEL_TYPE innerRingColor, |
43 return; | 43 PIXEL_TYPE checkColor1, PIXEL_TYPE checkColor2) { |
44 } | |
45 #if SK_SUPPORT_GPU | |
46 GrSurfaceDesc desc; | |
47 desc.fConfig = kAlpha_8_SkColorType == bitmap.colorType() ? kAlpha_8_GrPixel Config : | |
48 kSkia8888_GrPixe lConfig; | |
49 // Add some padding to the right and beneath the bitmap contents to exercise the case where | |
50 // the texture is larger than the bitmap. Outsets chosen to be small and dif ferent. | |
51 desc.fWidth = bitmap.width() + 16; | |
52 desc.fHeight = bitmap.height() + 23; | |
53 SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(de sc, true)); | |
54 if (!texture) { | |
55 return; | |
56 } | |
57 // Init the whole texture to 0 in the alpha case or solid green in the 32bit rgba case. | |
58 SkAutoLockPixels al(bitmap); | |
59 if (kAlpha_8_GrPixelConfig == texture->config()) { | |
60 SkAutoMalloc pixels(texture->width() * texture->height()); | |
61 memset(pixels.get(), 0, texture->width() * texture->height()); | |
62 texture->writePixels(0, 0, texture->width(), texture->height(), desc.fCo nfig, pixels.get(), | |
63 0); | |
64 } else { | |
65 SkAutoMalloc pixels(texture->width() * texture->height() * sizeof(uint32 _t)); | |
66 SkOpts::memset32((uint32_t*)pixels.get(), 0xFF00FF00, texture->width()*t exture->height()); | |
67 texture->writePixels(0, 0, texture->width(), texture->height(), desc.fCo nfig, pixels.get(), | |
68 0); | |
69 } | |
70 | |
71 // Upload the bitmap contents to the upper left. | |
72 texture->writePixels(0, 0, bitmap.width(), bitmap.height(), desc.fConfig, bi tmap.getPixels(), | |
73 bitmap.rowBytes()); | |
74 | |
75 // Wrap the texture in a bitmap and draw it. | |
76 SkBitmap textureBmp; | |
77 GrWrapTextureInBitmap(texture, bitmap.width(), bitmap.height(), true, &textu reBmp); | |
78 canvas->drawBitmapRect(textureBmp, src, dst, paint, constraint); | |
79 #endif | |
80 } | |
81 | |
82 // Create a black&white checked texture with 2 1-pixel rings | |
83 // around the outside edge. The inner ring is red and the outer ring is blue. | |
84 static void make_ringed_color_bitmap(SkBitmap* result, int width, int height) { | |
85 SkASSERT(0 == width % 2 && 0 == height % 2); | 44 SkASSERT(0 == width % 2 && 0 == height % 2); |
robertphillips
2015/11/09 17:11:39
I think the don't stomp memory limit is 2x2 but th
bsalomon
2015/11/09 17:44:11
Done.
| |
86 | 45 |
87 static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED); | 46 result->fType = TestPixels::kBitmap; |
88 static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE); | 47 SkImageInfo info = SkImageInfo::Make(width, height, ct, at); |
48 size_t rowBytes = SkAlign4(info.minRowBytes()); | |
49 result->fBitmap.allocPixels(info, rowBytes); | |
50 | |
51 PIXEL_TYPE* scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, 0); | |
52 for (int x = 0; x < width; ++x) { | |
53 scanline[x] = outerRingColor; | |
54 } | |
55 scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, 1); | |
56 scanline[0] = outerRingColor; | |
57 for (int x = 1; x < width - 1; ++x) { | |
58 scanline[x] = innerRingColor; | |
59 } | |
60 scanline[width - 1] = outerRingColor; | |
61 | |
62 for (int y = 2; y < height / 2; ++y) { | |
63 scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, y); | |
64 scanline[0] = outerRingColor; | |
65 scanline[1] = innerRingColor; | |
66 for (int x = 2; x < width / 2; ++x) { | |
67 scanline[x] = checkColor1; | |
68 } | |
69 for (int x = width / 2; x < width - 2; ++x) { | |
70 scanline[x] = checkColor2; | |
71 } | |
72 scanline[width - 2] = innerRingColor; | |
73 scanline[width - 1] = outerRingColor; | |
74 } | |
75 | |
76 for (int y = height / 2; y < height - 2; ++y) { | |
77 scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, y); | |
78 scanline[0] = outerRingColor; | |
79 scanline[1] = innerRingColor; | |
80 for (int x = 2; x < width / 2; ++x) { | |
81 scanline[x] = checkColor2; | |
82 } | |
83 for (int x = width / 2; x < width - 2; ++x) { | |
84 scanline[x] = checkColor1; | |
85 } | |
86 scanline[width - 2] = innerRingColor; | |
87 scanline[width - 1] = outerRingColor; | |
88 } | |
89 | |
90 scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, height - 2); | |
91 scanline[0] = outerRingColor; | |
92 for (int x = 1; x < width - 1; ++x) { | |
93 scanline[x] = innerRingColor; | |
94 } | |
95 scanline[width - 1] = outerRingColor; | |
96 | |
97 scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, height - 1); | |
98 for (int x = 0; x < width; ++x) { | |
99 scanline[x] = outerRingColor; | |
100 } | |
101 result->fBitmap.setImmutable(); | |
102 result->fRect.set(2, 2, width - 2, height - 2); | |
103 return true; | |
104 } | |
105 | |
106 /** Create a black and white checked texture with 2 1-pixel rings around the out side edge. | |
107 The inner ring is red and the outer ring is blue. */ | |
108 static bool make_ringed_color_bitmap(GrContext* ctx, TestPixels* result, int wid th, int height) { | |
109 static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE); | |
110 static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED); | |
89 static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK); | 111 static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK); |
90 static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE); | 112 static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE); |
91 | 113 return make_ringed_bitmap<SkPMColor>(ctx, result, width, height, kBGRA_8888_ SkColorType, |
92 result->allocN32Pixels(width, height, true); | 114 kPremul_SkAlphaType, kBlue, kRed, kBlac k, kWhite); |
93 | |
94 SkPMColor* scanline = result->getAddr32(0, 0); | |
95 for (int x = 0; x < width; ++x) { | |
96 scanline[x] = kBlue; | |
97 } | |
98 scanline = result->getAddr32(0, 1); | |
99 scanline[0] = kBlue; | |
100 for (int x = 1; x < width - 1; ++x) { | |
101 scanline[x] = kRed; | |
102 } | |
103 scanline[width-1] = kBlue; | |
104 | |
105 for (int y = 2; y < height/2; ++y) { | |
106 scanline = result->getAddr32(0, y); | |
107 scanline[0] = kBlue; | |
108 scanline[1] = kRed; | |
109 for (int x = 2; x < width/2; ++x) { | |
110 scanline[x] = kBlack; | |
111 } | |
112 for (int x = width/2; x < width-2; ++x) { | |
113 scanline[x] = kWhite; | |
114 } | |
115 scanline[width-2] = kRed; | |
116 scanline[width-1] = kBlue; | |
117 } | |
118 | |
119 for (int y = height/2; y < height-2; ++y) { | |
120 scanline = result->getAddr32(0, y); | |
121 scanline[0] = kBlue; | |
122 scanline[1] = kRed; | |
123 for (int x = 2; x < width/2; ++x) { | |
124 scanline[x] = kWhite; | |
125 } | |
126 for (int x = width/2; x < width-2; ++x) { | |
127 scanline[x] = kBlack; | |
128 } | |
129 scanline[width-2] = kRed; | |
130 scanline[width-1] = kBlue; | |
131 } | |
132 | |
133 scanline = result->getAddr32(0, height-2); | |
134 scanline[0] = kBlue; | |
135 for (int x = 1; x < width - 1; ++x) { | |
136 scanline[x] = kRed; | |
137 } | |
138 scanline[width-1] = kBlue; | |
139 | |
140 scanline = result->getAddr32(0, height-1); | |
141 for (int x = 0; x < width; ++x) { | |
142 scanline[x] = kBlue; | |
143 } | |
144 result->setImmutable(); | |
145 } | 115 } |
146 | 116 |
147 /** Makes a alpha bitmap with 1 wide rect/ring of 0s, an inset of 1s, and the in terior is a 2x2 | 117 /** Makes a alpha bitmap with 1 wide rect/ring of 0s, an inset of 1s, and the in terior is a 2x2 |
148 checker board of 3/4 and 1/2. The inner checkers are large enough to fill th e interior with | 118 checker board of 3/4 and 1/2. The inner checkers are large enough to fill th e interior with |
149 the 2x2 checker grid. */ | 119 the 2x2 checker grid. */ |
150 static void make_ringed_alpha_bitmap(SkBitmap* result, int width, int height) { | 120 static bool make_ringed_alpha_bitmap(GrContext* ctx, TestPixels* result, int wid th, int height) { |
121 static const uint8_t kZero = 0x00; | |
122 static const uint8_t kHalf = 0x80; | |
123 static const uint8_t k3Q = 0xC0; | |
124 static const uint8_t kOne = 0xFF; | |
125 return make_ringed_bitmap<uint8_t>(ctx, result, width, height, kAlpha_8_SkCo lorType, | |
126 kPremul_SkAlphaType, kZero, kOne, k3Q, kH alf); | |
127 } | |
128 | |
129 /** Helper to reuse above functions to produce images rather than bmps */ | |
130 static void bmp_to_image(TestPixels* result) { | |
131 SkASSERT(TestPixels::kBitmap == result->fType); | |
132 result->fImage.reset(SkImage::NewFromBitmap(result->fBitmap)); | |
133 SkASSERT(result->fImage); | |
134 result->fType = TestPixels::kImage; | |
135 result->fBitmap.reset(); | |
136 } | |
137 | |
138 /** Color image case. */ | |
139 bool make_ringed_color_image(GrContext* ctx, TestPixels* result, int width, int height) { | |
140 if (make_ringed_color_bitmap(ctx, result, width, height)) { | |
141 bmp_to_image(result); | |
142 return true; | |
143 } | |
144 return false; | |
145 } | |
146 | |
147 /** Alpha image case. */ | |
148 bool make_ringed_alpha_image(GrContext* ctx, TestPixels* result, int width, int height) { | |
149 if (make_ringed_alpha_bitmap(ctx, result, width, height)) { | |
150 bmp_to_image(result); | |
151 return true; | |
152 } | |
153 return false; | |
154 } | |
155 | |
156 /** Similar to make_ringed_bitmap with these modifications: | |
157 - The backing store is a texture. | |
158 - The texture is larger than the bitmap dimensions (it is surrounded by non-content | |
159 padding on the right/bottom of the contents.) | |
160 - The right/bottom sides of the rings are omitted so that the rect to dr aw is adjacent to | |
161 the texture padding. | |
162 */ | |
163 template <typename PIXEL_TYPE> | |
164 bool make_oversized_texture_bitmap(GrContext* ctx, TestPixels* result, int width , int height, | |
165 GrPixelConfig config, PIXEL_TYPE outerRingCol or, | |
166 PIXEL_TYPE innerRingColor, PIXEL_TYPE checkCo lor1, | |
167 PIXEL_TYPE checkColor2, PIXEL_TYPE padColor) { | |
151 SkASSERT(0 == width % 2 && 0 == height % 2); | 168 SkASSERT(0 == width % 2 && 0 == height % 2); |
robertphillips
2015/11/09 17:11:39
Same extra assert here ?
bsalomon
2015/11/09 17:44:11
Done.
| |
152 | 169 #if SK_SUPPORT_GPU |
153 static const SkPMColor kZero = 0x00; | 170 if (!ctx) { |
154 static const SkPMColor kHalf = 0x80; | 171 return false; |
155 static const SkPMColor k3Q = 0xC0; | 172 } |
156 static const SkPMColor kOne = 0xFF; | 173 /** Put arbitrary pad to the right and below the bitmap content. */ |
157 SkImageInfo info = SkImageInfo::MakeA8(width, height); | 174 static const int kXPad = 10; |
158 // The 4 byte alignment seems to be necessary to allow this bmp to be conver ted | 175 static const int kYPad = 17; |
159 // to an image. | 176 size_t rowBytes = (width + kXPad) * sizeof(PIXEL_TYPE); |
160 result->allocPixels(info, SkAlign4(width)); | 177 SkAutoTMalloc<PIXEL_TYPE> pixels(rowBytes*(height + kYPad)); |
161 | 178 |
162 uint8_t* scanline = result->getAddr8(0, 0); | 179 PIXEL_TYPE* scanline = pixels.get(); |
163 for (int x = 0; x < width; ++x) { | 180 for (int x = 0; x < width; ++x) { |
164 scanline[x] = kOne; | 181 scanline[x] = outerRingColor; |
165 } | 182 } |
166 scanline = result->getAddr8(0, 1); | 183 for (int x = width; x < width + kXPad; ++x) { |
167 scanline[0] = kOne; | 184 scanline[x] = padColor; |
168 for (int x = 1; x < width - 1; ++x) { | 185 } |
169 scanline[x] = kOne; | 186 |
170 } | 187 scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); |
171 scanline[width - 1] = kZero; | 188 scanline[0] = outerRingColor; |
172 | 189 for (int x = 1; x < width; ++x) { |
173 for (int y = 2; y < height / 2; ++y) { | 190 scanline[x] = innerRingColor; |
174 scanline = result->getAddr8(0, y); | 191 } |
175 scanline[0] = kZero; | 192 for (int x = width; x < width + kXPad; ++x) { |
176 scanline[1] = kOne; | 193 scanline[x] = padColor; |
177 for (int x = 2; x < width / 2; ++x) { | 194 } |
178 scanline[x] = k3Q; | 195 |
179 } | 196 for (int y = 2; y < height / 2 + 1; ++y) { |
180 for (int x = width / 2; x < width - 2; ++x) { | 197 scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); |
181 scanline[x] = kHalf; | 198 scanline[0] = outerRingColor; |
182 } | 199 scanline[1] = innerRingColor; |
183 scanline[width - 2] = kOne; | 200 for (int x = 2; x < width / 2 + 1; ++x) { |
184 scanline[width - 1] = kZero; | 201 scanline[x] = checkColor1; |
185 } | 202 } |
186 | 203 for (int x = width / 2 + 1; x < width; ++x) { |
187 for (int y = height / 2; y < height - 2; ++y) { | 204 scanline[x] = checkColor2; |
188 scanline = result->getAddr8(0, y); | 205 } |
189 scanline[0] = kZero; | 206 for (int x = width; x < width + kXPad; ++x) { |
190 scanline[1] = kOne; | 207 scanline[x] = padColor; |
191 for (int x = 2; x < width / 2; ++x) { | 208 } |
192 scanline[x] = kHalf; | 209 } |
193 } | 210 |
194 for (int x = width / 2; x < width - 2; ++x) { | 211 for (int y = height / 2 + 1; y < height; ++y) { |
195 scanline[x] = k3Q; | 212 scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); |
196 } | 213 scanline[0] = outerRingColor; |
197 scanline[width - 2] = kOne; | 214 scanline[1] = innerRingColor; |
198 scanline[width - 1] = kZero; | 215 for (int x = 2; x < width / 2 + 1; ++x) { |
199 } | 216 scanline[x] = checkColor2; |
200 | 217 } |
201 scanline = result->getAddr8(0, height - 2); | 218 for (int x = width / 2 + 1; x < width; ++x) { |
202 scanline[0] = kZero; | 219 scanline[x] = checkColor1; |
203 for (int x = 1; x < width - 1; ++x) { | 220 } |
204 scanline[x] = kOne; | 221 for (int x = width; x < width + kXPad; ++x) { |
205 } | 222 scanline[x] = padColor; |
206 scanline[width - 1] = kZero; | 223 } |
207 | 224 } |
208 scanline = result->getAddr8(0, height - 1); | 225 |
209 for (int x = 0; x < width; ++x) { | 226 for (int y = height; y < height + kYPad; ++y) { |
210 scanline[x] = kZero; | 227 scanline = (PIXEL_TYPE*)((char*)scanline + rowBytes); |
211 } | 228 for (int x = 0; x < width + kXPad; ++x) { |
212 result->setImmutable(); | 229 scanline[x] = padColor; |
230 } | |
231 } | |
232 | |
233 GrSurfaceDesc desc; | |
234 desc.fConfig = config; | |
235 desc.fWidth = width + kXPad; | |
236 desc.fHeight = height + kYPad; | |
237 SkAutoTUnref<GrTexture> texture(ctx->textureProvider()->createTexture(desc, true, pixels.get(), | |
238 rowByt es)); | |
239 | |
240 if (!texture) { | |
241 return false; | |
242 } | |
243 | |
244 GrWrapTextureInBitmap(texture, width, height, true, &result->fBitmap); | |
245 result->fType = TestPixels::kBitmap; | |
246 result->fBitmap.setImmutable(); | |
247 result->fRect.set(2, 2, width, height); | |
248 return true; | |
249 #else | |
250 return false; | |
251 #endif | |
252 } | |
253 | |
254 /** Make the color version of the oversized texture-backed bitmap */ | |
255 static bool make_ringed_oversized_color_texture_bitmap(GrContext* ctx, TestPixel s* result, | |
256 int width, int height) { | |
257 static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE); | |
258 static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED); | |
259 static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK); | |
260 static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE); | |
261 static const SkPMColor kGreen = SkPreMultiplyColor(SK_ColorGREEN); | |
262 return make_oversized_texture_bitmap<SkPMColor>( | |
263 ctx, result, width, height, kSkia8888_GrPixelConfig, kBlue, kRed, kBlack , kWhite, kGreen); | |
264 } | |
265 | |
266 /** Make the alpha version of the oversized texture-backed bitmap */ | |
267 static bool make_ringed_oversized_alpha_texture_bitmap(GrContext* ctx, TestPixel s* result, | |
268 int width, int height) { | |
269 static const uint8_t kZero = 0x00; | |
270 static const uint8_t kHalf = 0x80; | |
271 static const uint8_t k3Q = 0xC0; | |
272 static const uint8_t kOne = 0xFF; | |
273 static const uint8_t k1Q = 0x40; | |
274 return make_oversized_texture_bitmap<uint8_t>( | |
275 ctx, result, width, height, kAlpha_8_GrPixelConfig, kZero, kOne, k3Q, kH alf, k1Q); | |
213 } | 276 } |
214 | 277 |
215 static SkShader* make_shader() { | 278 static SkShader* make_shader() { |
216 static const SkPoint pts[] = { {0, 0}, {20, 20} }; | 279 static const SkPoint pts[] = { {0, 0}, {20, 20} }; |
217 static const SkColor colors[] = { SK_ColorGREEN, SK_ColorYELLOW }; | 280 static const SkColor colors[] = { SK_ColorGREEN, SK_ColorYELLOW }; |
218 return SkGradientShader::CreateLinear(pts, colors, nullptr, 2, SkShader::kMi rror_TileMode); | 281 return SkGradientShader::CreateLinear(pts, colors, nullptr, 2, SkShader::kMi rror_TileMode); |
219 } | 282 } |
220 | 283 |
221 static SkShader* make_null_shader() { return nullptr; } | 284 static SkShader* make_null_shader() { return nullptr; } |
222 | 285 |
223 enum BleedTest { | 286 enum BleedTest { |
224 kUseBitmap_BleedTest, | 287 kUseBitmap_BleedTest, |
225 kUseTextureBitmap_BleedTest, | 288 kUseTextureBitmap_BleedTest, |
226 kUseImage_BleedTest, | 289 kUseImage_BleedTest, |
227 kUseAlphaBitmap_BleedTest, | 290 kUseAlphaBitmap_BleedTest, |
228 kUseAlphaTextureBitmap_BleedTest, | 291 kUseAlphaTextureBitmap_BleedTest, |
229 kUseAlphaImage_BleedTest, | 292 kUseAlphaImage_BleedTest, |
230 kUseAlphaBitmapShader_BleedTest, | 293 kUseAlphaBitmapShader_BleedTest, |
231 kUseAlphaTextureBitmapShader_BleedTest, | 294 kUseAlphaTextureBitmapShader_BleedTest, |
232 kUseAlphaImageShader_BleedTest, | 295 kUseAlphaImageShader_BleedTest, |
233 }; | 296 }; |
234 | 297 |
235 const struct { | 298 const struct { |
236 const char* fName; | 299 const char* fName; |
237 void(*fBmpMaker)(SkBitmap* result, int width, int height); | 300 bool (*fPixelMaker)(GrContext*, TestPixels* result, int width, int height); |
238 SkShader*(*fShaderMaker)(); | 301 SkShader* (*fShaderMaker)(); |
239 void(*fDraw)(SkCanvas*, const SkBitmap&, const SkImage*, const SkRect&, cons t SkRect&, | |
240 const SkPaint*, SkCanvas::SrcRectConstraint); | |
241 } gBleedRec[] = { | 302 } gBleedRec[] = { |
242 { "bleed", make_ringed_color_bitmap, make_null_shad er, draw_bitmap_rect }, | 303 { "bleed", make_ringed_color_bitmap, make_null_shader }, |
243 { "bleed_texture_bmp", make_ringed_color_bitmap, make_null_shad er, draw_texture_bitmap_rect }, | 304 { "bleed_texture_bmp", make_ringed_oversized_color_texture_bitm ap, make_null_shader }, |
244 { "bleed_image", make_ringed_color_bitmap, make_null_shad er, draw_image_rect }, | 305 { "bleed_image", make_ringed_color_image, make_null_shader }, |
245 { "bleed_alpha_bmp", make_ringed_alpha_bitmap, make_null_shad er, draw_bitmap_rect }, | 306 { "bleed_alpha_bmp", make_ringed_alpha_bitmap, make_null_shader }, |
246 { "bleed_alpha_texture_bmp", make_ringed_alpha_bitmap, make_null_shad er, draw_texture_bitmap_rect }, | 307 { "bleed_alpha_texture_bmp", make_ringed_oversized_alpha_texture_bitm ap, make_null_shader }, |
247 { "bleed_alpha_image", make_ringed_alpha_bitmap, make_null_shad er, draw_image_rect }, | 308 { "bleed_alpha_image", make_ringed_alpha_image, make_null_shader }, |
248 { "bleed_alpha_bmp_shader", make_ringed_alpha_bitmap, make_shader, draw_bitmap_rect }, | 309 { "bleed_alpha_bmp_shader", make_ringed_alpha_bitmap, make_shader }, |
249 { "bleed_alpha_texture_bmp_shader", make_ringed_alpha_bitmap, make_shader, draw_texture_bitmap_rect }, | 310 { "bleed_alpha_texture_bmp_shader", make_ringed_oversized_alpha_texture_bitm ap, make_shader }, |
250 { "bleed_alpha_image_shader", make_ringed_alpha_bitmap, make_shader, draw_image_rect }, | 311 { "bleed_alpha_image_shader", make_ringed_alpha_image, make_shader }, |
251 }; | 312 }; |
252 | 313 |
robertphillips
2015/11/09 17:11:39
// This GM exercises the behavior of the drawBitma
bsalomon
2015/11/09 17:44:11
Done
| |
253 // This GM exercises the drawBitmapRect constraints | 314 // This GM exercises the drawBitmapRect constraints |
254 class BleedGM : public skiagm::GM { | 315 class BleedGM : public skiagm::GM { |
255 public: | 316 public: |
256 BleedGM(BleedTest bt) : fBT(bt) {} | 317 BleedGM(BleedTest bt) : fBT(bt), fCreatedPixels(false) {} |
257 | 318 |
258 protected: | 319 protected: |
259 | 320 |
260 SkString onShortName() override { | 321 SkString onShortName() override { |
261 return SkString(gBleedRec[fBT].fName); | 322 return SkString(gBleedRec[fBT].fName); |
262 } | 323 } |
263 | 324 |
264 SkISize onISize() override { | 325 SkISize onISize() override { |
265 return SkISize::Make(1200, 1080); | 326 return SkISize::Make(1200, 1080); |
266 } | 327 } |
267 | 328 |
268 void onOnceBeforeDraw() override { | 329 void drawPixels(SkCanvas* canvas, const TestPixels& pixels, const SkRect& sr c, |
269 gBleedRec[fBT].fBmpMaker(&fBitmapSmall, kSmallTextureSize, kSmallTexture Size); | 330 const SkRect& dst, const SkPaint* paint, |
270 fImageSmall.reset(SkImage::NewFromBitmap(fBitmapSmall)); | 331 SkCanvas::SrcRectConstraint constraint) { |
271 | 332 if (TestPixels::kBitmap == pixels.fType) { |
272 // To exercise the GPU's tiling path we need a texture | 333 canvas->drawBitmapRect(pixels.fBitmap, src, dst, paint, constraint); |
273 // too big for the GPU to handle in one go | 334 } else { |
274 gBleedRec[fBT].fBmpMaker(&fBitmapBig, 2*kMaxTileSize, 2*kMaxTileSize); | 335 canvas->drawImageRect(pixels.fImage, src, dst, paint, constraint); |
275 fImageBig.reset(SkImage::NewFromBitmap(fBitmapBig)); | 336 } |
276 | |
277 fShader.reset(gBleedRec[fBT].fShaderMaker()); | |
278 } | 337 } |
279 | 338 |
280 // Draw only the center of the small bitmap | 339 // Draw the area of interest of the small image |
281 void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa, | 340 void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa, |
282 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { | 341 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { |
283 SkRect src = SkRect::MakeXYWH(2, 2, | 342 |
284 SkIntToScalar(kSmallTextureSize-4), | 343 SkRect src = SkRect::Make(fSmallTestPixels.fRect); |
285 SkIntToScalar(kSmallTextureSize-4)); | |
286 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), | 344 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), |
287 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); | 345 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); |
288 | 346 |
289 SkPaint paint; | 347 SkPaint paint; |
290 paint.setFilterQuality(filter); | 348 paint.setFilterQuality(filter); |
291 paint.setShader(fShader); | 349 paint.setShader(fShader); |
292 paint.setColor(SK_ColorBLUE); | 350 paint.setColor(SK_ColorBLUE); |
293 paint.setAntiAlias(aa); | 351 paint.setAntiAlias(aa); |
294 | 352 |
295 gBleedRec[fBT].fDraw(canvas, fBitmapSmall, fImageSmall, src, dst, &paint , constraint); | 353 this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint) ; |
296 } | 354 } |
297 | 355 |
298 // Draw almost all of the large bitmap | 356 // Draw the area of interest of the large image |
299 void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa, | 357 void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa, |
300 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { | 358 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { |
301 SkRect src = SkRect::MakeXYWH(2, 2, | 359 SkRect src = SkRect::Make(fBigTestPixels.fRect); |
302 SkIntToScalar(fBitmapBig.width()-4), | |
303 SkIntToScalar(fBitmapBig.height()-4)); | |
304 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), | 360 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), |
305 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); | 361 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); |
306 | 362 |
307 SkPaint paint; | 363 SkPaint paint; |
308 paint.setFilterQuality(filter); | 364 paint.setFilterQuality(filter); |
309 paint.setShader(fShader); | 365 paint.setShader(fShader); |
310 paint.setColor(SK_ColorBLUE); | 366 paint.setColor(SK_ColorBLUE); |
311 paint.setAntiAlias(aa); | 367 paint.setAntiAlias(aa); |
312 | 368 |
313 gBleedRec[fBT].fDraw(canvas, fBitmapBig, fImageBig, src, dst, &paint, co nstraint); | 369 this->drawPixels(canvas, fBigTestPixels, src, dst, &paint, constraint); |
314 } | 370 } |
315 | 371 |
316 // Draw ~1/4 of the large bitmap | 372 // Draw upper-left 1/4 of the area of interest of the large image |
317 void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa, | 373 void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa, |
318 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { | 374 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { |
319 SkRect src = SkRect::MakeXYWH(2, 2, | 375 SkRect src = SkRect::MakeXYWH(SkIntToScalar(fBigTestPixels.fRect.fLeft), |
320 SkIntToScalar(fBitmapBig.width()/2-2), | 376 SkIntToScalar(fBigTestPixels.fRect.fTop), |
321 SkIntToScalar(fBitmapBig.height()/2-2)); | 377 fBigTestPixels.fRect.width()/2.f, |
378 fBigTestPixels.fRect.height()/2.f); | |
322 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), | 379 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), |
323 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); | 380 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); |
324 | 381 |
325 SkPaint paint; | 382 SkPaint paint; |
326 paint.setFilterQuality(filter); | 383 paint.setFilterQuality(filter); |
327 paint.setShader(fShader); | 384 paint.setShader(fShader); |
328 paint.setColor(SK_ColorBLUE); | 385 paint.setColor(SK_ColorBLUE); |
329 paint.setAntiAlias(aa); | 386 paint.setAntiAlias(aa); |
330 | 387 |
331 gBleedRec[fBT].fDraw(canvas, fBitmapBig, fImageBig, src, dst, &paint, co nstraint); | 388 this->drawPixels(canvas, fBigTestPixels, src, dst, &paint, constraint); |
332 } | 389 } |
333 | 390 |
334 // Draw the center of the small bitmap with a normal blur | 391 // Draw the area of interest of the small image with a normal blur |
335 void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa, | 392 void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa, |
336 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { | 393 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { |
337 SkRect src = SkRect::MakeXYWH(2, 2, | 394 SkRect src = SkRect::Make(fSmallTestPixels.fRect); |
338 SkIntToScalar(kSmallTextureSize-4), | |
339 SkIntToScalar(kSmallTextureSize-4)); | |
340 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), | 395 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), |
341 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); | 396 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); |
342 | 397 |
343 SkPaint paint; | 398 SkPaint paint; |
344 paint.setFilterQuality(filter); | 399 paint.setFilterQuality(filter); |
345 SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, | 400 SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, |
346 SkBlurMask::ConvertRadiusToSigma(3)); | 401 SkBlurMask::ConvertRadiusToSigma(3)); |
347 paint.setMaskFilter(mf)->unref(); | 402 paint.setMaskFilter(mf)->unref(); |
348 paint.setShader(fShader); | 403 paint.setShader(fShader); |
349 paint.setColor(SK_ColorBLUE); | 404 paint.setColor(SK_ColorBLUE); |
350 paint.setAntiAlias(aa); | 405 paint.setAntiAlias(aa); |
351 | 406 |
352 gBleedRec[fBT].fDraw(canvas, fBitmapSmall, fImageSmall, src, dst, &paint , constraint); | 407 this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint) ; |
353 } | 408 } |
354 | 409 |
355 // Draw the center of the small bitmap with a outer blur | 410 // Draw the area of interest of the small image with a outer blur |
356 void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa, | 411 void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa, |
357 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { | 412 SkCanvas::SrcRectConstraint constraint, SkFilterQuality filte r) { |
358 SkRect src = SkRect::MakeXYWH(2, 2, | 413 SkRect src = SkRect::Make(fSmallTestPixels.fRect); |
359 SkIntToScalar(kSmallTextureSize - 4), | |
360 SkIntToScalar(kSmallTextureSize - 4)); | |
361 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), | 414 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(trans Y), |
362 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); | 415 SkIntToScalar(kBlockSize), SkIntToScalar(k BlockSize)); |
363 | 416 |
364 SkPaint paint; | 417 SkPaint paint; |
365 paint.setFilterQuality(filter); | 418 paint.setFilterQuality(filter); |
366 SkMaskFilter* mf = SkBlurMaskFilter::Create(kOuter_SkBlurStyle, | 419 SkMaskFilter* mf = SkBlurMaskFilter::Create(kOuter_SkBlurStyle, |
367 SkBlurMask::ConvertRadiusToS igma(7)); | 420 SkBlurMask::ConvertRadiusToS igma(7)); |
368 paint.setMaskFilter(mf)->unref(); | 421 paint.setMaskFilter(mf)->unref(); |
369 paint.setShader(fShader); | 422 paint.setShader(fShader); |
370 paint.setColor(SK_ColorBLUE); | 423 paint.setColor(SK_ColorBLUE); |
371 paint.setAntiAlias(aa); | 424 paint.setAntiAlias(aa); |
372 | 425 |
373 gBleedRec[fBT].fDraw(canvas, fBitmapSmall, fImageSmall, src, dst, &paint , constraint); | 426 this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint) ; |
374 } | 427 } |
375 | 428 |
376 void onDraw(SkCanvas* canvas) override { | 429 void onDraw(SkCanvas* canvas) override { |
430 // We don't create pixels in an onOnceBeforeDraw() override because we w ant access to | |
431 // GrContext. | |
432 GrContext* context = canvas->getGrContext(); | |
433 #if SK_SUPPORT_GPU | |
434 // Workaround for SampleApp. | |
435 if (GrTexture* tex = fBigTestPixels.fBitmap.getTexture()) { | |
436 if (tex->wasDestroyed()) { | |
437 fCreatedPixels = false; | |
438 } | |
439 } | |
440 #endif | |
441 bool madePixels = fCreatedPixels; | |
442 | |
443 if (!madePixels) { | |
444 madePixels = gBleedRec[fBT].fPixelMaker(context, &fSmallTestPixels, kSmallTextureSize, | |
445 kSmallTextureSize); | |
446 madePixels &= gBleedRec[fBT].fPixelMaker(context, &fBigTestPixels, 2 * kMaxTileSize, | |
447 2 * kMaxTileSize); | |
448 fCreatedPixels = madePixels; | |
449 } | |
450 | |
451 // Assume that if we coulnd't make the bitmap/image it's because it's a GPU test on a | |
452 // non-GPU backend. | |
453 if (!madePixels) { | |
454 skiagm::GM::DrawGpuOnlyMessage(canvas); | |
455 return; | |
456 } | |
457 | |
458 fShader.reset(gBleedRec[fBT].fShaderMaker()); | |
459 | |
377 canvas->clear(SK_ColorGRAY); | 460 canvas->clear(SK_ColorGRAY); |
378 SkTDArray<SkMatrix> matrices; | 461 SkTDArray<SkMatrix> matrices; |
379 // Draw with identity | 462 // Draw with identity |
380 *matrices.append() = SkMatrix::I(); | 463 *matrices.append() = SkMatrix::I(); |
381 | 464 |
382 // Draw with rotation and scale down in x, up in y. | 465 // Draw with rotation and scale down in x, up in y. |
383 SkMatrix m; | 466 SkMatrix m; |
384 static const SkScalar kBottom = SkIntToScalar(kRow4Y + kBlockSize + kBlo ckSpacing); | 467 static const SkScalar kBottom = SkIntToScalar(kRow4Y + kBlockSize + kBlo ckSpacing); |
385 m.setTranslate(0, kBottom); | 468 m.setTranslate(0, kBottom); |
386 m.preRotate(15.f, 0, kBottom + kBlockSpacing); | 469 m.preRotate(15.f, 0, kBottom + kBlockSpacing); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
479 | 562 |
480 static const int kRow0Y = kBlockSpacing; | 563 static const int kRow0Y = kBlockSpacing; |
481 static const int kRow1Y = 2*kBlockSpacing + kBlockSize; | 564 static const int kRow1Y = 2*kBlockSpacing + kBlockSize; |
482 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize; | 565 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize; |
483 static const int kRow3Y = 4*kBlockSpacing + 3*kBlockSize; | 566 static const int kRow3Y = 4*kBlockSpacing + 3*kBlockSize; |
484 static const int kRow4Y = 5*kBlockSpacing + 4*kBlockSize; | 567 static const int kRow4Y = 5*kBlockSpacing + 4*kBlockSize; |
485 | 568 |
486 static const int kSmallTextureSize = 6; | 569 static const int kSmallTextureSize = 6; |
487 static const int kMaxTileSize = 32; | 570 static const int kMaxTileSize = 32; |
488 | 571 |
489 SkBitmap fBitmapSmall; | 572 bool fCreatedPixels; |
490 SkBitmap fBitmapBig; | 573 TestPixels fBigTestPixels; |
491 SkAutoTUnref<SkImage> fImageSmall; | 574 TestPixels fSmallTestPixels; |
492 SkAutoTUnref<SkImage> fImageBig; | |
493 | 575 |
494 SkAutoTUnref<SkShader> fShader; | 576 SkAutoTUnref<SkShader> fShader; |
495 | 577 |
496 const BleedTest fBT; | 578 const BleedTest fBT; |
497 | 579 |
498 typedef GM INHERITED; | 580 typedef GM INHERITED; |
499 }; | 581 }; |
500 | 582 |
501 | 583 |
502 DEF_GM( return new BleedGM(kUseBitmap_BleedTest); ) | 584 DEF_GM( return new BleedGM(kUseBitmap_BleedTest); ) |
503 DEF_GM( return new BleedGM(kUseTextureBitmap_BleedTest); ) | 585 DEF_GM( return new BleedGM(kUseTextureBitmap_BleedTest); ) |
504 DEF_GM( return new BleedGM(kUseImage_BleedTest); ) | 586 DEF_GM( return new BleedGM(kUseImage_BleedTest); ) |
505 DEF_GM( return new BleedGM(kUseAlphaBitmap_BleedTest); ) | 587 DEF_GM( return new BleedGM(kUseAlphaBitmap_BleedTest); ) |
506 DEF_GM( return new BleedGM(kUseAlphaTextureBitmap_BleedTest); ) | 588 DEF_GM( return new BleedGM(kUseAlphaTextureBitmap_BleedTest); ) |
507 DEF_GM( return new BleedGM(kUseAlphaImage_BleedTest); ) | 589 DEF_GM( return new BleedGM(kUseAlphaImage_BleedTest); ) |
508 DEF_GM( return new BleedGM(kUseAlphaBitmapShader_BleedTest); ) | 590 DEF_GM( return new BleedGM(kUseAlphaBitmapShader_BleedTest); ) |
509 DEF_GM( return new BleedGM(kUseAlphaTextureBitmapShader_BleedTest); ) | 591 DEF_GM( return new BleedGM(kUseAlphaTextureBitmapShader_BleedTest); ) |
510 DEF_GM( return new BleedGM(kUseAlphaImageShader_BleedTest); ) | 592 DEF_GM( return new BleedGM(kUseAlphaImageShader_BleedTest); ) |
OLD | NEW |