1 /* 2 * Copyright 2013 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 "GrContext.h" 13 #include "GrContextPriv.h" 14 #include "GrGpu.h" 15 #include "GrResourceProvider.h" 16 #include "GrTest.h" 17 #include "GrTexture.h" 18 #include "GrSurfacePriv.h" 19 #include "SkMipMap.h" 20 #include "Test.h" 21 22 // Tests that GrSurface::asTexture(), GrSurface::asRenderTarget(), and static upcasting of texture 23 // and render targets to GrSurface all work as expected. 24 DEF_GPUTEST_FOR_NULLGL_CONTEXT(GrSurface, reporter, ctxInfo) { 25 GrContext* context = ctxInfo.grContext(); 26 GrSurfaceDesc desc; 27 desc.fConfig = kRGBA_8888_GrPixelConfig; 28 desc.fFlags = kRenderTarget_GrSurfaceFlag; 29 desc.fWidth = 256; 30 desc.fHeight = 256; 31 desc.fSampleCnt = 0; 32 sk_sp<GrSurface> texRT1 = context->resourceProvider()->createTexture(desc, SkBudgeted::kNo); 33 34 REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asRenderTarget()); 35 REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asTexture()); 36 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) == 37 texRT1->asTexture()); 38 REPORTER_ASSERT(reporter, texRT1->asRenderTarget() == 39 static_cast<GrSurface*>(texRT1->asTexture())); 40 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) == 41 static_cast<GrSurface*>(texRT1->asTexture())); 42 43 desc.fFlags = kNone_GrSurfaceFlags; 44 sk_sp<GrTexture> tex1 = context->resourceProvider()->createTexture(desc, SkBudgeted::kNo); 45 REPORTER_ASSERT(reporter, nullptr == tex1->asRenderTarget()); 46 REPORTER_ASSERT(reporter, tex1.get() == tex1->asTexture()); 47 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(tex1.get()) == tex1->asTexture()); 48 49 GrBackendObject backendTexHandle = context->getGpu()->createTestingOnlyBackendTexture( 50 nullptr, 256, 256, kRGBA_8888_GrPixelConfig); 51 GrBackendTexture backendTex = GrTest::CreateBackendTexture(context->contextPriv().getBackend(), 52 256, 53 256, 54 kRGBA_8888_GrPixelConfig, 55 backendTexHandle); 56 57 sk_sp<GrSurface> texRT2 = context->resourceProvider()->wrapBackendTexture( 58 backendTex, kTopLeft_GrSurfaceOrigin, kRenderTarget_GrBackendTextureFlag, 0, 59 kBorrow_GrWrapOwnership); 60 61 REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asRenderTarget()); 62 REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asTexture()); 63 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) == 64 texRT2->asTexture()); 65 REPORTER_ASSERT(reporter, texRT2->asRenderTarget() == 66 static_cast<GrSurface*>(texRT2->asTexture())); 67 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) == 68 static_cast<GrSurface*>(texRT2->asTexture())); 69 70 context->getGpu()->deleteTestingOnlyBackendTexture(backendTexHandle); 71 } 72 73 // This test checks that the isConfigTexturable and isConfigRenderable are 74 // consistent with createTexture's result. 75 DEF_GPUTEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability, reporter, ctxInfo) { 76 GrContext* context = ctxInfo.grContext(); 77 GrResourceProvider* resourceProvider = context->resourceProvider(); 78 const GrCaps* caps = context->caps(); 79 80 GrPixelConfig configs[] = { 81 kUnknown_GrPixelConfig, 82 kAlpha_8_GrPixelConfig, 83 kGray_8_GrPixelConfig, 84 kRGB_565_GrPixelConfig, 85 kRGBA_4444_GrPixelConfig, 86 kRGBA_8888_GrPixelConfig, 87 kBGRA_8888_GrPixelConfig, 88 kSRGBA_8888_GrPixelConfig, 89 kSBGRA_8888_GrPixelConfig, 90 kRGBA_8888_sint_GrPixelConfig, 91 kRGBA_float_GrPixelConfig, 92 kRG_float_GrPixelConfig, 93 kAlpha_half_GrPixelConfig, 94 kRGBA_half_GrPixelConfig, 95 }; 96 SkASSERT(kGrPixelConfigCnt == SK_ARRAY_COUNT(configs)); 97 98 GrSurfaceDesc desc; 99 desc.fWidth = 64; 100 desc.fHeight = 64; 101 102 // Enough space for the first mip of our largest pixel config 103 const size_t pixelBufferSize = desc.fWidth * desc.fHeight * 104 GrBytesPerPixel(kRGBA_float_GrPixelConfig); 105 std::unique_ptr<char[]> pixelData(new char[pixelBufferSize]); 106 memset(pixelData.get(), 0, pixelBufferSize); 107 108 // We re-use the same mip level objects (with updated pointers and rowBytes) for each config 109 const int levelCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1; 110 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[levelCount]); 111 112 for (GrPixelConfig config : configs) { 113 for (GrSurfaceOrigin origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin }) { 114 desc.fFlags = kNone_GrSurfaceFlags; 115 desc.fOrigin = origin; 116 desc.fSampleCnt = 0; 117 desc.fConfig = config; 118 119 sk_sp<GrSurface> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo); 120 REPORTER_ASSERT(reporter, SkToBool(tex.get()) == caps->isConfigTexturable(desc.fConfig)); 121 122 size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig); 123 for (int i = 0; i < levelCount; ++i) { 124 texels[i].fPixels = pixelData.get(); 125 texels[i].fRowBytes = rowBytes >> i; 126 } 127 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferredMipMap(resourceProvider, 128 desc, SkBudgeted::kNo, 129 texels.get(), 130 levelCount); 131 REPORTER_ASSERT(reporter, SkToBool(proxy.get()) == 132 (caps->isConfigTexturable(desc.fConfig) && 133 caps->mipMapSupport() && 134 !GrPixelConfigIsSint(desc.fConfig))); 135 136 desc.fFlags = kRenderTarget_GrSurfaceFlag; 137 tex = resourceProvider->createTexture(desc, SkBudgeted::kNo); 138 REPORTER_ASSERT(reporter, SkToBool(tex.get()) == caps->isConfigRenderable(config, false)); 139 140 desc.fSampleCnt = 4; 141 tex = resourceProvider->createTexture(desc, SkBudgeted::kNo); 142 REPORTER_ASSERT(reporter, SkToBool(tex.get()) == caps->isConfigRenderable(config, true)); 143 } 144 } 145 } 146 147 #include "GrDrawingManager.h" 148 #include "GrSurfaceProxy.h" 149 #include "GrTextureContext.h" 150 151 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(InitialTextureClear, reporter, context_info) { 152 static constexpr int kSize = 100; 153 GrSurfaceDesc desc; 154 desc.fWidth = desc.fHeight = kSize; 155 std::unique_ptr<uint32_t[]> data(new uint32_t[kSize * kSize]); 156 GrContext* context = context_info.grContext(); 157 for (int c = 0; c <= kLast_GrPixelConfig; ++c) { 158 desc.fConfig = static_cast<GrPixelConfig>(c); 159 if (!context_info.grContext()->caps()->isConfigTexturable(desc.fConfig)) { 160 continue; 161 } 162 desc.fFlags = kPerformInitialClear_GrSurfaceFlag; 163 for (bool rt : {false, true}) { 164 if (rt && !context->caps()->isConfigRenderable(desc.fConfig, false)) { 165 continue; 166 } 167 desc.fFlags |= rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags; 168 for (bool mipped : {false, true}) { 169 desc.fIsMipMapped = mipped; 170 for (GrSurfaceOrigin origin : 171 {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) { 172 desc.fOrigin = origin; 173 for (bool approx : {false, true}) { 174 auto resourceProvider = context->resourceProvider(); 175 // Try directly creating the texture. 176 // Do this twice in an attempt to hit the cache on the second time through. 177 for (int i = 0; i < 2; ++i) { 178 sk_sp<GrTexture> tex; 179 if (approx) { 180 tex = sk_sp<GrTexture>( 181 resourceProvider->createApproxTexture(desc, 0)); 182 } else { 183 tex = resourceProvider->createTexture(desc, SkBudgeted::kYes); 184 } 185 if (!tex) { 186 continue; 187 } 188 auto proxy = GrSurfaceProxy::MakeWrapped(std::move(tex)); 189 auto texCtx = context->contextPriv().makeWrappedSurfaceContext( 190 std::move(proxy), nullptr); 191 SkImageInfo info = SkImageInfo::Make( 192 kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 193 memset(data.get(), 0xAB, kSize * kSize * sizeof(uint32_t)); 194 if (texCtx->readPixels(info, data.get(), 0, 0, 0)) { 195 uint32_t cmp = GrPixelConfigIsOpaque(desc.fConfig) ? 0xFF000000 : 0; 196 for (int i = 0; i < kSize * kSize; ++i) { 197 if (cmp != data.get()[i]) { 198 ERRORF(reporter, "Failed on config %d", desc.fConfig); 199 break; 200 } 201 } 202 } 203 memset(data.get(), 0xBC, kSize * kSize * sizeof(uint32_t)); 204 // Here we overwrite the texture so that the second time through we 205 // test against recycling without reclearing. 206 if (0 == i) { 207 texCtx->writePixels(info, data.get(), 0, 0, 0); 208 } 209 } 210 context->purgeAllUnlockedResources(); 211 212 // Try creating the texture as a deferred proxy. 213 for (int i = 0; i < 2; ++i) { 214 auto surfCtx = context->contextPriv().makeDeferredSurfaceContext( 215 desc, approx ? SkBackingFit::kApprox : SkBackingFit::kExact, 216 SkBudgeted::kYes); 217 if (!surfCtx) { 218 continue; 219 } 220 SkImageInfo info = SkImageInfo::Make( 221 kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 222 memset(data.get(), 0xAB, kSize * kSize * sizeof(uint32_t)); 223 if (surfCtx->readPixels(info, data.get(), 0, 0, 0)) { 224 uint32_t cmp = GrPixelConfigIsOpaque(desc.fConfig) ? 0xFF000000 : 0; 225 for (int i = 0; i < kSize * kSize; ++i) { 226 if (cmp != data.get()[i]) { 227 ERRORF(reporter, "Failed on config %d", desc.fConfig); 228 break; 229 } 230 } 231 } 232 // Here we overwrite the texture so that the second time through we 233 // test against recycling without reclearing. 234 if (0 == i) { 235 surfCtx->writePixels(info, data.get(), 0, 0, 0); 236 } 237 } 238 context->purgeAllUnlockedResources(); 239 } 240 } 241 } 242 } 243 } 244 } 245 #endif 246