1 /*
2  * Copyright 2012 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 
9 #ifndef GrGLCaps_DEFINED
10 #define GrGLCaps_DEFINED
11 
12 #include <functional>
13 
14 #include "glsl/GrGLSL.h"
15 #include "GrCaps.h"
16 #include "GrGLStencilAttachment.h"
17 #include "GrSwizzle.h"
18 #include "SkChecksum.h"
19 #include "SkTHash.h"
20 #include "SkTArray.h"
21 
22 class GrGLContextInfo;
23 class GrGLSLCaps;
24 class GrGLRenderTarget;
25 
26 /**
27  * Stores some capabilities of a GL context. Most are determined by the GL
28  * version and the extensions string. It also tracks formats that have passed
29  * the FBO completeness test.
30  */
31 class GrGLCaps : public GrCaps {
32 public:
33     typedef GrGLStencilAttachment::Format StencilFormat;
34 
35     /**
36      * The type of MSAA for FBOs supported. Different extensions have different
37      * semantics of how / when a resolve is performed.
38      */
39     enum MSFBOType {
40         /**
41          * no support for MSAA FBOs
42          */
43         kNone_MSFBOType = 0,
44         /**
45          * GL3.0-style MSAA FBO (GL_ARB_framebuffer_object).
46          */
47         kDesktop_ARB_MSFBOType,
48         /**
49          * earlier GL_EXT_framebuffer* extensions
50          */
51         kDesktop_EXT_MSFBOType,
52         /**
53          * Similar to kDesktop_ARB but with additional restrictions on glBlitFramebuffer.
54          */
55         kES_3_0_MSFBOType,
56         /**
57          * GL_APPLE_framebuffer_multisample ES extension
58          */
59         kES_Apple_MSFBOType,
60         /**
61          * GL_IMG_multisampled_render_to_texture. This variation does not have MSAA renderbuffers.
62          * Instead the texture is multisampled when bound to the FBO and then resolved automatically
63          * when read. It also defines an alternate value for GL_MAX_SAMPLES (which we call
64          * GR_GL_MAX_SAMPLES_IMG).
65          */
66         kES_IMG_MsToTexture_MSFBOType,
67         /**
68          * GL_EXT_multisampled_render_to_texture. Same as the IMG one above but uses the standard
69          * GL_MAX_SAMPLES value.
70          */
71         kES_EXT_MsToTexture_MSFBOType,
72         /**
73          * GL_NV_framebuffer_mixed_samples.
74          */
75         kMixedSamples_MSFBOType,
76 
77         kLast_MSFBOType = kMixedSamples_MSFBOType
78     };
79 
80     enum BlitFramebufferSupport {
81         kNone_BlitFramebufferSupport,
82         /**
83          * ANGLE exposes a limited blit framebuffer extension that does not allow for stretching
84          * or mirroring.
85          */
86         kNoScalingNoMirroring_BlitFramebufferSupport,
87         kFull_BlitFramebufferSupport
88     };
89 
90     enum InvalidateFBType {
91         kNone_InvalidateFBType,
92         kDiscard_InvalidateFBType,       //<! glDiscardFramebuffer()
93         kInvalidate_InvalidateFBType,    //<! glInvalidateFramebuffer()
94 
95         kLast_InvalidateFBType = kInvalidate_InvalidateFBType
96     };
97 
98     enum MapBufferType {
99         kNone_MapBufferType,
100         kMapBuffer_MapBufferType,         // glMapBuffer()
101         kMapBufferRange_MapBufferType,    // glMapBufferRange()
102         kChromium_MapBufferType,          // GL_CHROMIUM_map_sub
103 
104         kLast_MapBufferType = kChromium_MapBufferType,
105     };
106 
107     enum TransferBufferType {
108         kNone_TransferBufferType,
109         kPBO_TransferBufferType,          // ARB_pixel_buffer_object
110         kChromium_TransferBufferType,     // CHROMIUM_pixel_transfer_buffer_object
111 
112         kLast_TransferBufferType = kChromium_TransferBufferType,
113     };
114 
115     /**
116      * Initializes the GrGLCaps to the set of features supported in the current
117      * OpenGL context accessible via ctxInfo.
118      */
119     GrGLCaps(const GrContextOptions& contextOptions, const GrGLContextInfo& ctxInfo,
120              const GrGLInterface* glInterface);
121 
isConfigTexturable(GrPixelConfig config)122     bool isConfigTexturable(GrPixelConfig config) const override {
123         return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kTextureable_Flag);
124     }
125 
isConfigRenderable(GrPixelConfig config,bool withMSAA)126     bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override {
127         if (withMSAA) {
128             return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderableWithMSAA_Flag);
129         } else {
130             return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag);
131         }
132     }
133 
isConfigTexSupportEnabled(GrPixelConfig config)134     bool isConfigTexSupportEnabled(GrPixelConfig config) const {
135         return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseTexStorage_Flag);
136     }
137 
canUseConfigWithTexelBuffer(GrPixelConfig config)138     bool canUseConfigWithTexelBuffer(GrPixelConfig config) const {
139         return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseWithTexelBuffer_Flag);
140     }
141 
142     /** Returns the mapping between GrPixelConfig components and GL internal format components. */
configSwizzle(GrPixelConfig config)143     const GrSwizzle& configSwizzle(GrPixelConfig config) const {
144         return fConfigTable[config].fSwizzle;
145     }
146 
configSizedInternalFormat(GrPixelConfig config)147     GrGLenum configSizedInternalFormat(GrPixelConfig config) const {
148         return fConfigTable[config].fFormats.fSizedInternalFormat;
149     }
150 
151     bool getTexImageFormats(GrPixelConfig surfaceConfig, GrPixelConfig externalConfig,
152                             GrGLenum* internalFormat, GrGLenum* externalFormat,
153                             GrGLenum* externalType) const;
154 
155     bool getCompressedTexImageFormats(GrPixelConfig surfaceConfig, GrGLenum* internalFormat) const;
156 
157     bool getReadPixelsFormat(GrPixelConfig surfaceConfig, GrPixelConfig externalConfig,
158                              GrGLenum* externalFormat, GrGLenum* externalType) const;
159 
160     bool getRenderbufferFormat(GrPixelConfig config, GrGLenum* internalFormat) const;
161 
162     /**
163     * Gets an array of legal stencil formats. These formats are not guaranteed
164     * to be supported by the driver but are legal GLenum names given the GL
165     * version and extensions supported.
166     */
stencilFormats()167     const SkTArray<StencilFormat, true>& stencilFormats() const {
168         return fStencilFormats;
169     }
170 
171     /**
172      * Has a stencil format index been found for the config (or we've found that no format works).
173      */
hasStencilFormatBeenDeterminedForConfig(GrPixelConfig config)174     bool hasStencilFormatBeenDeterminedForConfig(GrPixelConfig config) const {
175         return fConfigTable[config].fStencilFormatIndex != ConfigInfo::kUnknown_StencilIndex;
176     }
177 
178     /**
179      * Gets the stencil format index for the config. This assumes
180      * hasStencilFormatBeenDeterminedForConfig has already been checked. Returns a value < 0 if
181      * no stencil format is supported with the config. Otherwise, returned index refers to the array
182      * returned by stencilFormats().
183      */
getStencilFormatIndexForConfig(GrPixelConfig config)184     int getStencilFormatIndexForConfig(GrPixelConfig config) const {
185         SkASSERT(this->hasStencilFormatBeenDeterminedForConfig(config));
186         return fConfigTable[config].fStencilFormatIndex;
187     }
188 
189     /**
190      * If index is >= 0 this records an index into stencilFormats() as the best stencil format for
191      * the config. If < 0 it records that the config has no supported stencil format index.
192      */
setStencilFormatIndexForConfig(GrPixelConfig config,int index)193     void setStencilFormatIndexForConfig(GrPixelConfig config, int index) {
194         SkASSERT(!this->hasStencilFormatBeenDeterminedForConfig(config));
195         if (index < 0) {
196             fConfigTable[config].fStencilFormatIndex = ConfigInfo::kUnsupported_StencilFormatIndex;
197         } else {
198             fConfigTable[config].fStencilFormatIndex = index;
199         }
200     }
201 
202     /**
203      * Call to note that a color config has been verified as a valid color
204      * attachment. This may save future calls to glCheckFramebufferStatus
205      * using isConfigVerifiedColorAttachment().
206      */
markConfigAsValidColorAttachment(GrPixelConfig config)207     void markConfigAsValidColorAttachment(GrPixelConfig config) {
208         fConfigTable[config].fFlags |= ConfigInfo::kVerifiedColorAttachment_Flag;
209     }
210 
211     /**
212      * Call to check whether a config has been verified as a valid color
213      * attachment.
214      */
isConfigVerifiedColorAttachment(GrPixelConfig config)215     bool isConfigVerifiedColorAttachment(GrPixelConfig config) const {
216         return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kVerifiedColorAttachment_Flag);
217     }
218 
219     /**
220      * Reports the type of MSAA FBO support.
221      */
msFBOType()222     MSFBOType msFBOType() const { return fMSFBOType; }
223 
224     /**
225      * Does the preferred MSAA FBO extension have MSAA renderbuffers?
226      */
usesMSAARenderBuffers()227     bool usesMSAARenderBuffers() const {
228         return kNone_MSFBOType != fMSFBOType &&
229                kES_IMG_MsToTexture_MSFBOType != fMSFBOType &&
230                kES_EXT_MsToTexture_MSFBOType != fMSFBOType &&
231                kMixedSamples_MSFBOType != fMSFBOType;
232     }
233 
234     /**
235      * What functionality is supported by glBlitFramebuffer.
236      */
blitFramebufferSupport()237     BlitFramebufferSupport blitFramebufferSupport() const { return fBlitFramebufferSupport; }
238 
239     /**
240      * Is the MSAA FBO extension one where the texture is multisampled when bound to an FBO and
241      * then implicitly resolved when read.
242      */
usesImplicitMSAAResolve()243     bool usesImplicitMSAAResolve() const {
244         return kES_IMG_MsToTexture_MSFBOType == fMSFBOType ||
245                kES_EXT_MsToTexture_MSFBOType == fMSFBOType;
246     }
247 
invalidateFBType()248     InvalidateFBType invalidateFBType() const { return fInvalidateFBType; }
249 
250     /// What type of buffer mapping is supported?
mapBufferType()251     MapBufferType mapBufferType() const { return fMapBufferType; }
252 
253     /// What type of transfer buffer is supported?
transferBufferType()254     TransferBufferType transferBufferType() const { return fTransferBufferType; }
255 
256     /// The maximum number of fragment uniform vectors (GLES has min. 16).
maxFragmentUniformVectors()257     int maxFragmentUniformVectors() const { return fMaxFragmentUniformVectors; }
258 
259     /**
260      * Depending on the ES extensions present the BGRA external format may
261      * correspond to either a BGRA or RGBA internalFormat. On desktop GL it is
262      * RGBA.
263      */
264     bool bgraIsInternalFormat() const;
265 
266     /// Is there support for GL_UNPACK_ROW_LENGTH
unpackRowLengthSupport()267     bool unpackRowLengthSupport() const { return fUnpackRowLengthSupport; }
268 
269     /// Is there support for GL_UNPACK_FLIP_Y
unpackFlipYSupport()270     bool unpackFlipYSupport() const { return fUnpackFlipYSupport; }
271 
272     /// Is there support for GL_PACK_ROW_LENGTH
packRowLengthSupport()273     bool packRowLengthSupport() const { return fPackRowLengthSupport; }
274 
275     /// Is there support for GL_PACK_REVERSE_ROW_ORDER
packFlipYSupport()276     bool packFlipYSupport() const { return fPackFlipYSupport; }
277 
278     /// Is there support for texture parameter GL_TEXTURE_USAGE
textureUsageSupport()279     bool textureUsageSupport() const { return fTextureUsageSupport; }
280 
281     /// Is there support for GL_RED and GL_R8
textureRedSupport()282     bool textureRedSupport() const { return fTextureRedSupport; }
283 
284     /// Is GL_ARB_IMAGING supported
imagingSupport()285     bool imagingSupport() const { return fImagingSupport; }
286 
287     /// Is there support for Vertex Array Objects?
vertexArrayObjectSupport()288     bool vertexArrayObjectSupport() const { return fVertexArrayObjectSupport; }
289 
290     /// Is there support for GL_EXT_direct_state_access?
directStateAccessSupport()291     bool directStateAccessSupport() const { return fDirectStateAccessSupport; }
292 
293     /// Is there support for GL_KHR_debug?
debugSupport()294     bool debugSupport() const { return fDebugSupport; }
295 
296     /// Is there support for ES2 compatability?
ES2CompatibilitySupport()297     bool ES2CompatibilitySupport() const { return fES2CompatibilitySupport; }
298 
299     /// Is there support for glDraw*Instanced?
drawInstancedSupport()300     bool drawInstancedSupport() const { return fDrawInstancedSupport; }
301 
302     /// Is there support for glDraw*Indirect? Note that the baseInstance fields of indirect draw
303     /// commands cannot be used unless we have base instance support.
drawIndirectSupport()304     bool drawIndirectSupport() const { return fDrawIndirectSupport; }
305 
306     /// Is there support for glMultiDraw*Indirect? Note that the baseInstance fields of indirect
307     /// draw commands cannot be used unless we have base instance support.
multiDrawIndirectSupport()308     bool multiDrawIndirectSupport() const { return fMultiDrawIndirectSupport; }
309 
310     /// Is there support for glDrawRangeElements?
drawRangeElementsSupport()311     bool drawRangeElementsSupport() const { return fDrawRangeElementsSupport; }
312 
313     /// Are the baseInstance fields supported in indirect draw commands?
baseInstanceSupport()314     bool baseInstanceSupport() const { return fBaseInstanceSupport; }
315 
316     /// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
useNonVBOVertexAndIndexDynamicData()317     bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
318 
319     /// Does ReadPixels support reading readConfig pixels from a FBO that is renderTargetConfig?
320     bool readPixelsSupported(GrPixelConfig renderTargetConfig,
321                              GrPixelConfig readConfig,
322                              std::function<void (GrGLenum, GrGLint*)> getIntegerv,
323                              std::function<bool ()> bindRenderTarget) const;
324 
isCoreProfile()325     bool isCoreProfile() const { return fIsCoreProfile; }
326 
bindFragDataLocationSupport()327     bool bindFragDataLocationSupport() const { return fBindFragDataLocationSupport; }
328 
bindUniformLocationSupport()329     bool bindUniformLocationSupport() const { return fBindUniformLocationSupport; }
330 
331     /// Are textures with GL_TEXTURE_RECTANGLE type supported.
rectangleTextureSupport()332     bool rectangleTextureSupport() const { return fRectangleTextureSupport; }
333 
334     /// GL_ARB_texture_swizzle
textureSwizzleSupport()335     bool textureSwizzleSupport() const { return fTextureSwizzleSupport; }
336 
mipMapLevelAndLodControlSupport()337     bool mipMapLevelAndLodControlSupport() const { return fMipMapLevelAndLodControlSupport; }
338 
doManualMipmapping()339     bool doManualMipmapping() const { return fDoManualMipmapping; }
340 
341     /**
342      * Returns a string containing the caps info.
343      */
344     SkString dump() const override;
345 
rgba8888PixelsOpsAreSlow()346     bool rgba8888PixelsOpsAreSlow() const { return fRGBA8888PixelsOpsAreSlow; }
partialFBOReadIsSlow()347     bool partialFBOReadIsSlow() const { return fPartialFBOReadIsSlow; }
rgbaToBgraReadbackConversionsAreSlow()348     bool rgbaToBgraReadbackConversionsAreSlow() const {
349         return fRGBAToBGRAReadbackConversionsAreSlow;
350     }
351 
glslCaps()352     const GrGLSLCaps* glslCaps() const { return reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get()); }
353 
354 private:
355     enum ExternalFormatUsage {
356         kTexImage_ExternalFormatUsage,
357         kOther_ExternalFormatUsage,
358 
359         kLast_ExternalFormatUsage = kOther_ExternalFormatUsage
360     };
361     static const int kExternalFormatUsageCnt = kLast_ExternalFormatUsage + 1;
362     bool getExternalFormat(GrPixelConfig surfaceConfig, GrPixelConfig memoryConfig,
363                            ExternalFormatUsage usage, GrGLenum* externalFormat,
364                            GrGLenum* externalType) const;
365 
366     void init(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*);
367     void initGLSL(const GrGLContextInfo&);
368     bool hasPathRenderingSupport(const GrGLContextInfo&, const GrGLInterface*);
369 
370     void onApplyOptionsOverrides(const GrContextOptions& options) override;
371 
372     void initFSAASupport(const GrGLContextInfo&, const GrGLInterface*);
373     void initBlendEqationSupport(const GrGLContextInfo&);
374     void initStencilFormats(const GrGLContextInfo&);
375     // This must be called after initFSAASupport().
376     void initConfigTable(const GrGLContextInfo&, const GrGLInterface* gli, GrGLSLCaps* glslCaps);
377 
378     void initShaderPrecisionTable(const GrGLContextInfo& ctxInfo,
379                                   const GrGLInterface* intf,
380                                   GrGLSLCaps* glslCaps);
381 
382     GrGLStandard fStandard;
383 
384     SkTArray<StencilFormat, true> fStencilFormats;
385 
386     int fMaxFragmentUniformVectors;
387 
388     MSFBOType           fMSFBOType;
389     InvalidateFBType    fInvalidateFBType;
390     MapBufferType       fMapBufferType;
391     TransferBufferType  fTransferBufferType;
392 
393     bool fUnpackRowLengthSupport : 1;
394     bool fUnpackFlipYSupport : 1;
395     bool fPackRowLengthSupport : 1;
396     bool fPackFlipYSupport : 1;
397     bool fTextureUsageSupport : 1;
398     bool fTextureRedSupport : 1;
399     bool fImagingSupport  : 1;
400     bool fVertexArrayObjectSupport : 1;
401     bool fDirectStateAccessSupport : 1;
402     bool fDebugSupport : 1;
403     bool fES2CompatibilitySupport : 1;
404     bool fDrawInstancedSupport : 1;
405     bool fDrawIndirectSupport : 1;
406     bool fDrawRangeElementsSupport : 1;
407     bool fMultiDrawIndirectSupport : 1;
408     bool fBaseInstanceSupport : 1;
409     bool fUseNonVBOVertexAndIndexDynamicData : 1;
410     bool fIsCoreProfile : 1;
411     bool fBindFragDataLocationSupport : 1;
412     bool fRGBA8888PixelsOpsAreSlow : 1;
413     bool fPartialFBOReadIsSlow : 1;
414     bool fBindUniformLocationSupport : 1;
415     bool fRectangleTextureSupport : 1;
416     bool fTextureSwizzleSupport : 1;
417     bool fMipMapLevelAndLodControlSupport : 1;
418     bool fRGBAToBGRAReadbackConversionsAreSlow : 1;
419     bool fDoManualMipmapping : 1;
420 
421     BlitFramebufferSupport fBlitFramebufferSupport;
422 
423     /** Number type of the components (with out considering number of bits.) */
424     enum FormatType {
425         kNormalizedFixedPoint_FormatType,
426         kFloat_FormatType,
427     };
428 
429     struct ReadPixelsFormat {
ReadPixelsFormatReadPixelsFormat430         ReadPixelsFormat() : fFormat(0), fType(0) {}
431         GrGLenum fFormat;
432         GrGLenum fType;
433     };
434 
435     struct ConfigFormats {
ConfigFormatsConfigFormats436         ConfigFormats() {
437             // Inits to known bad GL enum values.
438             memset(this, 0xAB, sizeof(ConfigFormats));
439         }
440         GrGLenum fBaseInternalFormat;
441         GrGLenum fSizedInternalFormat;
442 
443         /** The external format and type are to be used when uploading/downloading data using this
444             config where both the CPU data and GrSurface are the same config. To get the external
445             format and type when converting between configs while copying to/from memory use
446             getExternalFormat().
447             The kTexImage external format is usually the same as kOther except for kSRGBA on some
448             GL contexts. */
449         GrGLenum fExternalFormat[kExternalFormatUsageCnt];
450         GrGLenum fExternalType;
451 
452 
453         // Either the base or sized internal format depending on the GL and config.
454         GrGLenum fInternalFormatTexImage;
455         GrGLenum fInternalFormatRenderbuffer;
456     };
457 
458     struct ConfigInfo {
ConfigInfoConfigInfo459         ConfigInfo() : fStencilFormatIndex(kUnknown_StencilIndex), fFlags(0) {}
460 
461         ConfigFormats fFormats;
462 
463         FormatType fFormatType;
464 
465         // On ES contexts there are restrictions on type type/format that may be used for
466         // ReadPixels. One is implicitly specified by the current FBO's format. The other is
467         // queryable. This stores the queried option (lazily).
468         ReadPixelsFormat fSecondReadPixelsFormat;
469 
470         enum {
471             // This indicates that a stencil format has not yet been determined for the config.
472             kUnknown_StencilIndex = -1,
473             // This indicates that there is no supported stencil format for the config.
474             kUnsupported_StencilFormatIndex = -2
475         };
476 
477         // Index fStencilFormats.
478         int      fStencilFormatIndex;
479 
480         enum {
481             kVerifiedColorAttachment_Flag = 0x1,
482             kTextureable_Flag             = 0x2,
483             kRenderable_Flag              = 0x4,
484             kRenderableWithMSAA_Flag      = 0x8,
485             kCanUseTexStorage_Flag        = 0x10,
486             kCanUseWithTexelBuffer_Flag   = 0x20,
487         };
488         uint32_t fFlags;
489 
490         GrSwizzle fSwizzle;
491     };
492 
493     ConfigInfo fConfigTable[kGrPixelConfigCnt];
494 
495     typedef GrCaps INHERITED;
496 };
497 
498 #endif
499