Fix texture-backed image shaders drawing to raster canvas

Bug: skia:12685
Change-Id: Ie8785be73fd2f2670291e9c1295985ac7ad1d714
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/478497
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Brian Osman 2021-12-01 15:35:38 -05:00 committed by SkCQ
parent 5a7d91c35b
commit d498d0759c
2 changed files with 36 additions and 1 deletions

View File

@ -204,3 +204,37 @@ DEF_SIMPLE_GM(drawimage_sampling, canvas, 500, 500) {
} }
} }
// Test case for skbug.com/12685 (texture-backed image shaders silently fail drawing to CPU canvas)
DEF_SIMPLE_GM(textureimage_and_shader, canvas, 100, 50) {
canvas->clear(SK_ColorGREEN);
sk_sp<SkImage> image;
if (canvas->getSurface()) {
image = canvas->getSurface()->makeImageSnapshot();
canvas->clear(SK_ColorRED);
} else {
auto greenSurface = SkSurface::MakeRasterN32Premul(50, 50);
greenSurface->getCanvas()->clear(SK_ColorGREEN);
image = greenSurface->makeImageSnapshot();
}
// At this point, 'image' contains a green image. If our original canvas is GPU-backed, then
// the snapped image will be a (GPU) texture. We will try to draw that image to a non-GPU
// surface, to ensure that we get automatic read-back. If all goes well, we will get a pure
// green result. If either draw fails, we'll get red (most likely).
auto surface = SkSurface::MakeRasterN32Premul(50, 50);
// First, use drawImage:
surface->getCanvas()->clear(SK_ColorRED);
surface->getCanvas()->drawImage(image, 0, 0);
canvas->drawImage(surface->makeImageSnapshot(), 0, 0);
// Now, use an image shader:
SkPaint paint;
paint.setShader(image->makeShader(SkSamplingOptions()));
surface->getCanvas()->clear(SK_ColorRED);
surface->getCanvas()->drawPaint(paint);
canvas->drawImage(surface->makeImageSnapshot(), 50, 0);
}

View File

@ -34,7 +34,8 @@ SkMipmapAccessor::SkMipmapAccessor(const SkImage_Base* image, const SkMatrix& in
auto load_upper_from_base = [&]() { auto load_upper_from_base = [&]() {
// only do this once // only do this once
if (fBaseStorage.getPixels() == nullptr) { if (fBaseStorage.getPixels() == nullptr) {
(void)image->getROPixels(nullptr, &fBaseStorage); auto dContext = as_IB(image)->directContext();
(void)image->getROPixels(dContext, &fBaseStorage);
fUpper.reset(fBaseStorage.info(), fBaseStorage.getPixels(), fBaseStorage.rowBytes()); fUpper.reset(fBaseStorage.info(), fBaseStorage.getPixels(), fBaseStorage.rowBytes());
} }
}; };