From 4cd6713af1c699b79e04b590109768300faee531 Mon Sep 17 00:00:00 2001 From: cdalton Date: Wed, 10 Jun 2015 19:23:46 -0700 Subject: [PATCH] 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 --- include/gpu/GrCaps.h | 5 +- src/gpu/gl/GrGLCaps.cpp | 221 +++++++++++++++++++++++------------------------- src/gpu/gl/GrGLCaps.h | 6 +- 3 files changed, 109 insertions(+), 123 deletions(-) diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h index f219cb2..727e9fc 100644 --- a/include/gpu/GrCaps.h +++ b/include/gpu/GrCaps.h @@ -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; diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index ad0f2ca..40405fd 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -47,19 +47,52 @@ 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(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 { diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 742a74d..e924c60 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -264,7 +264,7 @@ public: GrGLSLCaps* glslCaps() const { return reinterpret_cast(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; }; -- 2.7.4