separate state for msaa renderability

R=robertphillips@google.com, brian@thesalomons.net

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/26695005

git-svn-id: http://skia.googlecode.com/svn/trunk@11770 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 973185c..7716f9a 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -286,7 +286,7 @@
     /**
      * Can the provided configuration act as a color render target?
      */
-    bool isConfigRenderable(GrPixelConfig config) const;
+    bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const;
 
     /**
      * Return the max width or height of a render target supported by the
diff --git a/src/effects/SkBitmapAlphaThresholdShader.cpp b/src/effects/SkBitmapAlphaThresholdShader.cpp
index 69e22c9..6f1c94a 100644
--- a/src/effects/SkBitmapAlphaThresholdShader.cpp
+++ b/src/effects/SkBitmapAlphaThresholdShader.cpp
@@ -218,7 +218,7 @@
     }
 
     GrTextureDesc maskDesc;
-    if (context->isConfigRenderable(kAlpha_8_GrPixelConfig)) {
+    if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
         maskDesc.fConfig = kAlpha_8_GrPixelConfig;
     } else {
         maskDesc.fConfig = kRGBA_8888_GrPixelConfig;
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 3709acf..bfca12f 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -406,7 +406,7 @@
         desc.fWidth = clipSpaceIBounds.width();
         desc.fHeight = clipSpaceIBounds.height();
         desc.fConfig = kRGBA_8888_GrPixelConfig;
-        if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig)) {
+        if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
             // We would always like A8 but it isn't supported on all platforms
             desc.fConfig = kAlpha_8_GrPixelConfig;
         }
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 66a86f3..dd45b25 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1687,9 +1687,8 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-
-bool GrContext::isConfigRenderable(GrPixelConfig config) const {
-    return fGpu->caps()->isConfigRenderable(config);
+bool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
+    return fGpu->caps()->isConfigRenderable(config, withMSAA);
 }
 
 static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index c33dcb7..9f35065 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -1047,7 +1047,10 @@
     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig]);
     for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
         if (i != kUnknown_GrPixelConfig) {
-            GrPrintf("%s is renderable: %s\n", kConfigNames[i], gNY[fConfigRenderSupport[i]]);
+            GrPrintf("%s is renderable: %s, with MSAA: %s\n",
+                     kConfigNames[i],
+                     gNY[fConfigRenderSupport[i][0]],
+                     gNY[fConfigRenderSupport[i][1]]);
         }
     }
 }
diff --git a/src/gpu/GrDrawTargetCaps.h b/src/gpu/GrDrawTargetCaps.h
index 11347e3..b0a721c 100644
--- a/src/gpu/GrDrawTargetCaps.h
+++ b/src/gpu/GrDrawTargetCaps.h
@@ -44,12 +44,9 @@
     // Will be 0 if MSAA is not supported
     int maxSampleCount() const { return fMaxSampleCount; }
 
-    /**
-     * Can the provided configuration act as a render target?
-     */
-    bool isConfigRenderable(GrPixelConfig config) const {
+    bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
         SkASSERT(kGrPixelConfigCnt > config);
-        return fConfigRenderSupport[config];
+        return fConfigRenderSupport[config][withMSAA];
     }
 
 protected:
@@ -70,7 +67,8 @@
     int fMaxTextureSize;
     int fMaxSampleCount;
 
-    bool fConfigRenderSupport[kGrPixelConfigCnt];
+    // The first entry for each config is without msaa and the second is with.
+    bool fConfigRenderSupport[kGrPixelConfigCnt][2];
 
     typedef SkRefCnt INHERITED;
 };
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 42b82f6..cd217f4 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -113,6 +113,10 @@
     if (kUnknown_GrPixelConfig == desc.fConfig) {
         return NULL;
     }
+    if ((desc.fFlags & kRenderTarget_GrTextureFlagBit) &&
+        !this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
+        return NULL;
+    }
 
     this->handleDirtyContext();
     GrTexture* tex = this->onCreateTexture(desc, srcData, rowBytes);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 8cf2e4b..d9aab02 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -847,7 +847,7 @@
     // We actually only need A8, but it often isn't supported as a
     // render target so default to RGBA_8888
     desc.fConfig = kRGBA_8888_GrPixelConfig;
-    if (context->isConfigRenderable(kAlpha_8_GrPixelConfig)) {
+    if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
         desc.fConfig = kAlpha_8_GrPixelConfig;
     }
 
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index eb0b245..a96526a 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -368,32 +368,54 @@
     // Same as ES 2.0 except R8 and RGBA8 are supported without extensions (the functions called
     // below already account for this).
 
+    enum {
+        kNo_MSAA = 0,
+        kYes_MSAA = 1,
+    };
+
     if (kDesktop_GrGLBinding == ctxInfo.binding()) {
         // Post 3.0 we will get R8
         // Prior to 3.0 we will get ALPHA8 (with GL_ARB_framebuffer_object)
         if (ctxInfo.version() >= GR_GL_VER(3,0) ||
             ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
-            fConfigRenderSupport[kAlpha_8_GrPixelConfig] = true;
+            fConfigRenderSupport[kAlpha_8_GrPixelConfig][kNo_MSAA] = true;
+            fConfigRenderSupport[kAlpha_8_GrPixelConfig][kYes_MSAA] = true;
         }
     } else {
         // On ES we can only hope for R8
-        fConfigRenderSupport[kAlpha_8_GrPixelConfig] = fTextureRedSupport;
+        fConfigRenderSupport[kAlpha_8_GrPixelConfig][kNo_MSAA] = fTextureRedSupport;
+        fConfigRenderSupport[kAlpha_8_GrPixelConfig][kYes_MSAA] = fTextureRedSupport;
     }
 
     if (kDesktop_GrGLBinding != ctxInfo.binding()) {
         // only available in ES
-        fConfigRenderSupport[kRGB_565_GrPixelConfig] = true;
+        fConfigRenderSupport[kRGB_565_GrPixelConfig][kNo_MSAA] = true;
+        fConfigRenderSupport[kRGB_565_GrPixelConfig][kYes_MSAA] = true;
     }
 
     // we no longer support 444 as a render target
-    fConfigRenderSupport[kRGBA_4444_GrPixelConfig] = false;
+    fConfigRenderSupport[kRGBA_4444_GrPixelConfig][kNo_MSAA]  = false;
+    fConfigRenderSupport[kRGBA_4444_GrPixelConfig][kYes_MSAA]  = false;
 
     if (this->fRGBA8RenderbufferSupport) {
-        fConfigRenderSupport[kRGBA_8888_GrPixelConfig] = true;
+        fConfigRenderSupport[kRGBA_8888_GrPixelConfig][kNo_MSAA]  = true;
+        fConfigRenderSupport[kRGBA_4444_GrPixelConfig][kYes_MSAA]  = false;
     }
 
     if (this->fBGRAFormatSupport) {
-        fConfigRenderSupport[kBGRA_8888_GrPixelConfig] = true;
+        fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kNo_MSAA]  = true;
+        // The GL_EXT_texture_format_BGRA8888 extension does not add BGRA to the list of
+        // configs that are color-renderable and can be passed to glRenderBufferStorageMultisample.
+        fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] =
+            !fBGRAIsInternalFormat || !this->usesMSAARenderBuffers();
+    }
+
+    // If we don't support MSAA then undo any places above where we set a config as renderable with
+    // msaa.
+    if (kNone_MSFBOType == fMSFBOType) {
+        for (int i = 0; i < kGrPixelConfigCnt; ++i) {
+            fConfigRenderSupport[i][kYes_MSAA] = false;
+        }
     }
 }
 
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 548e7f7..81391ec 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -288,6 +288,7 @@
 
     void initFSAASupport(const GrGLContextInfo&, const GrGLInterface*);
     void initStencilFormats(const GrGLContextInfo&);
+    // This must be called after initFSAASupport().
     void initConfigRenderableTable(const GrGLContextInfo&);
 
     // tracks configs that have been verified to pass the FBO completeness when
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 5845066..f0815a6 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -2398,8 +2398,8 @@
                                  const GrSurface* src,
                                  const GrGpuGL* gpu,
                                  bool* wouldNeedTempFBO = NULL) {
-    if (gpu->glCaps().isConfigRenderable(dst->config()) &&
-        gpu->glCaps().isConfigRenderable(src->config()) &&
+    if (gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) &&
+        gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) &&
         gpu->glCaps().usesMSAARenderBuffers()) {
         // ES3 doesn't allow framebuffer blits when the src has MSAA and the configs don't match
         // or the rects are not the same (not just the same size but have the same edges).
@@ -2439,8 +2439,10 @@
     if (NULL != srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) {
         return false;
     }
-    if (gpu->glCaps().isConfigRenderable(src->config()) && NULL != dst->asTexture() &&
-        dst->origin() == src->origin() && kIndex_8_GrPixelConfig != src->config()) {
+    if (gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) &&
+        NULL != dst->asTexture() &&
+        dst->origin() == src->origin() &&
+        kIndex_8_GrPixelConfig != src->config()) {
         if (NULL != wouldNeedTempFBO) {
             *wouldNeedTempFBO = NULL == src->asRenderTarget();
         }