1/* 2 * Copyright 2016 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// This is a GPU-backend specific test. 9 10#include "Test.h" 11 12#if SK_SUPPORT_GPU 13#include "GrRenderTargetPriv.h" 14#include "GrRenderTargetProxy.h" 15#include "GrResourceProvider.h" 16#include "GrSurfaceProxy.h" 17#include "GrTextureProxy.h" 18 19// Check that the surface proxy's member vars are set as expected 20static void check_surface(skiatest::Reporter* reporter, 21 GrSurfaceProxy* proxy, 22 GrSurfaceOrigin origin, 23 int width, int height, 24 GrPixelConfig config, 25 const GrGpuResource::UniqueID& uniqueID, 26 SkBudgeted budgeted) { 27 REPORTER_ASSERT(reporter, proxy->origin() == origin); 28 REPORTER_ASSERT(reporter, proxy->width() == width); 29 REPORTER_ASSERT(reporter, proxy->height() == height); 30 REPORTER_ASSERT(reporter, proxy->config() == config); 31 if (!uniqueID.isInvalid()) { 32 REPORTER_ASSERT(reporter, proxy->uniqueID().asUInt() == uniqueID.asUInt()); 33 } else { 34 REPORTER_ASSERT(reporter, !proxy->uniqueID().isInvalid()); 35 } 36 REPORTER_ASSERT(reporter, proxy->isBudgeted() == budgeted); 37} 38 39static void check_rendertarget(skiatest::Reporter* reporter, 40 const GrCaps& caps, 41 GrResourceProvider* provider, 42 GrRenderTargetProxy* rtProxy, 43 int numSamples, 44 SkBackingFit fit, 45 int expectedMaxWindowRects, 46 bool wasWrapped) { 47 REPORTER_ASSERT(reporter, rtProxy->maxWindowRectangles(caps) == expectedMaxWindowRects); 48 REPORTER_ASSERT(reporter, rtProxy->numStencilSamples() == numSamples); 49 50 GrSurfaceProxy::UniqueID idBefore = rtProxy->uniqueID(); 51 GrRenderTarget* rt = rtProxy->instantiate(provider); 52 REPORTER_ASSERT(reporter, rt); 53 54 REPORTER_ASSERT(reporter, rtProxy->uniqueID() == idBefore); 55 if (wasWrapped) { 56 // Wrapped resources share their uniqueID with the wrapping RenderTargetProxy 57 REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() == rt->uniqueID().asUInt()); 58 } else { 59 // Deferred resources should always have a different ID from their instantiated rendertarget 60 REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() != rt->uniqueID().asUInt()); 61 } 62 63 REPORTER_ASSERT(reporter, rt->origin() == rtProxy->origin()); 64 if (SkBackingFit::kExact == fit) { 65 REPORTER_ASSERT(reporter, rt->width() == rtProxy->width()); 66 REPORTER_ASSERT(reporter, rt->height() == rtProxy->height()); 67 } else { 68 REPORTER_ASSERT(reporter, rt->width() >= rtProxy->width()); 69 REPORTER_ASSERT(reporter, rt->height() >= rtProxy->height()); 70 } 71 REPORTER_ASSERT(reporter, rt->config() == rtProxy->config()); 72 73 REPORTER_ASSERT(reporter, rt->isUnifiedMultisampled() == rtProxy->isUnifiedMultisampled()); 74 REPORTER_ASSERT(reporter, rt->isStencilBufferMultisampled() == 75 rtProxy->isStencilBufferMultisampled()); 76 REPORTER_ASSERT(reporter, rt->numColorSamples() == rtProxy->numColorSamples()); 77 REPORTER_ASSERT(reporter, rt->numStencilSamples() == rtProxy->numStencilSamples()); 78 REPORTER_ASSERT(reporter, rt->isMixedSampled() == rtProxy->isMixedSampled()); 79 REPORTER_ASSERT(reporter, rt->renderTargetPriv().flags() == rtProxy->testingOnly_getFlags()); 80} 81 82static void check_texture(skiatest::Reporter* reporter, 83 GrResourceProvider* provider, 84 GrTextureProxy* texProxy, 85 SkBackingFit fit, 86 bool wasWrapped) { 87 GrSurfaceProxy::UniqueID idBefore = texProxy->uniqueID(); 88 GrTexture* tex = texProxy->instantiate(provider); 89 REPORTER_ASSERT(reporter, tex); 90 91 REPORTER_ASSERT(reporter, texProxy->uniqueID() == idBefore); 92 if (wasWrapped) { 93 // Wrapped resources share their uniqueID with the wrapping TextureProxy 94 REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() == tex->uniqueID().asUInt()); 95 } else { 96 // Deferred resources should always have a different ID from their instantiated texture 97 REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() != tex->uniqueID().asUInt()); 98 } 99 100 REPORTER_ASSERT(reporter, tex->origin() == texProxy->origin()); 101 if (SkBackingFit::kExact == fit) { 102 REPORTER_ASSERT(reporter, tex->width() == texProxy->width()); 103 REPORTER_ASSERT(reporter, tex->height() == texProxy->height()); 104 } else { 105 REPORTER_ASSERT(reporter, tex->width() >= texProxy->width()); 106 REPORTER_ASSERT(reporter, tex->height() >= texProxy->height()); 107 } 108 REPORTER_ASSERT(reporter, tex->config() == texProxy->config()); 109} 110 111 112DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest, reporter, ctxInfo) { 113 GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider(); 114 const GrCaps& caps = *ctxInfo.grContext()->caps(); 115 116 const GrGpuResource::UniqueID kInvalidResourceID = GrGpuResource::UniqueID::InvalidID(); 117 118 int attempt = 0; // useful for debugging 119 120 for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) { 121 for (auto widthHeight : { 100, 128, 1048576 }) { 122 for (auto config : { kAlpha_8_GrPixelConfig, kRGB_565_GrPixelConfig, 123 kETC1_GrPixelConfig, kRGBA_8888_GrPixelConfig }) { 124 for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) { 125 for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) { 126 for (auto numSamples : { 0, 4, 16, 128 }) { 127 GrSurfaceDesc desc; 128 desc.fFlags = kRenderTarget_GrSurfaceFlag; 129 desc.fOrigin = origin; 130 desc.fWidth = widthHeight; 131 desc.fHeight = widthHeight; 132 desc.fConfig = config; 133 desc.fSampleCnt = numSamples; 134 135 { 136 sk_sp<GrTexture> tex; 137 if (SkBackingFit::kApprox == fit) { 138 tex.reset(provider->createApproxTexture(desc, 0)); 139 } else { 140 tex.reset(provider->createTexture(desc, budgeted)); 141 } 142 143 sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred( 144 provider, desc, 145 fit, budgeted)); 146 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy)); 147 if (proxy) { 148 REPORTER_ASSERT(reporter, proxy->asRenderTargetProxy()); 149 // This forces the proxy to compute and cache its 150 // pre-instantiation size guess. Later, when it is actually 151 // instantiated, it checks that the instantiated size is <= to 152 // the pre-computation. If the proxy never computed its 153 // pre-instantiation size then the check is skipped. 154 proxy->gpuMemorySize(); 155 156 check_surface(reporter, proxy.get(), origin, 157 widthHeight, widthHeight, config, 158 kInvalidResourceID, budgeted); 159 check_rendertarget(reporter, caps, provider, 160 proxy->asRenderTargetProxy(), 161 SkTMin(numSamples, caps.maxSampleCount()), 162 fit, caps.maxWindowRectangles(), false); 163 } 164 } 165 166 desc.fFlags = kNone_GrSurfaceFlags; 167 168 { 169 sk_sp<GrTexture> tex; 170 if (SkBackingFit::kApprox == fit) { 171 tex.reset(provider->createApproxTexture(desc, 0)); 172 } else { 173 tex.reset(provider->createTexture(desc, budgeted)); 174 } 175 176 sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(provider, 177 desc, 178 fit, 179 budgeted)); 180 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy)); 181 if (proxy) { 182 // This forces the proxy to compute and cache its pre-instantiation 183 // size guess. Later, when it is actually instantiated, it checks 184 // that the instantiated size is <= to the pre-computation. 185 // If the proxy never computed its pre-instantiation size then the 186 // check is skipped. 187 proxy->gpuMemorySize(); 188 189 check_surface(reporter, proxy.get(), origin, 190 widthHeight, widthHeight, config, 191 kInvalidResourceID, budgeted); 192 check_texture(reporter, provider, proxy->asTextureProxy(), 193 fit, false); 194 } 195 } 196 197 attempt++; 198 } 199 } 200 } 201 } 202 } 203 } 204} 205 206DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) { 207 GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider(); 208 const GrCaps& caps = *ctxInfo.grContext()->caps(); 209 210 static const int kWidthHeight = 100; 211 212 for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) { 213 for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) { 214 for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) { 215 for (auto numSamples: { 0, 4}) { 216 bool renderable = caps.isConfigRenderable(config, numSamples > 0); 217 218 GrSurfaceDesc desc; 219 desc.fOrigin = origin; 220 desc.fWidth = kWidthHeight; 221 desc.fHeight = kWidthHeight; 222 desc.fConfig = config; 223 desc.fSampleCnt = numSamples; 224 225 // External on-screen render target. 226 if (renderable && kOpenGL_GrBackend == ctxInfo.backend()) { 227 GrBackendRenderTargetDesc backendDesc; 228 backendDesc.fWidth = kWidthHeight; 229 backendDesc.fHeight = kWidthHeight; 230 backendDesc.fConfig = config; 231 backendDesc.fOrigin = origin; 232 backendDesc.fSampleCnt = numSamples; 233 backendDesc.fStencilBits = 8; 234 backendDesc.fRenderTargetHandle = 0; 235 236 sk_sp<GrRenderTarget> defaultFBO( 237 provider->wrapBackendRenderTarget(backendDesc)); 238 239 sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeWrapped(defaultFBO)); 240 check_surface(reporter, sProxy.get(), origin, 241 kWidthHeight, kWidthHeight, config, 242 defaultFBO->uniqueID(), SkBudgeted::kNo); 243 check_rendertarget(reporter, caps, provider, sProxy->asRenderTargetProxy(), 244 numSamples, SkBackingFit::kExact, 0, true); 245 } 246 247 sk_sp<GrTexture> tex; 248 249 // Internal offscreen render target. 250 if (renderable) { 251 desc.fFlags = kRenderTarget_GrSurfaceFlag; 252 tex.reset(provider->createTexture(desc, budgeted)); 253 sk_sp<GrRenderTarget> rt(sk_ref_sp(tex->asRenderTarget())); 254 255 sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeWrapped(rt)); 256 check_surface(reporter, sProxy.get(), origin, 257 kWidthHeight, kWidthHeight, config, 258 rt->uniqueID(), budgeted); 259 check_rendertarget(reporter, caps, provider, sProxy->asRenderTargetProxy(), 260 numSamples, SkBackingFit::kExact, 261 caps.maxWindowRectangles(), true); 262 } 263 264 if (!tex) { 265 SkASSERT(kNone_GrSurfaceFlags == desc.fFlags ); 266 desc.fSampleCnt = 0; 267 tex.reset(provider->createTexture(desc, budgeted)); 268 } 269 270 sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeWrapped(tex)); 271 check_surface(reporter, sProxy.get(), origin, 272 kWidthHeight, kWidthHeight, config, tex->uniqueID(), budgeted); 273 check_texture(reporter, provider, sProxy->asTextureProxy(), 274 SkBackingFit::kExact, true); 275 } 276 } 277 } 278 } 279} 280 281#endif 282