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/gpu/GrCaps.h"
13 #include "src/gpu/GrSurfaceProxy.h"
14 #include "src/gpu/GrSwizzle.h"
15 
16 class GrResourceProvider;
17 class GrRenderTargetProxyPriv;
18 
19 // This class delays the acquisition of RenderTargets until they are actually
20 // required
21 // Beware: the uniqueID of the RenderTargetProxy will usually be different than
22 // the uniqueID of the RenderTarget it represents!
23 class GrRenderTargetProxy : virtual public GrSurfaceProxy {
24 public:
asRenderTargetProxy()25     GrRenderTargetProxy* asRenderTargetProxy() override { return this; }
asRenderTargetProxy()26     const GrRenderTargetProxy* asRenderTargetProxy() const override { return this; }
27 
28     // Actually instantiate the backing rendertarget, if necessary.
29     bool instantiate(GrResourceProvider*) override;
30 
canUseMixedSamples(const GrCaps & caps)31     bool canUseMixedSamples(const GrCaps& caps) const {
32         return caps.mixedSamplesSupport() && !this->glRTFBOIDIs0() &&
33                caps.internalMultisampleCount(this->backendFormat()) > 0 &&
34                this->canChangeStencilAttachment();
35     }
36 
37     /*
38      * Indicate that a draw to this proxy requires stencil, and how many stencil samples it needs.
39      * The number of stencil samples on this proxy will be equal to the largest sample count passed
40      * to this method.
41      */
setNeedsStencil(int8_t numStencilSamples)42     void setNeedsStencil(int8_t numStencilSamples) {
43         SkASSERT(numStencilSamples >= fSampleCnt);
44         fNumStencilSamples = SkTMax(numStencilSamples, fNumStencilSamples);
45     }
46 
47     /**
48      * Returns the number of stencil samples required by this proxy.
49      * NOTE: Once instantiated, the actual render target may have more samples, but it is guaranteed
50      * to have at least this many. (After a multisample stencil buffer has been attached to a render
51      * target, we never "downgrade" it to one with fewer samples.)
52      */
numStencilSamples()53     int numStencilSamples() const { return fNumStencilSamples; }
54 
55     /**
56      * Returns the number of samples/pixel in the color buffer (One if non-MSAA).
57      */
numSamples()58     int numSamples() const { return fSampleCnt; }
59 
60     int maxWindowRectangles(const GrCaps& caps) const;
61 
outputSwizzle()62     const GrSwizzle& outputSwizzle() const { return fOutputSwizzle; }
63 
wrapsVkSecondaryCB()64     bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; }
65 
markMSAADirty(const SkIRect & dirtyRect)66     void markMSAADirty(const SkIRect& dirtyRect) {
67         SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(dirtyRect));
68         SkASSERT(this->requiresManualMSAAResolve());
69         fMSAADirtyRect.join(dirtyRect);
70     }
markMSAAResolved()71     void markMSAAResolved() {
72         SkASSERT(this->requiresManualMSAAResolve());
73         fMSAADirtyRect.setEmpty();
74     }
isMSAADirty()75     bool isMSAADirty() const {
76         SkASSERT(fMSAADirtyRect.isEmpty() || this->requiresManualMSAAResolve());
77         return this->requiresManualMSAAResolve() && !fMSAADirtyRect.isEmpty();
78     }
msaaDirtyRect()79     const SkIRect& msaaDirtyRect() const {
80         SkASSERT(this->requiresManualMSAAResolve());
81         return fMSAADirtyRect;
82     }
83 
84     // TODO: move this to a priv class!
85     bool refsWrappedObjects() const;
86 
87     // Provides access to special purpose functions.
88     GrRenderTargetProxyPriv rtPriv();
89     const GrRenderTargetProxyPriv rtPriv() const;
90 
91 protected:
92     friend class GrProxyProvider;  // for ctors
93     friend class GrRenderTargetProxyPriv;
94 
95     // Deferred version
96     GrRenderTargetProxy(const GrCaps&,
97                         const GrBackendFormat&,
98                         const GrSurfaceDesc&,
99                         int sampleCount,
100                         GrSurfaceOrigin,
101                         const GrSwizzle& textureSwizzle,
102                         const GrSwizzle& outputSwizzle,
103                         SkBackingFit,
104                         SkBudgeted,
105                         GrProtected,
106                         GrInternalSurfaceFlags,
107                         UseAllocator);
108 
109     enum class WrapsVkSecondaryCB : bool { kNo = false, kYes = true };
110 
111     // Lazy-callback version
112     // There are two main use cases for lazily-instantiated proxies:
113     //   basic knowledge - width, height, config, samples, origin are known
114     //   minimal knowledge - only config is known.
115     //
116     // The basic knowledge version is used for DDL where we know the type of proxy we are going to
117     // use, but we don't have access to the GPU yet to instantiate it.
118     //
119     // The minimal knowledge version is used for CCPR where we are generating an atlas but we do not
120     // know the final size until flush time.
121     GrRenderTargetProxy(LazyInstantiateCallback&&,
122                         const GrBackendFormat&,
123                         const GrSurfaceDesc&,
124                         int sampleCount,
125                         GrSurfaceOrigin,
126                         const GrSwizzle& textureSwizzle,
127                         const GrSwizzle& outputSwizzle,
128                         SkBackingFit,
129                         SkBudgeted,
130                         GrProtected,
131                         GrInternalSurfaceFlags,
132                         UseAllocator,
133                         WrapsVkSecondaryCB);
134 
135     // Wrapped version
136     GrRenderTargetProxy(sk_sp<GrSurface>,
137                         GrSurfaceOrigin,
138                         const GrSwizzle& textureSwizzle,
139                         const GrSwizzle& outputSwizzle,
140                         UseAllocator,
141                         WrapsVkSecondaryCB = WrapsVkSecondaryCB::kNo);
142 
143     sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;
144 
145 private:
setGLRTFBOIDIs0()146     void setGLRTFBOIDIs0() {
147         fSurfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
148     }
glRTFBOIDIs0()149     bool glRTFBOIDIs0() const {
150         return fSurfaceFlags & GrInternalSurfaceFlags::kGLRTFBOIDIs0;
151     }
152     bool canChangeStencilAttachment() const;
153 
154     size_t onUninstantiatedGpuMemorySize(const GrCaps&) const override;
155     SkDEBUGCODE(void onValidateSurface(const GrSurface*) override;)
156 
157     // WARNING: Be careful when adding or removing fields here. ASAN is likely to trigger warnings
158     // when instantiating GrTextureRenderTargetProxy. The std::function in GrSurfaceProxy makes
159     // each class in the diamond require 16 byte alignment. Clang appears to layout the fields for
160     // each class to achieve the necessary alignment. However, ASAN checks the alignment of 'this'
161     // in the constructors, and always looks for the full 16 byte alignment, even if the fields in
162     // that particular class don't require it. Changing the size of this object can move the start
163     // address of other types, leading to this problem.
164     int8_t             fSampleCnt;
165     int8_t             fNumStencilSamples = 0;
166     WrapsVkSecondaryCB fWrapsVkSecondaryCB;
167     GrSwizzle          fOutputSwizzle;
168     SkIRect            fMSAADirtyRect = SkIRect::MakeEmpty();
169     // This is to fix issue in large comment above. Without the padding we end 6 bytes into a 16
170     // byte range, so the GrTextureProxy ends up starting 8 byte aligned by not 16. We add the
171     // padding here to get us right up to the 16 byte alignment (technically any padding of 3-10
172     // bytes would work since it always goes up to 8 byte alignment, but we use 10 to more explicit
173     // about what we're doing).
174     char               fDummyPadding[10];
175 
176     typedef GrSurfaceProxy INHERITED;
177 };
178 
179 #endif
180