| Index: src/gpu/gl/GrGLCaps.cpp
|
| diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
|
| index b4287cced995447ef234f9a6c94d252199ae0dfc..2edf1d0219ac6e3ad4f4f7a1eabb8acfc5955bfa 100644
|
| --- a/src/gpu/gl/GrGLCaps.cpp
|
| +++ b/src/gpu/gl/GrGLCaps.cpp
|
| @@ -47,14 +47,12 @@ void GrGLCaps::reset() {
|
| fUseNonVBOVertexAndIndexDynamicData = false;
|
| fIsCoreProfile = false;
|
| fFullClearIsFree = false;
|
| - fDropsTileOnZeroDivide = false;
|
| - fFBFetchSupport = false;
|
| - fFBFetchNeedsCustomOutput = false;
|
| - fFBFetchColorName = NULL;
|
| - fFBFetchExtensionString = NULL;
|
| fFBMixedSamplesSupport = false;
|
|
|
| fReadPixelsSupportedCache.reset();
|
| +
|
| + fShaderCaps.reset(SkNEW(GrGLSLCaps));
|
| +
|
| }
|
|
|
| GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
|
| @@ -91,13 +89,11 @@ GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
|
| fUseNonVBOVertexAndIndexDynamicData = caps.fUseNonVBOVertexAndIndexDynamicData;
|
| fIsCoreProfile = caps.fIsCoreProfile;
|
| fFullClearIsFree = caps.fFullClearIsFree;
|
| - fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
|
| - fFBFetchSupport = caps.fFBFetchSupport;
|
| - fFBFetchNeedsCustomOutput = caps.fFBFetchNeedsCustomOutput;
|
| - fFBFetchColorName = caps.fFBFetchColorName;
|
| - fFBFetchExtensionString = caps.fFBFetchExtensionString;
|
| fFBMixedSamplesSupport = caps.fFBMixedSamplesSupport;
|
|
|
| + *(reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get())) =
|
| + *(reinterpret_cast<GrGLSLCaps*>(caps.fShaderCaps.get()));
|
| +
|
| return *this;
|
| }
|
|
|
| @@ -253,30 +249,6 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
| fES2CompatibilitySupport = true;
|
| }
|
|
|
| - 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();
|
| -
|
| this->initFSAASupport(ctxInfo, gli);
|
| this->initStencilFormats(ctxInfo);
|
|
|
| @@ -344,46 +316,14 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
| // attachment, hence this min:
|
| fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
|
|
|
| - 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);
|
| - }
|
| - }
|
| -
|
| fFBMixedSamplesSupport = ctxInfo.hasExtension("GL_NV_framebuffer_mixed_samples");
|
|
|
| fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker");
|
|
|
| - // For now these two are equivalent but we could have dst read in shader via some other method
|
| - fDstReadInShaderSupport = fFBFetchSupport;
|
| -
|
| // Disable scratch texture reuse on Mali and Adreno devices
|
| fReuseScratchTextures = kARM_GrGLVendor != ctxInfo.vendor() &&
|
| kQualcomm_GrGLVendor != ctxInfo.vendor();
|
|
|
| - // Enable supported shader-related caps
|
| - if (kGL_GrGLStandard == standard) {
|
| - fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) ||
|
| - ctxInfo.hasExtension("GL_ARB_blend_func_extended");
|
| - 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");
|
| - }
|
| -
|
| if (GrGLCaps::kES_IMG_MsToTexture_MSFBOType == fMSFBOType) {
|
| GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &fMaxSampleCount);
|
| } else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) {
|
| @@ -412,7 +352,7 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
| this->initConfigTexturableTable(ctxInfo, gli);
|
| this->initConfigRenderableTable(ctxInfo);
|
|
|
| - this->initShaderPrecisionTable(ctxInfo, gli);
|
| + reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get())->init(ctxInfo, gli);
|
|
|
| return true;
|
| }
|
| @@ -835,85 +775,6 @@ void GrGLCaps::initStencilFormats(const GrGLContextInfo& ctxInfo) {
|
| fStencilVerifiedColorConfigs.push_back_n(fStencilFormats.count());
|
| }
|
|
|
| -static GrGLenum precision_to_gl_float_type(GrSLPrecision p) {
|
| - switch (p) {
|
| - case kLow_GrSLPrecision:
|
| - return GR_GL_LOW_FLOAT;
|
| - case kMedium_GrSLPrecision:
|
| - return GR_GL_MEDIUM_FLOAT;
|
| - case kHigh_GrSLPrecision:
|
| - return GR_GL_HIGH_FLOAT;
|
| - }
|
| - SkFAIL("Unknown precision.");
|
| - return -1;
|
| -}
|
| -
|
| -static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
|
| - switch (type) {
|
| - case kVertex_GrShaderType:
|
| - return GR_GL_VERTEX_SHADER;
|
| - case kGeometry_GrShaderType:
|
| - return GR_GL_GEOMETRY_SHADER;
|
| - case kFragment_GrShaderType:
|
| - return GR_GL_FRAGMENT_SHADER;
|
| - }
|
| - SkFAIL("Unknown shader type.");
|
| - return -1;
|
| -}
|
| -
|
| -void GrGLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* intf) {
|
| - if (kGLES_GrGLStandard == ctxInfo.standard() || ctxInfo.version() >= GR_GL_VER(4,1) ||
|
| - ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
|
| - for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
| - if (kGeometry_GrShaderType != s) {
|
| - GrShaderType shaderType = static_cast<GrShaderType>(s);
|
| - GrGLenum glShader = shader_type_to_gl_shader(shaderType);
|
| - PrecisionInfo* first = NULL;
|
| - fShaderPrecisionVaries = false;
|
| - for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
| - GrSLPrecision precision = static_cast<GrSLPrecision>(p);
|
| - GrGLenum glPrecision = precision_to_gl_float_type(precision);
|
| - GrGLint range[2];
|
| - GrGLint bits;
|
| - GR_GL_GetShaderPrecisionFormat(intf, glShader, glPrecision, range, &bits);
|
| - if (bits) {
|
| - fFloatPrecisions[s][p].fLogRangeLow = range[0];
|
| - fFloatPrecisions[s][p].fLogRangeHigh = range[1];
|
| - fFloatPrecisions[s][p].fBits = bits;
|
| - if (!first) {
|
| - first = &fFloatPrecisions[s][p];
|
| - } else if (!fShaderPrecisionVaries) {
|
| - fShaderPrecisionVaries = (*first != fFloatPrecisions[s][p]);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - } else {
|
| - // We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
|
| - fShaderPrecisionVaries = false;
|
| - for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
| - if (kGeometry_GrShaderType != s) {
|
| - for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
| - fFloatPrecisions[s][p].fLogRangeLow = 127;
|
| - fFloatPrecisions[s][p].fLogRangeHigh = 127;
|
| - fFloatPrecisions[s][p].fBits = 23;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - // GetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Assume they're
|
| - // the same as the vertex shader. Only fragment shaders were ever allowed to omit support for
|
| - // highp. GS was added after GetShaderPrecisionFormat was added to the list of features that
|
| - // are recommended against.
|
| - if (fGeometryShaderSupport) {
|
| - for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
| - fFloatPrecisions[kGeometry_GrShaderType][p] = fFloatPrecisions[kVertex_GrShaderType][p];
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| void GrGLCaps::markColorConfigAndStencilFormatAsVerified(
|
| GrPixelConfig config,
|
| const GrGLStencilAttachment::Format& format) {
|
| @@ -1013,7 +874,6 @@ SkString GrGLCaps::dump() const {
|
|
|
| r.appendf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO"));
|
| r.appendf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]);
|
| - r.appendf("FB Fetch Support: %s\n", (fFBFetchSupport ? "YES" : "NO"));
|
| r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]);
|
| r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]);
|
| r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
|
| @@ -1038,6 +898,214 @@ SkString GrGLCaps::dump() const {
|
| r.appendf("Use non-VBO for dynamic data: %s\n",
|
| (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
|
| r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
|
| + return r;
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GrGLSLCaps::GrGLSLCaps() {
|
| + this->reset();
|
| +}
|
| +
|
| +
|
| +void GrGLSLCaps::reset() {
|
| + INHERITED::reset();
|
| +
|
| + fDropsTileOnZeroDivide = false;
|
| + fFBFetchSupport = false;
|
| + fFBFetchNeedsCustomOutput = false;
|
| + fFBFetchColorName = NULL;
|
| + fFBFetchExtensionString = NULL;
|
| +}
|
| +
|
| +GrGLSLCaps::GrGLSLCaps(const GrGLSLCaps& caps) : GrShaderCaps() {
|
| + *this = caps;
|
| +}
|
| +
|
| +GrGLSLCaps& GrGLSLCaps::operator= (const GrGLSLCaps& caps) {
|
| + INHERITED::operator=(caps);
|
| + fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
|
| + fFBFetchSupport = caps.fFBFetchSupport;
|
| + fFBFetchNeedsCustomOutput = caps.fFBFetchNeedsCustomOutput;
|
| + fFBFetchColorName = caps.fFBFetchColorName;
|
| + fFBFetchExtensionString = caps.fFBFetchExtensionString;
|
| +
|
| + return *this;
|
| +}
|
| +
|
| +bool GrGLSLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
| + this->reset();
|
| + if (!ctxInfo.isInitialized()) {
|
| + return false;
|
| + }
|
| +
|
| + 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");
|
| + 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");
|
| + }
|
| +
|
| + this->initShaderPrecisionTable(ctxInfo, gli);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +SkString GrGLSLCaps::dump() const {
|
| + SkString r = INHERITED::dump();
|
| +
|
| + r.appendf("--- GLSL-Specific ---\n");
|
| +
|
| + r.appendf("FB Fetch Support: %s\n", (fFBFetchSupport ? "YES" : "NO"));
|
| r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO"));
|
| return r;
|
| }
|
| +
|
| +static GrGLenum precision_to_gl_float_type(GrSLPrecision p) {
|
| + switch (p) {
|
| + case kLow_GrSLPrecision:
|
| + return GR_GL_LOW_FLOAT;
|
| + case kMedium_GrSLPrecision:
|
| + return GR_GL_MEDIUM_FLOAT;
|
| + case kHigh_GrSLPrecision:
|
| + return GR_GL_HIGH_FLOAT;
|
| + }
|
| + SkFAIL("Unknown precision.");
|
| + return -1;
|
| +}
|
| +
|
| +static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
|
| + switch (type) {
|
| + case kVertex_GrShaderType:
|
| + return GR_GL_VERTEX_SHADER;
|
| + case kGeometry_GrShaderType:
|
| + return GR_GL_GEOMETRY_SHADER;
|
| + case kFragment_GrShaderType:
|
| + return GR_GL_FRAGMENT_SHADER;
|
| + }
|
| + SkFAIL("Unknown shader type.");
|
| + return -1;
|
| +}
|
| +
|
| +void GrGLSLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo,
|
| + const GrGLInterface* intf) {
|
| + if (kGLES_GrGLStandard == ctxInfo.standard() || ctxInfo.version() >= GR_GL_VER(4, 1) ||
|
| + ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
|
| + for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
| + if (kGeometry_GrShaderType != s) {
|
| + GrShaderType shaderType = static_cast<GrShaderType>(s);
|
| + GrGLenum glShader = shader_type_to_gl_shader(shaderType);
|
| + PrecisionInfo* first = NULL;
|
| + fShaderPrecisionVaries = false;
|
| + for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
| + GrSLPrecision precision = static_cast<GrSLPrecision>(p);
|
| + GrGLenum glPrecision = precision_to_gl_float_type(precision);
|
| + GrGLint range[2];
|
| + GrGLint bits;
|
| + GR_GL_GetShaderPrecisionFormat(intf, glShader, glPrecision, range, &bits);
|
| + if (bits) {
|
| + fFloatPrecisions[s][p].fLogRangeLow = range[0];
|
| + fFloatPrecisions[s][p].fLogRangeHigh = range[1];
|
| + fFloatPrecisions[s][p].fBits = bits;
|
| + if (!first) {
|
| + first = &fFloatPrecisions[s][p];
|
| + }
|
| + else if (!fShaderPrecisionVaries) {
|
| + fShaderPrecisionVaries = (*first != fFloatPrecisions[s][p]);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + else {
|
| + // We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
|
| + fShaderPrecisionVaries = false;
|
| + for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
| + if (kGeometry_GrShaderType != s) {
|
| + for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
| + fFloatPrecisions[s][p].fLogRangeLow = 127;
|
| + fFloatPrecisions[s][p].fLogRangeHigh = 127;
|
| + fFloatPrecisions[s][p].fBits = 23;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + // GetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Assume they're
|
| + // the same as the vertex shader. Only fragment shaders were ever allowed to omit support for
|
| + // highp. GS was added after GetShaderPrecisionFormat was added to the list of features that
|
| + // are recommended against.
|
| + if (fGeometryShaderSupport) {
|
| + for (int p = 0; p < kGrSLPrecisionCount; ++p) {
|
| + fFloatPrecisions[kGeometry_GrShaderType][p] = fFloatPrecisions[kVertex_GrShaderType][p];
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +
|
| +
|
|
|