|  | /* | 
|  | * 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/SkAlphaType.h" | 
|  | #include "include/core/SkCanvas.h" | 
|  | #include "include/core/SkColor.h" | 
|  | #include "include/core/SkColorSpace.h" | 
|  | #include "include/core/SkColorType.h" | 
|  | #include "include/core/SkImage.h" | 
|  | #include "include/core/SkImageInfo.h" | 
|  | #include "include/core/SkPaint.h" | 
|  | #include "include/core/SkRect.h" | 
|  | #include "include/core/SkRefCnt.h" | 
|  | #include "include/core/SkSamplingOptions.h" | 
|  | #include "include/core/SkSurface.h" | 
|  | #include "include/core/SkTypes.h" | 
|  | #include "include/gpu/GrBackendSurface.h" | 
|  | #include "include/gpu/GrDirectContext.h" | 
|  | #include "include/gpu/GrTypes.h" | 
|  | #include "src/gpu/ganesh/GrCaps.h" | 
|  | #include "src/gpu/ganesh/GrDirectContextPriv.h" | 
|  | #include "src/gpu/ganesh/GrTexture.h" | 
|  | #include "src/gpu/ganesh/GrTextureProxy.h" | 
|  | #include "tests/CtsEnforcement.h" | 
|  | #include "tests/Test.h" | 
|  | #include "tools/gpu/ProxyUtils.h" | 
|  |  | 
|  | #include <cstdint> | 
|  | #include <functional> | 
|  | #include <initializer_list> | 
|  | #include <utility> | 
|  |  | 
|  | struct GrContextOptions; | 
|  |  | 
|  | // Tests that MIP maps are created and invalidated as expected when drawing to and from GrTextures. | 
|  | DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrTextureMipMapInvalidationTest, | 
|  | reporter, | 
|  | ctxInfo, | 
|  | CtsEnforcement::kApiLevel_T) { | 
|  | auto context = ctxInfo.directContext(); | 
|  | if (!context->priv().caps()->mipmapSupport()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | auto isMipped = [reporter](SkSurface* surf) { | 
|  | sk_sp<SkImage> image = surf->makeImageSnapshot(); | 
|  | GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(image.get(), | 
|  | surf->recordingContext()); | 
|  | bool proxyIsMipmapped = proxy->mipmapped() == GrMipmapped::kYes; | 
|  | REPORTER_ASSERT(reporter, proxyIsMipmapped == image->hasMipmaps()); | 
|  | return image->hasMipmaps(); | 
|  | }; | 
|  |  | 
|  | auto mipsAreDirty = [](SkSurface* surf) { | 
|  | sk_sp<SkImage> image = surf->makeImageSnapshot(); | 
|  | GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(image.get(), | 
|  | surf->recordingContext()); | 
|  | return proxy->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_GANESH_TEST_FOR_RENDERING_CONTEXTS(ReimportImageTextureWithMipLevels, | 
|  | reporter, | 
|  | ctxInfo, | 
|  | CtsEnforcement::kApiLevel_T) { | 
|  | 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); | 
|  | } |