Init GrGLSLCaps fields from inside GrGLCaps
Fixes circular dependencies by allowing the initialization to be done intertwined. BUG=skia: Review URL: https://codereview.chromium.org/1177053002
This commit is contained in:
parent
026beb52a2
commit
4cd6713af1
@ -84,9 +84,8 @@ public:
|
||||
bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }
|
||||
|
||||
protected:
|
||||
/** Subclasses must call this at the end of their constructors in order to apply caps
|
||||
overrides requested by the client. Note that overrides will only reduce the caps never
|
||||
expand them. */
|
||||
/** Subclasses must call this after initialization in order to apply caps overrides requested by
|
||||
the client. Note that overrides will only reduce the caps never expand them. */
|
||||
void applyOptionsOverrides(const GrContextOptions& options);
|
||||
|
||||
bool fShaderDerivativeSupport : 1;
|
||||
|
@ -47,18 +47,51 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
|
||||
|
||||
fReadPixelsSupportedCache.reset();
|
||||
|
||||
this->init(ctxInfo, glInterface);
|
||||
|
||||
fShaderCaps.reset(SkNEW_ARGS(GrGLSLCaps, (contextOptions,
|
||||
ctxInfo, glInterface, *this)));
|
||||
|
||||
this->applyOptionsOverrides(contextOptions);
|
||||
this->init(contextOptions, ctxInfo, glInterface);
|
||||
}
|
||||
|
||||
void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
const GrGLContextInfo& ctxInfo,
|
||||
const GrGLInterface* gli) {
|
||||
GrGLStandard standard = ctxInfo.standard();
|
||||
GrGLVersion version = ctxInfo.version();
|
||||
|
||||
/**************************************************************************
|
||||
* Caps specific to GrGLSLCaps
|
||||
**************************************************************************/
|
||||
|
||||
GrGLSLCaps* glslCaps = static_cast<GrGLSLCaps*>(fShaderCaps.get());
|
||||
glslCaps->fGLSLGeneration = ctxInfo.glslGeneration();
|
||||
|
||||
if (kGLES_GrGLStandard == standard) {
|
||||
if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) {
|
||||
glslCaps->fFBFetchNeedsCustomOutput = (version >= GR_GL_VER(3, 0));
|
||||
glslCaps->fFBFetchSupport = true;
|
||||
glslCaps->fFBFetchColorName = "gl_LastFragData[0]";
|
||||
glslCaps->fFBFetchExtensionString = "GL_EXT_shader_framebuffer_fetch";
|
||||
}
|
||||
else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) {
|
||||
// Actually, we haven't seen an ES3.0 device with this extension yet, so we don't know
|
||||
glslCaps->fFBFetchNeedsCustomOutput = false;
|
||||
glslCaps->fFBFetchSupport = true;
|
||||
glslCaps->fFBFetchColorName = "gl_LastFragData[0]";
|
||||
glslCaps->fFBFetchExtensionString = "GL_NV_shader_framebuffer_fetch";
|
||||
}
|
||||
else if (ctxInfo.hasExtension("GL_ARM_shader_framebuffer_fetch")) {
|
||||
// The arm extension also requires an additional flag which we will set onResetContext
|
||||
glslCaps->fFBFetchNeedsCustomOutput = false;
|
||||
glslCaps->fFBFetchSupport = true;
|
||||
glslCaps->fFBFetchColorName = "gl_LastFragColorARM";
|
||||
glslCaps->fFBFetchExtensionString = "GL_ARM_shader_framebuffer_fetch";
|
||||
}
|
||||
}
|
||||
|
||||
// Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
|
||||
glslCaps->fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();
|
||||
|
||||
/**************************************************************************
|
||||
* Caps specific to GrGLCaps
|
||||
**************************************************************************/
|
||||
@ -210,12 +243,63 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
fMultisampleDisableSupport = false;
|
||||
}
|
||||
|
||||
this->initFSAASupport(ctxInfo, gli);
|
||||
this->initStencilFormats(ctxInfo);
|
||||
/**************************************************************************
|
||||
* GrShaderCaps fields
|
||||
**************************************************************************/
|
||||
|
||||
glslCaps->fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering");
|
||||
|
||||
if (glslCaps->fPathRenderingSupport) {
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
// We only support v1.3+ of GL_NV_path_rendering which allows us to
|
||||
// set individual fragment inputs with ProgramPathFragmentInputGen. The API
|
||||
// additions are detected by checking the existence of the function.
|
||||
glslCaps->fPathRenderingSupport =
|
||||
ctxInfo.hasExtension("GL_EXT_direct_state_access") &&
|
||||
((ctxInfo.version() >= GR_GL_VER(4, 3) ||
|
||||
ctxInfo.hasExtension("GL_ARB_program_interface_query")) &&
|
||||
gli->fFunctions.fProgramPathFragmentInputGen);
|
||||
}
|
||||
else {
|
||||
glslCaps->fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// For now these two are equivalent but we could have dst read in shader via some other method
|
||||
glslCaps->fDstReadInShaderSupport = glslCaps->fFBFetchSupport;
|
||||
|
||||
// Enable supported shader-related caps
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
glslCaps->fDualSourceBlendingSupport = (ctxInfo.version() >= GR_GL_VER(3, 3) ||
|
||||
ctxInfo.hasExtension("GL_ARB_blend_func_extended")) &&
|
||||
GrGLSLSupportsNamedFragmentShaderOutputs(ctxInfo.glslGeneration());
|
||||
glslCaps->fShaderDerivativeSupport = true;
|
||||
// we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
|
||||
glslCaps->fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3, 2) &&
|
||||
ctxInfo.glslGeneration() >= k150_GrGLSLGeneration;
|
||||
}
|
||||
else {
|
||||
glslCaps->fShaderDerivativeSupport = ctxInfo.version() >= GR_GL_VER(3, 0) ||
|
||||
ctxInfo.hasExtension("GL_OES_standard_derivatives");
|
||||
}
|
||||
|
||||
// We need dual source blending and the ability to disable multisample in order to support mixed
|
||||
// samples in every corner case.
|
||||
if (fMultisampleDisableSupport && glslCaps->fDualSourceBlendingSupport) {
|
||||
// We understand "mixed samples" to mean the collective capability of 3 different extensions
|
||||
glslCaps->fMixedSamplesSupport =
|
||||
ctxInfo.hasExtension("GL_NV_framebuffer_mixed_samples") &&
|
||||
ctxInfo.hasExtension("GL_NV_sample_mask_override_coverage") &&
|
||||
ctxInfo.hasExtension("GL_EXT_raster_multisample");
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* GrCaps fields
|
||||
**************************************************************************/
|
||||
|
||||
this->initFSAASupport(ctxInfo, gli);
|
||||
this->initStencilFormats(ctxInfo);
|
||||
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
// we could also look for GL_ATI_separate_stencil extension or
|
||||
// GL_EXT_stencil_two_side but they use different function signatures
|
||||
@ -233,18 +317,19 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
// Disabling advanced blend until we can resolve various bugs
|
||||
#if 0
|
||||
if (kIntel_GrGLVendor != ctxInfo.vendor()) {
|
||||
if (ctxInfo.hasExtension("GL_KHR_blend_equation_advanced_coherent") ||
|
||||
ctxInfo.hasExtension("GL_NV_blend_equation_advanced_coherent")) {
|
||||
if (ctxInfo.hasExtension("GL_NV_blend_equation_advanced_coherent")) {
|
||||
fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
|
||||
} else if (ctxInfo.hasExtension("GL_KHR_blend_equation_advanced") ||
|
||||
ctxInfo.hasExtension("GL_NV_blend_equation_advanced")) {
|
||||
glslCaps->fAdvBlendEqInteraction = GrGLSLCaps::kAutomatic_AdvBlendEqInteraction;
|
||||
} else if (ctxInfo.hasExtension("GL_KHR_blend_equation_advanced_coherent")) {
|
||||
fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
|
||||
glslCaps->fAdvBlendEqInteraction = GrGLSLCaps::kGeneralEnable_AdvBlendEqInteraction;
|
||||
} else if (ctxInfo.hasExtension("GL_NV_blend_equation_advanced")) {
|
||||
fBlendEquationSupport = kAdvanced_BlendEquationSupport;
|
||||
} else {
|
||||
fBlendEquationSupport = kBasic_BlendEquationSupport;
|
||||
glslCaps->fAdvBlendEqInteraction = GrGLSLCaps::kAutomatic_AdvBlendEqInteraction;
|
||||
} else if (ctxInfo.hasExtension("GL_KHR_blend_equation_advanced")) {
|
||||
fBlendEquationSupport = kAdvanced_BlendEquationSupport;
|
||||
glslCaps->fAdvBlendEqInteraction = GrGLSLCaps::kGeneralEnable_AdvBlendEqInteraction;
|
||||
}
|
||||
} else {
|
||||
// On Intel platforms, KHR_blend_equation_advanced is not conformant.
|
||||
fBlendEquationSupport = kBasic_BlendEquationSupport;
|
||||
}
|
||||
#endif
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
@ -338,6 +423,10 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
|
||||
this->initConfigTexturableTable(ctxInfo, gli);
|
||||
this->initConfigRenderableTable(ctxInfo);
|
||||
glslCaps->initShaderPrecisionTable(ctxInfo, gli);
|
||||
|
||||
this->applyOptionsOverrides(contextOptions);
|
||||
glslCaps->applyOptionsOverrides(contextOptions);
|
||||
}
|
||||
|
||||
void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
|
||||
@ -917,108 +1006,6 @@ GrGLSLCaps::GrGLSLCaps(const GrContextOptions& options,
|
||||
fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
|
||||
fFBFetchColorName = NULL;
|
||||
fFBFetchExtensionString = NULL;
|
||||
this->init(ctxInfo, gli, glCaps);
|
||||
this->applyOptionsOverrides(options);
|
||||
}
|
||||
|
||||
void GrGLSLCaps::init(const GrGLContextInfo& ctxInfo,
|
||||
const GrGLInterface* gli,
|
||||
const GrGLCaps& glCaps) {
|
||||
fGLSLGeneration = ctxInfo.glslGeneration();
|
||||
GrGLStandard standard = ctxInfo.standard();
|
||||
GrGLVersion version = ctxInfo.version();
|
||||
|
||||
/**************************************************************************
|
||||
* Caps specific to GrGLSLCaps
|
||||
**************************************************************************/
|
||||
|
||||
if (kGLES_GrGLStandard == standard) {
|
||||
if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) {
|
||||
fFBFetchNeedsCustomOutput = (version >= GR_GL_VER(3, 0));
|
||||
fFBFetchSupport = true;
|
||||
fFBFetchColorName = "gl_LastFragData[0]";
|
||||
fFBFetchExtensionString = "GL_EXT_shader_framebuffer_fetch";
|
||||
}
|
||||
else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) {
|
||||
// Actually, we haven't seen an ES3.0 device with this extension yet, so we don't know
|
||||
fFBFetchNeedsCustomOutput = false;
|
||||
fFBFetchSupport = true;
|
||||
fFBFetchColorName = "gl_LastFragData[0]";
|
||||
fFBFetchExtensionString = "GL_NV_shader_framebuffer_fetch";
|
||||
}
|
||||
else if (ctxInfo.hasExtension("GL_ARM_shader_framebuffer_fetch")) {
|
||||
// The arm extension also requires an additional flag which we will set onResetContext
|
||||
fFBFetchNeedsCustomOutput = false;
|
||||
fFBFetchSupport = true;
|
||||
fFBFetchColorName = "gl_LastFragColorARM";
|
||||
fFBFetchExtensionString = "GL_ARM_shader_framebuffer_fetch";
|
||||
}
|
||||
}
|
||||
|
||||
// Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
|
||||
fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();
|
||||
|
||||
/**************************************************************************
|
||||
* GrShaderCaps fields
|
||||
**************************************************************************/
|
||||
|
||||
fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering");
|
||||
|
||||
if (fPathRenderingSupport) {
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
// We only support v1.3+ of GL_NV_path_rendering which allows us to
|
||||
// set individual fragment inputs with ProgramPathFragmentInputGen. The API
|
||||
// additions are detected by checking the existence of the function.
|
||||
fPathRenderingSupport = ctxInfo.hasExtension("GL_EXT_direct_state_access") &&
|
||||
((ctxInfo.version() >= GR_GL_VER(4, 3) ||
|
||||
ctxInfo.hasExtension("GL_ARB_program_interface_query")) &&
|
||||
gli->fFunctions.fProgramPathFragmentInputGen);
|
||||
}
|
||||
else {
|
||||
fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// For now these two are equivalent but we could have dst read in shader via some other method
|
||||
fDstReadInShaderSupport = fFBFetchSupport;
|
||||
|
||||
// Enable supported shader-related caps
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
fDualSourceBlendingSupport = (ctxInfo.version() >= GR_GL_VER(3, 3) ||
|
||||
ctxInfo.hasExtension("GL_ARB_blend_func_extended")) &&
|
||||
GrGLSLSupportsNamedFragmentShaderOutputs(ctxInfo.glslGeneration());
|
||||
fShaderDerivativeSupport = true;
|
||||
// we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS
|
||||
fGeometryShaderSupport = ctxInfo.version() >= GR_GL_VER(3, 2) &&
|
||||
ctxInfo.glslGeneration() >= k150_GrGLSLGeneration;
|
||||
}
|
||||
else {
|
||||
fShaderDerivativeSupport = ctxInfo.version() >= GR_GL_VER(3, 0) ||
|
||||
ctxInfo.hasExtension("GL_OES_standard_derivatives");
|
||||
}
|
||||
|
||||
// We need dual source blending and the ability to disable multisample in order to support mixed
|
||||
// samples in every corner case.
|
||||
if (fDualSourceBlendingSupport && glCaps.multisampleDisableSupport()) {
|
||||
// We understand "mixed samples" to mean the collective capability of 3 different extensions
|
||||
fMixedSamplesSupport = ctxInfo.hasExtension("GL_NV_framebuffer_mixed_samples") &&
|
||||
ctxInfo.hasExtension("GL_NV_sample_mask_override_coverage") &&
|
||||
ctxInfo.hasExtension("GL_EXT_raster_multisample");
|
||||
}
|
||||
|
||||
if (glCaps.advancedBlendEquationSupport()) {
|
||||
bool coherent = glCaps.advancedCoherentBlendEquationSupport();
|
||||
if (ctxInfo.hasExtension(coherent ? "GL_NV_blend_equation_advanced_coherent"
|
||||
: "GL_NV_blend_equation_advanced")) {
|
||||
fAdvBlendEqInteraction = kAutomatic_AdvBlendEqInteraction;
|
||||
} else {
|
||||
fAdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction;
|
||||
// TODO: Use the following on any platform where "blend_support_all_equations" is slow.
|
||||
//fAdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction;
|
||||
}
|
||||
}
|
||||
|
||||
this->initShaderPrecisionTable(ctxInfo, gli);
|
||||
}
|
||||
|
||||
SkString GrGLSLCaps::dump() const {
|
||||
|
@ -264,7 +264,7 @@ public:
|
||||
GrGLSLCaps* glslCaps() const { return reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get()); }
|
||||
|
||||
private:
|
||||
void init(const GrGLContextInfo& ctxInfo, const GrGLInterface* glInterface);
|
||||
void init(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*);
|
||||
|
||||
/**
|
||||
* Maintains a bit per GrPixelConfig. It is used to avoid redundantly
|
||||
@ -428,8 +428,6 @@ public:
|
||||
SkString dump() const override;
|
||||
|
||||
private:
|
||||
void init(const GrGLContextInfo&, const GrGLInterface*, const GrGLCaps&);
|
||||
|
||||
// Must be called after fGeometryShaderSupport is initialized.
|
||||
void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*);
|
||||
|
||||
@ -444,6 +442,8 @@ private:
|
||||
|
||||
AdvBlendEqInteraction fAdvBlendEqInteraction;
|
||||
|
||||
friend class GrGLCaps; // For initialization.
|
||||
|
||||
typedef GrShaderCaps INHERITED;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user