1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 12cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 13cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h" 14cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 15cb93a386Sopenharmony_ci#ifdef SK_DIRECT3D 16cb93a386Sopenharmony_ci#include "include/gpu/d3d/GrD3DTypes.h" 17cb93a386Sopenharmony_ci#endif 18cb93a386Sopenharmony_ci#include "src/gpu/BaseDevice.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrBackendTextureImageGenerator.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrDrawingManager.h" 22cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 23cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h" 24cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 25cb93a386Sopenharmony_ci#include "src/gpu/GrSemaphore.h" 26cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h" 27cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 28cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h" 29cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h" 30cb93a386Sopenharmony_ci#include "src/image/SkImage_Base.h" 31cb93a386Sopenharmony_ci#include "src/image/SkSurface_Gpu.h" 32cb93a386Sopenharmony_ci#include "tests/Test.h" 33cb93a386Sopenharmony_ci#include "tests/TestUtils.h" 34cb93a386Sopenharmony_ci#include "tools/gpu/BackendSurfaceFactory.h" 35cb93a386Sopenharmony_ci#include "tools/gpu/BackendTextureImageFactory.h" 36cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h" 37cb93a386Sopenharmony_ci#include "tools/gpu/ProxyUtils.h" 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cistatic constexpr int kSize = 8; 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in 42cb93a386Sopenharmony_ci// SkImages and SkSurfaces 43cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) { 44cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 45cb93a386Sopenharmony_ci if (!dContext->priv().caps()->mipmapSupport()) { 46cb93a386Sopenharmony_ci return; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci for (auto mipmapped : {GrMipmapped::kNo, GrMipmapped::kYes}) { 50cb93a386Sopenharmony_ci for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) { 51cb93a386Sopenharmony_ci // createBackendTexture currently doesn't support uploading data to mip maps 52cb93a386Sopenharmony_ci // so we don't send any. However, we pretend there is data for the checks below which is 53cb93a386Sopenharmony_ci // fine since we are never actually using these textures for any work on the gpu. 54cb93a386Sopenharmony_ci auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(dContext, 55cb93a386Sopenharmony_ci kSize, 56cb93a386Sopenharmony_ci kSize, 57cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 58cb93a386Sopenharmony_ci SkColors::kTransparent, 59cb93a386Sopenharmony_ci mipmapped, 60cb93a386Sopenharmony_ci renderable, 61cb93a386Sopenharmony_ci GrProtected::kNo); 62cb93a386Sopenharmony_ci if (!mbet) { 63cb93a386Sopenharmony_ci ERRORF(reporter, "Could not make texture."); 64cb93a386Sopenharmony_ci return; 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy; 68cb93a386Sopenharmony_ci sk_sp<SkImage> image; 69cb93a386Sopenharmony_ci if (renderable == GrRenderable::kYes) { 70cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture( 71cb93a386Sopenharmony_ci dContext, 72cb93a386Sopenharmony_ci mbet->texture(), 73cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 74cb93a386Sopenharmony_ci 0, 75cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 76cb93a386Sopenharmony_ci /*color space*/ nullptr, 77cb93a386Sopenharmony_ci /*surface props*/ nullptr, 78cb93a386Sopenharmony_ci sk_gpu_test::ManagedBackendTexture::ReleaseProc, 79cb93a386Sopenharmony_ci mbet->releaseContext()); 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci auto device = ((SkSurface_Gpu*)surface.get())->getDevice(); 82cb93a386Sopenharmony_ci proxy = device->readSurfaceView().asTextureProxyRef(); 83cb93a386Sopenharmony_ci } else { 84cb93a386Sopenharmony_ci image = SkImage::MakeFromTexture(dContext, 85cb93a386Sopenharmony_ci mbet->texture(), 86cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 87cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 88cb93a386Sopenharmony_ci kPremul_SkAlphaType, 89cb93a386Sopenharmony_ci /* color space */ nullptr, 90cb93a386Sopenharmony_ci sk_gpu_test::ManagedBackendTexture::ReleaseProc, 91cb93a386Sopenharmony_ci mbet->releaseContext()); 92cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (mipmapped == GrMipmapped::kYes) == image->hasMipmaps()); 93cb93a386Sopenharmony_ci proxy = sk_ref_sp(sk_gpu_test::GetTextureImageProxy(image.get(), dContext)); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy); 96cb93a386Sopenharmony_ci if (!proxy) { 97cb93a386Sopenharmony_ci continue; 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->isInstantiated()); 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci GrTexture* texture = proxy->peekTexture(); 103cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, texture); 104cb93a386Sopenharmony_ci if (!texture) { 105cb93a386Sopenharmony_ci continue; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci if (mipmapped == GrMipmapped::kYes) { 109cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, GrMipmapped::kYes == texture->mipmapped()); 110cb93a386Sopenharmony_ci if (GrRenderable::kYes == renderable) { 111cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, texture->mipmapsAreDirty()); 112cb93a386Sopenharmony_ci } else { 113cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !texture->mipmapsAreDirty()); 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci } else { 116cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, GrMipmapped::kNo == texture->mipmapped()); 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci} 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator 123cb93a386Sopenharmony_ci// based on if we will use mips in the draw and the mip status of the GrBackendTexture. 124cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) { 125cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 126cb93a386Sopenharmony_ci if (!dContext->priv().caps()->mipmapSupport()) { 127cb93a386Sopenharmony_ci return; 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci for (auto betMipmapped : {GrMipmapped::kNo, GrMipmapped::kYes}) { 131cb93a386Sopenharmony_ci for (auto requestMipmapped : {GrMipmapped::kNo, GrMipmapped::kYes}) { 132cb93a386Sopenharmony_ci auto ii = 133cb93a386Sopenharmony_ci SkImageInfo::Make({kSize, kSize}, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 134cb93a386Sopenharmony_ci sk_sp<SkImage> image = sk_gpu_test::MakeBackendTextureImage( 135cb93a386Sopenharmony_ci dContext, ii, SkColors::kTransparent, betMipmapped); 136cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (betMipmapped == GrMipmapped::kYes) == image->hasMipmaps()); 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(image.get(), dContext); 139cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy); 140cb93a386Sopenharmony_ci if (!proxy) { 141cb93a386Sopenharmony_ci return; 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->isInstantiated()); 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture()); 147cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, texture); 148cb93a386Sopenharmony_ci if (!texture) { 149cb93a386Sopenharmony_ci return; 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make( 153cb93a386Sopenharmony_ci texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType, 154cb93a386Sopenharmony_ci kPremul_SkAlphaType, nullptr); 155cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, imageGen); 156cb93a386Sopenharmony_ci if (!imageGen) { 157cb93a386Sopenharmony_ci return; 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci SkIPoint origin = SkIPoint::Make(0,0); 161cb93a386Sopenharmony_ci SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, 162cb93a386Sopenharmony_ci kPremul_SkAlphaType); 163cb93a386Sopenharmony_ci GrSurfaceProxyView genView = imageGen->generateTexture( 164cb93a386Sopenharmony_ci dContext, imageInfo, origin, requestMipmapped, GrImageTexGenPolicy::kDraw); 165cb93a386Sopenharmony_ci GrSurfaceProxy* genProxy = genView.proxy(); 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, genProxy); 168cb93a386Sopenharmony_ci if (!genProxy) { 169cb93a386Sopenharmony_ci return; 170cb93a386Sopenharmony_ci } 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci if (genProxy->isLazy()) { 173cb93a386Sopenharmony_ci genProxy->priv().doLazyInstantiation(dContext->priv().resourceProvider()); 174cb93a386Sopenharmony_ci } else if (!genProxy->isInstantiated()) { 175cb93a386Sopenharmony_ci genProxy->instantiate(dContext->priv().resourceProvider()); 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, genProxy->isInstantiated()); 179cb93a386Sopenharmony_ci if (!genProxy->isInstantiated()) { 180cb93a386Sopenharmony_ci return; 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci GrTexture* genTexture = genProxy->peekTexture(); 184cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, genTexture); 185cb93a386Sopenharmony_ci if (!genTexture) { 186cb93a386Sopenharmony_ci return; 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci GrBackendTexture backendTex = texture->getBackendTexture(); 190cb93a386Sopenharmony_ci GrBackendTexture genBackendTex = genTexture->getBackendTexture(); 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci if (GrBackendApi::kOpenGL == genBackendTex.backend()) { 193cb93a386Sopenharmony_ci#ifdef SK_GL 194cb93a386Sopenharmony_ci GrGLTextureInfo genTexInfo; 195cb93a386Sopenharmony_ci GrGLTextureInfo origTexInfo; 196cb93a386Sopenharmony_ci if (genBackendTex.getGLTextureInfo(&genTexInfo) && 197cb93a386Sopenharmony_ci backendTex.getGLTextureInfo(&origTexInfo)) { 198cb93a386Sopenharmony_ci if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) { 199cb93a386Sopenharmony_ci // We did a copy so the texture IDs should be different 200cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID); 201cb93a386Sopenharmony_ci } else { 202cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID); 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci } else { 205cb93a386Sopenharmony_ci ERRORF(reporter, "Failed to get GrGLTextureInfo"); 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci#endif 208cb93a386Sopenharmony_ci#ifdef SK_VULKAN 209cb93a386Sopenharmony_ci } else if (GrBackendApi::kVulkan == genBackendTex.backend()) { 210cb93a386Sopenharmony_ci GrVkImageInfo genImageInfo; 211cb93a386Sopenharmony_ci GrVkImageInfo origImageInfo; 212cb93a386Sopenharmony_ci if (genBackendTex.getVkImageInfo(&genImageInfo) && 213cb93a386Sopenharmony_ci backendTex.getVkImageInfo(&origImageInfo)) { 214cb93a386Sopenharmony_ci if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) { 215cb93a386Sopenharmony_ci // We did a copy so the texture IDs should be different 216cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage); 217cb93a386Sopenharmony_ci } else { 218cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage); 219cb93a386Sopenharmony_ci } 220cb93a386Sopenharmony_ci } else { 221cb93a386Sopenharmony_ci ERRORF(reporter, "Failed to get GrVkImageInfo"); 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci#endif 224cb93a386Sopenharmony_ci#ifdef SK_METAL 225cb93a386Sopenharmony_ci } else if (GrBackendApi::kMetal == genBackendTex.backend()) { 226cb93a386Sopenharmony_ci GrMtlTextureInfo genImageInfo; 227cb93a386Sopenharmony_ci GrMtlTextureInfo origImageInfo; 228cb93a386Sopenharmony_ci if (genBackendTex.getMtlTextureInfo(&genImageInfo) && 229cb93a386Sopenharmony_ci backendTex.getMtlTextureInfo(&origImageInfo)) { 230cb93a386Sopenharmony_ci if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) { 231cb93a386Sopenharmony_ci // We did a copy so the texture IDs should be different 232cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture); 233cb93a386Sopenharmony_ci } else { 234cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture); 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci } else { 237cb93a386Sopenharmony_ci ERRORF(reporter, "Failed to get GrMtlTextureInfo"); 238cb93a386Sopenharmony_ci } 239cb93a386Sopenharmony_ci#endif 240cb93a386Sopenharmony_ci#ifdef SK_DIRECT3D 241cb93a386Sopenharmony_ci } else if (GrBackendApi::kDirect3D == genBackendTex.backend()) { 242cb93a386Sopenharmony_ci GrD3DTextureResourceInfo genImageInfo; 243cb93a386Sopenharmony_ci GrD3DTextureResourceInfo origImageInfo; 244cb93a386Sopenharmony_ci if (genBackendTex.getD3DTextureResourceInfo(&genImageInfo) && 245cb93a386Sopenharmony_ci backendTex.getD3DTextureResourceInfo(&origImageInfo)) { 246cb93a386Sopenharmony_ci if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) { 247cb93a386Sopenharmony_ci // We did a copy so the texture resources should be different 248cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 249cb93a386Sopenharmony_ci origImageInfo.fResource != genImageInfo.fResource); 250cb93a386Sopenharmony_ci } else { 251cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 252cb93a386Sopenharmony_ci origImageInfo.fResource == genImageInfo.fResource); 253cb93a386Sopenharmony_ci } 254cb93a386Sopenharmony_ci } else { 255cb93a386Sopenharmony_ci ERRORF(reporter, "Failed to get GrMtlTextureInfo"); 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci#endif 258cb93a386Sopenharmony_ci#ifdef SK_DAWN 259cb93a386Sopenharmony_ci } else if (GrBackendApi::kDawn == genBackendTex.backend()) { 260cb93a386Sopenharmony_ci GrDawnTextureInfo genImageInfo; 261cb93a386Sopenharmony_ci GrDawnTextureInfo origImageInfo; 262cb93a386Sopenharmony_ci if (genBackendTex.getDawnTextureInfo(&genImageInfo) && 263cb93a386Sopenharmony_ci backendTex.getDawnTextureInfo(&origImageInfo)) { 264cb93a386Sopenharmony_ci if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) { 265cb93a386Sopenharmony_ci // We did a copy so the texture IDs should be different 266cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 267cb93a386Sopenharmony_ci origImageInfo.fTexture.Get() != genImageInfo.fTexture.Get()); 268cb93a386Sopenharmony_ci } else { 269cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 270cb93a386Sopenharmony_ci origImageInfo.fTexture.Get() == genImageInfo.fTexture.Get()); 271cb93a386Sopenharmony_ci } 272cb93a386Sopenharmony_ci } else { 273cb93a386Sopenharmony_ci ERRORF(reporter, "Failed to get GrDawnTextureInfo"); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci#endif 276cb93a386Sopenharmony_ci } else { 277cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false); 278cb93a386Sopenharmony_ci } 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci } 281cb93a386Sopenharmony_ci} 282cb93a386Sopenharmony_ci 283cb93a386Sopenharmony_ci// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the 284cb93a386Sopenharmony_ci// resource we took the snapshot of. 285cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) { 286cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 287cb93a386Sopenharmony_ci if (!dContext->priv().caps()->mipmapSupport()) { 288cb93a386Sopenharmony_ci return; 289cb93a386Sopenharmony_ci } 290cb93a386Sopenharmony_ci 291cb93a386Sopenharmony_ci auto resourceProvider = dContext->priv().resourceProvider(); 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci for (auto willUseMips : {false, true}) { 294cb93a386Sopenharmony_ci for (auto isWrapped : {false, true}) { 295cb93a386Sopenharmony_ci GrMipmapped mipmapped = willUseMips ? GrMipmapped::kYes : GrMipmapped::kNo; 296cb93a386Sopenharmony_ci sk_sp<SkSurface> surface; 297cb93a386Sopenharmony_ci SkImageInfo info = 298cb93a386Sopenharmony_ci SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 299cb93a386Sopenharmony_ci if (isWrapped) { 300cb93a386Sopenharmony_ci surface = sk_gpu_test::MakeBackendTextureSurface(dContext, 301cb93a386Sopenharmony_ci info, 302cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 303cb93a386Sopenharmony_ci /* sample count */ 1, 304cb93a386Sopenharmony_ci mipmapped); 305cb93a386Sopenharmony_ci } else { 306cb93a386Sopenharmony_ci surface = SkSurface::MakeRenderTarget(dContext, 307cb93a386Sopenharmony_ci SkBudgeted::kYes, 308cb93a386Sopenharmony_ci info, 309cb93a386Sopenharmony_ci /* sample count */ 1, 310cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 311cb93a386Sopenharmony_ci nullptr, 312cb93a386Sopenharmony_ci willUseMips); 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surface); 315cb93a386Sopenharmony_ci auto device = ((SkSurface_Gpu*)surface.get())->getDevice(); 316cb93a386Sopenharmony_ci GrTextureProxy* texProxy = device->readSurfaceView().asTextureProxy(); 317cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipmapped == texProxy->mipmapped()); 318cb93a386Sopenharmony_ci 319cb93a386Sopenharmony_ci texProxy->instantiate(resourceProvider); 320cb93a386Sopenharmony_ci GrTexture* texture = texProxy->peekTexture(); 321cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipmapped == texture->mipmapped()); 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci sk_sp<SkImage> image = surface->makeImageSnapshot(); 324cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, willUseMips == image->hasMipmaps()); 325cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, image); 326cb93a386Sopenharmony_ci texProxy = sk_gpu_test::GetTextureImageProxy(image.get(), dContext); 327cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipmapped == texProxy->mipmapped()); 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_ci texProxy->instantiate(resourceProvider); 330cb93a386Sopenharmony_ci texture = texProxy->peekTexture(); 331cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipmapped == texture->mipmapped()); 332cb93a386Sopenharmony_ci } 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci} 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_ci// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set 337cb93a386Sopenharmony_ci// to use mips. This test passes by not crashing or hitting asserts in code. 338cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) { 339cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 340cb93a386Sopenharmony_ci if (!dContext->priv().caps()->mipmapSupport()) { 341cb93a386Sopenharmony_ci return; 342cb93a386Sopenharmony_ci } 343cb93a386Sopenharmony_ci 344cb93a386Sopenharmony_ci // Make surface to draw into 345cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType); 346cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info); 347cb93a386Sopenharmony_ci 348cb93a386Sopenharmony_ci // Make 1x1 raster bitmap 349cb93a386Sopenharmony_ci SkBitmap bmp; 350cb93a386Sopenharmony_ci bmp.allocN32Pixels(1, 1); 351cb93a386Sopenharmony_ci SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels()); 352cb93a386Sopenharmony_ci *pixel = 0; 353cb93a386Sopenharmony_ci 354cb93a386Sopenharmony_ci sk_sp<SkImage> bmpImage = bmp.asImage(); 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_ci // Make sure we scale so we don't optimize out the use of mips. 357cb93a386Sopenharmony_ci surface->getCanvas()->scale(0.5f, 0.5f); 358cb93a386Sopenharmony_ci 359cb93a386Sopenharmony_ci // This should upload the image to a non mipped GrTextureProxy. 360cb93a386Sopenharmony_ci surface->getCanvas()->drawImage(bmpImage, 0, 0); 361cb93a386Sopenharmony_ci surface->flushAndSubmit(); 362cb93a386Sopenharmony_ci 363cb93a386Sopenharmony_ci // Now set the filter quality to high so we use mip maps. We should find the non mipped texture 364cb93a386Sopenharmony_ci // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture 365cb93a386Sopenharmony_ci // instead of trying to do a copy to a mipped texture. 366cb93a386Sopenharmony_ci surface->getCanvas()->drawImage(bmpImage, 0, 0, SkSamplingOptions({1.0f/3, 1.0f/3})); 367cb93a386Sopenharmony_ci surface->flushAndSubmit(); 368cb93a386Sopenharmony_ci} 369cb93a386Sopenharmony_ci 370cb93a386Sopenharmony_ci// Create a new render target and draw 'mipmapView' into it using the provided 'filter'. 371cb93a386Sopenharmony_cistatic std::unique_ptr<skgpu::v1::SurfaceDrawContext> draw_mipmap_into_new_render_target( 372cb93a386Sopenharmony_ci GrRecordingContext* rContext, 373cb93a386Sopenharmony_ci GrColorType colorType, 374cb93a386Sopenharmony_ci SkAlphaType alphaType, 375cb93a386Sopenharmony_ci GrSurfaceProxyView mipmapView, 376cb93a386Sopenharmony_ci GrSamplerState::MipmapMode mm) { 377cb93a386Sopenharmony_ci auto proxyProvider = rContext->priv().proxyProvider(); 378cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> renderTarget = 379cb93a386Sopenharmony_ci proxyProvider->createProxy(mipmapView.proxy()->backendFormat(), 380cb93a386Sopenharmony_ci {1, 1}, 381cb93a386Sopenharmony_ci GrRenderable::kYes, 382cb93a386Sopenharmony_ci 1, 383cb93a386Sopenharmony_ci GrMipmapped::kNo, 384cb93a386Sopenharmony_ci SkBackingFit::kApprox, 385cb93a386Sopenharmony_ci SkBudgeted::kYes, 386cb93a386Sopenharmony_ci GrProtected::kNo); 387cb93a386Sopenharmony_ci 388cb93a386Sopenharmony_ci auto sdc = skgpu::v1::SurfaceDrawContext::Make(rContext, 389cb93a386Sopenharmony_ci colorType, 390cb93a386Sopenharmony_ci std::move(renderTarget), 391cb93a386Sopenharmony_ci nullptr, 392cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 393cb93a386Sopenharmony_ci SkSurfaceProps(), 394cb93a386Sopenharmony_ci false); 395cb93a386Sopenharmony_ci 396cb93a386Sopenharmony_ci sdc->drawTexture(nullptr, 397cb93a386Sopenharmony_ci std::move(mipmapView), 398cb93a386Sopenharmony_ci alphaType, 399cb93a386Sopenharmony_ci GrSamplerState::Filter::kLinear, 400cb93a386Sopenharmony_ci mm, 401cb93a386Sopenharmony_ci SkBlendMode::kSrcOver, 402cb93a386Sopenharmony_ci {1, 1, 1, 1}, 403cb93a386Sopenharmony_ci SkRect::MakeWH(4, 4), 404cb93a386Sopenharmony_ci SkRect::MakeWH(1, 1), 405cb93a386Sopenharmony_ci GrAA::kYes, 406cb93a386Sopenharmony_ci GrQuadAAFlags::kAll, 407cb93a386Sopenharmony_ci SkCanvas::kFast_SrcRectConstraint, 408cb93a386Sopenharmony_ci SkMatrix::I(), 409cb93a386Sopenharmony_ci nullptr); 410cb93a386Sopenharmony_ci return sdc; 411cb93a386Sopenharmony_ci} 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_ci// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask. 414cb93a386Sopenharmony_ciDEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) { 415cb93a386Sopenharmony_ci using Enable = GrContextOptions::Enable; 416cb93a386Sopenharmony_ci using MipmapMode = GrSamplerState::MipmapMode; 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) { 419cb93a386Sopenharmony_ci GrMockOptions mockOptions; 420cb93a386Sopenharmony_ci mockOptions.fMipmapSupport = true; 421cb93a386Sopenharmony_ci GrContextOptions ctxOptions; 422cb93a386Sopenharmony_ci ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction; 423cb93a386Sopenharmony_ci sk_sp<GrDirectContext> dContext = GrDirectContext::MakeMock(&mockOptions, ctxOptions); 424cb93a386Sopenharmony_ci GrDrawingManager* drawingManager = dContext->priv().drawingManager(); 425cb93a386Sopenharmony_ci if (!dContext) { 426cb93a386Sopenharmony_ci ERRORF(reporter, "could not create mock dContext with fReduceOpsTaskSplitting %s.", 427cb93a386Sopenharmony_ci (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled"); 428cb93a386Sopenharmony_ci continue; 429cb93a386Sopenharmony_ci } 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ci SkASSERT(dContext->priv().caps()->mipmapSupport()); 432cb93a386Sopenharmony_ci 433cb93a386Sopenharmony_ci GrBackendFormat format = dContext->defaultBackendFormat( 434cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, GrRenderable::kYes); 435cb93a386Sopenharmony_ci GrColorType colorType = GrColorType::kRGBA_8888; 436cb93a386Sopenharmony_ci SkAlphaType alphaType = kPremul_SkAlphaType; 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_ci GrProxyProvider* proxyProvider = dContext->priv().proxyProvider(); 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_ci // Create a mipmapped render target. 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy( 443cb93a386Sopenharmony_ci format, {4, 4}, GrRenderable::kYes, 1, GrMipmapped::kYes, SkBackingFit::kExact, 444cb93a386Sopenharmony_ci SkBudgeted::kYes, GrProtected::kNo); 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_ci // Mark the mipmaps clean to ensure things still work properly when they won't be marked 447cb93a386Sopenharmony_ci // dirty again until GrRenderTask::makeClosed(). 448cb93a386Sopenharmony_ci mipmapProxy->markMipmapsClean(); 449cb93a386Sopenharmony_ci 450cb93a386Sopenharmony_ci auto mipmapSDC = skgpu::v1::SurfaceDrawContext::Make( 451cb93a386Sopenharmony_ci dContext.get(), colorType, mipmapProxy, nullptr, kTopLeft_GrSurfaceOrigin, 452cb93a386Sopenharmony_ci SkSurfaceProps(), false); 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci mipmapSDC->clear(SkPMColor4f{.1f, .2f, .3f, .4f}); 455cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, drawingManager->getLastRenderTask(mipmapProxy.get())); 456cb93a386Sopenharmony_ci // mipmapProxy's last render task should now just be the opsTask containing the clear. 457cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 458cb93a386Sopenharmony_ci mipmapSDC->testingOnly_PeekLastOpsTask() == 459cb93a386Sopenharmony_ci drawingManager->getLastRenderTask(mipmapProxy.get())); 460cb93a386Sopenharmony_ci 461cb93a386Sopenharmony_ci // Mipmaps don't get marked dirty until makeClosed(). 462cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty()); 463cb93a386Sopenharmony_ci 464cb93a386Sopenharmony_ci GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, colorType); 465cb93a386Sopenharmony_ci GrSurfaceProxyView mipmapView(mipmapProxy, kTopLeft_GrSurfaceOrigin, swizzle); 466cb93a386Sopenharmony_ci 467cb93a386Sopenharmony_ci // Draw the dirty mipmap texture into a render target. 468cb93a386Sopenharmony_ci auto sdc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType, 469cb93a386Sopenharmony_ci mipmapView, MipmapMode::kLinear); 470cb93a386Sopenharmony_ci auto sdc1Task = sk_ref_sp(sdc1->testingOnly_PeekLastOpsTask()); 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as 473cb93a386Sopenharmony_ci // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is 474cb93a386Sopenharmony_ci // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the 475cb93a386Sopenharmony_ci // task that resolved its mips. 476cb93a386Sopenharmony_ci GrRenderTask* initialMipmapRegenTask = drawingManager->getLastRenderTask(mipmapProxy.get()); 477cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, initialMipmapRegenTask); 478cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 479cb93a386Sopenharmony_ci initialMipmapRegenTask != mipmapSDC->testingOnly_PeekLastOpsTask()); 480cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty()); 481cb93a386Sopenharmony_ci 482cb93a386Sopenharmony_ci // Draw the now-clean mipmap texture into a second target. 483cb93a386Sopenharmony_ci auto sdc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType, 484cb93a386Sopenharmony_ci mipmapView, MipmapMode::kLinear); 485cb93a386Sopenharmony_ci auto sdc2Task = sk_ref_sp(sdc2->testingOnly_PeekLastOpsTask()); 486cb93a386Sopenharmony_ci 487cb93a386Sopenharmony_ci // Make sure the mipmap texture still has the same regen task. 488cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 489cb93a386Sopenharmony_ci drawingManager->getLastRenderTask(mipmapProxy.get()) == initialMipmapRegenTask); 490cb93a386Sopenharmony_ci SkASSERT(!mipmapProxy->mipmapsAreDirty()); 491cb93a386Sopenharmony_ci 492cb93a386Sopenharmony_ci // Reset everything so we can go again, this time with the first draw not mipmapped. 493cb93a386Sopenharmony_ci dContext->flushAndSubmit(); 494cb93a386Sopenharmony_ci 495cb93a386Sopenharmony_ci // Mip regen tasks don't get added as dependencies until makeClosed(). 496cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, sdc1Task->dependsOn(initialMipmapRegenTask)); 497cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, sdc2Task->dependsOn(initialMipmapRegenTask)); 498cb93a386Sopenharmony_ci 499cb93a386Sopenharmony_ci // Render something to dirty the mips. 500cb93a386Sopenharmony_ci mipmapSDC->clear(SkPMColor4f{.1f, .2f, .3f, .4f}); 501cb93a386Sopenharmony_ci auto mipmapRTCTask = sk_ref_sp(mipmapSDC->testingOnly_PeekLastOpsTask()); 502cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipmapRTCTask); 503cb93a386Sopenharmony_ci 504cb93a386Sopenharmony_ci // mipmapProxy's last render task should now just be the opsTask containing the clear. 505cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 506cb93a386Sopenharmony_ci mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get())); 507cb93a386Sopenharmony_ci 508cb93a386Sopenharmony_ci // Mipmaps don't get marked dirty until makeClosed(). 509cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty()); 510cb93a386Sopenharmony_ci 511cb93a386Sopenharmony_ci // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering. 512cb93a386Sopenharmony_ci sdc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType, 513cb93a386Sopenharmony_ci mipmapView, MipmapMode::kNone); 514cb93a386Sopenharmony_ci 515cb93a386Sopenharmony_ci // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency. 516cb93a386Sopenharmony_ci // Since the last draw did not use mips, they will not have been regenerated and should 517cb93a386Sopenharmony_ci // therefore still be dirty. 518cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipmapProxy->mipmapsAreDirty()); 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_ci // Since mips weren't regenerated, the last render task shouldn't have changed. 521cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 522cb93a386Sopenharmony_ci mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get())); 523cb93a386Sopenharmony_ci 524cb93a386Sopenharmony_ci // Draw the stil-dirty mipmap texture into a second target with mipmap filtering. 525cb93a386Sopenharmony_ci sdc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType, 526cb93a386Sopenharmony_ci std::move(mipmapView), MipmapMode::kLinear); 527cb93a386Sopenharmony_ci sdc2Task = sk_ref_sp(sdc2->testingOnly_PeekLastOpsTask()); 528cb93a386Sopenharmony_ci 529cb93a386Sopenharmony_ci // Make sure the mipmap texture now has a new last render task that regenerates the mips, 530cb93a386Sopenharmony_ci // and that the mipmaps are now clean. 531cb93a386Sopenharmony_ci auto mipRegenTask2 = drawingManager->getLastRenderTask(mipmapProxy.get()); 532cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipRegenTask2); 533cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mipmapRTCTask.get() != mipRegenTask2); 534cb93a386Sopenharmony_ci SkASSERT(!mipmapProxy->mipmapsAreDirty()); 535cb93a386Sopenharmony_ci 536cb93a386Sopenharmony_ci // Mip regen tasks don't get added as dependencies until makeClosed(). 537cb93a386Sopenharmony_ci dContext->flushAndSubmit(); 538cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, sdc2Task->dependsOn(mipRegenTask2)); 539cb93a386Sopenharmony_ci } 540cb93a386Sopenharmony_ci} 541