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 8 #ifndef GrRenderTargetProxy_DEFINED 9 #define GrRenderTargetProxy_DEFINED 10 11 #include "include/private/GrTypesPriv.h" 12 #include "src/core/SkArenaAlloc.h" 13 #include "src/gpu/GrCaps.h" 14 #include "src/gpu/GrNativeRect.h" 15 #include "src/gpu/GrSubRunAllocator.h" 16 #include "src/gpu/GrSurfaceProxy.h" 17 #include "src/gpu/GrSwizzle.h" 18 19 class GrResourceProvider; 20 21 // GrArenas matches the lifetime of a single frame. It is created and held on the 22 // GrSurfaceFillContext's RenderTargetProxy with the first call to get an arena. Each GrOpsTask 23 // takes a ref on it to keep the arenas alive. When the first GrOpsTask's onExecute() is 24 // completed, the arena ref on the GrSurfaceFillContext's RenderTargetProxy is nulled out so that 25 // any new GrOpsTasks will create and ref a new set of arenas. 26 class GrArenas : public SkNVRefCnt<GrArenas> { 27 public: arenaAlloc()28 SkArenaAlloc* arenaAlloc() { 29 SkDEBUGCODE(if (fIsFlushed) SK_ABORT("Using a flushed arena");) 30 return &fArenaAlloc; 31 } flush()32 void flush() { 33 SkDEBUGCODE(fIsFlushed = true;) 34 } subRunAlloc()35 GrSubRunAllocator* subRunAlloc() { return &fSubRunAllocator; } 36 37 private: 38 SkArenaAlloc fArenaAlloc{1024}; 39 // An allocator specifically designed to minimize the overhead of sub runs. It provides a 40 // different dtor semantics than SkArenaAlloc. 41 GrSubRunAllocator fSubRunAllocator{1024}; 42 SkDEBUGCODE(bool fIsFlushed = false;) 43 }; 44 45 // This class delays the acquisition of RenderTargets until they are actually 46 // required 47 // Beware: the uniqueID of the RenderTargetProxy will usually be different than 48 // the uniqueID of the RenderTarget it represents! 49 class GrRenderTargetProxy : virtual public GrSurfaceProxy { 50 public: asRenderTargetProxy()51 GrRenderTargetProxy* asRenderTargetProxy() override { return this; } asRenderTargetProxy()52 const GrRenderTargetProxy* asRenderTargetProxy() const override { return this; } 53 54 // Actually instantiate the backing rendertarget, if necessary. 55 bool instantiate(GrResourceProvider*) override; 56 57 // Returns true if this proxy either has a stencil attachment already, or if we can attach one 58 // during flush. Wrapped render targets without stencil will return false, since we are unable 59 // to modify their attachments. 60 bool canUseStencil(const GrCaps& caps) const; 61 62 /* 63 * Indicate that a draw to this proxy requires stencil. 64 */ setNeedsStencil()65 void setNeedsStencil() { fNeedsStencil = true; } 66 needsStencil()67 int needsStencil() const { return fNeedsStencil; } 68 69 /** 70 * Returns the number of samples/pixel in the color buffer (One if non-MSAA). 71 */ numSamples()72 int numSamples() const { return fSampleCnt; } 73 74 int maxWindowRectangles(const GrCaps& caps) const; 75 glRTFBOIDIs0()76 bool glRTFBOIDIs0() const { return fSurfaceFlags & GrInternalSurfaceFlags::kGLRTFBOIDIs0; } 77 wrapsVkSecondaryCB()78 bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; } 79 supportsVkInputAttachment()80 bool supportsVkInputAttachment() const { 81 return fSurfaceFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment; 82 } 83 markMSAADirty(SkIRect dirtyRect)84 void markMSAADirty(SkIRect dirtyRect) { 85 SkASSERT(SkIRect::MakeSize(this->backingStoreDimensions()).contains(dirtyRect)); 86 SkASSERT(this->requiresManualMSAAResolve()); 87 fMSAADirtyRect.join(dirtyRect); 88 } markMSAAResolved()89 void markMSAAResolved() { 90 SkASSERT(this->requiresManualMSAAResolve()); 91 fMSAADirtyRect.setEmpty(); 92 } isMSAADirty()93 bool isMSAADirty() const { 94 SkASSERT(fMSAADirtyRect.isEmpty() || this->requiresManualMSAAResolve()); 95 return this->requiresManualMSAAResolve() && !fMSAADirtyRect.isEmpty(); 96 } msaaDirtyRect()97 const SkIRect& msaaDirtyRect() const { 98 SkASSERT(this->requiresManualMSAAResolve()); 99 return fMSAADirtyRect; 100 } 101 102 // TODO: move this to a priv class! 103 bool refsWrappedObjects() const; 104 arenas()105 sk_sp<GrArenas> arenas() { 106 if (fArenas == nullptr) { 107 fArenas = sk_make_sp<GrArenas>(); 108 } 109 return fArenas; 110 } 111 clearArenas()112 void clearArenas() { 113 if (fArenas != nullptr) { 114 fArenas->flush(); 115 } 116 fArenas = nullptr; 117 } 118 119 protected: 120 friend class GrProxyProvider; // for ctors 121 friend class GrRenderTargetProxyPriv; 122 123 // Deferred version 124 GrRenderTargetProxy(const GrCaps&, 125 const GrBackendFormat&, 126 SkISize, 127 int sampleCount, 128 SkBackingFit, 129 SkBudgeted, 130 GrProtected, 131 GrInternalSurfaceFlags, 132 UseAllocator); 133 134 enum class WrapsVkSecondaryCB : bool { kNo = false, kYes = true }; 135 136 // Lazy-callback version 137 // There are two main use cases for lazily-instantiated proxies: 138 // basic knowledge - width, height, config, samples, origin are known 139 // minimal knowledge - only config is known. 140 // 141 // The basic knowledge version is used for DDL where we know the type of proxy we are going to 142 // use, but we don't have access to the GPU yet to instantiate it. 143 // 144 // The minimal knowledge version is used for CCPR where we are generating an atlas but we do not 145 // know the final size until flush time. 146 GrRenderTargetProxy(LazyInstantiateCallback&&, 147 const GrBackendFormat&, 148 SkISize, 149 int sampleCount, 150 SkBackingFit, 151 SkBudgeted, 152 GrProtected, 153 GrInternalSurfaceFlags, 154 UseAllocator, 155 WrapsVkSecondaryCB); 156 157 // Wrapped version 158 GrRenderTargetProxy(sk_sp<GrSurface>, 159 UseAllocator, 160 WrapsVkSecondaryCB = WrapsVkSecondaryCB::kNo); 161 162 sk_sp<GrSurface> createSurface(GrResourceProvider*) const override; 163 164 private: 165 size_t onUninstantiatedGpuMemorySize() const override; 166 SkDEBUGCODE(void onValidateSurface(const GrSurface*) override;) 167 168 LazySurfaceDesc callbackDesc() const override; 169 170 // WARNING: Be careful when adding or removing fields here. ASAN is likely to trigger warnings 171 // when instantiating GrTextureRenderTargetProxy. The std::function in GrSurfaceProxy makes 172 // each class in the diamond require 16 byte alignment. Clang appears to layout the fields for 173 // each class to achieve the necessary alignment. However, ASAN checks the alignment of 'this' 174 // in the constructors, and always looks for the full 16 byte alignment, even if the fields in 175 // that particular class don't require it. Changing the size of this object can move the start 176 // address of other types, leading to this problem. 177 int8_t fSampleCnt; 178 int8_t fNeedsStencil = false; 179 WrapsVkSecondaryCB fWrapsVkSecondaryCB; 180 SkIRect fMSAADirtyRect = SkIRect::MakeEmpty(); 181 sk_sp<GrArenas> fArenas{nullptr}; 182 183 // This is to fix issue in large comment above. Without the padding we can end up with the 184 // GrTextureProxy starting 8 byte aligned by not 16. This happens when the RT ends at bytes 1-8. 185 // Note: with the virtual inheritance an 8 byte pointer is at the start of GrRenderTargetProxy. 186 // 187 // In the current world we end the RT proxy at 12 bytes. Technically any padding between 0-4 188 // will work, but we use 4 to be more explicit about getting it to 16 byte alignment. 189 char fDummyPadding[4]; 190 191 using INHERITED = GrSurfaceProxy; 192 }; 193 194 #endif 195