Use raster mipmap levels when drawing to GPU.

Previously just the base level was uploaded and the level contents
were generated on the GPU.

showmiplevels_explicit now works on GPU.

Bug: skia:11983
Change-Id: I96ed8a7ad90a8252f55a736cb6146eec9b2a3ad1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/521356
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2022-04-15 09:06:52 -04:00 committed by SkCQ
parent fcbf28849b
commit 84e2586f15
4 changed files with 29 additions and 13 deletions

View File

@ -48,11 +48,6 @@ class ShowMipLevels3 : public skiagm::GM {
} }
DrawResult onDraw(SkCanvas* canvas, SkString*) override { DrawResult onDraw(SkCanvas* canvas, SkString*) override {
if (canvas->recordingContext()) {
// mips not supported yet
return DrawResult::kSkip;
}
canvas->drawColor(0xFFDDDDDD); canvas->drawColor(0xFFDDDDDD);
canvas->translate(10, 10); canvas->translate(10, 10);

View File

@ -1191,6 +1191,7 @@ private:
friend class SkImage_Raster; friend class SkImage_Raster;
friend class SkReadBuffer; // unflatten friend class SkReadBuffer; // unflatten
friend class GrProxyProvider; // fMips
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -269,11 +269,11 @@ GrSurfaceProxyView GrProxyProvider::findCachedProxyWithColorTypeFallback(
} }
sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap, sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap,
GrMipmapped mipMapped, GrMipmapped mipmapped,
SkBackingFit fit, SkBackingFit fit,
SkBudgeted budgeted) { SkBudgeted budgeted) {
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
SkASSERT(fit == SkBackingFit::kExact || mipMapped == GrMipmapped::kNo); SkASSERT(fit == SkBackingFit::kExact || mipmapped == GrMipmapped::kNo);
if (this->isAbandoned()) { if (this->isAbandoned()) {
return nullptr; return nullptr;
@ -296,12 +296,22 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bit
if (!bitmap.readPixels(copyBitmap.pixmap())) { if (!bitmap.readPixels(copyBitmap.pixmap())) {
return nullptr; return nullptr;
} }
if (mipmapped == GrMipmapped::kYes && bitmap.fMips) {
copyBitmap.fMips = sk_sp<SkMipmap>(SkMipmap::Build(copyBitmap.pixmap(),
nullptr,
false));
for (int i = 0; i < copyBitmap.fMips->countLevels(); ++i) {
SkMipmap::Level src, dst;
bitmap.fMips->getLevel(i, &src);
copyBitmap.fMips->getLevel(i, &dst);
src.fPixmap.readPixels(dst.fPixmap);
}
}
copyBitmap.setImmutable(); copyBitmap.setImmutable();
} }
sk_sp<GrTextureProxy> proxy; sk_sp<GrTextureProxy> proxy;
if (mipMapped == GrMipmapped::kNo || if (mipmapped == GrMipmapped::kNo || !SkMipmap::ComputeLevelCount(copyBitmap.dimensions())) {
0 == SkMipmap::ComputeLevelCount(copyBitmap.width(), copyBitmap.height())) {
proxy = this->createNonMippedProxyFromBitmap(copyBitmap, fit, budgeted); proxy = this->createNonMippedProxyFromBitmap(copyBitmap, fit, budgeted);
} else { } else {
proxy = this->createMippedProxyFromBitmap(copyBitmap, budgeted); proxy = this->createMippedProxyFromBitmap(copyBitmap, budgeted);
@ -372,9 +382,12 @@ sk_sp<GrTextureProxy> GrProxyProvider::createMippedProxyFromBitmap(const SkBitma
return nullptr; return nullptr;
} }
sk_sp<SkMipmap> mipmaps(SkMipmap::Build(bitmap.pixmap(), nullptr)); sk_sp<SkMipmap> mipmaps = bitmap.fMips;
if (!mipmaps) { if (!mipmaps) {
return nullptr; mipmaps.reset(SkMipmap::Build(bitmap.pixmap(), nullptr));
if (!mipmaps) {
return nullptr;
}
} }
auto dims = bitmap.dimensions(); auto dims = bitmap.dimensions();
@ -404,7 +417,7 @@ sk_sp<GrTextureProxy> GrProxyProvider::createMippedProxyFromBitmap(const SkBitma
GrRenderable::kNo, GrRenderable::kNo,
1, 1,
desc.fBudgeted, desc.fBudgeted,
GrMipMapped::kYes, GrMipmapped::kYes,
GrProtected::kNo, GrProtected::kNo,
texels.get())); texels.get()));
}, },

View File

@ -444,7 +444,7 @@ std::tuple<GrSurfaceProxyView, GrColorType> SkImage_Raster::onAsView(
if (fPinnedView) { if (fPinnedView) {
// We ignore the mipmap request here. If the pinned view isn't mipmapped then we will // We ignore the mipmap request here. If the pinned view isn't mipmapped then we will
// fallback to bilinear. The pin API is used by Android Framework which does not expose // fallback to bilinear. The pin API is used by Android Framework which does not expose
// mipmapping.Moreover, we're moving towards requiring that images be made with mip levels // mipmapping .Moreover, we're moving towards requiring that images be made with mip levels
// if mipmapping is desired (skbug.com/10411) // if mipmapping is desired (skbug.com/10411)
mipmapped = GrMipmapped::kNo; mipmapped = GrMipmapped::kNo;
if (policy != GrImageTexGenPolicy::kDraw) { if (policy != GrImageTexGenPolicy::kDraw) {
@ -453,6 +453,13 @@ std::tuple<GrSurfaceProxyView, GrColorType> SkImage_Raster::onAsView(
return {fPinnedView, fPinnedColorType}; return {fPinnedView, fPinnedColorType};
} }
if (policy == GrImageTexGenPolicy::kDraw) { if (policy == GrImageTexGenPolicy::kDraw) {
// If the draw doesn't require mipmaps but this SkImage has them go ahead and make a
// mipmapped texture. There are three reasons for this:
// 1) Avoiding another texture creation if a later draw requires mipmaps.
// 2) Ensuring we upload the bitmap's levels instead of generating on the GPU from the base.
if (this->hasMipmaps()) {
mipmapped = GrMipmapped::kYes;
}
return GrMakeCachedBitmapProxyView(rContext, fBitmap, mipmapped); return GrMakeCachedBitmapProxyView(rContext, fBitmap, mipmapped);
} }
auto budgeted = (policy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted) auto budgeted = (policy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted)