blob: 663cd4be41a644e1cf9f0e75cb3f3b8aa808052e [file] [log] [blame]
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLCaps_DEFINED
#define GrGLCaps_DEFINED
#include "GrDrawTargetCaps.h"
#include "GrGLStencilAttachment.h"
#include "SkChecksum.h"
#include "SkTHash.h"
#include "SkTArray.h"
class GrGLContextInfo;
class GrGLSLCaps;
/**
* Stores some capabilities of a GL context. Most are determined by the GL
* version and the extensions string. It also tracks formats that have passed
* the FBO completeness test.
*/
class GrGLCaps : public GrCaps {
public:
SK_DECLARE_INST_COUNT(GrGLCaps)
typedef GrGLStencilAttachment::Format StencilFormat;
/**
* The type of MSAA for FBOs supported. Different extensions have different
* semantics of how / when a resolve is performed.
*/
enum MSFBOType {
/**
* no support for MSAA FBOs
*/
kNone_MSFBOType = 0,
/**
* GL3.0-style MSAA FBO (GL_ARB_framebuffer_object).
*/
kDesktop_ARB_MSFBOType,
/**
* earlier GL_EXT_framebuffer* extensions
*/
kDesktop_EXT_MSFBOType,
/**
* Similar to kDesktop_ARB but with additional restrictions on glBlitFramebuffer.
*/
kES_3_0_MSFBOType,
/**
* GL_APPLE_framebuffer_multisample ES extension
*/
kES_Apple_MSFBOType,
/**
* GL_IMG_multisampled_render_to_texture. This variation does not have MSAA renderbuffers.
* Instead the texture is multisampled when bound to the FBO and then resolved automatically
* when read. It also defines an alternate value for GL_MAX_SAMPLES (which we call
* GR_GL_MAX_SAMPLES_IMG).
*/
kES_IMG_MsToTexture_MSFBOType,
/**
* GL_EXT_multisampled_render_to_texture. Same as the IMG one above but uses the standard
* GL_MAX_SAMPLES value.
*/
kES_EXT_MsToTexture_MSFBOType,
kLast_MSFBOType = kES_EXT_MsToTexture_MSFBOType
};
enum InvalidateFBType {
kNone_InvalidateFBType,
kDiscard_InvalidateFBType, //<! glDiscardFramebuffer()
kInvalidate_InvalidateFBType, //<! glInvalidateFramebuffer()
kLast_InvalidateFBType = kInvalidate_InvalidateFBType
};
enum MapBufferType {
kNone_MapBufferType,
kMapBuffer_MapBufferType, // glMapBuffer()
kMapBufferRange_MapBufferType, // glMapBufferRange()
kChromium_MapBufferType, // GL_CHROMIUM_map_sub
kLast_MapBufferType = kChromium_MapBufferType,
};
/**
* Creates a GrGLCaps that advertises no support for any extensions,
* formats, etc. Call init to initialize from a GrGLContextInfo.
*/
GrGLCaps();
GrGLCaps(const GrGLCaps& caps);
GrGLCaps& operator = (const GrGLCaps& caps);
/**
* Resets the caps such that nothing is supported.
*/
void reset() override;
/**
* Initializes the GrGLCaps to the set of features supported in the current
* OpenGL context accessible via ctxInfo.
*/
bool init(const GrGLContextInfo& ctxInfo, const GrGLInterface* glInterface);
/**
* Call to note that a color config has been verified as a valid color
* attachment. This may save future calls to glCheckFramebufferStatus
* using isConfigVerifiedColorAttachment().
*/
void markConfigAsValidColorAttachment(GrPixelConfig config) {
fVerifiedColorConfigs.markVerified(config);
}
/**
* Call to check whether a config has been verified as a valid color
* attachment.
*/
bool isConfigVerifiedColorAttachment(GrPixelConfig config) const {
return fVerifiedColorConfigs.isVerified(config);
}
/**
* Call to note that a color config / stencil format pair passed
* FBO status check. We may skip calling glCheckFramebufferStatus for
* this combination in the future using
* isColorConfigAndStencilFormatVerified().
*/
void markColorConfigAndStencilFormatAsVerified(
GrPixelConfig config,
const GrGLStencilAttachment::Format& format);
/**
* Call to check whether color config / stencil format pair has already
* passed FBO status check.
*/
bool isColorConfigAndStencilFormatVerified(
GrPixelConfig config,
const GrGLStencilAttachment::Format& format) const;
/**
* Reports the type of MSAA FBO support.
*/
MSFBOType msFBOType() const { return fMSFBOType; }
/**
* Does the supported MSAA FBO extension have MSAA renderbuffers?
*/
bool usesMSAARenderBuffers() const {
return kNone_MSFBOType != fMSFBOType &&
kES_IMG_MsToTexture_MSFBOType != fMSFBOType &&
kES_EXT_MsToTexture_MSFBOType != fMSFBOType;
}
/**
* Is the MSAA FBO extension one where the texture is multisampled when bound to an FBO and
* then implicitly resolved when read.
*/
bool usesImplicitMSAAResolve() const {
return kES_IMG_MsToTexture_MSFBOType == fMSFBOType ||
kES_EXT_MsToTexture_MSFBOType == fMSFBOType;
}
bool fbMixedSamplesSupport() const { return fFBMixedSamplesSupport; }
InvalidateFBType invalidateFBType() const { return fInvalidateFBType; }
/// What type of buffer mapping is supported?
MapBufferType mapBufferType() const { return fMapBufferType; }
/**
* Gets an array of legal stencil formats. These formats are not guaranteed
* to be supported by the driver but are legal GLenum names given the GL
* version and extensions supported.
*/
const SkTArray<StencilFormat, true>& stencilFormats() const {
return fStencilFormats;
}
/// The maximum number of fragment uniform vectors (GLES has min. 16).
int maxFragmentUniformVectors() const { return fMaxFragmentUniformVectors; }
/// maximum number of attribute values per vertex
int maxVertexAttributes() const { return fMaxVertexAttributes; }
/// maximum number of texture units accessible in the fragment shader.
int maxFragmentTextureUnits() const { return fMaxFragmentTextureUnits; }
/// ES requires an extension to support RGBA8 in RenderBufferStorage
bool rgba8RenderbufferSupport() const { return fRGBA8RenderbufferSupport; }
/**
* Depending on the ES extensions present the BGRA external format may
* correspond either a BGRA or RGBA internalFormat. On desktop GL it is
* RGBA.
*/
bool bgraIsInternalFormat() const { return fBGRAIsInternalFormat; }
/// GL_ARB_texture_swizzle support
bool textureSwizzleSupport() const { return fTextureSwizzleSupport; }
/// Is there support for GL_UNPACK_ROW_LENGTH
bool unpackRowLengthSupport() const { return fUnpackRowLengthSupport; }
/// Is there support for GL_UNPACK_FLIP_Y
bool unpackFlipYSupport() const { return fUnpackFlipYSupport; }
/// Is there support for GL_PACK_ROW_LENGTH
bool packRowLengthSupport() const { return fPackRowLengthSupport; }
/// Is there support for GL_PACK_REVERSE_ROW_ORDER
bool packFlipYSupport() const { return fPackFlipYSupport; }
/// Is there support for texture parameter GL_TEXTURE_USAGE
bool textureUsageSupport() const { return fTextureUsageSupport; }
/// Is there support for glTexStorage
bool texStorageSupport() const { return fTexStorageSupport; }
/// Is there support for GL_RED and GL_R8
bool textureRedSupport() const { return fTextureRedSupport; }
/// Is GL_ARB_IMAGING supported
bool imagingSupport() const { return fImagingSupport; }
/// Is GL_ARB_fragment_coord_conventions supported?
bool fragCoordConventionsSupport() const { return fFragCoordsConventionSupport; }
/// Is there support for Vertex Array Objects?
bool vertexArrayObjectSupport() const { return fVertexArrayObjectSupport; }
/// Is there support for ES2 compatability?
bool ES2CompatibilitySupport() const { return fES2CompatibilitySupport; }
/// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
bool useNonVBOVertexAndIndexDynamicData() const {
return fUseNonVBOVertexAndIndexDynamicData;
}
/// Does ReadPixels support the provided format/type combo?
bool readPixelsSupported(const GrGLInterface* intf,
GrGLenum format,
GrGLenum type,
GrGLenum currFboFormat) const;
bool isCoreProfile() const { return fIsCoreProfile; }
bool fullClearIsFree() const { return fFullClearIsFree; }
/**
* Returns a string containing the caps info.
*/
SkString dump() const override;
/**
* LATC can appear under one of three possible names. In order to know
* which GL internal format to use, we need to keep track of which name
* we found LATC under. The default is LATC.
*/
enum LATCAlias {
kLATC_LATCAlias,
kRGTC_LATCAlias,
k3DC_LATCAlias
};
LATCAlias latcAlias() const { return fLATCAlias; }
GrGLSLCaps* glslCaps() const { return reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get()); }
private:
/**
* Maintains a bit per GrPixelConfig. It is used to avoid redundantly
* performing glCheckFrameBufferStatus for the same config.
*/
struct VerifiedColorConfigs {
VerifiedColorConfigs() {
this->reset();
}
void reset() {
for (int i = 0; i < kNumUints; ++i) {
fVerifiedColorConfigs[i] = 0;
}
}
static const int kNumUints = (kGrPixelConfigCnt + 31) / 32;
uint32_t fVerifiedColorConfigs[kNumUints];
void markVerified(GrPixelConfig config) {
#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT
return;
#endif
int u32Idx = config / 32;
int bitIdx = config % 32;
fVerifiedColorConfigs[u32Idx] |= 1 << bitIdx;
}
bool isVerified(GrPixelConfig config) const {
#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT
return false;
#endif
int u32Idx = config / 32;
int bitIdx = config % 32;
return SkToBool(fVerifiedColorConfigs[u32Idx] & (1 << bitIdx));
}
};
void initFSAASupport(const GrGLContextInfo&, const GrGLInterface*);
void initStencilFormats(const GrGLContextInfo&);
// This must be called after initFSAASupport().
void initConfigRenderableTable(const GrGLContextInfo&);
void initConfigTexturableTable(const GrGLContextInfo&, const GrGLInterface*);
bool doReadPixelsSupported(const GrGLInterface* intf, GrGLenum format, GrGLenum type) const;
// tracks configs that have been verified to pass the FBO completeness when
// used as a color attachment
VerifiedColorConfigs fVerifiedColorConfigs;
SkTArray<StencilFormat, true> fStencilFormats;
// tracks configs that have been verified to pass the FBO completeness when
// used as a color attachment when a particular stencil format is used
// as a stencil attachment.
SkTArray<VerifiedColorConfigs, true> fStencilVerifiedColorConfigs;
int fMaxFragmentUniformVectors;
int fMaxVertexAttributes;
int fMaxFragmentTextureUnits;
MSFBOType fMSFBOType;
InvalidateFBType fInvalidateFBType;
MapBufferType fMapBufferType;
LATCAlias fLATCAlias;
bool fRGBA8RenderbufferSupport : 1;
bool fBGRAIsInternalFormat : 1;
bool fTextureSwizzleSupport : 1;
bool fUnpackRowLengthSupport : 1;
bool fUnpackFlipYSupport : 1;
bool fPackRowLengthSupport : 1;
bool fPackFlipYSupport : 1;
bool fTextureUsageSupport : 1;
bool fTexStorageSupport : 1;
bool fTextureRedSupport : 1;
bool fImagingSupport : 1;
bool fTwoFormatLimit : 1;
bool fFragCoordsConventionSupport : 1;
bool fVertexArrayObjectSupport : 1;
bool fES2CompatibilitySupport : 1;
bool fUseNonVBOVertexAndIndexDynamicData : 1;
bool fIsCoreProfile : 1;
bool fFullClearIsFree : 1;
bool fFBMixedSamplesSupport : 1;
struct ReadPixelsSupportedFormat {
GrGLenum fFormat;
GrGLenum fType;
GrGLenum fFboFormat;
bool operator==(const ReadPixelsSupportedFormat& rhs) const {
return fFormat == rhs.fFormat
&& fType == rhs.fType
&& fFboFormat == rhs.fFboFormat;
}
};
mutable SkTHashMap<ReadPixelsSupportedFormat, bool> fReadPixelsSupportedCache;
typedef GrCaps INHERITED;
};
class GrGLSLCaps : public GrShaderCaps {
public:
SK_DECLARE_INST_COUNT(GrGLSLCaps)
/**
* Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
* special layout qualifiers in the fragment shader.
*/
enum AdvBlendEqInteraction {
kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension
kAutomatic_AdvBlendEqInteraction, //<! No interaction required
kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out
kSpecificEnables_AdvBlendEqInteraction, //<! Specific layout qualifiers per equation
kLast_AdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction
};
/**
* Creates a GrGLSLCaps that advertises no support for any extensions,
* formats, etc. Call init to initialize from a GrGLContextInfo.
*/
GrGLSLCaps();
~GrGLSLCaps() override {}
GrGLSLCaps(const GrGLSLCaps& caps);
GrGLSLCaps& operator = (const GrGLSLCaps& caps);
/**
* Resets the caps such that nothing is supported.
*/
void reset() override;
/**
* Initializes the GrGLSLCaps to the set of features supported in the current
* OpenGL context accessible via ctxInfo.
*/
bool init(const GrGLContextInfo&, const GrGLInterface*, const GrGLCaps&);
/**
* Some helper functions for encapsulating various extensions to read FB Buffer on openglES
*
* TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
*/
bool fbFetchSupport() const { return fFBFetchSupport; }
bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
const char* fbFetchColorName() const { return fFBFetchColorName; }
const char* fbFetchExtensionString() const { return fFBFetchExtensionString; }
bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
bool mustEnableAdvBlendEqs() const {
return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
}
bool mustEnableSpecificAdvBlendEqs() const {
return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
}
/**
* Returns a string containing the caps info.
*/
SkString dump() const override;
private:
// Must be called after fGeometryShaderSupport is initialized.
void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*);
bool fDropsTileOnZeroDivide : 1;
bool fFBFetchSupport : 1;
bool fFBFetchNeedsCustomOutput : 1;
const char* fFBFetchColorName;
const char* fFBFetchExtensionString;
AdvBlendEqInteraction fAdvBlendEqInteraction;
typedef GrShaderCaps INHERITED;
};
#endif