Add support for GL_*_shader__framebuffer_fetch
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 3 May 2013 13:35:14 +0000 (13:35 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 3 May 2013 13:35:14 +0000 (13:35 +0000)
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
src/gpu/GrDrawTargetCaps.h
src/gpu/gl/GrGLCaps.cpp
src/gpu/gl/GrGLCaps.h
src/gpu/gl/GrGLProgramDesc.cpp
src/gpu/gl/GrGLShaderBuilder.cpp
src/gpu/gl/GrGLShaderBuilder.h

index aa876a0..7268015 100644 (file)
@@ -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);
index 35a05f9..236f939 100644 (file)
@@ -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;
index 8ec76a8..5568c48 100644 (file)
@@ -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"));
index 1ce5fa6..23c53c6 100644 (file)
@@ -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<MSAACoverageMode> fMSAACoverageModes;
 
+    FBFetchType fFBFetchType;
+
     bool fRGBA8RenderbufferSupport : 1;
     bool fBGRAFormatSupport : 1;
     bool fBGRAIsInternalFormat : 1;
index 8677179..1ae6aa6 100644 (file)
@@ -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;
index 752464c..b379c78 100644 (file)
@@ -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;
index ab093fb..9021a0d 100644 (file)
@@ -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);