GrResourceProvider.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. /*
  2. * Copyright 2015 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 "src/gpu/GrResourceProvider.h"
  8. #include "include/gpu/GrBackendSemaphore.h"
  9. #include "include/gpu/GrContext.h"
  10. #include "include/private/GrResourceKey.h"
  11. #include "include/private/GrSingleOwner.h"
  12. #include "src/core/SkConvertPixels.h"
  13. #include "src/core/SkMathPriv.h"
  14. #include "src/gpu/GrCaps.h"
  15. #include "src/gpu/GrContextPriv.h"
  16. #include "src/gpu/GrGpu.h"
  17. #include "src/gpu/GrGpuBuffer.h"
  18. #include "src/gpu/GrPath.h"
  19. #include "src/gpu/GrPathRendering.h"
  20. #include "src/gpu/GrProxyProvider.h"
  21. #include "src/gpu/GrRenderTargetPriv.h"
  22. #include "src/gpu/GrResourceCache.h"
  23. #include "src/gpu/GrSemaphore.h"
  24. #include "src/gpu/GrStencilAttachment.h"
  25. #include "src/gpu/GrTexturePriv.h"
  26. #include "src/gpu/SkGr.h"
  27. const uint32_t GrResourceProvider::kMinScratchTextureSize = 16;
  28. #define ASSERT_SINGLE_OWNER \
  29. SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
  30. GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
  31. : fCache(cache)
  32. , fGpu(gpu)
  33. #ifdef SK_DEBUG
  34. , fSingleOwner(owner)
  35. #endif
  36. {
  37. fCaps = sk_ref_sp(fGpu->caps());
  38. }
  39. // Ensures the row bytes are populated (not 0) and makes a copy to a temporary
  40. // to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
  41. static bool prepare_level(const GrMipLevel& inLevel, size_t bpp, int w, int h, bool rowBytesSupport,
  42. bool mustInitializeAllLevels, GrMipLevel* outLevel,
  43. std::unique_ptr<char[]>* data) {
  44. size_t minRB = w * bpp;
  45. if (!inLevel.fPixels) {
  46. if (mustInitializeAllLevels) {
  47. data->reset(new char[minRB * h]());
  48. outLevel->fPixels = data->get();
  49. outLevel->fRowBytes = minRB;
  50. } else {
  51. outLevel->fPixels = nullptr;
  52. outLevel->fRowBytes = 0;
  53. }
  54. return true;
  55. }
  56. size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
  57. if (actualRB < minRB) {
  58. return false;
  59. }
  60. if (actualRB == minRB || rowBytesSupport) {
  61. outLevel->fRowBytes = actualRB;
  62. outLevel->fPixels = inLevel.fPixels;
  63. } else {
  64. data->reset(new char[minRB * h]);
  65. outLevel->fPixels = data->get();
  66. outLevel->fRowBytes = minRB;
  67. SkRectMemcpy(data->get(), outLevel->fRowBytes, inLevel.fPixels, inLevel.fRowBytes, minRB,
  68. h);
  69. }
  70. return true;
  71. }
  72. sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
  73. GrRenderable renderable,
  74. int renderTargetSampleCnt, SkBudgeted budgeted,
  75. GrProtected isProtected,
  76. const GrMipLevel texels[], int mipLevelCount) {
  77. ASSERT_SINGLE_OWNER
  78. SkASSERT(mipLevelCount > 0);
  79. if (this->isAbandoned()) {
  80. return nullptr;
  81. }
  82. GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
  83. if (!fCaps->validateSurfaceDesc(desc, renderable, renderTargetSampleCnt, mipMapped)) {
  84. return nullptr;
  85. }
  86. bool mustInitializeAllLevels = this->caps()->createTextureMustSpecifyAllLevels();
  87. bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
  88. SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
  89. SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
  90. if (mipLevelCount > 0 && texels) {
  91. tmpTexels.reset(mipLevelCount);
  92. tmpDatas.reset(mipLevelCount);
  93. int w = desc.fWidth;
  94. int h = desc.fHeight;
  95. size_t bpp = GrBytesPerPixel(desc.fConfig);
  96. for (int i = 0; i < mipLevelCount; ++i) {
  97. if (!prepare_level(texels[i], bpp, w, h, rowBytesSupport, mustInitializeAllLevels,
  98. &tmpTexels[i], &tmpDatas[i])) {
  99. return nullptr;
  100. }
  101. w = std::max(w / 2, 1);
  102. h = std::max(h / 2, 1);
  103. }
  104. }
  105. return fGpu->createTexture(desc, renderable, renderTargetSampleCnt, budgeted, isProtected,
  106. tmpTexels.get(), mipLevelCount);
  107. }
  108. sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
  109. GrRenderable renderable,
  110. int renderTargetSampleCnt,
  111. SkBudgeted budgeted,
  112. GrProtected isProtected,
  113. Flags flags) {
  114. sk_sp<GrTexture> tex(
  115. this->refScratchTexture(desc, renderable, renderTargetSampleCnt, isProtected, flags));
  116. if (tex && SkBudgeted::kNo == budgeted) {
  117. tex->resourcePriv().makeUnbudgeted();
  118. }
  119. return tex;
  120. }
  121. sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
  122. GrRenderable renderable,
  123. int renderTargetSampleCnt,
  124. SkBudgeted budgeted,
  125. SkBackingFit fit,
  126. GrProtected isProtected,
  127. const GrMipLevel& mipLevel,
  128. Flags flags) {
  129. ASSERT_SINGLE_OWNER
  130. if (this->isAbandoned()) {
  131. return nullptr;
  132. }
  133. if (!mipLevel.fPixels) {
  134. return nullptr;
  135. }
  136. if (!fCaps->validateSurfaceDesc(desc, renderable, renderTargetSampleCnt, GrMipMapped::kNo)) {
  137. return nullptr;
  138. }
  139. GrContext* context = fGpu->getContext();
  140. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  141. bool mustInitialize = this->caps()->createTextureMustSpecifyAllLevels();
  142. bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
  143. size_t bpp = GrBytesPerPixel(desc.fConfig);
  144. std::unique_ptr<char[]> tmpData;
  145. GrMipLevel tmpLevel;
  146. if (!prepare_level(mipLevel, bpp, desc.fWidth, desc.fHeight, rowBytesSupport, mustInitialize,
  147. &tmpLevel, &tmpData)) {
  148. return nullptr;
  149. }
  150. GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
  151. sk_sp<GrTexture> tex =
  152. (SkBackingFit::kApprox == fit)
  153. ? this->createApproxTexture(desc, renderable, renderTargetSampleCnt,
  154. isProtected, flags)
  155. : this->createTexture(desc, renderable, renderTargetSampleCnt, budgeted,
  156. isProtected, flags);
  157. if (!tex) {
  158. return nullptr;
  159. }
  160. sk_sp<GrTextureProxy> proxy = proxyProvider->createWrapped(tex, kTopLeft_GrSurfaceOrigin);
  161. if (!proxy) {
  162. return nullptr;
  163. }
  164. // Here we don't really know the alpha type of the data we want to upload. All we really
  165. // care about is that it is not converted. So we use the same alpha type for the data
  166. // and the surface context.
  167. static constexpr auto kAlphaType = kPremul_SkAlphaType;
  168. sk_sp<GrSurfaceContext> sContext =
  169. context->priv().makeWrappedSurfaceContext(std::move(proxy), colorType, kAlphaType);
  170. if (!sContext) {
  171. return nullptr;
  172. }
  173. GrPixelInfo srcInfo(colorType, kAlphaType, nullptr, desc.fWidth, desc.fHeight);
  174. SkAssertResult(sContext->writePixels(srcInfo, tmpLevel.fPixels, tmpLevel.fRowBytes, {0, 0}));
  175. return tex;
  176. }
  177. sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(int width, int height,
  178. SkImage::CompressionType compression,
  179. SkBudgeted budgeted, SkData* data) {
  180. ASSERT_SINGLE_OWNER
  181. if (this->isAbandoned()) {
  182. return nullptr;
  183. }
  184. return fGpu->createCompressedTexture(width, height, compression, budgeted, data->data(),
  185. data->size());
  186. }
  187. sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
  188. GrRenderable renderable,
  189. int renderTargetSampleCnt,
  190. SkBudgeted budgeted,
  191. GrProtected isProtected,
  192. Flags flags) {
  193. ASSERT_SINGLE_OWNER
  194. if (this->isAbandoned()) {
  195. return nullptr;
  196. }
  197. if (!fCaps->validateSurfaceDesc(desc, renderable, renderTargetSampleCnt, GrMipMapped::kNo)) {
  198. return nullptr;
  199. }
  200. // Compressed textures are read-only so they don't support re-use for scratch.
  201. if (!GrPixelConfigIsCompressed(desc.fConfig)) {
  202. sk_sp<GrTexture> tex = this->getExactScratch(desc, renderable, renderTargetSampleCnt,
  203. budgeted, isProtected, flags);
  204. if (tex) {
  205. return tex;
  206. }
  207. }
  208. if (fCaps->createTextureMustSpecifyAllLevels()) {
  209. size_t rowBytes = GrBytesPerPixel(desc.fConfig) * desc.fWidth;
  210. size_t size = rowBytes * desc.fHeight;
  211. std::unique_ptr<char[]> zeros(new char[size]());
  212. GrMipLevel level;
  213. level.fRowBytes = rowBytes;
  214. level.fPixels = zeros.get();
  215. return fGpu->createTexture(desc, renderable, renderTargetSampleCnt, budgeted, isProtected,
  216. &level, 1);
  217. }
  218. return fGpu->createTexture(desc, renderable, renderTargetSampleCnt, budgeted, isProtected);
  219. }
  220. // Map 'value' to a larger multiple of 2. Values <= 'kMagicTol' will pop up to
  221. // the next power of 2. Those above 'kMagicTol' will only go up half the floor power of 2.
  222. uint32_t GrResourceProvider::MakeApprox(uint32_t value) {
  223. static const int kMagicTol = 1024;
  224. value = SkTMax(kMinScratchTextureSize, value);
  225. if (SkIsPow2(value)) {
  226. return value;
  227. }
  228. uint32_t ceilPow2 = GrNextPow2(value);
  229. if (value <= kMagicTol) {
  230. return ceilPow2;
  231. }
  232. uint32_t floorPow2 = ceilPow2 >> 1;
  233. uint32_t mid = floorPow2 + (floorPow2 >> 1);
  234. if (value <= mid) {
  235. return mid;
  236. }
  237. return ceilPow2;
  238. }
  239. sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
  240. GrRenderable renderable,
  241. int renderTargetSampleCnt,
  242. GrProtected isProtected, Flags flags) {
  243. ASSERT_SINGLE_OWNER
  244. SkASSERT(Flags::kNone == flags || Flags::kNoPendingIO == flags);
  245. if (this->isAbandoned()) {
  246. return nullptr;
  247. }
  248. // Currently we don't recycle compressed textures as scratch.
  249. if (GrPixelConfigIsCompressed(desc.fConfig)) {
  250. return nullptr;
  251. }
  252. if (!fCaps->validateSurfaceDesc(desc, renderable, renderTargetSampleCnt, GrMipMapped::kNo)) {
  253. return nullptr;
  254. }
  255. if (auto tex = this->refScratchTexture(desc, renderable, renderTargetSampleCnt, isProtected,
  256. flags)) {
  257. return tex;
  258. }
  259. SkTCopyOnFirstWrite<GrSurfaceDesc> copyDesc(desc);
  260. // bin by some multiple or power of 2 with a reasonable min
  261. if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
  262. GrSurfaceDesc* wdesc = copyDesc.writable();
  263. wdesc->fWidth = MakeApprox(wdesc->fWidth);
  264. wdesc->fHeight = MakeApprox(wdesc->fHeight);
  265. }
  266. if (auto tex = this->refScratchTexture(*copyDesc, renderable, renderTargetSampleCnt,
  267. isProtected, flags)) {
  268. return tex;
  269. }
  270. if (this->caps()->createTextureMustSpecifyAllLevels()) {
  271. size_t rowBytes = GrBytesPerPixel(copyDesc->fConfig) * copyDesc->fWidth;
  272. size_t size = rowBytes * copyDesc->fHeight;
  273. std::unique_ptr<char[]> zeros(new char[size]());
  274. GrMipLevel level;
  275. level.fRowBytes = rowBytes;
  276. level.fPixels = zeros.get();
  277. return fGpu->createTexture(*copyDesc, renderable, renderTargetSampleCnt, SkBudgeted::kYes,
  278. isProtected, &level, 1);
  279. }
  280. return fGpu->createTexture(*copyDesc, renderable, renderTargetSampleCnt, SkBudgeted::kYes,
  281. isProtected);
  282. }
  283. sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc,
  284. GrRenderable renderable,
  285. int renderTargetSampleCnt,
  286. GrProtected isProtected,
  287. Flags flags) {
  288. ASSERT_SINGLE_OWNER
  289. SkASSERT(!this->isAbandoned());
  290. SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
  291. SkASSERT(fCaps->validateSurfaceDesc(desc, renderable, renderTargetSampleCnt, GrMipMapped::kNo));
  292. // We could make initial clears work with scratch textures but it is a rare case so we just opt
  293. // to fall back to making a new texture.
  294. if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
  295. GrScratchKey key;
  296. GrTexturePriv::ComputeScratchKey(desc, renderable, renderTargetSampleCnt, &key);
  297. auto scratchFlags = GrResourceCache::ScratchFlags::kNone;
  298. if (Flags::kNoPendingIO & flags) {
  299. scratchFlags |= GrResourceCache::ScratchFlags::kRequireNoPendingIO;
  300. } else if (renderable == GrRenderable::kNo) {
  301. // If it is not a render target then it will most likely be populated by
  302. // writePixels() which will trigger a flush if the texture has pending IO.
  303. scratchFlags |= GrResourceCache::ScratchFlags::kPreferNoPendingIO;
  304. }
  305. GrGpuResource* resource = fCache->findAndRefScratchResource(
  306. key, GrSurface::WorstCaseSize(desc, renderable, renderTargetSampleCnt),
  307. scratchFlags);
  308. if (resource) {
  309. fGpu->stats()->incNumScratchTexturesReused();
  310. GrSurface* surface = static_cast<GrSurface*>(resource);
  311. return sk_sp<GrTexture>(surface->asTexture());
  312. }
  313. }
  314. return nullptr;
  315. }
  316. sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
  317. GrColorType colorType,
  318. GrWrapOwnership ownership,
  319. GrWrapCacheable cacheable,
  320. GrIOType ioType) {
  321. ASSERT_SINGLE_OWNER
  322. if (this->isAbandoned()) {
  323. return nullptr;
  324. }
  325. return fGpu->wrapBackendTexture(tex, colorType, ownership, cacheable, ioType);
  326. }
  327. sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
  328. int sampleCnt,
  329. GrColorType colorType,
  330. GrWrapOwnership ownership,
  331. GrWrapCacheable cacheable) {
  332. ASSERT_SINGLE_OWNER
  333. if (this->isAbandoned()) {
  334. return nullptr;
  335. }
  336. return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, colorType, ownership, cacheable);
  337. }
  338. sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
  339. const GrBackendRenderTarget& backendRT, GrColorType colorType)
  340. {
  341. ASSERT_SINGLE_OWNER
  342. return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, colorType);
  343. }
  344. sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
  345. const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
  346. ASSERT_SINGLE_OWNER
  347. return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
  348. vkInfo);
  349. }
  350. void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
  351. GrGpuResource* resource) {
  352. ASSERT_SINGLE_OWNER
  353. if (this->isAbandoned() || !resource) {
  354. return;
  355. }
  356. resource->resourcePriv().setUniqueKey(key);
  357. }
  358. sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
  359. ASSERT_SINGLE_OWNER
  360. return this->isAbandoned() ? nullptr
  361. : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
  362. }
  363. sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
  364. size_t size,
  365. const void* data,
  366. const GrUniqueKey& key) {
  367. if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
  368. return std::move(buffer);
  369. }
  370. if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, data)) {
  371. // We shouldn't bin and/or cache static buffers.
  372. SkASSERT(buffer->size() == size);
  373. SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
  374. SkASSERT(!buffer->resourcePriv().hasPendingIO_debugOnly());
  375. buffer->resourcePriv().setUniqueKey(key);
  376. return sk_sp<const GrGpuBuffer>(buffer);
  377. }
  378. return nullptr;
  379. }
  380. sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
  381. int patternSize,
  382. int reps,
  383. int vertCount,
  384. const GrUniqueKey* key) {
  385. size_t bufferSize = patternSize * reps * sizeof(uint16_t);
  386. // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO.
  387. sk_sp<GrGpuBuffer> buffer(
  388. this->createBuffer(bufferSize, GrGpuBufferType::kIndex, kStatic_GrAccessPattern));
  389. if (!buffer) {
  390. return nullptr;
  391. }
  392. uint16_t* data = (uint16_t*) buffer->map();
  393. SkAutoTArray<uint16_t> temp;
  394. if (!data) {
  395. temp.reset(reps * patternSize);
  396. data = temp.get();
  397. }
  398. for (int i = 0; i < reps; ++i) {
  399. int baseIdx = i * patternSize;
  400. uint16_t baseVert = (uint16_t)(i * vertCount);
  401. for (int j = 0; j < patternSize; ++j) {
  402. data[baseIdx+j] = baseVert + pattern[j];
  403. }
  404. }
  405. if (temp.get()) {
  406. if (!buffer->updateData(data, bufferSize)) {
  407. return nullptr;
  408. }
  409. } else {
  410. buffer->unmap();
  411. }
  412. if (key) {
  413. SkASSERT(key->isValid());
  414. this->assignUniqueKeyToResource(*key, buffer.get());
  415. }
  416. return std::move(buffer);
  417. }
  418. static constexpr int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
  419. sk_sp<const GrGpuBuffer> GrResourceProvider::createQuadIndexBuffer() {
  420. GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
  421. static const uint16_t kPattern[] = { 0, 1, 2, 2, 1, 3 };
  422. return this->createPatternedIndexBuffer(kPattern, 6, kMaxQuads, 4, nullptr);
  423. }
  424. int GrResourceProvider::QuadCountOfQuadBuffer() { return kMaxQuads; }
  425. sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
  426. if (this->isAbandoned()) {
  427. return nullptr;
  428. }
  429. SkASSERT(this->gpu()->pathRendering());
  430. return this->gpu()->pathRendering()->createPath(path, style);
  431. }
  432. sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
  433. GrAccessPattern accessPattern,
  434. const void* data) {
  435. if (this->isAbandoned()) {
  436. return nullptr;
  437. }
  438. if (kDynamic_GrAccessPattern != accessPattern) {
  439. return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
  440. }
  441. // bin by pow2 with a reasonable min
  442. static const size_t MIN_SIZE = 1 << 12;
  443. size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
  444. GrScratchKey key;
  445. GrGpuBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
  446. auto buffer =
  447. sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
  448. key, allocSize, GrResourceCache::ScratchFlags::kNone)));
  449. if (!buffer) {
  450. buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
  451. if (!buffer) {
  452. return nullptr;
  453. }
  454. }
  455. if (data) {
  456. buffer->updateData(data, size);
  457. }
  458. return buffer;
  459. }
  460. bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, int minStencilSampleCount) {
  461. SkASSERT(rt);
  462. GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
  463. if (stencil && stencil->numSamples() >= minStencilSampleCount) {
  464. return true;
  465. }
  466. if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
  467. GrUniqueKey sbKey;
  468. int width = rt->width();
  469. int height = rt->height();
  470. #if 0
  471. if (this->caps()->oversizedStencilSupport()) {
  472. width = SkNextPow2(width);
  473. height = SkNextPow2(height);
  474. }
  475. #endif
  476. GrStencilAttachment::ComputeSharedStencilAttachmentKey(
  477. width, height, minStencilSampleCount, &sbKey);
  478. auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
  479. if (!stencil) {
  480. // Need to try and create a new stencil
  481. stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(
  482. rt, width, height, minStencilSampleCount));
  483. if (!stencil) {
  484. return false;
  485. }
  486. this->assignUniqueKeyToResource(sbKey, stencil.get());
  487. }
  488. rt->renderTargetPriv().attachStencilAttachment(std::move(stencil));
  489. }
  490. if (GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment()) {
  491. return stencil->numSamples() >= minStencilSampleCount;
  492. }
  493. return false;
  494. }
  495. sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
  496. const GrBackendTexture& tex, int sampleCnt, GrColorType colorType)
  497. {
  498. if (this->isAbandoned()) {
  499. return nullptr;
  500. }
  501. return fGpu->wrapBackendTextureAsRenderTarget(tex, sampleCnt, colorType);
  502. }
  503. sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool isOwned) {
  504. return fGpu->makeSemaphore(isOwned);
  505. }
  506. sk_sp<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
  507. SemaphoreWrapType wrapType,
  508. GrWrapOwnership ownership) {
  509. ASSERT_SINGLE_OWNER
  510. return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
  511. wrapType,
  512. ownership);
  513. }