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 here to ensure SK_SUPPORT_GPU is set correctly before it is examined. 9#include "SkTypes.h" 10 11#if SK_SUPPORT_GPU 12#ifndef SK_DISABLE_DEFERRED_PROXIES 13#include "Test.h" 14 15#include "GrContextPriv.h" 16#include "GrGpu.h" 17#include "GrProxyProvider.h" 18#include "GrResourceAllocator.h" 19#include "GrResourceProvider.h" 20#include "GrSurfaceProxyPriv.h" 21#include "GrTest.h" 22#include "GrTexture.h" 23#include "GrTextureProxy.h" 24 25struct ProxyParams { 26 int fSize; 27 bool fIsRT; 28 GrPixelConfig fConfig; 29 SkBackingFit fFit; 30 int fSampleCnt; 31 GrSurfaceOrigin fOrigin; 32 // TODO: do we care about mipmapping 33}; 34 35static sk_sp<GrSurfaceProxy> make_deferred(GrProxyProvider* proxyProvider, const ProxyParams& p) { 36 GrSurfaceDesc desc; 37 desc.fFlags = p.fIsRT ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags; 38 desc.fOrigin = p.fOrigin; 39 desc.fWidth = p.fSize; 40 desc.fHeight = p.fSize; 41 desc.fConfig = p.fConfig; 42 desc.fSampleCnt = p.fSampleCnt; 43 44 return proxyProvider->createProxy(desc, p.fFit, SkBudgeted::kNo); 45} 46 47static sk_sp<GrSurfaceProxy> make_backend(GrContext* context, const ProxyParams& p, 48 GrBackendTexture* backendTex) { 49 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); 50 GrGpu* gpu = context->contextPriv().getGpu(); 51 52 *backendTex = gpu->createTestingOnlyBackendTexture(nullptr, p.fSize, p.fSize, 53 p.fConfig, false, 54 GrMipMapped::kNo); 55 56 return proxyProvider->createWrappedTextureProxy(*backendTex, p.fOrigin); 57} 58 59static void cleanup_backend(GrContext* context, GrBackendTexture* backendTex) { 60 context->contextPriv().getGpu()->deleteTestingOnlyBackendTexture(backendTex); 61} 62 63// Basic test that two proxies with overlapping intervals and compatible descriptors are 64// assigned different GrSurfaces. 65static void overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider, 66 sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2, 67 bool expectedResult) { 68 GrResourceAllocator alloc(resourceProvider); 69 70 alloc.addInterval(p1.get(), 0, 4); 71 alloc.addInterval(p2.get(), 1, 2); 72 alloc.markEndOfOpList(0); 73 74 int startIndex, stopIndex; 75 GrResourceAllocator::AssignError error; 76 alloc.assign(&startIndex, &stopIndex, &error); 77 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error); 78 79 REPORTER_ASSERT(reporter, p1->priv().peekSurface()); 80 REPORTER_ASSERT(reporter, p2->priv().peekSurface()); 81 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID(); 82 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch); 83} 84 85// Test various cases when two proxies do not have overlapping intervals. 86// This mainly acts as a test of the ResourceAllocator's free pool. 87static void non_overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider, 88 sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2, 89 bool expectedResult) { 90 GrResourceAllocator alloc(resourceProvider); 91 92 alloc.addInterval(p1.get(), 0, 2); 93 alloc.addInterval(p2.get(), 3, 5); 94 alloc.markEndOfOpList(0); 95 96 int startIndex, stopIndex; 97 GrResourceAllocator::AssignError error; 98 alloc.assign(&startIndex, &stopIndex, &error); 99 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error); 100 101 REPORTER_ASSERT(reporter, p1->priv().peekSurface()); 102 REPORTER_ASSERT(reporter, p2->priv().peekSurface()); 103 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID(); 104 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch); 105} 106 107DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest, reporter, ctxInfo) { 108 GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider(); 109 GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider(); 110 111 struct TestCase { 112 ProxyParams fP1; 113 ProxyParams fP2; 114 bool fExpectation; 115 }; 116 117 constexpr bool kRT = true; 118 constexpr bool kNotRT = false; 119 120 constexpr bool kShare = true; 121 constexpr bool kDontShare = false; 122 // Non-RT GrSurfaces are never recycled on some platforms. 123 bool kConditionallyShare = resourceProvider->caps()->reuseScratchTextures(); 124 125 const GrPixelConfig kRGBA = kRGBA_8888_GrPixelConfig; 126 const GrPixelConfig kBGRA = kBGRA_8888_GrPixelConfig; 127 128 const SkBackingFit kE = SkBackingFit::kExact; 129 const SkBackingFit kA = SkBackingFit::kApprox; 130 131 const GrSurfaceOrigin kTL = kTopLeft_GrSurfaceOrigin; 132 const GrSurfaceOrigin kBL = kBottomLeft_GrSurfaceOrigin; 133 134 //-------------------------------------------------------------------------------------------- 135 TestCase gOverlappingTests[] = { 136 //---------------------------------------------------------------------------------------- 137 // Two proxies with overlapping intervals and compatible descriptors should never share 138 // RT version 139 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kDontShare }, 140 // non-RT version 141 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare }, 142 }; 143 144 for (auto test : gOverlappingTests) { 145 sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, test.fP1); 146 sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, test.fP2); 147 overlap_test(reporter, resourceProvider, 148 std::move(p1), std::move(p2), test.fExpectation); 149 } 150 151 int k2 = ctxInfo.grContext()->caps()->getSampleCount(2, kRGBA); 152 int k4 = ctxInfo.grContext()->caps()->getSampleCount(4, kRGBA); 153 154 //-------------------------------------------------------------------------------------------- 155 TestCase gNonOverlappingTests[] = { 156 //---------------------------------------------------------------------------------------- 157 // Two non-overlapping intervals w/ compatible proxies should share 158 // both same size & approx 159 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kShare }, 160 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare }, 161 // diffs sizes but still approx 162 { { 64, kRT, kRGBA, kA, 0, kTL }, { 50, kRT, kRGBA, kA, 0, kTL }, kShare }, 163 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 50, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare }, 164 // sames sizes but exact 165 { { 64, kRT, kRGBA, kE, 0, kTL }, { 64, kRT, kRGBA, kE, 0, kTL }, kShare }, 166 { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kConditionallyShare }, 167 //---------------------------------------------------------------------------------------- 168 // Two non-overlapping intervals w/ different exact sizes should not share 169 { { 56, kRT, kRGBA, kE, 0, kTL }, { 54, kRT, kRGBA, kE, 0, kTL }, kDontShare }, 170 // Two non-overlapping intervals w/ _very different_ approx sizes should not share 171 { { 255, kRT, kRGBA, kA, 0, kTL }, { 127, kRT, kRGBA, kA, 0, kTL }, kDontShare }, 172 // Two non-overlapping intervals w/ different MSAA sample counts should not share 173 { { 64, kRT, kRGBA, kA, k2, kTL },{ 64, kRT, kRGBA, kA, k4, kTL}, k2 == k4 }, 174 // Two non-overlapping intervals w/ different configs should not share 175 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kBGRA, kA, 0, kTL }, kDontShare }, 176 // Two non-overlapping intervals w/ different RT classifications should never share 177 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare }, 178 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kDontShare }, 179 // Two non-overlapping intervals w/ different origins should share 180 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kBL }, kShare }, 181 }; 182 183 for (auto test : gNonOverlappingTests) { 184 sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, test.fP1); 185 sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, test.fP2); 186 if (!p1 || !p2) { 187 continue; // creation can fail (i.e., for msaa4 on iOS) 188 } 189 non_overlap_test(reporter, resourceProvider, 190 std::move(p1), std::move(p2), test.fExpectation); 191 } 192 193 { 194 // Wrapped backend textures should never be reused 195 TestCase t[1] = { 196 { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kDontShare } 197 }; 198 199 GrBackendTexture backEndTex; 200 sk_sp<GrSurfaceProxy> p1 = make_backend(ctxInfo.grContext(), t[0].fP1, &backEndTex); 201 sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, t[0].fP2); 202 non_overlap_test(reporter, resourceProvider, 203 std::move(p1), std::move(p2), t[0].fExpectation); 204 cleanup_backend(ctxInfo.grContext(), &backEndTex); 205 } 206} 207 208#endif 209#endif 210