1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkTypes.h" 9 10 #if SK_SUPPORT_GPU 11 12 #include "GrBackendSurface.h" 13 #include "GrBackendTextureImageGenerator.h" 14 #include "GrContext.h" 15 #include "GrContextPriv.h" 16 #include "GrGpu.h" 17 #include "GrRenderTargetContext.h" 18 #include "GrSemaphore.h" 19 #include "GrSurfaceProxyPriv.h" 20 #include "GrTest.h" 21 #include "GrTexturePriv.h" 22 #include "GrTextureProxy.h" 23 #include "SkCanvas.h" 24 #include "SkImage_Base.h" 25 #include "SkGpuDevice.h" 26 #include "SkPoint.h" 27 #include "SkSurface.h" 28 #include "SkSurface_Gpu.h" 29 #include "Test.h" 30 31 static constexpr int kSize = 8; 32 33 // Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in 34 // SkImages and SkSurfaces 35 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) { 36 GrContext* context = ctxInfo.grContext(); 37 if (!context->caps()->mipMapSupport()) { 38 return; 39 } 40 GrGpu* gpu = context->contextPriv().getGpu(); 41 42 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) { 43 for (auto isRT : {false, true}) { 44 // CreateTestingOnlyBackendTexture currently doesn't support uploading data to mip maps 45 // so we don't send any. However, we pretend there is data for the checks below which is 46 // fine since we are never actually using these textures for any work on the gpu. 47 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture( 48 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, isRT, mipMapped); 49 50 sk_sp<GrTextureProxy> proxy; 51 sk_sp<SkImage> image; 52 if (isRT) { 53 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture( 54 context, 55 backendTex, 56 kTopLeft_GrSurfaceOrigin, 57 0, 58 kRGBA_8888_SkColorType, 59 nullptr, 60 nullptr); 61 62 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice(); 63 proxy = device->accessRenderTargetContext()->asTextureProxyRef(); 64 } else { 65 image = SkImage::MakeFromTexture(context, backendTex, 66 kTopLeft_GrSurfaceOrigin, 67 kRGBA_8888_SkColorType, 68 kPremul_SkAlphaType, nullptr, 69 nullptr, nullptr); 70 proxy = as_IB(image)->asTextureProxyRef(); 71 } 72 REPORTER_ASSERT(reporter, proxy); 73 if (!proxy) { 74 gpu->deleteTestingOnlyBackendTexture(&backendTex); 75 return; 76 } 77 78 REPORTER_ASSERT(reporter, proxy->priv().isInstantiated()); 79 80 GrTexture* texture = proxy->priv().peekTexture(); 81 REPORTER_ASSERT(reporter, texture); 82 if (!texture) { 83 gpu->deleteTestingOnlyBackendTexture(&backendTex); 84 return; 85 } 86 87 if (GrMipMapped::kYes == mipMapped) { 88 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped()); 89 if (isRT) { 90 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty()); 91 } else { 92 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty()); 93 } 94 } else { 95 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped()); 96 } 97 gpu->deleteTestingOnlyBackendTexture(&backendTex); 98 } 99 } 100 } 101 102 // Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator 103 // based on if we will use mips in the draw and the mip status of the GrBackendTexture. 104 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) { 105 GrContext* context = ctxInfo.grContext(); 106 if (!context->caps()->mipMapSupport()) { 107 return; 108 } 109 GrGpu* gpu = context->contextPriv().getGpu(); 110 111 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) { 112 for (auto willUseMips : {false, true}) { 113 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture( 114 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, false, mipMapped); 115 116 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex, 117 kTopLeft_GrSurfaceOrigin, 118 kRGBA_8888_SkColorType, 119 kPremul_SkAlphaType, nullptr, 120 nullptr, nullptr); 121 122 GrTextureProxy* proxy = as_IB(image)->peekProxy(); 123 REPORTER_ASSERT(reporter, proxy); 124 if (!proxy) { 125 gpu->deleteTestingOnlyBackendTexture(&backendTex); 126 return; 127 } 128 129 REPORTER_ASSERT(reporter, proxy->priv().isInstantiated()); 130 131 sk_sp<GrTexture> texture = sk_ref_sp(proxy->priv().peekTexture()); 132 REPORTER_ASSERT(reporter, texture); 133 if (!texture) { 134 gpu->deleteTestingOnlyBackendTexture(&backendTex); 135 return; 136 } 137 138 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make( 139 texture, kTopLeft_GrSurfaceOrigin, nullptr, kPremul_SkAlphaType, nullptr); 140 REPORTER_ASSERT(reporter, imageGen); 141 if (!imageGen) { 142 gpu->deleteTestingOnlyBackendTexture(&backendTex); 143 return; 144 } 145 146 SkIPoint origin = SkIPoint::Make(0,0); 147 // The transfer function behavior isn't used in the generator so set we set it 148 // arbitrarily here. 149 SkTransferFunctionBehavior behavior = SkTransferFunctionBehavior::kIgnore; 150 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, 151 kPremul_SkAlphaType); 152 sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo, 153 origin, behavior, 154 willUseMips); 155 156 REPORTER_ASSERT(reporter, genProxy); 157 if (!genProxy) { 158 gpu->deleteTestingOnlyBackendTexture(&backendTex); 159 return; 160 } 161 162 if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) { 163 genProxy->priv().doLazyInstantiation(context->contextPriv().resourceProvider()); 164 } 165 166 REPORTER_ASSERT(reporter, genProxy->priv().isInstantiated()); 167 if (!genProxy->priv().isInstantiated()) { 168 gpu->deleteTestingOnlyBackendTexture(&backendTex); 169 return; 170 } 171 172 GrTexture* genTexture = genProxy->priv().peekTexture(); 173 REPORTER_ASSERT(reporter, genTexture); 174 if (!genTexture) { 175 gpu->deleteTestingOnlyBackendTexture(&backendTex); 176 return; 177 } 178 179 GrBackendTexture genBackendTex = genTexture->getBackendTexture(); 180 181 if (const GrGLTextureInfo* genTexInfo = genBackendTex.getGLTextureInfo()) { 182 const GrGLTextureInfo* origTexInfo = backendTex.getGLTextureInfo(); 183 if (willUseMips && GrMipMapped::kNo == mipMapped) { 184 // We did a copy so the texture IDs should be different 185 REPORTER_ASSERT(reporter, origTexInfo->fID != genTexInfo->fID); 186 } else { 187 REPORTER_ASSERT(reporter, origTexInfo->fID == genTexInfo->fID); 188 } 189 #ifdef SK_VULKAN 190 } else if (const GrVkImageInfo* genImageInfo = genBackendTex.getVkImageInfo()) { 191 const GrVkImageInfo* origImageInfo = backendTex.getVkImageInfo(); 192 if (willUseMips && GrMipMapped::kNo == mipMapped) { 193 // We did a copy so the texture IDs should be different 194 REPORTER_ASSERT(reporter, origImageInfo->fImage != genImageInfo->fImage); 195 } else { 196 REPORTER_ASSERT(reporter, origImageInfo->fImage == genImageInfo->fImage); 197 } 198 #endif 199 } else { 200 REPORTER_ASSERT(reporter, false); 201 } 202 203 // Must make sure the uses of the backend texture have finished (we possibly have a 204 // queued up copy) before we delete the backend texture. 205 context->flush(); 206 gpu->testingOnly_flushGpuAndSync(); 207 208 gpu->deleteTestingOnlyBackendTexture(&backendTex); 209 } 210 } 211 } 212 213 // Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the 214 // resource we took the snapshot of. 215 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) { 216 GrContext* context = ctxInfo.grContext(); 217 if (!context->caps()->mipMapSupport()) { 218 return; 219 } 220 221 auto resourceProvider = context->contextPriv().resourceProvider(); 222 GrGpu* gpu = context->contextPriv().getGpu(); 223 224 for (auto willUseMips : {false, true}) { 225 for (auto isWrapped : {false, true}) { 226 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo; 227 sk_sp<SkSurface> surface; 228 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture( 229 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, true, mipMapped); 230 if (isWrapped) { 231 surface = SkSurface::MakeFromBackendTexture(context, 232 backendTex, 233 kTopLeft_GrSurfaceOrigin, 234 0, 235 kRGBA_8888_SkColorType, 236 nullptr, 237 nullptr); 238 } else { 239 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, 240 kPremul_SkAlphaType); 241 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0, 242 kTopLeft_GrSurfaceOrigin, nullptr, 243 willUseMips); 244 } 245 REPORTER_ASSERT(reporter, surface); 246 if (!surface) { 247 gpu->deleteTestingOnlyBackendTexture(&backendTex); 248 } 249 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice(); 250 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy(); 251 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped()); 252 253 texProxy->instantiate(resourceProvider); 254 GrTexture* texture = texProxy->priv().peekTexture(); 255 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped()); 256 257 sk_sp<SkImage> image = surface->makeImageSnapshot(); 258 REPORTER_ASSERT(reporter, image); 259 if (!image) { 260 gpu->deleteTestingOnlyBackendTexture(&backendTex); 261 } 262 texProxy = as_IB(image)->peekProxy(); 263 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped()); 264 265 texProxy->instantiate(resourceProvider); 266 texture = texProxy->priv().peekTexture(); 267 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped()); 268 269 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent 270 // to the gpu before we delete the backendHandle. 271 context->flush(); 272 gpu->deleteTestingOnlyBackendTexture(&backendTex); 273 } 274 } 275 } 276 277 #endif 278