OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SkBitmapDevice.h" | 8 #include "SkBitmapDevice.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 | 53 |
54 static SkPMColor getBitmapColor(int x, int y, int w) { | 54 static SkPMColor getBitmapColor(int x, int y, int w) { |
55 int n = y * w + x; | 55 int n = y * w + x; |
56 | 56 |
57 U8CPU b = n & 0xff; | 57 U8CPU b = n & 0xff; |
58 U8CPU g = (n >> 8) & 0xff; | 58 U8CPU g = (n >> 8) & 0xff; |
59 U8CPU r = (n >> 16) & 0xff; | 59 U8CPU r = (n >> 16) & 0xff; |
60 return SkPackARGB32(0xff, r, g , b); | 60 return SkPackARGB32(0xff, r, g , b); |
61 } | 61 } |
62 | 62 |
63 static SkPMColor convertConfig8888ToPMColor(SkCanvas::Config8888 config8888, | 63 static SkPMColor convertToPMColor(SkColorType ct, SkAlphaType at, const uint32_t
* addr, |
64 uint32_t color, | 64 bool* doUnpremul) { |
65 bool* premul) { | 65 *doUnpremul = (kUnpremul_SkAlphaType == at); |
66 const uint8_t* c = reinterpret_cast<uint8_t*>(&color); | 66 |
| 67 const uint8_t* c = reinterpret_cast<const uint8_t*>(addr); |
67 U8CPU a,r,g,b; | 68 U8CPU a,r,g,b; |
68 *premul = false; | 69 switch (ct) { |
69 switch (config8888) { | 70 case kBGRA_8888_SkColorType: |
70 case SkCanvas::kNative_Premul_Config8888: | 71 b = static_cast<U8CPU>(c[0]); |
71 return color; | 72 g = static_cast<U8CPU>(c[1]); |
72 case SkCanvas::kNative_Unpremul_Config8888: | 73 r = static_cast<U8CPU>(c[2]); |
73 *premul = true; | 74 a = static_cast<U8CPU>(c[3]); |
74 a = SkGetPackedA32(color); | |
75 r = SkGetPackedR32(color); | |
76 g = SkGetPackedG32(color); | |
77 b = SkGetPackedB32(color); | |
78 break; | 75 break; |
79 case SkCanvas::kBGRA_Unpremul_Config8888: | 76 case kRGBA_8888_SkColorType: |
80 *premul = true; // fallthru | |
81 case SkCanvas::kBGRA_Premul_Config8888: | |
82 a = static_cast<U8CPU>(c[3]); | |
83 r = static_cast<U8CPU>(c[2]); | |
84 g = static_cast<U8CPU>(c[1]); | |
85 b = static_cast<U8CPU>(c[0]); | |
86 break; | |
87 case SkCanvas::kRGBA_Unpremul_Config8888: | |
88 *premul = true; // fallthru | |
89 case SkCanvas::kRGBA_Premul_Config8888: | |
90 a = static_cast<U8CPU>(c[3]); | |
91 r = static_cast<U8CPU>(c[0]); | 77 r = static_cast<U8CPU>(c[0]); |
92 g = static_cast<U8CPU>(c[1]); | 78 g = static_cast<U8CPU>(c[1]); |
93 b = static_cast<U8CPU>(c[2]); | 79 b = static_cast<U8CPU>(c[2]); |
| 80 a = static_cast<U8CPU>(c[3]); |
94 break; | 81 break; |
95 default: | 82 default: |
96 SkDEBUGFAIL("Unexpected Config8888"); | 83 SkDEBUGFAIL("Unexpected colortype"); |
97 return 0; | 84 return 0; |
98 } | 85 } |
99 if (*premul) { | 86 |
| 87 if (*doUnpremul) { |
100 r = SkMulDiv255Ceiling(r, a); | 88 r = SkMulDiv255Ceiling(r, a); |
101 g = SkMulDiv255Ceiling(g, a); | 89 g = SkMulDiv255Ceiling(g, a); |
102 b = SkMulDiv255Ceiling(b, a); | 90 b = SkMulDiv255Ceiling(b, a); |
103 } | 91 } |
104 return SkPackARGB32(a, r, g, b); | 92 return SkPackARGB32(a, r, g, b); |
105 } | 93 } |
106 | 94 |
107 static void fillCanvas(SkCanvas* canvas) { | 95 static void fillCanvas(SkCanvas* canvas) { |
108 static SkBitmap bmp; | 96 static SkBitmap bmp; |
109 if (bmp.isNull()) { | 97 if (bmp.isNull()) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 SkAbs32(aB - bB) <= 1; | 149 SkAbs32(aB - bB) <= 1; |
162 } | 150 } |
163 | 151 |
164 // checks the bitmap contains correct pixels after the readPixels | 152 // checks the bitmap contains correct pixels after the readPixels |
165 // if the bitmap was prefilled with pixels it checks that these weren't | 153 // if the bitmap was prefilled with pixels it checks that these weren't |
166 // overwritten in the area outside the readPixels. | 154 // overwritten in the area outside the readPixels. |
167 static bool checkRead(skiatest::Reporter* reporter, | 155 static bool checkRead(skiatest::Reporter* reporter, |
168 const SkBitmap& bitmap, | 156 const SkBitmap& bitmap, |
169 int x, int y, | 157 int x, int y, |
170 bool checkCanvasPixels, | 158 bool checkCanvasPixels, |
171 bool checkBitmapPixels, | 159 bool checkBitmapPixels) { |
172 SkCanvas::Config8888 config8888) { | 160 SkASSERT(4 == bitmap.bytesPerPixel()); |
173 SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config()); | |
174 SkASSERT(!bitmap.isNull()); | 161 SkASSERT(!bitmap.isNull()); |
175 SkASSERT(checkCanvasPixels || checkBitmapPixels); | 162 SkASSERT(checkCanvasPixels || checkBitmapPixels); |
176 | 163 |
| 164 const SkColorType ct = bitmap.colorType(); |
| 165 const SkAlphaType at = bitmap.alphaType(); |
| 166 |
177 int bw = bitmap.width(); | 167 int bw = bitmap.width(); |
178 int bh = bitmap.height(); | 168 int bh = bitmap.height(); |
179 | 169 |
180 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh); | 170 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh); |
181 SkIRect clippedSrcRect = DEV_RECT; | 171 SkIRect clippedSrcRect = DEV_RECT; |
182 if (!clippedSrcRect.intersect(srcRect)) { | 172 if (!clippedSrcRect.intersect(srcRect)) { |
183 clippedSrcRect.setEmpty(); | 173 clippedSrcRect.setEmpty(); |
184 } | 174 } |
185 SkAutoLockPixels alp(bitmap); | 175 SkAutoLockPixels alp(bitmap); |
186 intptr_t pixels = reinterpret_cast<intptr_t>(bitmap.getPixels()); | |
187 for (int by = 0; by < bh; ++by) { | 176 for (int by = 0; by < bh; ++by) { |
188 for (int bx = 0; bx < bw; ++bx) { | 177 for (int bx = 0; bx < bw; ++bx) { |
189 int devx = bx + srcRect.fLeft; | 178 int devx = bx + srcRect.fLeft; |
190 int devy = by + srcRect.fTop; | 179 int devy = by + srcRect.fTop; |
191 | 180 |
192 uint32_t pixel = *reinterpret_cast<SkPMColor*>(pixels + by * bitmap.
rowBytes() + bx * bitmap.bytesPerPixel()); | 181 const uint32_t* pixel = bitmap.getAddr32(bx, by); |
193 | 182 |
194 if (clippedSrcRect.contains(devx, devy)) { | 183 if (clippedSrcRect.contains(devx, devy)) { |
195 if (checkCanvasPixels) { | 184 if (checkCanvasPixels) { |
196 SkPMColor canvasPixel = getCanvasColor(devx, devy); | 185 SkPMColor canvasPixel = getCanvasColor(devx, devy); |
197 bool didPremul; | 186 bool didPremul; |
198 SkPMColor pmPixel = convertConfig8888ToPMColor(config8888, p
ixel, &didPremul); | 187 SkPMColor pmPixel = convertToPMColor(ct, at, pixel, &didPrem
ul); |
199 bool check; | 188 bool check; |
200 REPORTER_ASSERT(reporter, check = checkPixel(pmPixel, canvas
Pixel, didPremul)); | 189 REPORTER_ASSERT(reporter, check = checkPixel(pmPixel, canvas
Pixel, didPremul)); |
201 if (!check) { | 190 if (!check) { |
202 return false; | 191 return false; |
203 } | 192 } |
204 } | 193 } |
205 } else if (checkBitmapPixels) { | 194 } else if (checkBitmapPixels) { |
206 REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw) == pixel); | 195 REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw) == *pixel); |
207 if (getBitmapColor(bx, by, bw) != pixel) { | 196 if (getBitmapColor(bx, by, bw) != *pixel) { |
208 return false; | 197 return false; |
209 } | 198 } |
210 } | 199 } |
211 } | 200 } |
212 } | 201 } |
213 return true; | 202 return true; |
214 } | 203 } |
215 | 204 |
216 enum BitmapInit { | 205 enum BitmapInit { |
217 kFirstBitmapInit = 0, | 206 kFirstBitmapInit = 0, |
218 | 207 |
219 kNoPixels_BitmapInit = kFirstBitmapInit, | 208 kNoPixels_BitmapInit = kFirstBitmapInit, |
220 kTight_BitmapInit, | 209 kTight_BitmapInit, |
221 kRowBytes_BitmapInit, | 210 kRowBytes_BitmapInit, |
222 | 211 |
223 kBitmapInitCnt | 212 kBitmapInitCnt |
224 }; | 213 }; |
225 | 214 |
226 static BitmapInit nextBMI(BitmapInit bmi) { | 215 static BitmapInit nextBMI(BitmapInit bmi) { |
227 int x = bmi; | 216 int x = bmi; |
228 return static_cast<BitmapInit>(++x); | 217 return static_cast<BitmapInit>(++x); |
229 } | 218 } |
230 | 219 |
231 static void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init)
{ | 220 static void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init,
SkColorType ct, |
232 SkImageInfo info = SkImageInfo::MakeN32Premul(rect.width(), rect.height()); | 221 SkAlphaType at) { |
| 222 SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), ct, at); |
233 size_t rowBytes = 0; | 223 size_t rowBytes = 0; |
234 bool alloc = true; | 224 bool alloc = true; |
235 switch (init) { | 225 switch (init) { |
236 case kNoPixels_BitmapInit: | 226 case kNoPixels_BitmapInit: |
237 alloc = false; | 227 alloc = false; |
238 case kTight_BitmapInit: | 228 case kTight_BitmapInit: |
239 break; | 229 break; |
240 case kRowBytes_BitmapInit: | 230 case kRowBytes_BitmapInit: |
241 rowBytes = (info.width() + 16) * sizeof(SkPMColor); | 231 rowBytes = (info.width() + 16) * sizeof(SkPMColor); |
242 break; | 232 break; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 GrAutoScratchTexture ast(context, desc, GrContext::kExact_Scratc
hTexMatch); | 323 GrAutoScratchTexture ast(context, desc, GrContext::kExact_Scratc
hTexMatch); |
334 SkAutoTUnref<GrTexture> tex(ast.detach()); | 324 SkAutoTUnref<GrTexture> tex(ast.detach()); |
335 device.reset(new SkGpuDevice(context, tex)); | 325 device.reset(new SkGpuDevice(context, tex)); |
336 #else | 326 #else |
337 continue; | 327 continue; |
338 #endif | 328 #endif |
339 } | 329 } |
340 SkCanvas canvas(device); | 330 SkCanvas canvas(device); |
341 fillCanvas(&canvas); | 331 fillCanvas(&canvas); |
342 | 332 |
343 static const SkCanvas::Config8888 gReadConfigs[] = { | 333 static const struct { |
344 SkCanvas::kNative_Premul_Config8888, | 334 SkColorType fColorType; |
345 SkCanvas::kNative_Unpremul_Config8888, | 335 SkAlphaType fAlphaType; |
346 | 336 } gReadConfigs[] = { |
347 SkCanvas::kBGRA_Premul_Config8888, | 337 { kRGBA_8888_SkColorType, kPremul_SkAlphaType }, |
348 SkCanvas::kBGRA_Unpremul_Config8888, | 338 { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType }, |
349 | 339 { kBGRA_8888_SkColorType, kPremul_SkAlphaType }, |
350 SkCanvas::kRGBA_Premul_Config8888, | 340 { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType }, |
351 SkCanvas::kRGBA_Unpremul_Config8888, | |
352 }; | 341 }; |
353 for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) { | 342 for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) { |
354 const SkIRect& srcRect = testRects[rect]; | 343 const SkIRect& srcRect = testRects[rect]; |
355 for (BitmapInit bmi = kFirstBitmapInit; | 344 for (BitmapInit bmi = kFirstBitmapInit; bmi < kBitmapInitCnt; bm
i = nextBMI(bmi)) { |
356 bmi < kBitmapInitCnt; | |
357 bmi = nextBMI(bmi)) { | |
358 for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) { | 345 for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) { |
359 SkCanvas::Config8888 config8888 = gReadConfigs[c]; | |
360 SkBitmap bmp; | 346 SkBitmap bmp; |
361 init_bitmap(&bmp, srcRect, bmi); | 347 init_bitmap(&bmp, srcRect, bmi, |
| 348 gReadConfigs[c].fColorType, gReadConfigs[c].
fAlphaType); |
362 | 349 |
363 // if the bitmap has pixels allocated before the readPix
els, | 350 // if the bitmap has pixels allocated before the readPix
els, |
364 // note that and fill them with pattern | 351 // note that and fill them with pattern |
365 bool startsWithPixels = !bmp.isNull(); | 352 bool startsWithPixels = !bmp.isNull(); |
366 if (startsWithPixels) { | 353 if (startsWithPixels) { |
367 fillBitmap(&bmp); | 354 fillBitmap(&bmp); |
368 } | 355 } |
369 uint32_t idBefore = canvas.getDevice()->accessBitmap(fal
se).getGenerationID(); | 356 uint32_t idBefore = canvas.getDevice()->accessBitmap(fal
se).getGenerationID(); |
370 bool success = | 357 bool success = canvas.readPixels(&bmp, srcRect.fLeft, sr
cRect.fTop); |
371 canvas.readPixels(&bmp, srcRect.fLeft, | |
372 srcRect.fTop, config8888); | |
373 uint32_t idAfter = canvas.getDevice()->accessBitmap(fals
e).getGenerationID(); | 358 uint32_t idAfter = canvas.getDevice()->accessBitmap(fals
e).getGenerationID(); |
374 | 359 |
375 // we expect to succeed when the read isn't fully clippe
d | 360 // we expect to succeed when the read isn't fully clippe
d |
376 // out. | 361 // out. |
377 bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RE
CT); | 362 bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RE
CT); |
378 // determine whether we expected the read to succeed. | 363 // determine whether we expected the read to succeed. |
379 REPORTER_ASSERT(reporter, success == expectSuccess); | 364 REPORTER_ASSERT(reporter, success == expectSuccess); |
380 // read pixels should never change the gen id | 365 // read pixels should never change the gen id |
381 REPORTER_ASSERT(reporter, idBefore == idAfter); | 366 REPORTER_ASSERT(reporter, idBefore == idAfter); |
382 | 367 |
383 if (success || startsWithPixels) { | 368 if (success || startsWithPixels) { |
384 checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop
, | 369 checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop
, |
385 success, startsWithPixels, config8888); | 370 success, startsWithPixels); |
386 } else { | 371 } else { |
387 // if we had no pixels beforehand and the readPixels | 372 // if we had no pixels beforehand and the readPixels |
388 // failed then our bitmap should still not have pixe
ls | 373 // failed then our bitmap should still not have pixe
ls |
389 REPORTER_ASSERT(reporter, bmp.isNull()); | 374 REPORTER_ASSERT(reporter, bmp.isNull()); |
390 } | 375 } |
391 } | 376 } |
392 // check the old webkit version of readPixels that clips the | 377 // check the old webkit version of readPixels that clips the |
393 // bitmap size | 378 // bitmap size |
394 SkBitmap wkbmp; | 379 SkBitmap wkbmp; |
395 bool success = canvas.readPixels(srcRect, &wkbmp); | 380 bool success = canvas.readPixels(srcRect, &wkbmp); |
396 SkIRect clippedRect = DEV_RECT; | 381 SkIRect clippedRect = DEV_RECT; |
397 if (clippedRect.intersect(srcRect)) { | 382 if (clippedRect.intersect(srcRect)) { |
398 REPORTER_ASSERT(reporter, success); | 383 REPORTER_ASSERT(reporter, success); |
| 384 REPORTER_ASSERT(reporter, kPMColor_SkColorType == wkbmp.
colorType()); |
| 385 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.a
lphaType()); |
399 checkRead(reporter, wkbmp, clippedRect.fLeft, | 386 checkRead(reporter, wkbmp, clippedRect.fLeft, |
400 clippedRect.fTop, true, false, | 387 clippedRect.fTop, true, false); |
401 SkCanvas::kNative_Premul_Config8888); | |
402 } else { | 388 } else { |
403 REPORTER_ASSERT(reporter, !success); | 389 REPORTER_ASSERT(reporter, !success); |
404 } | 390 } |
405 } | 391 } |
406 } | 392 } |
407 } | 393 } |
408 } | 394 } |
409 } | 395 } |
OLD | NEW |