From 6b0cf0273fdffbbdf69235b57b5b5a311e7f1ca6 Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Fri, 3 May 2013 13:35:14 +0000 Subject: [PATCH] Add support for GL_*_shader__framebuffer_fetch R=robertphillips@google.com Review URL: https://codereview.chromium.org/14875002 git-svn-id: http://skia.googlecode.com/svn/trunk@8980 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrDrawTarget.cpp | 3 ++- src/gpu/GrDrawTargetCaps.h | 2 ++ src/gpu/gl/GrGLCaps.cpp | 38 ++++++++++++++++++++++++++++++++------ src/gpu/gl/GrGLCaps.h | 16 ++++++++++++++++ src/gpu/gl/GrGLProgramDesc.cpp | 8 ++++++-- src/gpu/gl/GrGLShaderBuilder.cpp | 40 ++++++++++++++++++++++++++++++++++------ src/gpu/gl/GrGLShaderBuilder.h | 6 ++++-- 7 files changed, 96 insertions(+), 17 deletions(-) diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index aa876a0..7268015 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -407,7 +407,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, } bool GrDrawTarget::setupDstReadIfNecessary(DrawInfo* info) { - if (!this->getDrawState().willEffectReadDst()) { + if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDst()) { return true; } GrRenderTarget* rt = this->drawState()->getRenderTarget(); @@ -946,6 +946,7 @@ void GrDrawTargetCaps::print() const { GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]); GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); GrPrintf("Path Stenciling Support : %s\n", gNY[fPathStencilingSupport]); + GrPrintf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); GrPrintf("Max Texture Size : %d\n", fMaxTextureSize); GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize); GrPrintf("Max Sample Count : %d\n", fMaxSampleCount); diff --git a/src/gpu/GrDrawTargetCaps.h b/src/gpu/GrDrawTargetCaps.h index 35a05f9..236f939 100644 --- a/src/gpu/GrDrawTargetCaps.h +++ b/src/gpu/GrDrawTargetCaps.h @@ -35,6 +35,7 @@ public: bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; } bool bufferLockSupport() const { return fBufferLockSupport; } bool pathStencilingSupport() const { return fPathStencilingSupport; } + bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } int maxRenderTargetSize() const { return fMaxRenderTargetSize; } int maxTextureSize() const { return fMaxTextureSize; } @@ -52,6 +53,7 @@ protected: bool fDualSourceBlendingSupport : 1; bool fBufferLockSupport : 1; bool fPathStencilingSupport : 1; + bool fDstReadInShaderSupport : 1; int fMaxRenderTargetSize; int fMaxTextureSize; diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 8ec76a8..5568c48 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -24,6 +24,7 @@ void GrGLCaps::reset() { fStencilVerifiedColorConfigs.reset(); fMSFBOType = kNone_MSFBOType; fCoverageAAType = kNone_CoverageAAType; + fFBFetchType = kNone_FBFetchType; fMaxFragmentUniformVectors = 0; fMaxVertexAttributes = 0; fRGBA8RenderbufferSupport = false; @@ -60,6 +61,7 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) { fMSFBOType = caps.fMSFBOType; fCoverageAAType = caps.fCoverageAAType; fMSAACoverageModes = caps.fMSAACoverageModes; + fFBFetchType = caps.fFBFetchType; fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport; fBGRAFormatSupport = caps.fBGRAFormatSupport; fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat; @@ -205,6 +207,14 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { fVertexArrayObjectSupport = ctxInfo.hasExtension("GL_OES_vertex_array_object"); } + if (kES2_GrGLBinding == binding) { + if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) { + fFBFetchType = kEXT_FBFetchType; + } else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) { + fFBFetchType = kNV_FBFetchType; + } + } + this->initFSAASupport(ctxInfo, gli); this->initStencilFormats(ctxInfo); @@ -274,6 +284,8 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { fPathStencilingSupport = GR_GL_USE_NV_PATH_RENDERING && ctxInfo.hasExtension("GL_NV_path_rendering"); + fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType; + // Enable supported shader-related caps if (kDesktop_GrGLBinding == binding) { fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) || @@ -521,21 +533,35 @@ void GrGLCaps::print() const { fStencilFormats[i].fTotalBits); } + static const char* kMSFBOExtStr[] = { + "None", + "ARB", + "EXT", + "Apple", + "IMG MS To Texture", + "EXT MS To Texture", + }; GR_STATIC_ASSERT(0 == kNone_MSFBOType); GR_STATIC_ASSERT(1 == kDesktop_ARB_MSFBOType); GR_STATIC_ASSERT(2 == kDesktop_EXT_MSFBOType); GR_STATIC_ASSERT(3 == kES_Apple_MSFBOType); GR_STATIC_ASSERT(4 == kES_IMG_MsToTexture_MSFBOType); GR_STATIC_ASSERT(5 == kES_EXT_MsToTexture_MSFBOType); - static const char* gMSFBOExtStr[] = { + GR_STATIC_ASSERT(GR_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1); + + static const char* kFBFetchTypeStr[] = { "None", - "ARB", "EXT", - "Apple", - "IMG MS To Texture", - "EXT MS To Texture", + "NV", }; - GrPrintf("MSAA Type: %s\n", gMSFBOExtStr[fMSFBOType]); + GR_STATIC_ASSERT(0 == kNone_FBFetchType); + GR_STATIC_ASSERT(1 == kEXT_FBFetchType); + GR_STATIC_ASSERT(2 == kNV_FBFetchType); + GR_STATIC_ASSERT(GR_ARRAY_COUNT(kFBFetchTypeStr) == kLast_FBFetchType + 1); + + + GrPrintf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]); + GrPrintf("FB Fetch Type: %s\n", kFBFetchTypeStr[fFBFetchType]); GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors); GrPrintf("Max Vertex Attributes: %d\n", fMaxVertexAttributes); GrPrintf("Support RGBA8 Render Buffer: %s\n", (fRGBA8RenderbufferSupport ? "YES": "NO")); diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 1ce5fa6..23c53c6 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -77,6 +77,18 @@ public: * GL_MAX_SAMPLES value. */ kES_EXT_MsToTexture_MSFBOType, + + kLast_MSFBOType = kES_EXT_MsToTexture_MSFBOType + }; + + enum FBFetchType { + kNone_FBFetchType, + /** GL_EXT_shader_framebuffer_fetch */ + kEXT_FBFetchType, + /** GL_NV_shader_framebuffer_fetch */ + kNV_FBFetchType, + + kLast_FBFetchType = kNV_FBFetchType, }; enum CoverageAAType { @@ -184,6 +196,8 @@ public: */ const MSAACoverageMode& getMSAACoverageMode(int desiredSampleCount) const; + FBFetchType fbFetchType() const { return fFBFetchType; } + /** * Prints the caps info using GrPrintf. */ @@ -323,6 +337,8 @@ private: CoverageAAType fCoverageAAType; SkTDArray fMSAACoverageModes; + FBFetchType fFBFetchType; + bool fRGBA8RenderbufferSupport : 1; bool fBGRAFormatSupport : 1; bool fBGRAIsInternalFormat : 1; diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 8677179..1ae6aa6 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -96,8 +96,12 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, } if (readsDst) { - GrAssert(NULL != dstCopy); - desc->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstCopy->texture(), gpu->glCaps()); + GrAssert(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport()); + const GrTexture* dstCopyTexture = NULL; + if (NULL != dstCopy) { + dstCopyTexture = dstCopy->texture(); + } + desc->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps()); GrAssert(0 != desc->fDstRead); } else { desc->fDstRead = 0; diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index 752464c..b379c78 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -87,7 +87,7 @@ void append_swizzle(SkString* outAppend, } -static const char kDstColorName[] = "_dstColor"; +static const char kDstCopyColorName[] = "_dstColor"; /////////////////////////////////////////////////////////////////////////////// @@ -125,7 +125,9 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, } else { fLocalCoordsVar = fPositionVar; } - if (kNoDstRead_DstReadKey != desc.fDstRead) { + // Emit code to read the dst copy textue if necessary. + if (kNoDstRead_DstReadKey != desc.fDstRead && + GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) { bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & desc.fDstRead); const char* dstCopyTopLeftName; const char* dstCopyCoordScaleName; @@ -152,7 +154,7 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, if (!topDown) { this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); } - this->fsCodeAppendf("\tvec4 %s = ", kDstColorName); + this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); this->appendTextureLookup(kFragment_ShaderType, fDstCopySampler, "_dstTexCoord"); this->fsCodeAppend(";\n\n"); } @@ -186,6 +188,20 @@ bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) { "GL_ARB_fragment_coord_conventions"); } return true; + case kEXTShaderFramebufferFetch_GLSLPrivateFeature: + if (GrGLCaps::kEXT_FBFetchType != fCtxInfo.caps()->fbFetchType()) { + return false; + } + this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature, + "GL_EXT_shader_framebuffer_fetch"); + return true; + case kNVShaderFramebufferFetch_GLSLPrivateFeature: + if (GrGLCaps::kNV_FBFetchType != fCtxInfo.caps()->fbFetchType()) { + return false; + } + this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature, + "GL_NV_shader_framebuffer_fetch"); + return true; default: GrCrash("Unexpected GLSLPrivateFeature requested."); return false; @@ -199,9 +215,17 @@ void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionN } } -const char* GrGLShaderBuilder::dstColor() const { - if (fDstCopySampler.isInitialized()) { - return kDstColorName; +const char* GrGLShaderBuilder::dstColor() { + static const char kFBFetchColorName[] = "gl_LastFragData[0]"; + GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType(); + if (GrGLCaps::kEXT_FBFetchType == fetchType) { + SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature)); + return kFBFetchColorName; + } else if (GrGLCaps::kNV_FBFetchType == fetchType) { + SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature)); + return kFBFetchColorName; + } else if (fDstCopySampler.isInitialized()) { + return kDstCopyColorName; } else { return NULL; } @@ -290,6 +314,10 @@ GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess( GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps& caps) { uint32_t key = kYesDstRead_DstReadKeyBit; + if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) { + return key; + } + GrAssert(NULL != dstCopy); if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { // The fact that the config is alpha-only must be considered when generating code. key |= kUseAlphaConfig_DstReadKeyBit; diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h index ab093fb..9021a0d 100644 --- a/src/gpu/gl/GrGLShaderBuilder.h +++ b/src/gpu/gl/GrGLShaderBuilder.h @@ -259,7 +259,7 @@ public: /** Returns the color of the destination pixel. This may be NULL if no effect advertised that it will read the destination. */ - const char* dstColor() const; + const char* dstColor(); /** * Are explicit local coordinates provided as input to the vertex shader. @@ -346,7 +346,9 @@ private: * Features that should only be enabled by GrGLShaderBuilder itself. */ enum GLSLPrivateFeature { - kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1 + kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1, + kEXTShaderFramebufferFetch_GLSLPrivateFeature, + kNVShaderFramebufferFetch_GLSLPrivateFeature, }; bool enablePrivateFeature(GLSLPrivateFeature); -- 2.7.4