GrCCAtlas.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright 2017 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 GrCCAtlas_DEFINED
  8. #define GrCCAtlas_DEFINED
  9. #include "include/core/SkRefCnt.h"
  10. #include "include/core/SkSize.h"
  11. #include "include/gpu/GrTexture.h"
  12. #include "include/private/GrResourceKey.h"
  13. #include "src/gpu/GrAllocator.h"
  14. #include "src/gpu/GrNonAtomicRef.h"
  15. class GrCCCachedAtlas;
  16. class GrOnFlushResourceProvider;
  17. class GrRenderTargetContext;
  18. class GrResourceProvider;
  19. class GrTextureProxy;
  20. struct SkIPoint16;
  21. struct SkIRect;
  22. /**
  23. * This class implements a dynamic size GrRectanizer that grows until it reaches the implementation-
  24. * dependent max texture size. When finalized, it also creates and stores a GrTextureProxy for the
  25. * underlying atlas.
  26. */
  27. class GrCCAtlas {
  28. public:
  29. // As long as GrSurfaceOrigin exists, we just have to decide on one for the atlas texture.
  30. static constexpr GrSurfaceOrigin kTextureOrigin = kTopLeft_GrSurfaceOrigin;
  31. static constexpr int kPadding = 1; // Amount of padding below and to the right of each path.
  32. // This struct encapsulates the minimum and desired requirements for an atlas, as well as an
  33. // approximate number of pixels to help select a good initial size.
  34. struct Specs {
  35. int fMaxPreferredTextureSize = 0;
  36. int fMinTextureSize = 0;
  37. int fMinWidth = 0; // If there are 100 20x10 paths, this should be 20.
  38. int fMinHeight = 0; // If there are 100 20x10 paths, this should be 10.
  39. int fApproxNumPixels = 0;
  40. // Add space for a rect in the desired atlas specs.
  41. void accountForSpace(int width, int height);
  42. };
  43. enum class CoverageType {
  44. kFP16_CoverageCount,
  45. kA8_Multisample,
  46. kA8_LiteralCoverage
  47. };
  48. using LazyInstantiateAtlasCallback = std::function<sk_sp<GrTexture>(
  49. GrResourceProvider*, GrPixelConfig, int sampleCount)>;
  50. static sk_sp<GrTextureProxy> MakeLazyAtlasProxy(
  51. const LazyInstantiateAtlasCallback&, CoverageType, const GrCaps&);
  52. GrCCAtlas(CoverageType, const Specs&, const GrCaps&);
  53. ~GrCCAtlas();
  54. GrTextureProxy* textureProxy() const { return fTextureProxy.get(); }
  55. int currentWidth() const { return fWidth; }
  56. int currentHeight() const { return fHeight; }
  57. // Attempts to add a rect to the atlas. If successful, returns the integer offset from
  58. // device-space pixels where the path will be drawn, to atlas pixels where its mask resides.
  59. bool addRect(const SkIRect& devIBounds, SkIVector* atlasOffset);
  60. const SkISize& drawBounds() { return fDrawBounds; }
  61. // This is an optional space for the caller to jot down user-defined instance data to use when
  62. // rendering atlas content.
  63. void setFillBatchID(int id);
  64. int getFillBatchID() const { return fFillBatchID; }
  65. void setStrokeBatchID(int id);
  66. int getStrokeBatchID() const { return fStrokeBatchID; }
  67. void setEndStencilResolveInstance(int idx);
  68. int getEndStencilResolveInstance() const { return fEndStencilResolveInstance; }
  69. sk_sp<GrCCCachedAtlas> refOrMakeCachedAtlas(GrOnFlushResourceProvider*);
  70. // Instantiates our texture proxy for the atlas and returns a pre-cleared GrRenderTargetContext
  71. // that the caller may use to render the content. After this call, it is no longer valid to call
  72. // addRect(), setUserBatchID(), or this method again.
  73. //
  74. // 'backingTexture', if provided, is a renderable texture with which to instantiate our proxy.
  75. // If null then we will create a texture using the resource provider. The purpose of this param
  76. // is to provide a guaranteed way to recycle a stashed atlas texture from a previous flush.
  77. sk_sp<GrRenderTargetContext> makeRenderTargetContext(GrOnFlushResourceProvider*,
  78. sk_sp<GrTexture> backingTexture = nullptr);
  79. private:
  80. class Node;
  81. bool internalPlaceRect(int w, int h, SkIPoint16* loc);
  82. const CoverageType fCoverageType;
  83. const int fMaxTextureSize;
  84. int fWidth, fHeight;
  85. std::unique_ptr<Node> fTopNode;
  86. SkISize fDrawBounds = {0, 0};
  87. int fFillBatchID;
  88. int fStrokeBatchID;
  89. int fEndStencilResolveInstance;
  90. sk_sp<GrCCCachedAtlas> fCachedAtlas;
  91. sk_sp<GrTextureProxy> fTextureProxy;
  92. sk_sp<GrTexture> fBackingTexture;
  93. };
  94. /**
  95. * This class implements an unbounded stack of atlases. When the current atlas reaches the
  96. * implementation-dependent max texture size, a new one is pushed to the back and we continue on.
  97. */
  98. class GrCCAtlasStack {
  99. public:
  100. using CoverageType = GrCCAtlas::CoverageType;
  101. GrCCAtlasStack(CoverageType coverageType, const GrCCAtlas::Specs& specs, const GrCaps* caps)
  102. : fCoverageType(coverageType), fSpecs(specs), fCaps(caps) {}
  103. CoverageType coverageType() const { return fCoverageType; }
  104. bool empty() const { return fAtlases.empty(); }
  105. const GrCCAtlas& front() const { SkASSERT(!this->empty()); return fAtlases.front(); }
  106. GrCCAtlas& front() { SkASSERT(!this->empty()); return fAtlases.front(); }
  107. GrCCAtlas& current() { SkASSERT(!this->empty()); return fAtlases.back(); }
  108. class Iter {
  109. public:
  110. Iter(GrCCAtlasStack& stack) : fImpl(&stack.fAtlases) {}
  111. bool next() { return fImpl.next(); }
  112. GrCCAtlas* operator->() const { return fImpl.get(); }
  113. private:
  114. typename GrTAllocator<GrCCAtlas>::Iter fImpl;
  115. };
  116. // Adds a rect to the current atlas and returns the offset from device space to atlas space.
  117. // Call current() to get the atlas it was added to.
  118. //
  119. // If the return value is non-null, it means the given rect did not fit in the then-current
  120. // atlas, so it was retired and a new one was added to the stack. The return value is the
  121. // newly-retired atlas. The caller should call setUserBatchID() on the retired atlas before
  122. // moving on.
  123. GrCCAtlas* addRect(const SkIRect& devIBounds, SkIVector* devToAtlasOffset);
  124. private:
  125. const CoverageType fCoverageType;
  126. const GrCCAtlas::Specs fSpecs;
  127. const GrCaps* const fCaps;
  128. GrSTAllocator<4, GrCCAtlas> fAtlases;
  129. };
  130. inline void GrCCAtlas::Specs::accountForSpace(int width, int height) {
  131. fMinWidth = SkTMax(width, fMinWidth);
  132. fMinHeight = SkTMax(height, fMinHeight);
  133. fApproxNumPixels += (width + kPadding) * (height + kPadding);
  134. }
  135. #endif