GrSurfaceProxy.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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. #include "src/gpu/GrSurfaceProxy.h"
  8. #include "src/gpu/GrSurfaceProxyPriv.h"
  9. #include "include/gpu/GrContext.h"
  10. #include "include/private/GrRecordingContext.h"
  11. #include "src/core/SkMathPriv.h"
  12. #include "src/core/SkMipMap.h"
  13. #include "src/gpu/GrCaps.h"
  14. #include "src/gpu/GrClip.h"
  15. #include "src/gpu/GrContextPriv.h"
  16. #include "src/gpu/GrGpuResourcePriv.h"
  17. #include "src/gpu/GrOpList.h"
  18. #include "src/gpu/GrProxyProvider.h"
  19. #include "src/gpu/GrRecordingContextPriv.h"
  20. #include "src/gpu/GrStencilAttachment.h"
  21. #include "src/gpu/GrSurfacePriv.h"
  22. #include "src/gpu/GrTextureContext.h"
  23. #include "src/gpu/GrTexturePriv.h"
  24. #include "src/gpu/GrTextureRenderTargetProxy.h"
  25. #ifdef SK_DEBUG
  26. #include "include/gpu/GrRenderTarget.h"
  27. #include "src/gpu/GrRenderTargetPriv.h"
  28. static bool is_valid_fully_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
  29. return desc.fWidth <= 0 &&
  30. desc.fHeight <= 0 &&
  31. desc.fConfig != kUnknown_GrPixelConfig &&
  32. SkBackingFit::kApprox == fit;
  33. }
  34. static bool is_valid_partially_lazy(const GrSurfaceDesc& desc) {
  35. return ((desc.fWidth > 0 && desc.fHeight > 0) ||
  36. (desc.fWidth <= 0 && desc.fHeight <= 0)) &&
  37. desc.fConfig != kUnknown_GrPixelConfig;
  38. }
  39. static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
  40. return desc.fWidth > 0 &&
  41. desc.fHeight > 0 &&
  42. desc.fConfig != kUnknown_GrPixelConfig;
  43. }
  44. #endif
  45. // Lazy-callback version
  46. GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
  47. const GrBackendFormat& format, const GrSurfaceDesc& desc,
  48. GrRenderable renderable, GrSurfaceOrigin origin,
  49. const GrSwizzle& textureSwizzle, SkBackingFit fit,
  50. SkBudgeted budgeted, GrProtected isProtected,
  51. GrInternalSurfaceFlags surfaceFlags)
  52. : fSurfaceFlags(surfaceFlags)
  53. , fFormat(format)
  54. , fConfig(desc.fConfig)
  55. , fWidth(desc.fWidth)
  56. , fHeight(desc.fHeight)
  57. , fOrigin(origin)
  58. , fTextureSwizzle(textureSwizzle)
  59. , fFit(fit)
  60. , fBudgeted(budgeted)
  61. , fLazyInstantiateCallback(std::move(callback))
  62. , fLazyInstantiationType(lazyType)
  63. , fIsProtected(isProtected)
  64. , fGpuMemorySize(kInvalidGpuMemorySize)
  65. , fLastOpList(nullptr) {
  66. SkASSERT(fFormat.isValid());
  67. // NOTE: the default fUniqueID ctor pulls a value from the same pool as the GrGpuResources.
  68. if (fLazyInstantiateCallback) {
  69. SkASSERT(is_valid_fully_lazy(desc, fit) || is_valid_partially_lazy(desc));
  70. } else {
  71. SkASSERT(is_valid_non_lazy(desc));
  72. }
  73. if (GrPixelConfigIsCompressed(desc.fConfig)) {
  74. SkASSERT(renderable == GrRenderable::kNo);
  75. fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
  76. }
  77. }
  78. // Wrapped version
  79. GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin,
  80. const GrSwizzle& textureSwizzle, SkBackingFit fit)
  81. : fTarget(std::move(surface))
  82. , fSurfaceFlags(fTarget->surfacePriv().flags())
  83. , fFormat(fTarget->backendFormat())
  84. , fConfig(fTarget->config())
  85. , fWidth(fTarget->width())
  86. , fHeight(fTarget->height())
  87. , fOrigin(origin)
  88. , fTextureSwizzle(textureSwizzle)
  89. , fFit(fit)
  90. , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
  91. ? SkBudgeted::kYes
  92. : SkBudgeted::kNo)
  93. , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
  94. , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
  95. , fGpuMemorySize(kInvalidGpuMemorySize)
  96. , fLastOpList(nullptr) {
  97. SkASSERT(fFormat.isValid());
  98. }
  99. GrSurfaceProxy::~GrSurfaceProxy() {
  100. // For this to be deleted the opList that held a ref on it (if there was one) must have been
  101. // deleted. Which would have cleared out this back pointer.
  102. SkASSERT(!fLastOpList);
  103. }
  104. bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
  105. GrSurface* surface, int minStencilSampleCount) {
  106. if (minStencilSampleCount) {
  107. GrRenderTarget* rt = surface->asRenderTarget();
  108. if (!rt) {
  109. SkASSERT(0);
  110. return false;
  111. }
  112. if (!resourceProvider->attachStencilAttachment(rt, minStencilSampleCount)) {
  113. return false;
  114. }
  115. }
  116. return true;
  117. }
  118. sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
  119. int sampleCnt, int minStencilSampleCount,
  120. GrRenderable renderable,
  121. GrMipMapped mipMapped) const {
  122. SkASSERT(GrSurfaceProxy::LazyState::kNot == this->lazyInstantiationState());
  123. SkASSERT(!fTarget);
  124. GrSurfaceDesc desc;
  125. desc.fWidth = fWidth;
  126. desc.fHeight = fHeight;
  127. desc.fConfig = fConfig;
  128. // The explicit resource allocator requires that any resources it pulls out of the
  129. // cache have no pending IO.
  130. GrResourceProvider::Flags resourceProviderFlags = GrResourceProvider::Flags::kNoPendingIO;
  131. sk_sp<GrSurface> surface;
  132. if (GrMipMapped::kYes == mipMapped) {
  133. SkASSERT(SkBackingFit::kExact == fFit);
  134. // SkMipMap doesn't include the base level in the level count so we have to add 1
  135. int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
  136. // We should have caught the case where mipCount == 1 when making the proxy and instead
  137. // created a non-mipmapped proxy.
  138. SkASSERT(mipCount > 1);
  139. std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
  140. // We don't want to upload any texel data
  141. for (int i = 0; i < mipCount; i++) {
  142. texels[i].fPixels = nullptr;
  143. texels[i].fRowBytes = 0;
  144. }
  145. surface = resourceProvider->createTexture(desc, renderable, sampleCnt, fBudgeted,
  146. fIsProtected, texels.get(), mipCount);
  147. if (surface) {
  148. SkASSERT(surface->asTexture());
  149. SkASSERT(GrMipMapped::kYes == surface->asTexture()->texturePriv().mipMapped());
  150. }
  151. } else {
  152. if (SkBackingFit::kApprox == fFit) {
  153. surface = resourceProvider->createApproxTexture(desc, renderable, sampleCnt,
  154. fIsProtected, resourceProviderFlags);
  155. } else {
  156. surface = resourceProvider->createTexture(desc, renderable, sampleCnt, fBudgeted,
  157. fIsProtected, resourceProviderFlags);
  158. }
  159. }
  160. if (!surface) {
  161. return nullptr;
  162. }
  163. if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(),
  164. minStencilSampleCount)) {
  165. return nullptr;
  166. }
  167. return surface;
  168. }
  169. bool GrSurfaceProxy::canSkipResourceAllocator() const {
  170. if (this->ignoredByResourceAllocator()) {
  171. // Usually an atlas or onFlush proxy
  172. return true;
  173. }
  174. auto peek = this->peekSurface();
  175. if (!peek) {
  176. return false;
  177. }
  178. // If this resource is already allocated and not recyclable then the resource allocator does
  179. // not need to do anything with it.
  180. return !peek->resourcePriv().getScratchKey().isValid();
  181. }
  182. void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
  183. SkASSERT(!fTarget && surface);
  184. SkDEBUGCODE(this->validateSurface(surface.get());)
  185. fTarget = std::move(surface);
  186. #ifdef SK_DEBUG
  187. if (this->asRenderTargetProxy()) {
  188. SkASSERT(fTarget->asRenderTarget());
  189. if (int minStencilSampleCount = this->asRenderTargetProxy()->numStencilSamples()) {
  190. auto* stencil = fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment();
  191. SkASSERT(stencil);
  192. SkASSERT(stencil->numSamples() >= minStencilSampleCount);
  193. }
  194. }
  195. if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
  196. SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
  197. }
  198. #endif
  199. }
  200. bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
  201. int minStencilSampleCount, GrRenderable renderable,
  202. GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
  203. SkASSERT(LazyState::kNot == this->lazyInstantiationState());
  204. if (fTarget) {
  205. if (uniqueKey && uniqueKey->isValid()) {
  206. SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
  207. }
  208. return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget.get(),
  209. minStencilSampleCount);
  210. }
  211. sk_sp<GrSurface> surface = this->createSurfaceImpl(
  212. resourceProvider, sampleCnt, minStencilSampleCount, renderable, mipMapped);
  213. if (!surface) {
  214. return false;
  215. }
  216. // If there was an invalidation message pending for this key, we might have just processed it,
  217. // causing the key (stored on this proxy) to become invalid.
  218. if (uniqueKey && uniqueKey->isValid()) {
  219. resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
  220. }
  221. this->assign(std::move(surface));
  222. return true;
  223. }
  224. void GrSurfaceProxy::deinstantiate() {
  225. SkASSERT(this->isInstantiated());
  226. fTarget = nullptr;
  227. }
  228. void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
  229. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  230. GrRenderable renderable = GrRenderable::kNo;
  231. int sampleCount = 1;
  232. if (const auto* rtp = this->asRenderTargetProxy()) {
  233. renderable = GrRenderable::kYes;
  234. sampleCount = rtp->numSamples();
  235. }
  236. const GrTextureProxy* tp = this->asTextureProxy();
  237. GrMipMapped mipMapped = GrMipMapped::kNo;
  238. if (tp) {
  239. mipMapped = tp->mipMapped();
  240. }
  241. int width = this->worstCaseWidth();
  242. int height = this->worstCaseHeight();
  243. GrTexturePriv::ComputeScratchKey(this->config(), width, height, renderable, sampleCount,
  244. mipMapped, key);
  245. }
  246. void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
  247. #ifdef SK_DEBUG
  248. if (fLastOpList) {
  249. SkASSERT(fLastOpList->isClosed());
  250. }
  251. #endif
  252. // Un-reffed
  253. fLastOpList = opList;
  254. }
  255. GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
  256. return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
  257. }
  258. GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
  259. return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
  260. }
  261. int GrSurfaceProxy::worstCaseWidth() const {
  262. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  263. if (fTarget) {
  264. return fTarget->width();
  265. }
  266. if (SkBackingFit::kExact == fFit) {
  267. return fWidth;
  268. }
  269. return GrResourceProvider::MakeApprox(fWidth);
  270. }
  271. int GrSurfaceProxy::worstCaseHeight() const {
  272. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  273. if (fTarget) {
  274. return fTarget->height();
  275. }
  276. if (SkBackingFit::kExact == fFit) {
  277. return fHeight;
  278. }
  279. return GrResourceProvider::MakeApprox(fHeight);
  280. }
  281. #ifdef SK_DEBUG
  282. void GrSurfaceProxy::validate(GrContext_Base* context) const {
  283. if (fTarget) {
  284. SkASSERT(fTarget->getContext() == context);
  285. }
  286. }
  287. #endif
  288. sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
  289. GrSurfaceProxy* src,
  290. GrMipMapped mipMapped,
  291. SkIRect srcRect,
  292. SkBackingFit fit,
  293. SkBudgeted budgeted,
  294. RectsMustMatch rectsMustMatch) {
  295. SkASSERT(LazyState::kFully != src->lazyInstantiationState());
  296. GrProtected isProtected = src->isProtected() ? GrProtected::kYes : GrProtected::kNo;
  297. int width;
  298. int height;
  299. SkIPoint dstPoint;
  300. if (rectsMustMatch == RectsMustMatch::kYes) {
  301. width = src->width();
  302. height = src->height();
  303. dstPoint = {srcRect.fLeft, srcRect.fTop};
  304. } else {
  305. width = srcRect.width();
  306. height = srcRect.height();
  307. dstPoint = {0, 0};
  308. }
  309. if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
  310. return nullptr;
  311. }
  312. auto colorType = GrPixelConfigToColorType(src->config());
  313. if (src->backendFormat().textureType() != GrTextureType::kExternal) {
  314. sk_sp<GrTextureContext> dstContext(context->priv().makeDeferredTextureContext(
  315. fit, width, height, colorType, kUnknown_SkAlphaType, nullptr, mipMapped,
  316. src->origin(), budgeted, isProtected));
  317. if (!dstContext) {
  318. return nullptr;
  319. }
  320. if (dstContext->copy(src, srcRect, dstPoint)) {
  321. return dstContext->asTextureProxyRef();
  322. }
  323. }
  324. if (src->asTextureProxy()) {
  325. sk_sp<GrRenderTargetContext> dstContext = context->priv().makeDeferredRenderTargetContext(
  326. fit, width, height, colorType, nullptr, 1, mipMapped, src->origin(), nullptr,
  327. budgeted);
  328. if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
  329. return dstContext->asTextureProxyRef();
  330. }
  331. }
  332. // Can't use backend copies or draws.
  333. return nullptr;
  334. }
  335. sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
  336. GrMipMapped mipMapped, SkBackingFit fit,
  337. SkBudgeted budgeted) {
  338. SkASSERT(LazyState::kFully != src->lazyInstantiationState());
  339. return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
  340. budgeted);
  341. }
  342. #if GR_TEST_UTILS
  343. int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
  344. if (fTarget) {
  345. return fTarget->testingOnly_getRefCnt();
  346. }
  347. return -1; // no backing GrSurface
  348. }
  349. GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
  350. return fSurfaceFlags;
  351. }
  352. #endif
  353. void GrSurfaceProxyPriv::exactify() {
  354. SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState());
  355. if (this->isExact()) {
  356. return;
  357. }
  358. SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
  359. if (fProxy->fTarget) {
  360. // The kApprox but already instantiated case. Setting the proxy's width & height to
  361. // the instantiated width & height could have side-effects going forward, since we're
  362. // obliterating the area of interest information. This call (exactify) only used
  363. // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
  364. // used for additional draws.
  365. fProxy->fWidth = fProxy->fTarget->width();
  366. fProxy->fHeight = fProxy->fTarget->height();
  367. return;
  368. }
  369. // The kApprox uninstantiated case. Making this proxy be exact should be okay.
  370. // It could mess things up if prior decisions were based on the approximate size.
  371. fProxy->fFit = SkBackingFit::kExact;
  372. // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
  373. // already been computed we want to leave it alone so that amount will be removed when
  374. // the special image goes away. If it hasn't been computed yet it might as well compute the
  375. // exact amount.
  376. }
  377. bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
  378. SkASSERT(GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState());
  379. sk_sp<GrSurface> surface;
  380. if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
  381. // First try to reattach to a cached version if the proxy is uniquely keyed
  382. surface = resourceProvider->findByUniqueKey<GrSurface>(
  383. fProxy->asTextureProxy()->getUniqueKey());
  384. }
  385. bool syncKey = true;
  386. if (!surface) {
  387. auto result = fProxy->fLazyInstantiateCallback(resourceProvider);
  388. surface = std::move(result.fSurface);
  389. syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
  390. }
  391. if (GrSurfaceProxy::LazyInstantiationType::kSingleUse == fProxy->fLazyInstantiationType) {
  392. fProxy->fLazyInstantiateCallback = nullptr;
  393. }
  394. if (!surface) {
  395. fProxy->fWidth = 0;
  396. fProxy->fHeight = 0;
  397. return false;
  398. }
  399. if (fProxy->fWidth <= 0 || fProxy->fHeight <= 0) {
  400. // This was a fully lazy proxy. We need to fill in the width & height. For partially
  401. // lazy proxies we must preserve the original width & height since that indicates
  402. // the content area.
  403. SkASSERT(fProxy->fWidth <= 0 && fProxy->fHeight <= 0);
  404. fProxy->fWidth = surface->width();
  405. fProxy->fHeight = surface->height();
  406. }
  407. SkASSERT(fProxy->fWidth <= surface->width());
  408. SkASSERT(fProxy->fHeight <= surface->height());
  409. int minStencilSampleCount = (fProxy->asRenderTargetProxy())
  410. ? fProxy->asRenderTargetProxy()->numSamples()
  411. : 0;
  412. if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(
  413. resourceProvider, surface.get(), minStencilSampleCount)) {
  414. return false;
  415. }
  416. if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
  417. texProxy->setTargetKeySync(syncKey);
  418. if (syncKey) {
  419. const GrUniqueKey& key = texProxy->getUniqueKey();
  420. if (key.isValid()) {
  421. if (!surface->asTexture()->getUniqueKey().isValid()) {
  422. // If 'surface' is newly created, attach the unique key
  423. resourceProvider->assignUniqueKeyToResource(key, surface.get());
  424. } else {
  425. // otherwise we had better have reattached to a cached version
  426. SkASSERT(surface->asTexture()->getUniqueKey() == key);
  427. }
  428. } else {
  429. SkASSERT(!surface->getUniqueKey().isValid());
  430. }
  431. }
  432. }
  433. this->assign(std::move(surface));
  434. return true;
  435. }
  436. #ifdef SK_DEBUG
  437. void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
  438. SkASSERT(surface->config() == fConfig);
  439. this->onValidateSurface(surface);
  440. }
  441. #endif