GrContext.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*
  2. * Copyright 2011 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. #include "include/core/SkTraceMemoryDump.h"
  8. #include "include/gpu/GrBackendSemaphore.h"
  9. #include "include/gpu/GrContext.h"
  10. #include "include/private/SkDeferredDisplayList.h"
  11. #include "include/private/SkImageInfoPriv.h"
  12. #include "src/core/SkMakeUnique.h"
  13. #include "src/core/SkTaskGroup.h"
  14. #include "src/gpu/GrDrawingManager.h"
  15. #include "src/gpu/GrGpu.h"
  16. #include "src/gpu/GrMemoryPool.h"
  17. #include "src/gpu/GrPathRendererChain.h"
  18. #include "src/gpu/GrProxyProvider.h"
  19. #include "src/gpu/GrRenderTargetProxy.h"
  20. #include "src/gpu/GrResourceCache.h"
  21. #include "src/gpu/GrResourceProvider.h"
  22. #include "src/gpu/GrSemaphore.h"
  23. #include "src/gpu/GrShaderUtils.h"
  24. #include "src/gpu/GrSoftwarePathRenderer.h"
  25. #include "src/gpu/GrTracing.h"
  26. #include "src/gpu/SkGr.h"
  27. #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
  28. #include "src/gpu/effects/GrSkSLFP.h"
  29. #include "src/gpu/text/GrTextBlobCache.h"
  30. #include "src/gpu/text/GrTextContext.h"
  31. #include "src/image/SkSurface_Gpu.h"
  32. #include <atomic>
  33. #include <unordered_map>
  34. #define ASSERT_OWNED_PROXY(P) \
  35. SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this)
  36. #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
  37. #define ASSERT_SINGLE_OWNER \
  38. SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
  39. #define RETURN_IF_ABANDONED if (this->abandoned()) { return; }
  40. #define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; }
  41. #define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; }
  42. ////////////////////////////////////////////////////////////////////////////////
  43. GrContext::GrContext(GrBackendApi backend, const GrContextOptions& options, int32_t contextID)
  44. : INHERITED(backend, options, contextID) {
  45. fResourceCache = nullptr;
  46. fResourceProvider = nullptr;
  47. }
  48. GrContext::~GrContext() {
  49. ASSERT_SINGLE_OWNER
  50. if (this->drawingManager()) {
  51. this->drawingManager()->cleanup();
  52. }
  53. delete fResourceProvider;
  54. delete fResourceCache;
  55. }
  56. bool GrContext::init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> FPFactoryCache) {
  57. ASSERT_SINGLE_OWNER
  58. SkASSERT(fThreadSafeProxy); // needs to have been initialized by derived classes
  59. SkASSERT(this->proxyProvider());
  60. if (!INHERITED::init(std::move(caps), std::move(FPFactoryCache))) {
  61. return false;
  62. }
  63. SkASSERT(this->caps());
  64. SkASSERT(this->getGrStrikeCache());
  65. SkASSERT(this->getTextBlobCache());
  66. if (fGpu) {
  67. fResourceCache = new GrResourceCache(this->caps(), this->singleOwner(), this->contextID());
  68. fResourceProvider = new GrResourceProvider(fGpu.get(), fResourceCache, this->singleOwner());
  69. }
  70. if (fResourceCache) {
  71. fResourceCache->setProxyProvider(this->proxyProvider());
  72. }
  73. fDidTestPMConversions = false;
  74. // DDL TODO: we need to think through how the task group & persistent cache
  75. // get passed on to/shared between all the DDLRecorders created with this context.
  76. if (this->options().fExecutor) {
  77. fTaskGroup = skstd::make_unique<SkTaskGroup>(*this->options().fExecutor);
  78. }
  79. fPersistentCache = this->options().fPersistentCache;
  80. fShaderErrorHandler = this->options().fShaderErrorHandler;
  81. if (!fShaderErrorHandler) {
  82. fShaderErrorHandler = GrShaderUtils::DefaultShaderErrorHandler();
  83. }
  84. return true;
  85. }
  86. sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
  87. return fThreadSafeProxy;
  88. }
  89. //////////////////////////////////////////////////////////////////////////////
  90. void GrContext::abandonContext() {
  91. if (this->abandoned()) {
  92. return;
  93. }
  94. INHERITED::abandonContext();
  95. fResourceProvider->abandon();
  96. // Need to cleanup the drawing manager first so all the render targets
  97. // will be released/forgotten before they too are abandoned.
  98. this->drawingManager()->cleanup();
  99. // abandon first to so destructors
  100. // don't try to free the resources in the API.
  101. fResourceCache->abandonAll();
  102. fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
  103. }
  104. void GrContext::releaseResourcesAndAbandonContext() {
  105. if (this->abandoned()) {
  106. return;
  107. }
  108. INHERITED::abandonContext();
  109. fResourceProvider->abandon();
  110. // Need to cleanup the drawing manager first so all the render targets
  111. // will be released/forgotten before they too are abandoned.
  112. this->drawingManager()->cleanup();
  113. // Release all resources in the backend 3D API.
  114. fResourceCache->releaseAll();
  115. fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
  116. }
  117. void GrContext::resetGLTextureBindings() {
  118. if (this->abandoned() || this->backend() != GrBackendApi::kOpenGL) {
  119. return;
  120. }
  121. fGpu->resetTextureBindings();
  122. }
  123. void GrContext::resetContext(uint32_t state) {
  124. ASSERT_SINGLE_OWNER
  125. fGpu->markContextDirty(state);
  126. }
  127. void GrContext::freeGpuResources() {
  128. ASSERT_SINGLE_OWNER
  129. // TODO: the glyph cache doesn't hold any GpuResources so this call should not be needed here.
  130. // Some slack in the GrTextBlob's implementation requires it though. That could be fixed.
  131. this->getGrStrikeCache()->freeAll();
  132. this->drawingManager()->freeGpuResources();
  133. fResourceCache->purgeAllUnlocked();
  134. }
  135. void GrContext::purgeUnlockedResources(bool scratchResourcesOnly) {
  136. ASSERT_SINGLE_OWNER
  137. fResourceCache->purgeUnlockedResources(scratchResourcesOnly);
  138. fResourceCache->purgeAsNeeded();
  139. // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
  140. // place to purge stale blobs
  141. this->getTextBlobCache()->purgeStaleBlobs();
  142. }
  143. void GrContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed) {
  144. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  145. ASSERT_SINGLE_OWNER
  146. auto purgeTime = GrStdSteadyClock::now() - msNotUsed;
  147. fResourceCache->purgeAsNeeded();
  148. fResourceCache->purgeResourcesNotUsedSince(purgeTime);
  149. if (auto ccpr = this->drawingManager()->getCoverageCountingPathRenderer()) {
  150. ccpr->purgeCacheEntriesOlderThan(this->proxyProvider(), purgeTime);
  151. }
  152. // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
  153. // place to purge stale blobs
  154. this->getTextBlobCache()->purgeStaleBlobs();
  155. }
  156. void GrContext::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
  157. ASSERT_SINGLE_OWNER
  158. fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
  159. }
  160. void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
  161. ASSERT_SINGLE_OWNER
  162. if (resourceCount) {
  163. *resourceCount = fResourceCache->getBudgetedResourceCount();
  164. }
  165. if (resourceBytes) {
  166. *resourceBytes = fResourceCache->getBudgetedResourceBytes();
  167. }
  168. }
  169. size_t GrContext::getResourceCachePurgeableBytes() const {
  170. ASSERT_SINGLE_OWNER
  171. return fResourceCache->getPurgeableBytes();
  172. }
  173. size_t GrContext::ComputeTextureSize(SkColorType type, int width, int height, GrMipMapped mipMapped,
  174. bool useNextPow2) {
  175. int colorSamplesPerPixel = 1;
  176. return GrSurface::ComputeSize(SkColorType2GrPixelConfig(type), width, height,
  177. colorSamplesPerPixel, mipMapped, useNextPow2);
  178. }
  179. ////////////////////////////////////////////////////////////////////////////////
  180. int GrContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }
  181. int GrContext::maxRenderTargetSize() const { return this->caps()->maxRenderTargetSize(); }
  182. bool GrContext::colorTypeSupportedAsImage(SkColorType colorType) const {
  183. GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
  184. return this->caps()->isConfigTexturable(config);
  185. }
  186. int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
  187. GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
  188. return this->caps()->maxRenderTargetSampleCount(config);
  189. }
  190. ////////////////////////////////////////////////////////////////////////////////
  191. bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[]) {
  192. if (!fGpu || fGpu->caps()->semaphoreSupport()) {
  193. return false;
  194. }
  195. for (int i = 0; i < numSemaphores; ++i) {
  196. sk_sp<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
  197. waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
  198. kAdopt_GrWrapOwnership);
  199. fGpu->waitSemaphore(std::move(sema));
  200. }
  201. return true;
  202. }
  203. ////////////////////////////////////////////////////////////////////////////////
  204. GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info,
  205. const GrPrepareForExternalIORequests& externalRequests) {
  206. ASSERT_SINGLE_OWNER
  207. if (this->abandoned()) {
  208. return GrSemaphoresSubmitted::kNo;
  209. }
  210. return this->drawingManager()->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess,
  211. info, externalRequests);
  212. }
  213. ////////////////////////////////////////////////////////////////////////////////
  214. void GrContext::checkAsyncWorkCompletion() {
  215. if (fGpu) {
  216. fGpu->checkFinishProcs();
  217. }
  218. }
  219. ////////////////////////////////////////////////////////////////////////////////
  220. void GrContext::storeVkPipelineCacheData() {
  221. if (fGpu) {
  222. fGpu->storeVkPipelineCacheData();
  223. }
  224. }
  225. ////////////////////////////////////////////////////////////////////////////////
  226. bool GrContext::supportsDistanceFieldText() const {
  227. return this->caps()->shaderCaps()->supportsDistanceFieldText();
  228. }
  229. //////////////////////////////////////////////////////////////////////////////
  230. // DDL TODO: remove 'maxResources'
  231. void GrContext::getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const {
  232. ASSERT_SINGLE_OWNER
  233. if (maxResources) {
  234. *maxResources = fResourceCache->getMaxResourceCount();
  235. }
  236. if (maxResourceBytes) {
  237. *maxResourceBytes = fResourceCache->getMaxResourceBytes();
  238. }
  239. }
  240. void GrContext::setResourceCacheLimits(int maxResources, size_t maxResourceBytes) {
  241. ASSERT_SINGLE_OWNER
  242. fResourceCache->setLimits(maxResources, maxResourceBytes);
  243. }
  244. //////////////////////////////////////////////////////////////////////////////
  245. void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
  246. ASSERT_SINGLE_OWNER
  247. fResourceCache->dumpMemoryStatistics(traceMemoryDump);
  248. traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
  249. this->getTextBlobCache()->usedBytes());
  250. }
  251. //////////////////////////////////////////////////////////////////////////////
  252. GrBackendTexture GrContext::createBackendTexture(int width, int height,
  253. const GrBackendFormat& backendFormat,
  254. GrMipMapped mipMapped,
  255. GrRenderable renderable,
  256. GrProtected isProtected) {
  257. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  258. if (!this->asDirectContext()) {
  259. return GrBackendTexture();
  260. }
  261. if (this->abandoned()) {
  262. return GrBackendTexture();
  263. }
  264. if (!backendFormat.isValid()) {
  265. return GrBackendTexture();
  266. }
  267. return fGpu->createBackendTexture(width, height, backendFormat,
  268. mipMapped, renderable,
  269. nullptr, 0, nullptr, isProtected);
  270. }
  271. GrBackendTexture GrContext::createBackendTexture(int width, int height,
  272. SkColorType colorType,
  273. GrMipMapped mipMapped,
  274. GrRenderable renderable,
  275. GrProtected isProtected) {
  276. if (!this->asDirectContext()) {
  277. return GrBackendTexture();
  278. }
  279. if (this->abandoned()) {
  280. return GrBackendTexture();
  281. }
  282. GrBackendFormat format =
  283. this->caps()->getBackendFormatFromColorType(SkColorTypeToGrColorType(colorType));
  284. if (!format.isValid()) {
  285. return GrBackendTexture();
  286. }
  287. return this->createBackendTexture(width, height, format, mipMapped, renderable, isProtected);
  288. }
  289. GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c) {
  290. const GrCaps* caps = this->caps();
  291. if (!this->asDirectContext() || !c.isValid()) {
  292. return GrBackendTexture();
  293. }
  294. if (this->abandoned()) {
  295. return GrBackendTexture();
  296. }
  297. if (c.usesGLFBO0()) {
  298. // If we are making the surface we will never use FBO0.
  299. return GrBackendTexture();
  300. }
  301. if (c.vulkanSecondaryCBCompatible()) {
  302. return {};
  303. }
  304. const GrBackendFormat format =
  305. caps->getBackendFormatFromColorType(SkColorTypeToGrColorType(c.colorType()));
  306. if (!format.isValid()) {
  307. return GrBackendTexture();
  308. }
  309. if (!SkSurface_Gpu::Valid(caps, format)) {
  310. return GrBackendTexture();
  311. }
  312. GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format,
  313. GrMipMapped(c.isMipMapped()),
  314. GrRenderable::kYes,
  315. c.isProtected());
  316. SkASSERT(c.isCompatible(result));
  317. return result;
  318. }
  319. GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c,
  320. const SkColor4f& color) {
  321. const GrCaps* caps = this->caps();
  322. if (!this->asDirectContext() || !c.isValid()) {
  323. return GrBackendTexture();
  324. }
  325. if (this->abandoned()) {
  326. return GrBackendTexture();
  327. }
  328. if (c.usesGLFBO0()) {
  329. // If we are making the surface we will never use FBO0.
  330. return GrBackendTexture();
  331. }
  332. if (c.vulkanSecondaryCBCompatible()) {
  333. return {};
  334. }
  335. const GrBackendFormat format =
  336. caps->getBackendFormatFromColorType(SkColorTypeToGrColorType(c.colorType()));
  337. if (!format.isValid()) {
  338. return GrBackendTexture();
  339. }
  340. if (!SkSurface_Gpu::Valid(caps, format)) {
  341. return GrBackendTexture();
  342. }
  343. GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format, color,
  344. GrMipMapped(c.isMipMapped()),
  345. GrRenderable::kYes,
  346. c.isProtected());
  347. SkASSERT(c.isCompatible(result));
  348. return result;
  349. }
  350. GrBackendTexture GrContext::createBackendTexture(int width, int height,
  351. const GrBackendFormat& backendFormat,
  352. const SkColor4f& color,
  353. GrMipMapped mipMapped,
  354. GrRenderable renderable,
  355. GrProtected isProtected) {
  356. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  357. if (!this->asDirectContext()) {
  358. return GrBackendTexture();
  359. }
  360. if (this->abandoned()) {
  361. return GrBackendTexture();
  362. }
  363. if (!backendFormat.isValid()) {
  364. return GrBackendTexture();
  365. }
  366. return fGpu->createBackendTexture(width, height, backendFormat,
  367. mipMapped, renderable,
  368. nullptr, 0, &color, isProtected);
  369. }
  370. GrBackendTexture GrContext::createBackendTexture(int width, int height,
  371. SkColorType colorType,
  372. const SkColor4f& color,
  373. GrMipMapped mipMapped,
  374. GrRenderable renderable,
  375. GrProtected isProtected) {
  376. if (!this->asDirectContext()) {
  377. return GrBackendTexture();
  378. }
  379. if (this->abandoned()) {
  380. return GrBackendTexture();
  381. }
  382. GrColorType ct = SkColorTypeToGrColorType(colorType);
  383. GrBackendFormat format = this->caps()->getBackendFormatFromColorType(ct);
  384. if (!format.isValid()) {
  385. return GrBackendTexture();
  386. }
  387. SkColor4f swizzledColor = this->caps()->getOutputSwizzle(format, ct).applyTo(color);
  388. return this->createBackendTexture(width, height, format, swizzledColor, mipMapped, renderable,
  389. isProtected);
  390. }
  391. void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
  392. TRACE_EVENT0("skia.gpu", TRACE_FUNC);
  393. if (this->abandoned() || !backendTex.isValid()) {
  394. return;
  395. }
  396. fGpu->deleteBackendTexture(backendTex);
  397. }