1
2/*
3 * Copyright 2013 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#ifndef GrCaps_DEFINED
9#define GrCaps_DEFINED
10
11#include "GrTypes.h"
12#include "GrTypesPriv.h"
13#include "GrBlend.h"
14#include "GrShaderVar.h"
15#include "SkRefCnt.h"
16#include "SkString.h"
17
18struct GrContextOptions;
19
20class GrShaderCaps : public SkRefCnt {
21public:
22    /** Info about shader variable precision within a given shader stage. That is, this info
23        is relevant to a float (or vecNf) variable declared with a GrSLPrecision
24        in a given GrShaderType. The info here is hoisted from the OpenGL spec. */
25    struct PrecisionInfo {
26        PrecisionInfo() {
27            fLogRangeLow = 0;
28            fLogRangeHigh = 0;
29            fBits = 0;
30        }
31
32        /** Is this precision level allowed in the shader stage? */
33        bool supported() const { return 0 != fBits; }
34
35        bool operator==(const PrecisionInfo& that) const {
36            return fLogRangeLow == that.fLogRangeLow && fLogRangeHigh == that.fLogRangeHigh &&
37                   fBits == that.fBits;
38        }
39        bool operator!=(const PrecisionInfo& that) const { return !(*this == that); }
40
41        /** floor(log2(|min_value|)) */
42        int fLogRangeLow;
43        /** floor(log2(|max_value|)) */
44        int fLogRangeHigh;
45        /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this
46            struct) :
47            """
48            If the smallest representable value greater than 1 is 1 + e, then fBits will
49            contain floor(log2(e)), and every value in the range [2^fLogRangeLow,
50            2^fLogRangeHigh] can be represented to at least one part in 2^fBits.
51            """
52          */
53        int fBits;
54    };
55
56    GrShaderCaps();
57
58    virtual SkString dump() const;
59
60    bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
61    bool geometryShaderSupport() const { return fGeometryShaderSupport; }
62    bool pathRenderingSupport() const { return fPathRenderingSupport; }
63    bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
64    bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
65    bool integerSupport() const { return fIntegerSupport; }
66
67    /**
68    * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
69    * given shader type. If the shader type is not supported or the precision level is not
70    * supported in that shader type then the returned struct will report false when supported() is
71    * called.
72    */
73    const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
74                                                     GrSLPrecision precision) const {
75        return fFloatPrecisions[shaderType][precision];
76    };
77
78    /**
79    * Is there any difference between the float shader variable precision types? If this is true
80    * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
81    * report the same info for all precisions in all shader types.
82    */
83    bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }
84
85    /**
86     * PLS storage size in bytes (0 when not supported). The PLS spec defines a minimum size of 16
87     * bytes whenever PLS is supported.
88     */
89    int pixelLocalStorageSize() const { return fPixelLocalStorageSize; }
90
91    /**
92     * True if this context supports the necessary extensions and features to enable the PLS path
93     * renderer.
94     */
95    bool plsPathRenderingSupport() const {
96#if GR_ENABLE_PLS_PATH_RENDERING
97        return fPLSPathRenderingSupport;
98#else
99        return false;
100#endif
101    }
102
103protected:
104    /** Subclasses must call this after initialization in order to apply caps overrides requested by
105        the client. Note that overrides will only reduce the caps never expand them. */
106    void applyOptionsOverrides(const GrContextOptions& options);
107
108    bool fShaderDerivativeSupport : 1;
109    bool fGeometryShaderSupport : 1;
110    bool fPathRenderingSupport : 1;
111    bool fDstReadInShaderSupport : 1;
112    bool fDualSourceBlendingSupport : 1;
113    bool fIntegerSupport : 1;
114
115    bool fShaderPrecisionVaries;
116    PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
117    int fPixelLocalStorageSize;
118    bool fPLSPathRenderingSupport;
119
120private:
121    virtual void onApplyOptionsOverrides(const GrContextOptions&) {};
122    typedef SkRefCnt INHERITED;
123};
124
125/**
126 * Represents the capabilities of a GrContext.
127 */
128class GrCaps : public SkRefCnt {
129public:
130    GrCaps(const GrContextOptions&);
131
132    virtual SkString dump() const;
133
134    GrShaderCaps* shaderCaps() const { return fShaderCaps; }
135
136    bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
137    /** To avoid as-yet-unnecessary complexity we don't allow any partial support of MIP Maps (e.g.
138        only for POT textures) */
139    bool mipMapSupport() const { return fMipMapSupport; }
140    bool twoSidedStencilSupport() const { return fTwoSidedStencilSupport; }
141    bool stencilWrapOpsSupport() const { return  fStencilWrapOpsSupport; }
142    bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; }
143    bool gpuTracingSupport() const { return fGpuTracingSupport; }
144    bool compressedTexSubImageSupport() const { return fCompressedTexSubImageSupport; }
145    bool oversizedStencilSupport() const { return fOversizedStencilSupport; }
146    bool textureBarrierSupport() const { return fTextureBarrierSupport; }
147    bool usesMixedSamples() const { return fUsesMixedSamples; }
148
149    bool useDrawInsteadOfClear() const { return fUseDrawInsteadOfClear; }
150    bool useDrawInsteadOfPartialRenderTargetWrite() const {
151        return fUseDrawInsteadOfPartialRenderTargetWrite;
152    }
153
154    bool useDrawInsteadOfAllRenderTargetWrites() const {
155        return fUseDrawInsteadOfAllRenderTargetWrites;
156    }
157
158    bool preferVRAMUseOverFlushes() const { return fPreferVRAMUseOverFlushes; }
159
160    /**
161     * Indicates the capabilities of the fixed function blend unit.
162     */
163    enum BlendEquationSupport {
164        kBasic_BlendEquationSupport,             //<! Support to select the operator that
165                                                 //   combines src and dst terms.
166        kAdvanced_BlendEquationSupport,          //<! Additional fixed function support for specific
167                                                 //   SVG/PDF blend modes. Requires blend barriers.
168        kAdvancedCoherent_BlendEquationSupport,  //<! Advanced blend equation support that does not
169                                                 //   require blend barriers, and permits overlap.
170
171        kLast_BlendEquationSupport = kAdvancedCoherent_BlendEquationSupport
172    };
173
174    BlendEquationSupport blendEquationSupport() const { return fBlendEquationSupport; }
175
176    bool advancedBlendEquationSupport() const {
177        return fBlendEquationSupport >= kAdvanced_BlendEquationSupport;
178    }
179
180    bool advancedCoherentBlendEquationSupport() const {
181        return kAdvancedCoherent_BlendEquationSupport == fBlendEquationSupport;
182    }
183
184    bool canUseAdvancedBlendEquation(GrBlendEquation equation) const {
185        SkASSERT(GrBlendEquationIsAdvanced(equation));
186        return SkToBool(fAdvBlendEqBlacklist & (1 << equation));
187    }
188
189    /**
190     * Indicates whether GPU->CPU memory mapping for GPU resources such as vertex buffers and
191     * textures allows partial mappings or full mappings.
192     */
193    enum MapFlags {
194        kNone_MapFlags   = 0x0,       //<! Cannot map the resource.
195
196        kCanMap_MapFlag  = 0x1,       //<! The resource can be mapped. Must be set for any of
197                                      //   the other flags to have meaning.k
198        kSubset_MapFlag  = 0x2,       //<! The resource can be partially mapped.
199    };
200
201    uint32_t mapBufferFlags() const { return fMapBufferFlags; }
202
203    // Scratch textures not being reused means that those scratch textures
204    // that we upload to (i.e., don't have a render target) will not be
205    // recycled in the texture cache. This is to prevent ghosting by drivers
206    // (in particular for deferred architectures).
207    bool reuseScratchTextures() const { return fReuseScratchTextures; }
208    bool reuseScratchBuffers() const { return fReuseScratchBuffers; }
209
210    int maxRenderTargetSize() const { return fMaxRenderTargetSize; }
211    int maxTextureSize() const { return fMaxTextureSize; }
212    /** This is the maximum tile size to use by GPU devices for rendering sw-backed images/bitmaps.
213        It is usually the max texture size, unless we're overriding it for testing. */
214    int maxTileSize() const { SkASSERT(fMaxTileSize <= fMaxTextureSize); return fMaxTileSize; }
215
216    // Will be 0 if MSAA is not supported
217    int maxColorSampleCount() const { return fMaxColorSampleCount; }
218    // Will be 0 if MSAA is not supported
219    int maxStencilSampleCount() const { return fMaxStencilSampleCount; }
220    // Will be 0 if raster multisample is not supported. Raster multisample is a special HW mode
221    // where the rasterizer runs with more samples than are in the target framebuffer.
222    int maxRasterSamples() const { return fMaxRasterSamples; }
223    // We require the sample count to be less than maxColorSampleCount and maxStencilSampleCount.
224    // If we are using mixed samples, we only care about stencil.
225    int maxSampleCount() const {
226        if (this->usesMixedSamples()) {
227            return this->maxStencilSampleCount();
228        } else {
229            return SkTMin(this->maxColorSampleCount(), this->maxStencilSampleCount());
230        }
231    }
232
233
234    virtual bool isConfigTexturable(GrPixelConfig config) const = 0;
235    virtual bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const = 0;
236
237    bool suppressPrints() const { return fSuppressPrints; }
238
239    bool immediateFlush() const { return fImmediateFlush; }
240
241    bool drawPathMasksToCompressedTexturesSupport() const {
242        return fDrawPathMasksToCompressedTextureSupport;
243    }
244
245    size_t geometryBufferMapThreshold() const {
246        SkASSERT(fGeometryBufferMapThreshold >= 0);
247        return fGeometryBufferMapThreshold;
248    }
249
250    bool supportsInstancedDraws() const {
251        return fSupportsInstancedDraws;
252    }
253
254    bool fullClearIsFree() const { return fFullClearIsFree; }
255
256    /** True in environments that will issue errors if memory uploaded to buffers
257        is not initialized (even if not read by draw calls). */
258    bool mustClearUploadedBufferData() const { return fMustClearUploadedBufferData; }
259
260protected:
261    /** Subclasses must call this at the end of their constructors in order to apply caps
262        overrides requested by the client. Note that overrides will only reduce the caps never
263        expand them. */
264    void applyOptionsOverrides(const GrContextOptions& options);
265
266    SkAutoTUnref<GrShaderCaps>    fShaderCaps;
267
268    bool fNPOTTextureTileSupport                     : 1;
269    bool fMipMapSupport                              : 1;
270    bool fTwoSidedStencilSupport                     : 1;
271    bool fStencilWrapOpsSupport                      : 1;
272    bool fDiscardRenderTargetSupport                 : 1;
273    bool fReuseScratchTextures                       : 1;
274    bool fReuseScratchBuffers                        : 1;
275    bool fGpuTracingSupport                          : 1;
276    bool fCompressedTexSubImageSupport               : 1;
277    bool fOversizedStencilSupport                    : 1;
278    bool fTextureBarrierSupport                      : 1;
279    bool fUsesMixedSamples                           : 1;
280    bool fSupportsInstancedDraws                     : 1;
281    bool fFullClearIsFree                            : 1;
282    bool fMustClearUploadedBufferData                : 1;
283
284    // Driver workaround
285    bool fUseDrawInsteadOfClear                      : 1;
286    bool fUseDrawInsteadOfPartialRenderTargetWrite   : 1;
287    bool fUseDrawInsteadOfAllRenderTargetWrites      : 1;
288
289    // ANGLE workaround
290    bool fPreferVRAMUseOverFlushes                   : 1;
291
292    BlendEquationSupport fBlendEquationSupport;
293    uint32_t fAdvBlendEqBlacklist;
294    GR_STATIC_ASSERT(kLast_GrBlendEquation < 32);
295
296    uint32_t fMapBufferFlags;
297    int fGeometryBufferMapThreshold;
298
299    int fMaxRenderTargetSize;
300    int fMaxTextureSize;
301    int fMaxTileSize;
302    int fMaxColorSampleCount;
303    int fMaxStencilSampleCount;
304    int fMaxRasterSamples;
305
306private:
307    virtual void onApplyOptionsOverrides(const GrContextOptions&) {};
308
309    bool fSuppressPrints : 1;
310    bool fImmediateFlush: 1;
311    bool fDrawPathMasksToCompressedTextureSupport : 1;
312
313    typedef SkRefCnt INHERITED;
314};
315
316#endif
317