OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "SkBBoxHierarchy.h" | 8 #include "SkBBoxHierarchy.h" |
9 #include "SkBlurImageFilter.h" | 9 #include "SkBlurImageFilter.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 | 31 |
32 #if SK_SUPPORT_GPU | 32 #if SK_SUPPORT_GPU |
33 #include "SkSurface.h" | 33 #include "SkSurface.h" |
34 #include "GrContextFactory.h" | 34 #include "GrContextFactory.h" |
35 #endif | 35 #endif |
36 #include "Test.h" | 36 #include "Test.h" |
37 | 37 |
38 #include "SkLumaColorFilter.h" | 38 #include "SkLumaColorFilter.h" |
39 #include "SkColorFilterImageFilter.h" | 39 #include "SkColorFilterImageFilter.h" |
40 | 40 |
41 static const int gColorScale = 30; | |
42 static const int gColorOffset = 60; | |
43 | |
44 static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) { | 41 static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) { |
45 bm->allocN32Pixels(w, h); | 42 bm->allocN32Pixels(w, h); |
46 bm->eraseColor(color); | 43 bm->eraseColor(color); |
47 if (immutable) { | 44 if (immutable) { |
48 bm->setImmutable(); | 45 bm->setImmutable(); |
49 } | 46 } |
50 } | 47 } |
51 | 48 |
52 static void make_checkerboard(SkBitmap* bm, int w, int h, bool immutable) { | |
53 SkASSERT(w % 2 == 0); | |
54 SkASSERT(h % 2 == 0); | |
55 bm->allocPixels(SkImageInfo::Make(w, h, kAlpha_8_SkColorType, | |
56 kPremul_SkAlphaType)); | |
57 SkAutoLockPixels lock(*bm); | |
58 for (int y = 0; y < h; y += 2) { | |
59 uint8_t* s = bm->getAddr8(0, y); | |
60 for (int x = 0; x < w; x += 2) { | |
61 *s++ = 0xFF; | |
62 *s++ = 0x00; | |
63 } | |
64 s = bm->getAddr8(0, y + 1); | |
65 for (int x = 0; x < w; x += 2) { | |
66 *s++ = 0x00; | |
67 *s++ = 0xFF; | |
68 } | |
69 } | |
70 if (immutable) { | |
71 bm->setImmutable(); | |
72 } | |
73 } | |
74 | |
75 static void init_paint(SkPaint* paint, const SkBitmap &bm) { | |
76 SkShader* shader = SkShader::CreateBitmapShader(bm, | |
77 SkShader::kClamp_TileMode, | |
78 SkShader::kClamp_TileMode); | |
79 paint->setShader(shader)->unref(); | |
80 } | |
81 | |
robertphillips
2015/01/22 15:37:05
Remove this?
reed1
2015/01/22 17:02:40
Will do in followup CL
| |
82 typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&, | 49 typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&, |
83 const SkBitmap&, const SkPoint&, | 50 const SkBitmap&, const SkPoint&, |
84 SkTDArray<SkPixelRef*>* usedPixRefs); | 51 SkTDArray<SkPixelRef*>* usedPixRefs); |
85 | 52 |
86 static void drawpaint_proc(SkCanvas* canvas, const SkBitmap& bm, | |
87 const SkBitmap& altBM, const SkPoint& pos, | |
88 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
89 SkPaint paint; | |
90 init_paint(&paint, bm); | |
91 | |
92 canvas->drawPaint(paint); | |
93 *usedPixRefs->append() = bm.pixelRef(); | |
94 } | |
95 | |
96 static void drawpoints_proc(SkCanvas* canvas, const SkBitmap& bm, | |
97 const SkBitmap& altBM, const SkPoint& pos, | |
98 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
99 SkPaint paint; | |
100 init_paint(&paint, bm); | |
101 | |
102 // draw a rect | |
103 SkPoint points[5] = { | |
104 { pos.fX, pos.fY }, | |
105 { pos.fX + bm.width() - 1, pos.fY }, | |
106 { pos.fX + bm.width() - 1, pos.fY + bm.height() - 1 }, | |
107 { pos.fX, pos.fY + bm.height() - 1 }, | |
108 { pos.fX, pos.fY }, | |
109 }; | |
110 | |
111 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 5, points, paint); | |
112 *usedPixRefs->append() = bm.pixelRef(); | |
113 } | |
114 | |
115 static void drawrect_proc(SkCanvas* canvas, const SkBitmap& bm, | |
116 const SkBitmap& altBM, const SkPoint& pos, | |
117 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
118 SkPaint paint; | |
119 init_paint(&paint, bm); | |
120 | |
121 SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }; | |
122 r.offset(pos.fX, pos.fY); | |
123 | |
124 canvas->drawRect(r, paint); | |
125 *usedPixRefs->append() = bm.pixelRef(); | |
126 } | |
127 | |
128 static void drawoval_proc(SkCanvas* canvas, const SkBitmap& bm, | |
129 const SkBitmap& altBM, const SkPoint& pos, | |
130 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
131 SkPaint paint; | |
132 init_paint(&paint, bm); | |
133 | |
134 SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }; | |
135 r.offset(pos.fX, pos.fY); | |
136 | |
137 canvas->drawOval(r, paint); | |
138 *usedPixRefs->append() = bm.pixelRef(); | |
139 } | |
140 | |
141 static void drawrrect_proc(SkCanvas* canvas, const SkBitmap& bm, | |
142 const SkBitmap& altBM, const SkPoint& pos, | |
143 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
144 SkPaint paint; | |
145 init_paint(&paint, bm); | |
146 | |
147 SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }; | |
148 r.offset(pos.fX, pos.fY); | |
149 | |
150 SkRRect rr; | |
151 rr.setRectXY(r, SkIntToScalar(bm.width())/4, SkIntToScalar(bm.height())/4); | |
152 canvas->drawRRect(rr, paint); | |
153 *usedPixRefs->append() = bm.pixelRef(); | |
154 } | |
155 | |
156 static void drawpath_proc(SkCanvas* canvas, const SkBitmap& bm, | |
157 const SkBitmap& altBM, const SkPoint& pos, | |
158 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
159 SkPaint paint; | |
160 init_paint(&paint, bm); | |
161 | |
162 SkPath path; | |
163 path.lineTo(bm.width()/2.0f, SkIntToScalar(bm.height())); | |
164 path.lineTo(SkIntToScalar(bm.width()), 0); | |
165 path.close(); | |
166 path.offset(pos.fX, pos.fY); | |
167 | |
168 canvas->drawPath(path, paint); | |
169 *usedPixRefs->append() = bm.pixelRef(); | |
170 } | |
171 | |
172 static void drawbitmap_proc(SkCanvas* canvas, const SkBitmap& bm, | |
173 const SkBitmap& altBM, const SkPoint& pos, | |
174 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
175 canvas->drawBitmap(bm, pos.fX, pos.fY, NULL); | |
176 *usedPixRefs->append() = bm.pixelRef(); | |
177 } | |
178 | |
179 static void drawbitmap_withshader_proc(SkCanvas* canvas, const SkBitmap& bm, | |
180 const SkBitmap& altBM, const SkPoint& pos , | |
181 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
182 SkPaint paint; | |
183 init_paint(&paint, bm); | |
184 | |
185 // The bitmap in the paint is ignored unless we're drawing an A8 bitmap | |
186 canvas->drawBitmap(altBM, pos.fX, pos.fY, &paint); | |
187 *usedPixRefs->append() = bm.pixelRef(); | |
188 *usedPixRefs->append() = altBM.pixelRef(); | |
189 } | |
190 | |
191 static void drawsprite_proc(SkCanvas* canvas, const SkBitmap& bm, | |
192 const SkBitmap& altBM, const SkPoint& pos, | |
193 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
194 const SkMatrix& ctm = canvas->getTotalMatrix(); | |
195 | |
196 SkPoint p(pos); | |
197 ctm.mapPoints(&p, 1); | |
198 | |
199 canvas->drawSprite(bm, (int)p.fX, (int)p.fY, NULL); | |
200 *usedPixRefs->append() = bm.pixelRef(); | |
201 } | |
202 | |
robertphillips
2015/01/22 15:37:05
Remove this too
reed1
2015/01/22 17:02:40
Will do in followup CL
| |
203 #if 0 | 53 #if 0 |
204 // Although specifiable, this case doesn't seem to make sense (i.e., the | 54 // Although specifiable, this case doesn't seem to make sense (i.e., the |
205 // bitmap in the shader is never used). | 55 // bitmap in the shader is never used). |
206 static void drawsprite_withshader_proc(SkCanvas* canvas, const SkBitmap& bm, | 56 static void drawsprite_withshader_proc(SkCanvas* canvas, const SkBitmap& bm, |
207 const SkBitmap& altBM, const SkPoint& pos , | 57 const SkBitmap& altBM, const SkPoint& pos , |
208 SkTDArray<SkPixelRef*>* usedPixRefs) { | 58 SkTDArray<SkPixelRef*>* usedPixRefs) { |
209 SkPaint paint; | 59 SkPaint paint; |
210 init_paint(&paint, bm); | 60 init_paint(&paint, bm); |
211 | 61 |
212 const SkMatrix& ctm = canvas->getTotalMatrix(); | 62 const SkMatrix& ctm = canvas->getTotalMatrix(); |
213 | 63 |
214 SkPoint p(pos); | 64 SkPoint p(pos); |
215 ctm.mapPoints(&p, 1); | 65 ctm.mapPoints(&p, 1); |
216 | 66 |
217 canvas->drawSprite(altBM, (int)p.fX, (int)p.fY, &paint); | 67 canvas->drawSprite(altBM, (int)p.fX, (int)p.fY, &paint); |
218 *usedPixRefs->append() = bm.pixelRef(); | 68 *usedPixRefs->append() = bm.pixelRef(); |
219 *usedPixRefs->append() = altBM.pixelRef(); | 69 *usedPixRefs->append() = altBM.pixelRef(); |
220 } | 70 } |
221 #endif | 71 #endif |
222 | 72 |
223 static void drawbitmaprect_proc(SkCanvas* canvas, const SkBitmap& bm, | |
224 const SkBitmap& altBM, const SkPoint& pos, | |
225 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
226 SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }; | |
227 | |
228 r.offset(pos.fX, pos.fY); | |
229 canvas->drawBitmapRectToRect(bm, NULL, r, NULL); | |
230 *usedPixRefs->append() = bm.pixelRef(); | |
231 } | |
232 | |
233 static void drawbitmaprect_withshader_proc(SkCanvas* canvas, | |
234 const SkBitmap& bm, | |
235 const SkBitmap& altBM, | |
236 const SkPoint& pos, | |
237 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
238 SkPaint paint; | |
239 init_paint(&paint, bm); | |
240 | |
241 SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }; | |
242 r.offset(pos.fX, pos.fY); | |
243 | |
244 // The bitmap in the paint is ignored unless we're drawing an A8 bitmap | |
245 canvas->drawBitmapRectToRect(altBM, NULL, r, &paint); | |
246 *usedPixRefs->append() = bm.pixelRef(); | |
247 *usedPixRefs->append() = altBM.pixelRef(); | |
248 } | |
249 | |
250 static void drawtext_proc(SkCanvas* canvas, const SkBitmap& bm, | |
251 const SkBitmap& altBM, const SkPoint& pos, | |
252 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
253 SkPaint paint; | |
254 init_paint(&paint, bm); | |
255 paint.setTextSize(SkIntToScalar(1.5*bm.width())); | |
256 | |
257 canvas->drawText("0", 1, pos.fX, pos.fY+bm.width(), paint); | |
258 *usedPixRefs->append() = bm.pixelRef(); | |
259 } | |
260 | |
261 static void drawpostext_proc(SkCanvas* canvas, const SkBitmap& bm, | |
262 const SkBitmap& altBM, const SkPoint& pos, | |
263 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
264 SkPaint paint; | |
265 init_paint(&paint, bm); | |
266 paint.setTextSize(SkIntToScalar(1.5*bm.width())); | |
267 | |
268 SkPoint point = { pos.fX, pos.fY + bm.height() }; | |
269 canvas->drawPosText("O", 1, &point, paint); | |
270 *usedPixRefs->append() = bm.pixelRef(); | |
271 } | |
272 | |
273 static void drawtextonpath_proc(SkCanvas* canvas, const SkBitmap& bm, | |
274 const SkBitmap& altBM, const SkPoint& pos, | |
275 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
276 SkPaint paint; | |
277 | |
278 init_paint(&paint, bm); | |
279 paint.setTextSize(SkIntToScalar(1.5*bm.width())); | |
280 | |
281 SkPath path; | |
282 path.lineTo(SkIntToScalar(bm.width()), 0); | |
283 path.offset(pos.fX, pos.fY+bm.height()); | |
284 | |
285 canvas->drawTextOnPath("O", 1, path, NULL, paint); | |
286 *usedPixRefs->append() = bm.pixelRef(); | |
287 } | |
288 | |
289 static void drawverts_proc(SkCanvas* canvas, const SkBitmap& bm, | |
290 const SkBitmap& altBM, const SkPoint& pos, | |
291 SkTDArray<SkPixelRef*>* usedPixRefs) { | |
292 SkPaint paint; | |
293 init_paint(&paint, bm); | |
294 | |
295 SkPoint verts[4] = { | |
296 { pos.fX, pos.fY }, | |
297 { pos.fX + bm.width(), pos.fY }, | |
298 { pos.fX + bm.width(), pos.fY + bm.height() }, | |
299 { pos.fX, pos.fY + bm.height() } | |
300 }; | |
301 SkPoint texs[4] = { { 0, 0 }, | |
302 { SkIntToScalar(bm.width()), 0 }, | |
303 { SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }, | |
304 { 0, SkIntToScalar(bm.height()) } }; | |
305 uint16_t indices[6] = { 0, 1, 2, 0, 2, 3 }; | |
306 | |
307 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, 4, verts, texs, NULL, NULL, | |
308 indices, 6, paint); | |
309 *usedPixRefs->append() = bm.pixelRef(); | |
310 } | |
311 | |
312 // Return a picture with the bitmaps drawn at the specified positions. | |
313 static SkPicture* record_bitmaps(const SkBitmap bm[], | |
314 const SkPoint pos[], | |
315 SkTDArray<SkPixelRef*> analytic[], | |
316 int count, | |
317 DrawBitmapProc proc) { | |
318 SkPictureRecorder recorder; | |
319 SkCanvas* canvas = recorder.beginRecording(1000, 1000); | |
320 for (int i = 0; i < count; ++i) { | |
321 analytic[i].rewind(); | |
322 canvas->save(); | |
323 SkRect clipRect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY, | |
324 SkIntToScalar(bm[i].width()), | |
325 SkIntToScalar(bm[i].height())); | |
326 canvas->clipRect(clipRect, SkRegion::kIntersect_Op); | |
327 proc(canvas, bm[i], bm[count+i], pos[i], &analytic[i]); | |
328 canvas->restore(); | |
329 } | |
330 return recorder.endRecording(); | |
331 } | |
332 | |
333 static void rand_rect(SkRect* rect, SkRandom& rand, SkScalar W, SkScalar H) { | |
334 rect->fLeft = rand.nextRangeScalar(-W, 2*W); | |
335 rect->fTop = rand.nextRangeScalar(-H, 2*H); | |
336 rect->fRight = rect->fLeft + rand.nextRangeScalar(0, W); | |
337 rect->fBottom = rect->fTop + rand.nextRangeScalar(0, H); | |
338 | |
339 // we integralize rect to make our tests more predictable, since Gather is | |
340 // a little sloppy. | |
341 SkIRect ir; | |
342 rect->round(&ir); | |
343 rect->set(ir); | |
344 } | |
345 | |
346 static void draw(SkPicture* pic, int width, int height, SkBitmap* result) { | |
347 make_bm(result, width, height, SK_ColorBLACK, false); | |
348 | |
349 SkCanvas canvas(*result); | |
350 canvas.drawPicture(pic); | |
351 } | |
352 | |
353 template <typename T> int find_index(const T* array, T elem, int count) { | |
354 for (int i = 0; i < count; ++i) { | |
355 if (array[i] == elem) { | |
356 return i; | |
357 } | |
358 } | |
359 return -1; | |
360 } | |
361 | |
362 // Return true if 'ref' is found in array[] | |
363 static bool find(SkPixelRef const * const * array, SkPixelRef const * ref, int c ount) { | |
364 return find_index<const SkPixelRef*>(array, ref, count) >= 0; | |
365 } | |
366 | |
367 // Look at each pixel that is inside 'subset', and if its color appears in | |
368 // colors[], find the corresponding value in refs[] and append that ref into | |
369 // array, skipping duplicates of the same value. | |
370 // Note that gathering pixelRefs from rendered colors suffers from the problem | |
371 // that multiple simultaneous textures (e.g., A8 for alpha and 8888 for color) | |
372 // isn't easy to reconstruct. | |
373 static void gather_from_image(const SkBitmap& bm, SkPixelRef* const refs[], | |
374 int count, SkTDArray<SkPixelRef*>* array, | |
375 const SkRect& subset) { | |
376 SkIRect ir; | |
377 subset.roundOut(&ir); | |
378 | |
379 if (!ir.intersect(0, 0, bm.width()-1, bm.height()-1)) { | |
380 return; | |
381 } | |
382 | |
383 // Since we only want to return unique values in array, when we scan we just | |
384 // set a bit for each index'd color found. In practice we only have a few | |
385 // distinct colors, so we just use an int's bits as our array. Hence the | |
386 // assert that count <= number-of-bits-in-our-int. | |
387 SkASSERT((unsigned)count <= 32); | |
388 uint32_t bitarray = 0; | |
389 | |
390 SkAutoLockPixels alp(bm); | |
391 | |
392 for (int y = ir.fTop; y < ir.fBottom; ++y) { | |
393 for (int x = ir.fLeft; x < ir.fRight; ++x) { | |
394 SkPMColor pmc = *bm.getAddr32(x, y); | |
395 // the only good case where the color is not found would be if | |
396 // the color is transparent, meaning no bitmap was drawn in that | |
397 // pixel. | |
398 if (pmc) { | |
399 uint32_t index = SkGetPackedR32(pmc); | |
400 SkASSERT(SkGetPackedG32(pmc) == index); | |
401 SkASSERT(SkGetPackedB32(pmc) == index); | |
402 if (0 == index) { | |
403 continue; // background color | |
404 } | |
405 SkASSERT(0 == (index - gColorOffset) % gColorScale); | |
406 index = (index - gColorOffset) / gColorScale; | |
407 SkASSERT(static_cast<int>(index) < count); | |
408 bitarray |= 1 << index; | |
409 } | |
410 } | |
411 } | |
412 | |
413 for (int i = 0; i < count; ++i) { | |
414 if (bitarray & (1 << i)) { | |
415 *array->append() = refs[i]; | |
416 } | |
417 } | |
418 } | |
419 | |
420 static void gather_from_analytic(const SkPoint pos[], SkScalar w, SkScalar h, | |
421 const SkTDArray<SkPixelRef*> analytic[], | |
422 int count, | |
423 SkTDArray<SkPixelRef*>* result, | |
424 const SkRect& subset) { | |
425 for (int i = 0; i < count; ++i) { | |
426 SkRect rect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY, w, h); | |
427 | |
428 if (SkRect::Intersects(subset, rect)) { | |
429 result->append(analytic[i].count(), analytic[i].begin()); | |
430 } | |
431 } | |
432 } | |
433 | |
434 | |
435 static const struct { | |
436 const DrawBitmapProc proc; | |
437 const char* const desc; | |
438 } gProcs[] = { | |
439 {drawpaint_proc, "drawpaint"}, | |
440 {drawpoints_proc, "drawpoints"}, | |
441 {drawrect_proc, "drawrect"}, | |
442 {drawoval_proc, "drawoval"}, | |
443 {drawrrect_proc, "drawrrect"}, | |
444 {drawpath_proc, "drawpath"}, | |
445 {drawbitmap_proc, "drawbitmap"}, | |
446 {drawbitmap_withshader_proc, "drawbitmap_withshader"}, | |
447 {drawsprite_proc, "drawsprite"}, | |
448 #if 0 | |
449 {drawsprite_withshader_proc, "drawsprite_withshader"}, | |
450 #endif | |
451 {drawbitmaprect_proc, "drawbitmaprect"}, | |
452 {drawbitmaprect_withshader_proc, "drawbitmaprect_withshader"}, | |
453 {drawtext_proc, "drawtext"}, | |
454 {drawpostext_proc, "drawpostext"}, | |
455 {drawtextonpath_proc, "drawtextonpath"}, | |
456 {drawverts_proc, "drawverts"}, | |
457 }; | |
458 | |
459 static void create_textures(SkBitmap* bm, SkPixelRef** refs, int num, int w, int h) { | |
460 // Our convention is that the color components contain an encoding of | |
461 // the index of their corresponding bitmap/pixelref. (0,0,0,0) is | |
462 // reserved for the background | |
463 for (int i = 0; i < num; ++i) { | |
464 make_bm(&bm[i], w, h, | |
465 SkColorSetARGB(0xFF, | |
466 gColorScale*i+gColorOffset, | |
467 gColorScale*i+gColorOffset, | |
468 gColorScale*i+gColorOffset), | |
469 true); | |
470 refs[i] = bm[i].pixelRef(); | |
471 } | |
472 | |
473 // The A8 alternate bitmaps are all BW checkerboards | |
474 for (int i = 0; i < num; ++i) { | |
475 make_checkerboard(&bm[num+i], w, h, true); | |
476 refs[num+i] = bm[num+i].pixelRef(); | |
477 } | |
478 } | |
479 | |
480 static void test_gatherpixelrefs(skiatest::Reporter* reporter) { | |
481 const int IW = 32; | |
482 const int IH = IW; | |
483 const SkScalar W = SkIntToScalar(IW); | |
484 const SkScalar H = W; | |
485 | |
486 static const int N = 4; | |
487 SkBitmap bm[2*N]; | |
488 SkPixelRef* refs[2*N]; | |
489 SkTDArray<SkPixelRef*> analytic[N]; | |
490 | |
491 const SkPoint pos[N] = { | |
492 { 0, 0 }, { W, 0 }, { 0, H }, { W, H } | |
493 }; | |
494 | |
495 create_textures(bm, refs, N, IW, IH); | |
496 | |
497 SkRandom rand; | |
498 for (size_t k = 0; k < SK_ARRAY_COUNT(gProcs); ++k) { | |
499 SkAutoTUnref<SkPicture> pic( | |
500 record_bitmaps(bm, pos, analytic, N, gProcs[k].proc)); | |
501 | |
502 REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0); | |
503 // quick check for a small piece of each quadrant, which should just | |
504 // contain 1 or 2 bitmaps. | |
505 for (size_t i = 0; i < SK_ARRAY_COUNT(pos); ++i) { | |
506 SkRect r; | |
507 r.set(2, 2, W - 2, H - 2); | |
508 r.offset(pos[i].fX, pos[i].fY); | |
509 SkAutoDataUnref data(SkPictureUtils::GatherPixelRefs(pic, r)); | |
510 if (!data) { | |
511 ERRORF(reporter, "SkPictureUtils::GatherPixelRefs returned " | |
512 "NULL for %s.", gProcs[k].desc); | |
513 continue; | |
514 } | |
515 SkPixelRef** gatheredRefs = (SkPixelRef**)data->data(); | |
516 int count = static_cast<int>(data->size() / sizeof(SkPixelRef*)); | |
517 REPORTER_ASSERT(reporter, 1 == count || 2 == count); | |
518 if (1 == count) { | |
519 REPORTER_ASSERT(reporter, gatheredRefs[0] == refs[i]); | |
520 } else if (2 == count) { | |
521 REPORTER_ASSERT(reporter, | |
522 (gatheredRefs[0] == refs[i] && gatheredRefs[1] == refs[i+N]) || | |
523 (gatheredRefs[1] == refs[i] && gatheredRefs[0] == refs[i+N]) ); | |
524 } | |
525 } | |
526 | |
527 SkBitmap image; | |
528 draw(pic, 2*IW, 2*IH, &image); | |
529 | |
530 // Test a bunch of random (mostly) rects, and compare the gather results | |
531 // with a deduced list of refs by looking at the colors drawn. | |
532 for (int j = 0; j < 100; ++j) { | |
533 SkRect r; | |
534 rand_rect(&r, rand, 2*W, 2*H); | |
535 | |
536 SkTDArray<SkPixelRef*> fromImage; | |
537 gather_from_image(image, refs, N, &fromImage, r); | |
538 | |
539 SkTDArray<SkPixelRef*> fromAnalytic; | |
540 gather_from_analytic(pos, W, H, analytic, N, &fromAnalytic, r); | |
541 | |
542 SkData* data = SkPictureUtils::GatherPixelRefs(pic, r); | |
543 size_t dataSize = data ? data->size() : 0; | |
544 int gatherCount = static_cast<int>(dataSize / sizeof(SkPixelRef*)); | |
545 SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize); | |
546 SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL ; | |
547 SkAutoDataUnref adu(data); | |
548 | |
549 // Everything that we saw drawn should appear in the analytic list | |
550 // but the analytic list may contain some pixelRefs that were not | |
551 // seen in the image (e.g., A8 textures used as masks) | |
552 for (int i = 0; i < fromImage.count(); ++i) { | |
553 if (-1 == fromAnalytic.find(fromImage[i])) { | |
554 ERRORF(reporter, "PixelRef missing %d %s", | |
555 i, gProcs[k].desc); | |
556 } | |
557 } | |
558 | |
559 /* | |
560 * GatherPixelRefs is conservative, so it can return more bitmaps | |
561 * than are strictly required. Thus our check here is only that | |
562 * Gather didn't miss any that we actually needed. Even that isn't | |
563 * a strict requirement on Gather, which is meant to be quick and | |
564 * only mostly-correct, but at the moment this test should work. | |
565 */ | |
566 for (int i = 0; i < fromAnalytic.count(); ++i) { | |
567 bool found = find(gatherRefs, fromAnalytic[i], gatherCount); | |
568 if (!found) { | |
569 ERRORF(reporter, "PixelRef missing %d %s", | |
570 i, gProcs[k].desc); | |
571 } | |
572 #if 0 | |
573 // enable this block of code to debug failures, as it will rerun | |
574 // the case that failed. | |
575 if (!found) { | |
576 SkData* data = SkPictureUtils::GatherPixelRefs(pic, r); | |
577 size_t dataSize = data ? data->size() : 0; | |
578 } | |
579 #endif | |
580 } | |
581 } | |
582 } | |
583 } | |
584 | |
585 /* Hit a few SkPicture::Analysis cases not handled elsewhere. */ | 73 /* Hit a few SkPicture::Analysis cases not handled elsewhere. */ |
586 static void test_analysis(skiatest::Reporter* reporter) { | 74 static void test_analysis(skiatest::Reporter* reporter) { |
587 SkPictureRecorder recorder; | 75 SkPictureRecorder recorder; |
588 | 76 |
589 SkCanvas* canvas = recorder.beginRecording(100, 100); | 77 SkCanvas* canvas = recorder.beginRecording(100, 100); |
590 { | 78 { |
591 canvas->drawRect(SkRect::MakeWH(10, 10), SkPaint ()); | 79 canvas->drawRect(SkRect::MakeWH(10, 10), SkPaint ()); |
592 } | 80 } |
593 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); | 81 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); |
594 REPORTER_ASSERT(reporter, !picture->willPlayBackBitmaps()); | 82 REPORTER_ASSERT(reporter, !picture->willPlayBackBitmaps()); |
(...skipping 13 matching lines...) Expand all Loading... | |
608 REPORTER_ASSERT(reporter, | 96 REPORTER_ASSERT(reporter, |
609 shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefaul t_BitmapType); | 97 shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefaul t_BitmapType); |
610 | 98 |
611 canvas->drawRect(SkRect::MakeWH(10, 10), paint); | 99 canvas->drawRect(SkRect::MakeWH(10, 10), paint); |
612 } | 100 } |
613 picture.reset(recorder.endRecording()); | 101 picture.reset(recorder.endRecording()); |
614 REPORTER_ASSERT(reporter, picture->willPlayBackBitmaps()); | 102 REPORTER_ASSERT(reporter, picture->willPlayBackBitmaps()); |
615 } | 103 } |
616 | 104 |
617 | 105 |
618 static void test_gatherpixelrefsandrects(skiatest::Reporter* reporter) { | |
619 const int IW = 32; | |
620 const int IH = IW; | |
621 const SkScalar W = SkIntToScalar(IW); | |
622 const SkScalar H = W; | |
623 | |
624 static const int N = 4; | |
625 SkBitmap bm[2*N]; | |
626 SkPixelRef* refs[2*N]; | |
627 SkTDArray<SkPixelRef*> analytic[N]; | |
628 | |
629 const SkPoint pos[N] = { | |
630 { 0, 0 }, { W, 0 }, { 0, H }, { W, H } | |
631 }; | |
632 | |
633 create_textures(bm, refs, N, IW, IH); | |
634 | |
635 SkRandom rand; | |
636 for (size_t k = 0; k < SK_ARRAY_COUNT(gProcs); ++k) { | |
637 SkAutoTUnref<SkPicture> pic( | |
638 record_bitmaps(bm, pos, analytic, N, gProcs[k].proc)); | |
639 | |
640 REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0); | |
641 | |
642 SkAutoTUnref<SkPictureUtils::SkPixelRefContainer> prCont( | |
643 new SkPictureUtils::SkPixelRefsAndRectsList); | |
644 | |
645 SkPictureUtils::GatherPixelRefsAndRects(pic, prCont); | |
646 | |
647 // quick check for a small piece of each quadrant, which should just | |
648 // contain 1 or 2 bitmaps. | |
649 for (size_t i = 0; i < SK_ARRAY_COUNT(pos); ++i) { | |
650 SkRect r; | |
651 r.set(2, 2, W - 2, H - 2); | |
652 r.offset(pos[i].fX, pos[i].fY); | |
653 | |
654 SkTDArray<SkPixelRef*> gatheredRefs; | |
655 prCont->query(r, &gatheredRefs); | |
656 | |
657 int count = gatheredRefs.count(); | |
658 REPORTER_ASSERT(reporter, 1 == count || 2 == count); | |
659 if (1 == count) { | |
660 REPORTER_ASSERT(reporter, gatheredRefs[0] == refs[i]); | |
661 } else if (2 == count) { | |
662 REPORTER_ASSERT(reporter, | |
663 (gatheredRefs[0] == refs[i] && gatheredRefs[1] == refs[i+N]) || | |
664 (gatheredRefs[1] == refs[i] && gatheredRefs[0] == refs[i+N]) ); | |
665 } | |
666 } | |
667 | |
668 SkBitmap image; | |
669 draw(pic, 2*IW, 2*IH, &image); | |
670 | |
671 // Test a bunch of random (mostly) rects, and compare the gather results | |
672 // with the analytic results and the pixel refs seen in a rendering. | |
673 for (int j = 0; j < 100; ++j) { | |
674 SkRect r; | |
675 rand_rect(&r, rand, 2*W, 2*H); | |
676 | |
677 SkTDArray<SkPixelRef*> fromImage; | |
678 gather_from_image(image, refs, N, &fromImage, r); | |
679 | |
680 SkTDArray<SkPixelRef*> fromAnalytic; | |
681 gather_from_analytic(pos, W, H, analytic, N, &fromAnalytic, r); | |
682 | |
683 SkTDArray<SkPixelRef*> gatheredRefs; | |
684 prCont->query(r, &gatheredRefs); | |
685 | |
686 // Everything that we saw drawn should appear in the analytic list | |
687 // but the analytic list may contain some pixelRefs that were not | |
688 // seen in the image (e.g., A8 textures used as masks) | |
689 for (int i = 0; i < fromImage.count(); ++i) { | |
690 REPORTER_ASSERT(reporter, -1 != fromAnalytic.find(fromImage[i])) ; | |
691 } | |
692 | |
693 // Everything in the analytic list should appear in the gathered | |
694 // list. | |
695 for (int i = 0; i < fromAnalytic.count(); ++i) { | |
696 REPORTER_ASSERT(reporter, -1 != gatheredRefs.find(fromAnalytic[i ])); | |
697 } | |
698 } | |
699 } | |
700 } | |
701 | |
702 #ifdef SK_DEBUG | 106 #ifdef SK_DEBUG |
703 // Ensure that deleting an empty SkPicture does not assert. Asserts only fire | 107 // Ensure that deleting an empty SkPicture does not assert. Asserts only fire |
704 // in debug mode, so only run in debug mode. | 108 // in debug mode, so only run in debug mode. |
705 static void test_deleting_empty_picture() { | 109 static void test_deleting_empty_picture() { |
706 SkPictureRecorder recorder; | 110 SkPictureRecorder recorder; |
707 // Creates an SkPictureRecord | 111 // Creates an SkPictureRecord |
708 recorder.beginRecording(0, 0); | 112 recorder.beginRecording(0, 0); |
709 // Turns that into an SkPicture | 113 // Turns that into an SkPicture |
710 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); | 114 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); |
711 // Ceates a new SkPictureRecord | 115 // Ceates a new SkPictureRecord |
(...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1762 #else | 1166 #else |
1763 test_bad_bitmap(); | 1167 test_bad_bitmap(); |
1764 #endif | 1168 #endif |
1765 test_unbalanced_save_restores(reporter); | 1169 test_unbalanced_save_restores(reporter); |
1766 test_peephole(); | 1170 test_peephole(); |
1767 #if SK_SUPPORT_GPU | 1171 #if SK_SUPPORT_GPU |
1768 test_gpu_veto(reporter); | 1172 test_gpu_veto(reporter); |
1769 #endif | 1173 #endif |
1770 test_has_text(reporter); | 1174 test_has_text(reporter); |
1771 test_analysis(reporter); | 1175 test_analysis(reporter); |
1772 test_gatherpixelrefs(reporter); | |
1773 test_gatherpixelrefsandrects(reporter); | |
1774 test_bitmap_with_encoded_data(reporter); | 1176 test_bitmap_with_encoded_data(reporter); |
1775 test_clip_bound_opt(reporter); | 1177 test_clip_bound_opt(reporter); |
1776 test_clip_expansion(reporter); | 1178 test_clip_expansion(reporter); |
1777 test_hierarchical(reporter); | 1179 test_hierarchical(reporter); |
1778 test_gen_id(reporter); | 1180 test_gen_id(reporter); |
1779 test_savelayer_extraction(reporter); | 1181 test_savelayer_extraction(reporter); |
1780 test_bytes_used(reporter); | 1182 test_bytes_used(reporter); |
1781 } | 1183 } |
1782 | 1184 |
1783 static void draw_bitmaps(const SkBitmap bitmap, SkCanvas* canvas) { | 1185 static void draw_bitmaps(const SkBitmap bitmap, SkCanvas* canvas) { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1927 | 1329 |
1928 // The picture shares the immutable pixels but copies the mutable ones. | 1330 // The picture shares the immutable pixels but copies the mutable ones. |
1929 REPORTER_ASSERT(r, mut.pixelRef()->unique()); | 1331 REPORTER_ASSERT(r, mut.pixelRef()->unique()); |
1930 REPORTER_ASSERT(r, !immut.pixelRef()->unique()); | 1332 REPORTER_ASSERT(r, !immut.pixelRef()->unique()); |
1931 | 1333 |
1932 // When the picture goes away, it's just our bitmaps holding the refs. | 1334 // When the picture goes away, it's just our bitmaps holding the refs. |
1933 pic.reset(NULL); | 1335 pic.reset(NULL); |
1934 REPORTER_ASSERT(r, mut.pixelRef()->unique()); | 1336 REPORTER_ASSERT(r, mut.pixelRef()->unique()); |
1935 REPORTER_ASSERT(r, immut.pixelRef()->unique()); | 1337 REPORTER_ASSERT(r, immut.pixelRef()->unique()); |
1936 } | 1338 } |
OLD | NEW |