• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 GrProtected : bool;
30 enum class SkBackingFit;
31 struct SkISize;
32 namespace skgpu {
33 enum class Budgeted : 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 GrRenderTargetProxyPriv;
137 
138     // Deferred version
139     GrRenderTargetProxy(const GrCaps&,
140                         const GrBackendFormat&,
141                         SkISize,
142                         int sampleCount,
143                         SkBackingFit,
144                         skgpu::Budgeted,
145                         GrProtected,
146                         GrInternalSurfaceFlags,
147                         UseAllocator,
148                         std::string_view label);
149 
150     enum class WrapsVkSecondaryCB : bool { kNo = false, kYes = true };
151 
152     // Lazy-callback version
153     // There are two main use cases for lazily-instantiated proxies:
154     //   basic knowledge - width, height, config, samples, origin are known
155     //   minimal knowledge - only config is known.
156     //
157     // The basic knowledge version is used for DDL where we know the type of proxy we are going to
158     // use, but we don't have access to the GPU yet to instantiate it.
159     //
160     // The minimal knowledge version is used for when we are generating an atlas but we do not know
161     // the final size until we have finished adding to it.
162     GrRenderTargetProxy(LazyInstantiateCallback&&,
163                         const GrBackendFormat&,
164                         SkISize,
165                         int sampleCount,
166                         SkBackingFit,
167                         skgpu::Budgeted,
168                         GrProtected,
169                         GrInternalSurfaceFlags,
170                         UseAllocator,
171                         WrapsVkSecondaryCB,
172                         std::string_view label);
173 
174     // Wrapped version
175     GrRenderTargetProxy(sk_sp<GrSurface>,
176                         UseAllocator,
177                         WrapsVkSecondaryCB = WrapsVkSecondaryCB::kNo);
178 
179     sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;
180 
181 private:
182     size_t onUninstantiatedGpuMemorySize() const override;
183     SkDEBUGCODE(void onValidateSurface(const GrSurface*) override;)
184 
185             LazySurfaceDesc callbackDesc() const override;
186 
187     // WARNING: Be careful when adding or removing fields here. ASAN is likely to trigger warnings
188     // when instantiating GrTextureRenderTargetProxy. The std::function in GrSurfaceProxy makes
189     // each class in the diamond require 16 byte alignment. Clang appears to layout the fields for
190     // each class to achieve the necessary alignment. However, ASAN checks the alignment of 'this'
191     // in the constructors, and always looks for the full 16 byte alignment, even if the fields in
192     // that particular class don't require it. Changing the size of this object can move the start
193     // address of other types, leading to this problem.
194     int8_t             fSampleCnt;
195     int8_t             fNeedsStencil = false;
196     WrapsVkSecondaryCB fWrapsVkSecondaryCB;
197     SkIRect            fMSAADirtyRect = SkIRect::MakeEmpty();
198     sk_sp<GrArenas>    fArenas{nullptr};
199 
200     // This is to fix issue in large comment above. Without the padding we can end up with the
201     // GrTextureProxy starting 8 byte aligned by not 16. This happens when the RT ends at bytes 1-8.
202     // Note: with the virtual inheritance an 8 byte pointer is at the start of GrRenderTargetProxy.
203     //
204     // In the current world we end the RT proxy at 12 bytes. Technically any padding between 0-4
205     // will work, but we use 4 to be more explicit about getting it to 16 byte alignment.
206     char               fPadding[4];
207 
208     using INHERITED = GrSurfaceProxy;
209 };
210 
211 #endif
212