| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkSurface.h" |
| #include "include/gpu/GrDirectContext.h" |
| #include "src/gpu/GrDirectContextPriv.h" |
| #include "src/gpu/GrTexture.h" |
| #include "src/image/SkImage_Base.h" |
| #include "src/image/SkImage_GpuBase.h" |
| #include "tests/Test.h" |
| |
| // Tests that MIP maps are created and invalidated as expected when drawing to and from GrTextures. |
| DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextureMipMapInvalidationTest, reporter, ctxInfo) { |
| auto context = ctxInfo.directContext(); |
| if (!context->priv().caps()->mipmapSupport()) { |
| return; |
| } |
| |
| auto isMipped = [reporter](SkSurface* surf) { |
| SkImage_GpuBase* image = static_cast<SkImage_GpuBase*>(as_IB(surf->makeImageSnapshot())); |
| bool proxyIsMipmapped = image->peekProxy()->mipmapped() == GrMipmapped::kYes; |
| REPORTER_ASSERT(reporter, proxyIsMipmapped == image->hasMipmaps()); |
| return image->hasMipmaps(); |
| }; |
| |
| auto mipsAreDirty = [](SkSurface* surf) { |
| SkImage_GpuBase* image = static_cast<SkImage_GpuBase*>(as_IB(surf->makeImageSnapshot())); |
| return image->peekProxy()->peekTexture()->mipmapsAreDirty(); |
| }; |
| |
| auto info = SkImageInfo::MakeN32Premul(256, 256); |
| for (auto allocateMips : {false, true}) { |
| auto surf1 = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0, |
| kBottomLeft_GrSurfaceOrigin, nullptr, |
| allocateMips); |
| auto surf2 = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info); |
| // Draw something just in case we ever had a solid color optimization |
| surf1->getCanvas()->drawCircle(128, 128, 50, SkPaint()); |
| surf1->flushAndSubmit(); |
| |
| // No mipmaps initially |
| REPORTER_ASSERT(reporter, isMipped(surf1.get()) == allocateMips); |
| |
| // Painting with downscale and medium filter quality should result in mipmap creation |
| // Flush the context rather than the canvas as flushing the canvas triggers MIP level |
| // generation. |
| SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kLinear); |
| |
| surf2->getCanvas()->scale(0.2f, 0.2f); |
| surf2->getCanvas()->drawImage(surf1->makeImageSnapshot(), 0, 0, sampling); |
| context->flushAndSubmit(); |
| REPORTER_ASSERT(reporter, isMipped(surf1.get()) == allocateMips); |
| REPORTER_ASSERT(reporter, !allocateMips || !mipsAreDirty(surf1.get())); |
| |
| // Changing the contents of the surface should invalidate the mipmap, but not de-allocate |
| surf1->getCanvas()->drawCircle(128, 128, 100, SkPaint()); |
| context->flushAndSubmit(); |
| REPORTER_ASSERT(reporter, isMipped(surf1.get()) == allocateMips); |
| REPORTER_ASSERT(reporter, mipsAreDirty(surf1.get())); |
| } |
| } |
| |
| DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReimportImageTextureWithMipLevels, reporter, ctxInfo) { |
| auto dContext = ctxInfo.directContext(); |
| if (!dContext->priv().caps()->mipmapSupport()) { |
| return; |
| } |
| static constexpr auto kCreateWithMipMaps = true; |
| auto surf = SkSurface::MakeRenderTarget( |
| dContext, SkBudgeted::kYes, |
| SkImageInfo::Make(100, 100, kRGBA_8888_SkColorType, kPremul_SkAlphaType), 1, |
| kTopLeft_GrSurfaceOrigin, nullptr, kCreateWithMipMaps); |
| if (!surf) { |
| return; |
| } |
| surf->getCanvas()->drawColor(SK_ColorDKGRAY); |
| auto img = surf->makeImageSnapshot(); |
| if (!img) { |
| return; |
| } |
| surf.reset(); |
| GrBackendTexture btex; |
| SkImage::BackendTextureReleaseProc texRelease; |
| if (!SkImage::MakeBackendTextureFromSkImage(dContext, std::move(img), &btex, &texRelease)) { |
| // Not all backends support stealing textures yet. |
| // ERRORF(reporter, "Could not turn image into texture"); |
| return; |
| } |
| REPORTER_ASSERT(reporter, btex.hasMipmaps()); |
| // Reimport the texture as an image and perform a downsampling draw with medium quality which |
| // should use the upper MIP levels. |
| img = SkImage::MakeFromTexture(dContext, btex, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, |
| kPremul_SkAlphaType, nullptr); |
| const auto singlePixelInfo = |
| SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); |
| surf = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kYes, singlePixelInfo, 1, |
| kTopLeft_GrSurfaceOrigin, nullptr); |
| |
| surf->getCanvas()->drawImageRect(img, SkRect::MakeWH(1, 1), |
| SkSamplingOptions(SkFilterMode::kLinear, |
| SkMipmapMode::kLinear)); |
| uint32_t pixel; |
| surf->readPixels(singlePixelInfo, &pixel, sizeof(uint32_t), 0, 0); |
| REPORTER_ASSERT(reporter, pixel == SkPreMultiplyColor(SK_ColorDKGRAY)); |
| img.reset(); |
| texRelease(btex); |
| } |