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