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