Fix uncached getROPixels from GPU images

We were allocating a local bitmap, but then attempting to read into an
uninitialized local pixmap. The only public API that funnels the caching
hint to this function is scalePixels, so I added a test (which previously
failed).

Bug: skia:
Change-Id: Ib4370350be664935b4c85e34c70b675e6d82ba64
Reviewed-on: https://skia-review.googlesource.com/14402
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2017-04-26 15:28:30 -04:00 committed by Skia Commit-Bot
parent f6d7eb158e
commit b8a1392b02
2 changed files with 65 additions and 1 deletions

View File

@ -86,7 +86,7 @@ bool SkImage_Gpu::getROPixels(SkBitmap* dst, SkColorSpace* dstColorSpace, Cachin
return false;
}
} else {
if (!dst->tryAllocPixels(ii)) {
if (!dst->tryAllocPixels(ii) || !dst->peekPixels(&pmap)) {
return false;
}
}

View File

@ -1149,3 +1149,67 @@ DEF_TEST(image_roundtrip_premul, reporter) {
REPORTER_ASSERT(reporter, equal(bm0, bm2));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
static void check_scaled_pixels(skiatest::Reporter* reporter, SkPixmap* pmap, uint32_t expected) {
// Verify that all pixels contain the original test color
for (auto y = 0; y < pmap->height(); ++y) {
for (auto x = 0; x < pmap->width(); ++x) {
uint32_t pixel = *pmap->addr32(x, y);
if (pixel != expected) {
ERRORF(reporter, "Expected scaled pixels to be the same. At %d,%d 0x%08x != 0x%08x",
x, y, pixel, expected);
return;
}
}
}
}
static void test_scale_pixels(skiatest::Reporter* reporter, const SkImage* image,
uint32_t expected) {
SkImageInfo info = SkImageInfo::MakeN32Premul(image->width() * 2, image->height() * 2);
// Make sure to test kDisallow first, so we don't just get a cache hit in that case
for (auto chint : { SkImage::kDisallow_CachingHint, SkImage::kAllow_CachingHint }) {
SkAutoPixmapStorage scaled;
scaled.alloc(info);
if (!image->scalePixels(scaled, kLow_SkFilterQuality, chint)) {
ERRORF(reporter, "Failed to scale image");
continue;
}
check_scaled_pixels(reporter, &scaled, expected);
}
}
DEF_TEST(ImageScalePixels, reporter) {
const SkPMColor pmRed = SkPackARGB32(0xFF, 0xFF, 0, 0);
const SkColor red = SK_ColorRED;
// Test raster image
SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
surface->getCanvas()->clear(red);
sk_sp<SkImage> rasterImage = surface->makeImageSnapshot();
test_scale_pixels(reporter, rasterImage.get(), pmRed);
// Test encoded image
sk_sp<SkData> data(rasterImage->encode());
sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(data);
test_scale_pixels(reporter, codecImage.get(), pmRed);
}
#if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageScalePixels_Gpu, reporter, ctxInfo) {
const SkPMColor pmRed = SkPackARGB32(0xFF, 0xFF, 0, 0);
const SkColor red = SK_ColorRED;
SkImageInfo info = SkImageInfo::MakeN32Premul(16, 16);
sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kNo,
info);
surface->getCanvas()->clear(red);
sk_sp<SkImage> gpuImage = surface->makeImageSnapshot();
test_scale_pixels(reporter, gpuImage.get(), pmRed);
}
#endif