GrSurfaceProxy.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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. #ifndef GrSurfaceProxy_DEFINED
  8. #define GrSurfaceProxy_DEFINED
  9. #include "include/core/SkRect.h"
  10. #include "include/gpu/GrBackendSurface.h"
  11. #include "include/gpu/GrGpuResource.h"
  12. #include "include/gpu/GrSurface.h"
  13. #include "include/gpu/GrTexture.h"
  14. #include "include/private/SkNoncopyable.h"
  15. #include "src/gpu/GrSwizzle.h"
  16. class GrCaps;
  17. class GrContext_Base;
  18. class GrOpList;
  19. class GrRecordingContext;
  20. class GrRenderTargetOpList;
  21. class GrRenderTargetProxy;
  22. class GrResourceProvider;
  23. class GrSurfaceContext;
  24. class GrSurfaceProxyPriv;
  25. class GrTextureOpList;
  26. class GrTextureProxy;
  27. // This is basically SkRefCntBase except Ganesh uses internalGetProxyRefCnt for more than asserts.
  28. class GrIORefProxy : public SkNoncopyable {
  29. public:
  30. GrIORefProxy() : fRefCnt(1) {}
  31. virtual ~GrIORefProxy() {}
  32. bool unique() const {
  33. SkASSERT(fRefCnt > 0);
  34. return 1 == fRefCnt;
  35. }
  36. void ref() const {
  37. SkASSERT(fRefCnt > 0);
  38. ++fRefCnt;
  39. }
  40. void unref() const {
  41. SkASSERT(fRefCnt > 0);
  42. --fRefCnt;
  43. if (0 == fRefCnt) {
  44. delete this;
  45. }
  46. }
  47. protected:
  48. int32_t internalGetProxyRefCnt() const { return fRefCnt; }
  49. private:
  50. mutable int32_t fRefCnt;
  51. };
  52. class GrSurfaceProxy : public GrIORefProxy {
  53. public:
  54. /**
  55. * Some lazy proxy callbacks want to set their own (or no key) on the GrSurfaces they return.
  56. * Others want the GrSurface's key to be kept in sync with the proxy's key. This enum controls
  57. * the key relationship between proxies and their targets.
  58. */
  59. enum class LazyInstantiationKeyMode {
  60. /**
  61. * Don't key the GrSurface with the proxy's key. The lazy instantiation callback is free to
  62. * return a GrSurface that already has a unique key unrelated to the proxy's key.
  63. */
  64. kUnsynced,
  65. /**
  66. * Keep the GrSurface's unique key in sync with the proxy's unique key. The GrSurface
  67. * returned from the lazy instantiation callback must not have a unique key or have the same
  68. * same unique key as the proxy. If the proxy is later assigned a key it is in turn assigned
  69. * to the GrSurface.
  70. */
  71. kSynced
  72. };
  73. struct LazyInstantiationResult {
  74. LazyInstantiationResult() = default;
  75. LazyInstantiationResult(const LazyInstantiationResult&) = default;
  76. LazyInstantiationResult(LazyInstantiationResult&& that) = default;
  77. LazyInstantiationResult(sk_sp<GrSurface> surf,
  78. LazyInstantiationKeyMode mode = LazyInstantiationKeyMode::kSynced)
  79. : fSurface(std::move(surf)), fKeyMode(mode) {}
  80. LazyInstantiationResult(sk_sp<GrTexture> tex)
  81. : LazyInstantiationResult(sk_sp<GrSurface>(std::move(tex))) {}
  82. LazyInstantiationResult& operator=(const LazyInstantiationResult&) = default;
  83. LazyInstantiationResult& operator=(LazyInstantiationResult&&) = default;
  84. sk_sp<GrSurface> fSurface;
  85. LazyInstantiationKeyMode fKeyMode = LazyInstantiationKeyMode::kSynced;
  86. };
  87. using LazyInstantiateCallback = std::function<LazyInstantiationResult(GrResourceProvider*)>;
  88. enum class LazyInstantiationType {
  89. kSingleUse, // Instantiation callback is allowed to be called only once.
  90. kMultipleUse, // Instantiation callback can be called multiple times.
  91. kDeinstantiate, // Instantiation callback can be called multiple times,
  92. // but we will deinstantiate the proxy after every flush.
  93. };
  94. enum class LazyState {
  95. kNot, // The proxy is instantiated or does not have a lazy callback
  96. kPartially, // The proxy has a lazy callback but knows basic information about itself.
  97. kFully, // The proxy has a lazy callback and also doesn't know its width, height, etc.
  98. };
  99. LazyState lazyInstantiationState() const {
  100. if (this->isInstantiated() || !SkToBool(fLazyInstantiateCallback)) {
  101. return LazyState::kNot;
  102. } else {
  103. if (fWidth <= 0) {
  104. SkASSERT(fHeight <= 0);
  105. return LazyState::kFully;
  106. } else {
  107. SkASSERT(fHeight > 0);
  108. return LazyState::kPartially;
  109. }
  110. }
  111. }
  112. GrPixelConfig config() const { return fConfig; }
  113. int width() const {
  114. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  115. return fWidth;
  116. }
  117. int height() const {
  118. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  119. return fHeight;
  120. }
  121. SkISize isize() const { return {fWidth, fHeight}; }
  122. int worstCaseWidth() const;
  123. int worstCaseHeight() const;
  124. /**
  125. * Helper that gets the width and height of the surface as a bounding rectangle.
  126. */
  127. SkRect getBoundsRect() const {
  128. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  129. return SkRect::MakeIWH(this->width(), this->height());
  130. }
  131. /**
  132. * Helper that gets the worst case width and height of the surface as a bounding rectangle.
  133. */
  134. SkRect getWorstCaseBoundsRect() const {
  135. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  136. return SkRect::MakeIWH(this->worstCaseWidth(), this->worstCaseHeight());
  137. }
  138. GrSurfaceOrigin origin() const {
  139. SkASSERT(kTopLeft_GrSurfaceOrigin == fOrigin || kBottomLeft_GrSurfaceOrigin == fOrigin);
  140. return fOrigin;
  141. }
  142. const GrSwizzle& textureSwizzle() const { return fTextureSwizzle; }
  143. const GrBackendFormat& backendFormat() const { return fFormat; }
  144. class UniqueID {
  145. public:
  146. static UniqueID InvalidID() {
  147. return UniqueID(uint32_t(SK_InvalidUniqueID));
  148. }
  149. // wrapped
  150. explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }
  151. // deferred and lazy-callback
  152. UniqueID() : fID(GrGpuResource::CreateUniqueID()) { }
  153. uint32_t asUInt() const { return fID; }
  154. bool operator==(const UniqueID& other) const {
  155. return fID == other.fID;
  156. }
  157. bool operator!=(const UniqueID& other) const {
  158. return !(*this == other);
  159. }
  160. void makeInvalid() { fID = SK_InvalidUniqueID; }
  161. bool isInvalid() const { return SK_InvalidUniqueID == fID; }
  162. private:
  163. explicit UniqueID(uint32_t id) : fID(id) {}
  164. uint32_t fID;
  165. };
  166. /*
  167. * The contract for the uniqueID is:
  168. * for wrapped resources:
  169. * the uniqueID will match that of the wrapped resource
  170. *
  171. * for deferred resources:
  172. * the uniqueID will be different from the real resource, when it is allocated
  173. * the proxy's uniqueID will not change across the instantiate call
  174. *
  175. * the uniqueIDs of the proxies and the resources draw from the same pool
  176. *
  177. * What this boils down to is that the uniqueID of a proxy can be used to consistently
  178. * track/identify a proxy but should never be used to distinguish between
  179. * resources and proxies - beware!
  180. */
  181. UniqueID uniqueID() const { return fUniqueID; }
  182. UniqueID underlyingUniqueID() const {
  183. if (fTarget) {
  184. return UniqueID(fTarget->uniqueID());
  185. }
  186. return fUniqueID;
  187. }
  188. virtual bool instantiate(GrResourceProvider*) = 0;
  189. void deinstantiate();
  190. /**
  191. * Proxies that are already instantiated and whose backing surface cannot be recycled to
  192. * instantiate other proxies do not need to be considered by GrResourceAllocator.
  193. */
  194. bool canSkipResourceAllocator() const;
  195. /**
  196. * @return the texture proxy associated with the surface proxy, may be NULL.
  197. */
  198. virtual GrTextureProxy* asTextureProxy() { return nullptr; }
  199. virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }
  200. /**
  201. * @return the render target proxy associated with the surface proxy, may be NULL.
  202. */
  203. virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }
  204. virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }
  205. bool isInstantiated() const { return SkToBool(fTarget); }
  206. // If the proxy is already instantiated, return its backing GrTexture; if not, return null.
  207. GrSurface* peekSurface() const { return fTarget.get(); }
  208. // If this is a texture proxy and the proxy is already instantiated, return its backing
  209. // GrTexture; if not, return null.
  210. GrTexture* peekTexture() const { return fTarget ? fTarget->asTexture() : nullptr; }
  211. // If this is a render target proxy and the proxy is already instantiated, return its backing
  212. // GrRenderTarget; if not, return null.
  213. GrRenderTarget* peekRenderTarget() const {
  214. return fTarget ? fTarget->asRenderTarget() : nullptr;
  215. }
  216. /**
  217. * Does the resource count against the resource budget?
  218. */
  219. SkBudgeted isBudgeted() const { return fBudgeted; }
  220. /**
  221. * The pixel values of this proxy's surface cannot be modified (e.g. doesn't support write
  222. * pixels or MIP map level regen). Read-only proxies also bypass interval tracking and
  223. * assignment in GrResourceAllocator.
  224. */
  225. bool readOnly() const { return fSurfaceFlags & GrInternalSurfaceFlags::kReadOnly; }
  226. void setLastOpList(GrOpList* opList);
  227. GrOpList* getLastOpList() { return fLastOpList; }
  228. GrRenderTargetOpList* getLastRenderTargetOpList();
  229. GrTextureOpList* getLastTextureOpList();
  230. /**
  231. * Retrieves the amount of GPU memory that will be or currently is used by this resource
  232. * in bytes. It is approximate since we aren't aware of additional padding or copies made
  233. * by the driver.
  234. *
  235. * @return the amount of GPU memory used in bytes
  236. */
  237. size_t gpuMemorySize() const {
  238. SkASSERT(LazyState::kFully != this->lazyInstantiationState());
  239. if (fTarget) {
  240. return fTarget->gpuMemorySize();
  241. }
  242. if (kInvalidGpuMemorySize == fGpuMemorySize) {
  243. fGpuMemorySize = this->onUninstantiatedGpuMemorySize();
  244. SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
  245. }
  246. return fGpuMemorySize;
  247. }
  248. enum class RectsMustMatch : bool {
  249. kNo = false,
  250. kYes = true
  251. };
  252. // Helper function that creates a temporary SurfaceContext to perform the copy
  253. // The copy is is not a render target and not multisampled.
  254. static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
  255. SkIRect srcRect, SkBackingFit, SkBudgeted,
  256. RectsMustMatch = RectsMustMatch::kNo);
  257. // Copy the entire 'src'
  258. static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
  259. SkBackingFit, SkBudgeted);
  260. #if GR_TEST_UTILS
  261. int32_t testingOnly_getBackingRefCnt() const;
  262. GrInternalSurfaceFlags testingOnly_getFlags() const;
  263. #endif
  264. SkDEBUGCODE(void validate(GrContext_Base*) const;)
  265. // Provides access to functions that aren't part of the public API.
  266. inline GrSurfaceProxyPriv priv();
  267. inline const GrSurfaceProxyPriv priv() const;
  268. // Returns true if we are working with protected content.
  269. bool isProtected() const { return fIsProtected == GrProtected::kYes; }
  270. protected:
  271. // Deferred version
  272. GrSurfaceProxy(const GrBackendFormat& format, const GrSurfaceDesc& desc,
  273. GrRenderable renderable, GrSurfaceOrigin origin, const GrSwizzle& textureSwizzle,
  274. SkBackingFit fit, SkBudgeted budgeted, GrProtected isProtected,
  275. GrInternalSurfaceFlags surfaceFlags)
  276. : GrSurfaceProxy(nullptr, LazyInstantiationType::kSingleUse, format, desc, renderable,
  277. origin, textureSwizzle, fit, budgeted, isProtected, surfaceFlags) {
  278. // Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
  279. }
  280. // Lazy-callback version
  281. GrSurfaceProxy(LazyInstantiateCallback&&, LazyInstantiationType, const GrBackendFormat& format,
  282. const GrSurfaceDesc&, GrRenderable, GrSurfaceOrigin,
  283. const GrSwizzle& textureSwizzle, SkBackingFit, SkBudgeted, GrProtected,
  284. GrInternalSurfaceFlags);
  285. // Wrapped version.
  286. GrSurfaceProxy(sk_sp<GrSurface>, GrSurfaceOrigin, const GrSwizzle& textureSwizzle,
  287. SkBackingFit);
  288. ~GrSurfaceProxy() override;
  289. friend class GrSurfaceProxyPriv;
  290. // Methods made available via GrSurfaceProxyPriv
  291. bool ignoredByResourceAllocator() const { return fIgnoredByResourceAllocator; }
  292. void setIgnoredByResourceAllocator() { fIgnoredByResourceAllocator = true; }
  293. int32_t getProxyRefCnt() const { return this->internalGetProxyRefCnt(); }
  294. void computeScratchKey(GrScratchKey*) const;
  295. virtual sk_sp<GrSurface> createSurface(GrResourceProvider*) const = 0;
  296. void assign(sk_sp<GrSurface> surface);
  297. sk_sp<GrSurface> createSurfaceImpl(GrResourceProvider*, int sampleCnt,
  298. int minStencilSampleCount, GrRenderable, GrMipMapped) const;
  299. // Once the size of a fully-lazy proxy is decided, and before it gets instantiated, the client
  300. // can use this optional method to specify the proxy's size. (A proxy's size can be less than
  301. // the GPU surface that backs it. e.g., SkBackingFit::kApprox.) Otherwise, the proxy's size will
  302. // be set to match the underlying GPU surface upon instantiation.
  303. void setLazySize(int width, int height) {
  304. SkASSERT(GrSurfaceProxy::LazyState::kFully == this->lazyInstantiationState());
  305. SkASSERT(width > 0 && height > 0);
  306. fWidth = width;
  307. fHeight = height;
  308. }
  309. bool instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
  310. int minStencilSampleCount, GrRenderable, GrMipMapped, const GrUniqueKey*);
  311. // For deferred proxies this will be null until the proxy is instantiated.
  312. // For wrapped proxies it will point to the wrapped resource.
  313. sk_sp<GrSurface> fTarget;
  314. // In many cases these flags aren't actually known until the proxy has been instantiated.
  315. // However, Ganesh frequently needs to change its behavior based on these settings. For
  316. // internally create proxies we will know these properties ahead of time. For wrapped
  317. // proxies we will copy the properties off of the GrSurface. For lazy proxies we force the
  318. // call sites to provide the required information ahead of time. At instantiation time
  319. // we verify that the assumed properties match the actual properties.
  320. GrInternalSurfaceFlags fSurfaceFlags;
  321. private:
  322. // For wrapped resources, 'fFormat', 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always
  323. // be filled in from the wrapped resource.
  324. GrBackendFormat fFormat;
  325. GrPixelConfig fConfig;
  326. int fWidth;
  327. int fHeight;
  328. GrSurfaceOrigin fOrigin;
  329. GrSwizzle fTextureSwizzle;
  330. SkBackingFit fFit; // always kApprox for lazy-callback resources
  331. // always kExact for wrapped resources
  332. mutable SkBudgeted fBudgeted; // always kYes for lazy-callback resources
  333. // set from the backing resource for wrapped resources
  334. // mutable bc of SkSurface/SkImage wishy-washiness
  335. const UniqueID fUniqueID; // set from the backing resource for wrapped resources
  336. LazyInstantiateCallback fLazyInstantiateCallback;
  337. // If this is set to kSingleuse, then after one call to fLazyInstantiateCallback we will cleanup
  338. // the lazy callback and then delete it. This will allow for any refs and resources being held
  339. // by the standard function to be released. This is specifically useful in non-dll cases where
  340. // we make lazy proxies and instantiate them immediately.
  341. // Note: This is ignored if fLazyInstantiateCallback is null.
  342. LazyInstantiationType fLazyInstantiationType;
  343. SkDEBUGCODE(void validateSurface(const GrSurface*);)
  344. SkDEBUGCODE(virtual void onValidateSurface(const GrSurface*) = 0;)
  345. static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
  346. SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
  347. virtual size_t onUninstantiatedGpuMemorySize() const = 0;
  348. bool fIgnoredByResourceAllocator = false;
  349. GrProtected fIsProtected;
  350. // This entry is lazily evaluated so, when the proxy wraps a resource, the resource
  351. // will be called but, when the proxy is deferred, it will compute the answer itself.
  352. // If the proxy computes its own answer that answer is checked (in debug mode) in
  353. // the instantiation method.
  354. mutable size_t fGpuMemorySize;
  355. // The last opList that wrote to or is currently going to write to this surface
  356. // The opList can be closed (e.g., no surface context is currently bound
  357. // to this proxy).
  358. // This back-pointer is required so that we can add a dependancy between
  359. // the opList used to create the current contents of this surface
  360. // and the opList of a destination surface to which this one is being drawn or copied.
  361. // This pointer is unreffed. OpLists own a ref on their surface proxies.
  362. GrOpList* fLastOpList;
  363. typedef GrIORefProxy INHERITED;
  364. };
  365. #endif