Add support for GL_NV_framebuffer_multisample_coverage

Review URL: http://codereview.appspot.com/6005043


git-svn-id: http://skia.googlecode.com/svn/trunk@3651 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 5361967..c7e9380 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -9,6 +9,7 @@
 
 #include "GrGLCaps.h"
 #include "GrGLContextInfo.h"
+#include "SkTSearch.h"
 
 GrGLCaps::GrGLCaps() {
     this->reset();
@@ -19,6 +20,7 @@
     fStencilFormats.reset();
     fStencilVerifiedColorConfigs.reset();
     fMSFBOType = kNone_MSFBOType;
+    fCoverageAAType = kNone_CoverageAAType;
     fMaxFragmentUniformVectors = 0;
     fRGBA8RenderbufferSupport = false;
     fBGRAFormatSupport = false;
@@ -43,6 +45,8 @@
     fStencilVerifiedColorConfigs = caps.fStencilVerifiedColorConfigs;
     fMaxFragmentUniformVectors = caps.fMaxFragmentUniformVectors;
     fMSFBOType = caps.fMSFBOType;
+    fCoverageAAType = caps.fCoverageAAType;
+    fMSAACoverageModes = caps.fMSAACoverageModes;
     fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport;
     fBGRAFormatSupport = caps.fBGRAFormatSupport;
     fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat;
@@ -143,6 +147,22 @@
     this->initStencilFormats(ctxInfo);
 }
 
+namespace {
+int coverage_mode_compare(const GrGLCaps::MSAACoverageMode* left,
+                          const GrGLCaps::MSAACoverageMode* right) {
+    if (left->fCoverageSampleCnt < right->fCoverageSampleCnt) {
+        return -1;
+    } else if (right->fCoverageSampleCnt < left->fCoverageSampleCnt) {
+        return 1;
+    } else if (left->fColorSampleCnt < right->fColorSampleCnt) {
+        return -1;
+    } else if (right->fColorSampleCnt < left->fColorSampleCnt) {
+        return 1;
+    }
+    return 0;
+}
+}
+
 void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo) {
 
     fMSFBOType = kNone_MSFBOType;
@@ -152,8 +172,8 @@
            // and fbo_blit extensions.
            fMSFBOType = kDesktopEXT_MSFBOType;
        } else if (ctxInfo.hasExtension("GL_APPLE_framebuffer_multisample")) {
-            fMSFBOType = kAppleES_MSFBOType;
-        }
+           fMSFBOType = kAppleES_MSFBOType;
+       }
     } else {
         if ((ctxInfo.version() >= GR_GL_VER(3,0)) ||
             ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
@@ -162,6 +182,52 @@
                    ctxInfo.hasExtension("GL_EXT_framebuffer_blit")) {
             fMSFBOType = GrGLCaps::kDesktopEXT_MSFBOType;
         }
+        // TODO: We could populate fMSAACoverageModes using GetInternalformativ
+        // on GL 4.2+. It's format-specific, though. See also
+        // http://code.google.com/p/skia/issues/detail?id=470 about using actual
+        // rather than requested sample counts in cache key.
+        if (ctxInfo.hasExtension("GL_NV_framebuffer_multisample_coverage")) {
+            fCoverageAAType = kNVDesktop_CoverageAAType;
+            GrGLint count;
+            GR_GL_GetIntegerv(ctxInfo.interface(),
+                              GR_GL_MAX_MULTISAMPLE_COVERAGE_MODES,
+                              &count);
+            fMSAACoverageModes.setCount(count);
+            GR_GL_GetIntegerv(ctxInfo.interface(),
+                              GR_GL_MULTISAMPLE_COVERAGE_MODES,
+                              (int*)&fMSAACoverageModes[0]);
+            // The NV driver seems to return the modes already sorted but the
+            // spec doesn't require this. So we sort.
+            SkQSortCompareProc compareProc =
+                reinterpret_cast<SkQSortCompareProc>(&coverage_mode_compare);
+            SkQSort(&fMSAACoverageModes[0],
+                    count,
+                    sizeof(MSAACoverageMode),
+                    compareProc);
+        }
+    }
+}
+
+const GrGLCaps::MSAACoverageMode& GrGLCaps::getMSAACoverageMode(
+                                            int desiredSampleCount) const {
+    static const MSAACoverageMode kNoneMode = {0, 0};
+    if (0 == fMSAACoverageModes.count()) {
+        return kNoneMode;
+    } else {
+        GrAssert(kNone_CoverageAAType != fCoverageAAType);
+        int max = (fMSAACoverageModes.end() - 1)->fCoverageSampleCnt;
+        desiredSampleCount = GrMin(desiredSampleCount, max);
+        MSAACoverageMode desiredMode = {desiredSampleCount, 0};
+        int idx = SkTSearch<MSAACoverageMode>(&fMSAACoverageModes[0],
+                                              fMSAACoverageModes.count(),
+                                              desiredMode,
+                                              sizeof(MSAACoverageMode),
+                                              &coverage_mode_compare);
+        if (idx < 0) {
+            idx = ~idx;
+        }
+        GrAssert(idx >= 0 && idx < fMSAACoverageModes.count());
+        return fMSAACoverageModes[idx];
     }
 }