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