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 "SkCanvas.h" | 8 #include "SkCanvas.h" |
9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
10 #include "SkMathPriv.h" | 10 #include "SkMathPriv.h" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 } | 128 } |
129 #endif | 129 #endif |
130 | 130 |
131 static void fill_dst_bmp_with_init_data(SkBitmap* bitmap) { | 131 static void fill_dst_bmp_with_init_data(SkBitmap* bitmap) { |
132 SkAutoLockPixels alp(*bitmap); | 132 SkAutoLockPixels alp(*bitmap); |
133 int w = bitmap->width(); | 133 int w = bitmap->width(); |
134 int h = bitmap->height(); | 134 int h = bitmap->height(); |
135 intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels()); | 135 intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels()); |
136 for (int y = 0; y < h; ++y) { | 136 for (int y = 0; y < h; ++y) { |
137 for (int x = 0; x < w; ++x) { | 137 for (int x = 0; x < w; ++x) { |
138 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap-
>rowBytes() + x * bitmap->bytesPerPixel()); | 138 SkPMColor initColor = get_dst_bmp_init_color(x, y, w); |
139 *pixel = get_dst_bmp_init_color(x, y, w); | 139 if (kAlpha_8_SkColorType == bitmap->colorType()) { |
| 140 uint8_t* alpha = reinterpret_cast<uint8_t*>(pixels + y * bitmap-
>rowBytes() + x); |
| 141 *alpha = SkGetPackedA32(initColor); |
| 142 } else { |
| 143 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bit
map->rowBytes() + x * bitmap->bytesPerPixel()); |
| 144 *pixel = initColor; |
| 145 } |
140 } | 146 } |
141 } | 147 } |
142 } | 148 } |
143 | 149 |
144 static bool check_read_pixel(SkPMColor a, SkPMColor b, bool didPremulConversion)
{ | 150 static bool check_read_pixel(SkPMColor a, SkPMColor b, bool didPremulConversion)
{ |
145 if (!didPremulConversion) { | 151 if (!didPremulConversion) { |
146 return a == b; | 152 return a == b; |
147 } | 153 } |
148 int32_t aA = static_cast<int32_t>(SkGetPackedA32(a)); | 154 int32_t aA = static_cast<int32_t>(SkGetPackedA32(a)); |
149 int32_t aR = static_cast<int32_t>(SkGetPackedR32(a)); | 155 int32_t aR = static_cast<int32_t>(SkGetPackedR32(a)); |
(...skipping 11 matching lines...) Expand all Loading... |
161 SkAbs32(aB - bB) <= 1; | 167 SkAbs32(aB - bB) <= 1; |
162 } | 168 } |
163 | 169 |
164 // checks the bitmap contains correct pixels after the readPixels | 170 // checks the bitmap contains correct pixels after the readPixels |
165 // if the bitmap was prefilled with pixels it checks that these weren't | 171 // if the bitmap was prefilled with pixels it checks that these weren't |
166 // overwritten in the area outside the readPixels. | 172 // overwritten in the area outside the readPixels. |
167 static bool check_read(skiatest::Reporter* reporter, | 173 static bool check_read(skiatest::Reporter* reporter, |
168 const SkBitmap& bitmap, | 174 const SkBitmap& bitmap, |
169 int x, int y, | 175 int x, int y, |
170 bool checkCanvasPixels, | 176 bool checkCanvasPixels, |
171 bool checkBitmapPixels) { | 177 bool checkBitmapPixels, |
172 SkASSERT(4 == bitmap.bytesPerPixel()); | 178 SkColorType ct, |
| 179 SkAlphaType at) { |
| 180 SkASSERT(ct == bitmap.colorType() && at == bitmap.alphaType()); |
173 SkASSERT(!bitmap.isNull()); | 181 SkASSERT(!bitmap.isNull()); |
174 SkASSERT(checkCanvasPixels || checkBitmapPixels); | 182 SkASSERT(checkCanvasPixels || checkBitmapPixels); |
175 | 183 |
176 const SkColorType ct = bitmap.colorType(); | |
177 const SkAlphaType at = bitmap.alphaType(); | |
178 | |
179 int bw = bitmap.width(); | 184 int bw = bitmap.width(); |
180 int bh = bitmap.height(); | 185 int bh = bitmap.height(); |
181 | 186 |
182 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh); | 187 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh); |
183 SkIRect clippedSrcRect = DEV_RECT; | 188 SkIRect clippedSrcRect = DEV_RECT; |
184 if (!clippedSrcRect.intersect(srcRect)) { | 189 if (!clippedSrcRect.intersect(srcRect)) { |
185 clippedSrcRect.setEmpty(); | 190 clippedSrcRect.setEmpty(); |
186 } | 191 } |
187 SkAutoLockPixels alp(bitmap); | 192 SkAutoLockPixels alp(bitmap); |
| 193 if (kAlpha_8_SkColorType == ct) { |
| 194 for (int by = 0; by < bh; ++by) { |
| 195 for (int bx = 0; bx < bw; ++bx) { |
| 196 int devx = bx + srcRect.fLeft; |
| 197 int devy = by + srcRect.fTop; |
| 198 const uint8_t* alpha = bitmap.getAddr8(bx, by); |
| 199 |
| 200 if (clippedSrcRect.contains(devx, devy)) { |
| 201 if (checkCanvasPixels) { |
| 202 uint8_t canvasAlpha = SkGetPackedA32(get_src_color(devx,
devy)); |
| 203 if (canvasAlpha != *alpha) { |
| 204 ERRORF(reporter, "Expected readback alpha (%d, %d) v
alue 0x%02x, got 0x%02x. ", |
| 205 bx, by, canvasAlpha, *alpha); |
| 206 return false; |
| 207 } |
| 208 } |
| 209 } else if (checkBitmapPixels) { |
| 210 uint32_t origDstAlpha = SkGetPackedA32(get_dst_bmp_init_colo
r(bx, by, bw)); |
| 211 if (origDstAlpha != *alpha) { |
| 212 ERRORF(reporter, "Expected clipped out area of readback
to be unchanged. " |
| 213 "Expected 0x%02x, got 0x%02x", origDstAlpha, *alpha)
; |
| 214 return false; |
| 215 } |
| 216 } |
| 217 } |
| 218 } |
| 219 return true; |
| 220 } |
188 for (int by = 0; by < bh; ++by) { | 221 for (int by = 0; by < bh; ++by) { |
189 for (int bx = 0; bx < bw; ++bx) { | 222 for (int bx = 0; bx < bw; ++bx) { |
190 int devx = bx + srcRect.fLeft; | 223 int devx = bx + srcRect.fLeft; |
191 int devy = by + srcRect.fTop; | 224 int devy = by + srcRect.fTop; |
192 | 225 |
193 const uint32_t* pixel = bitmap.getAddr32(bx, by); | 226 const uint32_t* pixel = bitmap.getAddr32(bx, by); |
194 | 227 |
195 if (clippedSrcRect.contains(devx, devy)) { | 228 if (clippedSrcRect.contains(devx, devy)) { |
196 if (checkCanvasPixels) { | 229 if (checkCanvasPixels) { |
197 SkPMColor canvasPixel = get_src_color(devx, devy); | 230 SkPMColor canvasPixel = get_src_color(devx, devy); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 SkAlphaType at) { | 275 SkAlphaType at) { |
243 SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), ct, at); | 276 SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), ct, at); |
244 size_t rowBytes = 0; | 277 size_t rowBytes = 0; |
245 bool alloc = true; | 278 bool alloc = true; |
246 switch (init) { | 279 switch (init) { |
247 case kNoPixels_BitmapInit: | 280 case kNoPixels_BitmapInit: |
248 alloc = false; | 281 alloc = false; |
249 case kTight_BitmapInit: | 282 case kTight_BitmapInit: |
250 break; | 283 break; |
251 case kRowBytes_BitmapInit: | 284 case kRowBytes_BitmapInit: |
252 rowBytes = (info.width() + 16) * sizeof(SkPMColor); | 285 rowBytes = SkAlign4((info.width() + 16) * info.bytesPerPixel()); |
253 break; | 286 break; |
254 case kRowBytesOdd_BitmapInit: | 287 case kRowBytesOdd_BitmapInit: |
255 rowBytes = (info.width() * sizeof(SkPMColor)) + 3; | 288 rowBytes = SkAlign4(info.width() * info.bytesPerPixel()) + 3; |
256 break; | 289 break; |
257 default: | 290 default: |
258 SkASSERT(0); | 291 SkASSERT(0); |
259 break; | 292 break; |
260 } | 293 } |
261 | 294 |
262 if (alloc) { | 295 if (alloc) { |
263 bitmap->allocPixels(info, rowBytes); | 296 bitmap->allocPixels(info, rowBytes); |
264 } else { | 297 } else { |
265 bitmap->setInfo(info, rowBytes); | 298 bitmap->setInfo(info, rowBytes); |
266 } | 299 } |
267 } | 300 } |
268 | 301 |
269 static const struct { | 302 static const struct { |
270 SkColorType fColorType; | 303 SkColorType fColorType; |
271 SkAlphaType fAlphaType; | 304 SkAlphaType fAlphaType; |
272 } gReadPixelsConfigs[] = { | 305 } gReadPixelsConfigs[] = { |
273 { kRGBA_8888_SkColorType, kPremul_SkAlphaType }, | 306 { kRGBA_8888_SkColorType, kPremul_SkAlphaType }, |
274 { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType }, | 307 { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType }, |
275 { kBGRA_8888_SkColorType, kPremul_SkAlphaType }, | 308 { kBGRA_8888_SkColorType, kPremul_SkAlphaType }, |
276 { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType }, | 309 { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType }, |
| 310 { kAlpha_8_SkColorType, kPremul_SkAlphaType }, |
277 }; | 311 }; |
278 const SkIRect gReadPixelsTestRects[] = { | 312 const SkIRect gReadPixelsTestRects[] = { |
279 // entire thing | 313 // entire thing |
280 DEV_RECT, | 314 DEV_RECT, |
281 // larger on all sides | 315 // larger on all sides |
282 SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10), | 316 SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10), |
283 // fully contained | 317 // fully contained |
284 SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4), | 318 SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4), |
285 // outside top left | 319 // outside top left |
286 SkIRect::MakeLTRB(-10, -10, -1, -1), | 320 SkIRect::MakeLTRB(-10, -10, -1, -1), |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 // we expect to succeed when the read isn't fully clipped | 381 // we expect to succeed when the read isn't fully clipped |
348 // out. | 382 // out. |
349 bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT); | 383 bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT); |
350 // determine whether we expected the read to succeed. | 384 // determine whether we expected the read to succeed. |
351 REPORTER_ASSERT(reporter, success == expectSuccess); | 385 REPORTER_ASSERT(reporter, success == expectSuccess); |
352 // read pixels should never change the gen id | 386 // read pixels should never change the gen id |
353 REPORTER_ASSERT(reporter, idBefore == idAfter); | 387 REPORTER_ASSERT(reporter, idBefore == idAfter); |
354 | 388 |
355 if (success || startsWithPixels) { | 389 if (success || startsWithPixels) { |
356 check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop, | 390 check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop, |
357 success, startsWithPixels); | 391 success, startsWithPixels, |
| 392 gReadPixelsConfigs[c].fColorType, gReadPixelsConf
igs[c].fAlphaType); |
358 } else { | 393 } else { |
359 // if we had no pixels beforehand and the readPixels | 394 // if we had no pixels beforehand and the readPixels |
360 // failed then our bitmap should still not have pixels | 395 // failed then our bitmap should still not have pixels |
361 REPORTER_ASSERT(reporter, bmp.isNull()); | 396 REPORTER_ASSERT(reporter, bmp.isNull()); |
362 } | 397 } |
363 } | 398 } |
364 // check the old webkit version of readPixels that clips the | 399 // check the old webkit version of readPixels that clips the |
365 // bitmap size | 400 // bitmap size |
366 SkBitmap wkbmp; | 401 SkBitmap wkbmp; |
367 bool success = canvas->readPixels(srcRect, &wkbmp); | 402 bool success = canvas->readPixels(srcRect, &wkbmp); |
368 SkIRect clippedRect = DEV_RECT; | 403 SkIRect clippedRect = DEV_RECT; |
369 if (clippedRect.intersect(srcRect)) { | 404 if (clippedRect.intersect(srcRect)) { |
370 REPORTER_ASSERT(reporter, success); | 405 REPORTER_ASSERT(reporter, success); |
371 REPORTER_ASSERT(reporter, kN32_SkColorType == wkbmp.colorType())
; | 406 REPORTER_ASSERT(reporter, kN32_SkColorType == wkbmp.colorType())
; |
372 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.alphaType
()); | 407 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == wkbmp.alphaType
()); |
373 check_read(reporter, wkbmp, clippedRect.fLeft, | 408 check_read(reporter, wkbmp, clippedRect.fLeft, |
374 clippedRect.fTop, true, false); | 409 clippedRect.fTop, true, false, |
| 410 kN32_SkColorType, kPremul_SkAlphaType); |
375 } else { | 411 } else { |
376 REPORTER_ASSERT(reporter, !success); | 412 REPORTER_ASSERT(reporter, !success); |
377 } | 413 } |
378 } | 414 } |
379 } | 415 } |
380 } | 416 } |
381 DEF_TEST(ReadPixels, reporter) { | 417 DEF_TEST(ReadPixels, reporter) { |
382 const SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H); | 418 const SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H); |
383 auto surface(SkSurface::MakeRaster(info)); | 419 auto surface(SkSurface::MakeRaster(info)); |
384 // SW readback fails a premul check when reading back to an unaligned rowbyt
es. | 420 // SW readback fails a premul check when reading back to an unaligned rowbyt
es. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 uint32_t flags = 0; | 456 uint32_t flags = 0; |
421 if (gReadPixelsConfigs[c].fAlphaType == kUnpremul_SkAlphaTyp
e) { | 457 if (gReadPixelsConfigs[c].fAlphaType == kUnpremul_SkAlphaTyp
e) { |
422 flags = GrContext::kUnpremul_PixelOpsFlag; | 458 flags = GrContext::kUnpremul_PixelOpsFlag; |
423 } | 459 } |
424 bmp.lockPixels(); | 460 bmp.lockPixels(); |
425 bool success = texture->readPixels(srcRect.fLeft, srcRect.fT
op, bmp.width(), | 461 bool success = texture->readPixels(srcRect.fLeft, srcRect.fT
op, bmp.width(), |
426 bmp.height(), dstConfig,
bmp.getPixels(), | 462 bmp.height(), dstConfig,
bmp.getPixels(), |
427 bmp.rowBytes(), flags); | 463 bmp.rowBytes(), flags); |
428 bmp.unlockPixels(); | 464 bmp.unlockPixels(); |
429 check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop, | 465 check_read(reporter, bmp, srcRect.fLeft, srcRect.fTop, |
430 success, true); | 466 success, true, |
| 467 gReadPixelsConfigs[c].fColorType, gReadPixelsConf
igs[c].fAlphaType); |
431 } | 468 } |
432 } | 469 } |
433 } | 470 } |
434 } | 471 } |
435 } | 472 } |
436 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadPixels_Texture, reporter, ctxInfo) { | 473 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadPixels_Texture, reporter, ctxInfo) { |
437 // On the GPU we will also try reading back from a non-renderable texture. | 474 // On the GPU we will also try reading back from a non-renderable texture. |
438 for (auto& origin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin})
{ | 475 for (auto& origin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin})
{ |
439 SkAutoTUnref<GrTexture> texture; | 476 SkAutoTUnref<GrTexture> texture; |
440 GrSurfaceDesc desc; | 477 GrSurfaceDesc desc; |
441 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 478 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
442 desc.fWidth = DEV_W; | 479 desc.fWidth = DEV_W; |
443 desc.fHeight = DEV_H; | 480 desc.fHeight = DEV_H; |
444 desc.fConfig = kSkia8888_GrPixelConfig; | 481 desc.fConfig = kSkia8888_GrPixelConfig; |
445 desc.fOrigin = origin; | 482 desc.fOrigin = origin; |
446 desc.fFlags = kNone_GrSurfaceFlags; | 483 desc.fFlags = kNone_GrSurfaceFlags; |
447 texture.reset(ctxInfo.grContext()->textureProvider()->createTexture(desc
, | 484 texture.reset(ctxInfo.grContext()->textureProvider()->createTexture(desc
, |
448 SkBu
dgeted::kNo)); | 485 SkBu
dgeted::kNo)); |
449 test_readpixels_texture(reporter, texture); | 486 test_readpixels_texture(reporter, texture); |
450 } | 487 } |
451 } | 488 } |
452 #endif | 489 #endif |
OLD | NEW |