1 /* 2 * Copyright 2019 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 "src/gpu/GrContextPriv.h" 9 10 #include "include/gpu/GrContextThreadSafeProxy.h" 11 #include "include/gpu/GrTexture.h" 12 #include "src/gpu/GrAuditTrail.h" 13 #include "src/gpu/GrContextThreadSafeProxyPriv.h" 14 #include "src/gpu/GrDrawingManager.h" 15 #include "src/gpu/GrGpu.h" 16 #include "src/gpu/GrMemoryPool.h" 17 #include "src/gpu/GrRenderTargetContext.h" 18 #include "src/gpu/GrSkSLFPFactoryCache.h" 19 #include "src/gpu/GrSurfaceContextPriv.h" 20 #include "src/gpu/GrSurfacePriv.h" 21 #include "src/gpu/GrTextureContext.h" 22 #include "src/gpu/SkGr.h" 23 #include "src/gpu/effects/generated/GrConfigConversionEffect.h" 24 #include "src/gpu/text/GrTextBlobCache.h" 25 #include "src/image/SkImage_Base.h" 26 #include "src/image/SkImage_Gpu.h" 27 28 #define ASSERT_OWNED_PROXY(P) \ 29 SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext) 30 #define ASSERT_SINGLE_OWNER \ 31 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());) 32 #define RETURN_VALUE_IF_ABANDONED(value) if (fContext->abandoned()) { return (value); } 33 #define RETURN_IF_ABANDONED RETURN_VALUE_IF_ABANDONED(void) 34 refCaps() const35 sk_sp<const GrCaps> GrContextPriv::refCaps() const { 36 return fContext->refCaps(); 37 } 38 fpFactoryCache()39 sk_sp<GrSkSLFPFactoryCache> GrContextPriv::fpFactoryCache() { 40 return fContext->fpFactoryCache(); 41 } 42 refOpMemoryPool()43 sk_sp<GrOpMemoryPool> GrContextPriv::refOpMemoryPool() { 44 return fContext->refOpMemoryPool(); 45 } 46 addOnFlushCallbackObject(GrOnFlushCallbackObject * onFlushCBObject)47 void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) { 48 fContext->addOnFlushCallbackObject(onFlushCBObject); 49 } 50 makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)51 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy, 52 GrColorType colorType, 53 SkAlphaType alphaType, 54 sk_sp<SkColorSpace> colorSpace, 55 const SkSurfaceProps* props) { 56 return fContext->makeWrappedSurfaceContext(std::move(proxy), colorType, alphaType, 57 std::move(colorSpace), props); 58 } 59 makeDeferredTextureContext(SkBackingFit fit,int width,int height,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,GrMipMapped mipMapped,GrSurfaceOrigin origin,SkBudgeted budgeted,GrProtected isProtected)60 sk_sp<GrTextureContext> GrContextPriv::makeDeferredTextureContext(SkBackingFit fit, 61 int width, 62 int height, 63 GrColorType colorType, 64 SkAlphaType alphaType, 65 sk_sp<SkColorSpace> colorSpace, 66 GrMipMapped mipMapped, 67 GrSurfaceOrigin origin, 68 SkBudgeted budgeted, 69 GrProtected isProtected) { 70 return fContext->makeDeferredTextureContext(fit, width, height, colorType, alphaType, 71 std::move(colorSpace), mipMapped, origin, budgeted, 72 isProtected); 73 } 74 makeDeferredRenderTargetContext(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted,GrProtected isProtected)75 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContext( 76 SkBackingFit fit, 77 int width, 78 int height, 79 GrColorType colorType, 80 sk_sp<SkColorSpace> colorSpace, 81 int sampleCnt, 82 GrMipMapped mipMapped, 83 GrSurfaceOrigin origin, 84 const SkSurfaceProps* surfaceProps, 85 SkBudgeted budgeted, 86 GrProtected isProtected) { 87 return fContext->makeDeferredRenderTargetContext(fit, width, height, colorType, 88 std::move(colorSpace), sampleCnt, mipMapped, 89 origin, surfaceProps, budgeted, isProtected); 90 } 91 makeDeferredRenderTargetContextWithFallback(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted)92 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContextWithFallback( 93 SkBackingFit fit, int width, int height, GrColorType colorType, 94 sk_sp<SkColorSpace> colorSpace, int sampleCnt, GrMipMapped mipMapped, 95 GrSurfaceOrigin origin, const SkSurfaceProps* surfaceProps, SkBudgeted budgeted) { 96 return fContext->makeDeferredRenderTargetContextWithFallback( 97 fit, width, height, colorType, std::move(colorSpace), sampleCnt, mipMapped, origin, 98 surfaceProps, budgeted); 99 } 100 makeBackendTextureContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace)101 sk_sp<GrTextureContext> GrContextPriv::makeBackendTextureContext(const GrBackendTexture& tex, 102 GrSurfaceOrigin origin, 103 GrColorType colorType, 104 SkAlphaType alphaType, 105 sk_sp<SkColorSpace> colorSpace) { 106 ASSERT_SINGLE_OWNER 107 108 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendTexture( 109 tex, colorType, origin, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType); 110 if (!proxy) { 111 return nullptr; 112 } 113 114 return this->drawingManager()->makeTextureContext(std::move(proxy), colorType, alphaType, 115 std::move(colorSpace)); 116 } 117 makeBackendTextureRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props,ReleaseProc releaseProc,ReleaseContext releaseCtx)118 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext( 119 const GrBackendTexture& tex, 120 GrSurfaceOrigin origin, 121 int sampleCnt, 122 GrColorType colorType, 123 sk_sp<SkColorSpace> colorSpace, 124 const SkSurfaceProps* props, 125 ReleaseProc releaseProc, 126 ReleaseContext releaseCtx) { 127 ASSERT_SINGLE_OWNER 128 SkASSERT(sampleCnt > 0); 129 130 sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture( 131 tex, origin, sampleCnt, colorType, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, 132 releaseProc, releaseCtx)); 133 if (!proxy) { 134 return nullptr; 135 } 136 137 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), colorType, 138 std::move(colorSpace), props); 139 } 140 makeBackendRenderTargetRenderTargetContext(const GrBackendRenderTarget & backendRT,GrSurfaceOrigin origin,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * surfaceProps,ReleaseProc releaseProc,ReleaseContext releaseCtx)141 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext( 142 const GrBackendRenderTarget& backendRT, 143 GrSurfaceOrigin origin, 144 GrColorType colorType, 145 sk_sp<SkColorSpace> colorSpace, 146 const SkSurfaceProps* surfaceProps, 147 ReleaseProc releaseProc, 148 ReleaseContext releaseCtx) { 149 ASSERT_SINGLE_OWNER 150 151 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget( 152 backendRT, colorType, origin, releaseProc, releaseCtx); 153 if (!proxy) { 154 return nullptr; 155 } 156 157 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), colorType, 158 std::move(colorSpace), surfaceProps); 159 } 160 makeBackendTextureAsRenderTargetRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)161 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext( 162 const GrBackendTexture& tex, 163 GrSurfaceOrigin origin, 164 int sampleCnt, 165 GrColorType colorType, 166 sk_sp<SkColorSpace> colorSpace, 167 const SkSurfaceProps* props) { 168 ASSERT_SINGLE_OWNER 169 SkASSERT(sampleCnt > 0); 170 sk_sp<GrSurfaceProxy> proxy( 171 this->proxyProvider()->wrapBackendTextureAsRenderTarget(tex, colorType, 172 origin, sampleCnt)); 173 if (!proxy) { 174 return nullptr; 175 } 176 177 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), colorType, 178 std::move(colorSpace), props); 179 } 180 makeVulkanSecondaryCBRenderTargetContext(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)181 sk_sp<GrRenderTargetContext> GrContextPriv::makeVulkanSecondaryCBRenderTargetContext( 182 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo, const SkSurfaceProps* props) { 183 ASSERT_SINGLE_OWNER 184 sk_sp<GrSurfaceProxy> proxy( 185 this->proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo, vkInfo)); 186 if (!proxy) { 187 return nullptr; 188 } 189 190 return this->drawingManager()->makeRenderTargetContext( 191 std::move(proxy), 192 SkColorTypeToGrColorType(imageInfo.colorType()), 193 imageInfo.refColorSpace(), 194 props); 195 } 196 flushSurfaces(GrSurfaceProxy * proxies[],int numProxies,const GrFlushInfo & info)197 GrSemaphoresSubmitted GrContextPriv::flushSurfaces(GrSurfaceProxy* proxies[], int numProxies, 198 const GrFlushInfo& info) { 199 ASSERT_SINGLE_OWNER 200 RETURN_VALUE_IF_ABANDONED(GrSemaphoresSubmitted::kNo) 201 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "flushSurfaces", fContext); 202 SkASSERT(numProxies >= 0); 203 SkASSERT(!numProxies || proxies); 204 for (int i = 0; i < numProxies; ++i) { 205 SkASSERT(proxies[i]); 206 ASSERT_OWNED_PROXY(proxies[i]); 207 } 208 return fContext->drawingManager()->flushSurfaces( 209 proxies, numProxies, SkSurface::BackendSurfaceAccess::kNoAccess, info); 210 } 211 flushSurface(GrSurfaceProxy * proxy)212 void GrContextPriv::flushSurface(GrSurfaceProxy* proxy) { 213 this->flushSurfaces(proxy ? &proxy : nullptr, proxy ? 1 : 0, {}); 214 } 215 moveRenderTasksToDDL(SkDeferredDisplayList * ddl)216 void GrContextPriv::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) { 217 fContext->drawingManager()->moveRenderTasksToDDL(ddl); 218 } 219 copyRenderTasksFromDDL(const SkDeferredDisplayList * ddl,GrRenderTargetProxy * newDest)220 void GrContextPriv::copyRenderTasksFromDDL(const SkDeferredDisplayList* ddl, 221 GrRenderTargetProxy* newDest) { 222 fContext->drawingManager()->copyRenderTasksFromDDL(ddl, newDest); 223 } 224 225 ////////////////////////////////////////////////////////////////////////////// 226 227 #if GR_TEST_UTILS resetGpuStats() const228 void GrContextPriv::resetGpuStats() const { 229 #if GR_GPU_STATS 230 fContext->fGpu->stats()->reset(); 231 #endif 232 } 233 dumpCacheStats(SkString * out) const234 void GrContextPriv::dumpCacheStats(SkString* out) const { 235 #if GR_CACHE_STATS 236 fContext->fResourceCache->dumpStats(out); 237 #endif 238 } 239 dumpCacheStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const240 void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys, 241 SkTArray<double>* values) const { 242 #if GR_CACHE_STATS 243 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values); 244 #endif 245 } 246 printCacheStats() const247 void GrContextPriv::printCacheStats() const { 248 SkString out; 249 this->dumpCacheStats(&out); 250 SkDebugf("%s", out.c_str()); 251 } 252 dumpGpuStats(SkString * out) const253 void GrContextPriv::dumpGpuStats(SkString* out) const { 254 #if GR_GPU_STATS 255 return fContext->fGpu->stats()->dump(out); 256 #endif 257 } 258 dumpGpuStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const259 void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys, 260 SkTArray<double>* values) const { 261 #if GR_GPU_STATS 262 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values); 263 #endif 264 } 265 printGpuStats() const266 void GrContextPriv::printGpuStats() const { 267 SkString out; 268 this->dumpGpuStats(&out); 269 SkDebugf("%s", out.c_str()); 270 } 271 testingOnly_setTextBlobCacheLimit(size_t bytes)272 void GrContextPriv::testingOnly_setTextBlobCacheLimit(size_t bytes) { 273 fContext->priv().getTextBlobCache()->setBudget(bytes); 274 } 275 testingOnly_getFontAtlasImage(GrMaskFormat format,unsigned int index)276 sk_sp<SkImage> GrContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index) { 277 auto atlasManager = this->getAtlasManager(); 278 if (!atlasManager) { 279 return nullptr; 280 } 281 282 unsigned int numActiveProxies; 283 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies); 284 if (index >= numActiveProxies || !proxies || !proxies[index]) { 285 return nullptr; 286 } 287 288 SkASSERT(proxies[index]->priv().isExact()); 289 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID, 290 kPremul_SkAlphaType, proxies[index], nullptr)); 291 return image; 292 } 293 testingOnly_purgeAllUnlockedResources()294 void GrContextPriv::testingOnly_purgeAllUnlockedResources() { 295 fContext->fResourceCache->purgeAllUnlocked(); 296 } 297 testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject * cb)298 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) { 299 fContext->flush(); 300 fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb); 301 } 302 #endif 303 validPMUPMConversionExists()304 bool GrContextPriv::validPMUPMConversionExists() { 305 ASSERT_SINGLE_OWNER 306 if (!fContext->fDidTestPMConversions) { 307 fContext->fPMUPMConversionsRoundTrip = 308 GrConfigConversionEffect::TestForPreservingPMConversions(fContext); 309 fContext->fDidTestPMConversions = true; 310 } 311 312 // The PM<->UPM tests fail or succeed together so we only need to check one. 313 return fContext->fPMUPMConversionsRoundTrip; 314 } 315 createPMToUPMEffect(std::unique_ptr<GrFragmentProcessor> fp)316 std::unique_ptr<GrFragmentProcessor> GrContextPriv::createPMToUPMEffect( 317 std::unique_ptr<GrFragmentProcessor> fp) { 318 ASSERT_SINGLE_OWNER 319 // We should have already called this->priv().validPMUPMConversionExists() in this case 320 SkASSERT(fContext->fDidTestPMConversions); 321 // ...and it should have succeeded 322 SkASSERT(this->validPMUPMConversionExists()); 323 324 return GrConfigConversionEffect::Make(std::move(fp), PMConversion::kToUnpremul); 325 } 326 createUPMToPMEffect(std::unique_ptr<GrFragmentProcessor> fp)327 std::unique_ptr<GrFragmentProcessor> GrContextPriv::createUPMToPMEffect( 328 std::unique_ptr<GrFragmentProcessor> fp) { 329 ASSERT_SINGLE_OWNER 330 // We should have already called this->priv().validPMUPMConversionExists() in this case 331 SkASSERT(fContext->fDidTestPMConversions); 332 // ...and it should have succeeded 333 SkASSERT(this->validPMUPMConversionExists()); 334 335 return GrConfigConversionEffect::Make(std::move(fp), PMConversion::kToPremul); 336 } 337 338 ////////////////////////////////////////////////////////////////////////////// 339 340 #include "src/core/SkMipMap.h" 341 createBackendTexture(const SkPixmap srcData[],int numLevels,GrRenderable renderable,GrProtected isProtected)342 GrBackendTexture GrContextPriv::createBackendTexture(const SkPixmap srcData[], int numLevels, 343 GrRenderable renderable, 344 GrProtected isProtected) { 345 if (!fContext->asDirectContext()) { 346 return {}; 347 } 348 349 if (this->abandoned()) { 350 return {}; 351 } 352 353 if (!srcData || !numLevels) { 354 return {}; 355 } 356 357 int baseWidth = srcData[0].width(); 358 int baseHeight = srcData[0].height(); 359 SkColorType colorType = srcData[0].colorType(); 360 361 if (numLevels > 1) { 362 if (numLevels != SkMipMap::ComputeLevelCount(baseWidth, baseHeight) + 1) { 363 return {}; 364 } 365 366 int currentWidth = baseWidth; 367 int currentHeight = baseHeight; 368 for (int i = 1; i < numLevels; ++i) { 369 currentWidth = SkTMax(1, currentWidth / 2); 370 currentHeight = SkTMax(1, currentHeight / 2); 371 372 if (srcData[i].colorType() != colorType) { 373 return {}; 374 } 375 376 if (srcData[i].width() != currentWidth || srcData[i].height() != currentHeight) { 377 return {}; 378 } 379 } 380 } 381 382 GrBackendFormat backendFormat = fContext->defaultBackendFormat(colorType, renderable); 383 if (!backendFormat.isValid()) { 384 return {}; 385 } 386 387 GrGpu* gpu = fContext->fGpu.get(); 388 389 // TODO: propagate the array of pixmaps interface to GrGpu 390 return gpu->createBackendTexture(baseWidth, baseHeight, backendFormat, 391 GrMipMapped::kNo, // TODO: use real mipmap setting here 392 renderable, srcData[0].addr(), srcData[0].rowBytes(), 393 nullptr, isProtected); 394 } 395