Add isMultisampled() to GrRenderTarget. Cleanup MSAA vs smooth lines logic in GrGpuGL.

Skia issue: 178

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



git-svn-id: http://skia.googlecode.com/svn/trunk@1067 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index c178ed6..6759654 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -164,11 +164,14 @@
      *                              id.
      * @param stencilBits           the number of stencil bits that the render
      *                              target has.
+     * @param isMultisampled        specify whether the render target is 
+     *                              multisampled.
      * @param width                 width of the render target.
      * @param height                height of the render target.
      */
     GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
                                                int stencilBits,
+                                               bool isMultisampled,
                                                int width, int height);
 
     /**
diff --git a/gpu/include/GrGLTexture.h b/gpu/include/GrGLTexture.h
index 7924cc3..94ae7b4 100644
--- a/gpu/include/GrGLTexture.h
+++ b/gpu/include/GrGLTexture.h
@@ -64,13 +64,14 @@
         GrGLuint      fTexFBOID;
         GrGLuint      fStencilRenderbufferID;
         GrGLuint      fMSColorRenderbufferID;
-        bool        fOwnIDs;
+        bool          fOwnIDs;
     };
 
     GrGLRenderTarget(GrGpuGL* gpu,
                      const GLRenderTargetIDs& ids,
                      GrGLTexID* texID,
                      GrGLuint stencilBits,
+                     bool isMultisampled,
                      const GrGLIRect& fViewport,
                      GrGLTexture* texture);
 
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index cbe3e95..ebf28b1 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -188,12 +188,14 @@
      *                              underlying 3D API. Interpretation depends on
      *                              GrGpu subclass in use.
      * @param stencilBits           number of stencil bits the target has
+     * @param isMultisampled        specify whether the RT is multisampled
      * @param width                 width of the render target
      * @param height                height of the render target
      */
     virtual GrRenderTarget* createPlatformRenderTarget(
                                                 intptr_t platformRenderTarget,
                                                 int stencilBits,
+                                                bool isMultisampled,
                                                 int width, int height);
 
     /**
@@ -486,6 +488,7 @@
     virtual GrRenderTarget* createPlatformRenderTargetHelper(
                                                 intptr_t platformRenderTarget,
                                                 int stencilBits,
+                                                bool isMultisampled,
                                                 int width, int height) = 0;
     virtual GrRenderTarget* createRenderTargetFrom3DApiStateHelper() = 0;
     virtual GrVertexBuffer* createVertexBufferHelper(uint32_t size,
diff --git a/gpu/include/GrTexture.h b/gpu/include/GrTexture.h
index 8f9952a..493bb8d 100644
--- a/gpu/include/GrTexture.h
+++ b/gpu/include/GrTexture.h
@@ -54,6 +54,11 @@
     GrTexture* asTexture() {return fTexture;}
 
     /**
+     * @return true if the render target is multisampled, false otherwise
+     */
+    bool isMultisampled() { return fIsMultisampled; }
+
+    /**
      * Reads a rectangle of pixels from the render target.
      * @param left          left edge of the rectangle to read (inclusive)
      * @param top           top edge of the rectangle to read (inclusive)
@@ -73,12 +78,14 @@
                    GrTexture* texture,
                    int width,
                    int height,
-                   int stencilBits)
+                   int stencilBits,
+                   bool isMultisampled)
         : INHERITED(gpu)
         , fTexture(texture)
         , fWidth(width)
         , fHeight(height)
         , fStencilBits(stencilBits)
+        , fIsMultisampled(isMultisampled)
     {}
 
     friend class GrTexture;
@@ -96,6 +103,7 @@
     int        fWidth;
     int        fHeight;
     int        fStencilBits;
+    bool       fIsMultisampled;
 
 private:
     // GrGpu keeps a cached clip in the render target to avoid redundantly
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index a0f5c51..b17a238 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -270,8 +270,10 @@
 GrRenderTarget* GrContext::createPlatformRenderTarget(
                                                 intptr_t platformRenderTarget,
                                                 int stencilBits,
+                                                bool isMultisampled,
                                                 int width, int height) {
     return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits,
+                                            isMultisampled,
                                             width, height);
 }
 
diff --git a/gpu/src/GrGLTexture.cpp b/gpu/src/GrGLTexture.cpp
index ce9345b..6a5a005 100644
--- a/gpu/src/GrGLTexture.cpp
+++ b/gpu/src/GrGLTexture.cpp
@@ -24,9 +24,11 @@
                                    const GLRenderTargetIDs& ids,
                                    GrGLTexID* texID,
                                    GrGLuint stencilBits,
+                                   bool isMultisampled,
                                    const GrGLIRect& viewport,
                                    GrGLTexture* texture)
-    : INHERITED(gpu, texture, viewport.fWidth, viewport.fHeight, stencilBits) {
+    : INHERITED(gpu, texture, viewport.fWidth, 
+                viewport.fHeight, stencilBits, isMultisampled) {
     fRTFBOID                = ids.fRTFBOID;
     fTexFBOID               = ids.fTexFBOID;
     fStencilRenderbufferID  = ids.fStencilRenderbufferID;
@@ -96,7 +98,6 @@
     }
 };
 
-
 GrGLTexture::GrGLTexture(GrGpuGL* gpu,
                          const GLTextureDesc& textureDesc,
                          const GLRenderTargetIDs& rtIDs,
@@ -131,6 +132,7 @@
 
         fRenderTarget = new GrGLRenderTarget(gpu, rtIDs, fTexIDObj,
                                              textureDesc.fStencilBits,
+                                             rtIDs.fRTFBOID != rtIDs.fTexFBOID,
                                              vp, this);
     }
 }
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 06de3ac..4aaed79 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -144,10 +144,12 @@
 
 GrRenderTarget* GrGpu::createPlatformRenderTarget(intptr_t platformRenderTarget,
                                                   int stencilBits,
+                                                  bool isMultisampled,
                                                   int width, int height) {
     this->handleDirtyContext();
     return this->createPlatformRenderTargetHelper(platformRenderTarget,
                                                   stencilBits,
+                                                  isMultisampled,
                                                   width, height);
 }
 
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index e5f9fa2..a9e0e1d 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -481,6 +481,8 @@
         GR_GL(Disable(GR_GL_LINE_SMOOTH));
         GR_GL(Disable(GR_GL_POINT_SMOOTH));
         GR_GL(Disable(GR_GL_MULTISAMPLE));
+        fHWAAState.fMSAAEnabled = false;
+        fHWAAState.fSmoothLineEnabled = false;
     }
 
     GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
@@ -534,6 +536,7 @@
 GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
                                                 intptr_t platformRenderTarget,
                                                 int stencilBits,
+                                                bool isMultisampled,
                                                 int width,
                                                 int height) {
     GrGLRenderTarget::GLRenderTargetIDs rtIDs;
@@ -552,7 +555,8 @@
     rtIDs.fRTFBOID  = (GrGLuint)platformRenderTarget;
     rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
 
-    return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, viewport, NULL);
+    return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, 
+                                isMultisampled, viewport, NULL);
 }
 
 GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
@@ -569,9 +573,13 @@
     GrGLuint stencilBits;
     GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
 
+    GrGLint samples;
+    GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
+
     rtIDs.fOwnIDs = false;
 
-    return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, viewport, NULL);
+    return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, 
+                                (samples > 0), viewport, NULL);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1518,6 +1526,42 @@
     }
 }
 
+void GrGpuGL::flushAAState(GrPrimitiveType type) {
+    if (GR_GL_SUPPORT_DESKTOP) {
+        // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
+        // smooth lines.
+
+        // we prefer smooth lines over multisampled lines
+        // msaa should be disabled if drawing smooth lines.
+        if (kLines_PrimitiveType == type) {
+            if (!fHWAAState.fSmoothLineEnabled && 
+                (kAntialias_StateBit & fCurrDrawState.fFlagBits)) {
+                GR_GL(Enable(GR_GL_LINE_SMOOTH));
+                fHWAAState.fSmoothLineEnabled = true;
+            } else if (fHWAAState.fSmoothLineEnabled && 
+                       !(kAntialias_StateBit & fCurrDrawState.fFlagBits)) {
+                GR_GL(Disable(GR_GL_LINE_SMOOTH));
+                fHWAAState.fSmoothLineEnabled = false;
+            }
+            if (fCurrDrawState.fRenderTarget->isMultisampled() && 
+                fHWAAState.fMSAAEnabled) {
+                GR_GL(Disable(GR_GL_MULTISAMPLE));
+                fHWAAState.fMSAAEnabled = false;
+            }
+        } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
+                   !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
+                   fHWAAState.fMSAAEnabled) {
+            if (fHWAAState.fMSAAEnabled) {
+                GR_GL(Disable(GR_GL_MULTISAMPLE));
+                fHWAAState.fMSAAEnabled = false;
+            } else {
+                GR_GL(Enable(GR_GL_MULTISAMPLE));
+                fHWAAState.fMSAAEnabled = true;
+            }
+        }
+    }
+}
+
 bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
 
     // GrGpu::setupClipAndFlushState should have already checked this
@@ -1595,6 +1639,8 @@
 
     flushRenderTarget();
 
+    flushAAState(type);
+
     if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
         (fHWDrawState.fFlagBits & kDither_StateBit)) {
         if (fCurrDrawState.fFlagBits & kDither_StateBit) {
@@ -1615,34 +1661,6 @@
         GR_GL(ColorMask(mask, mask, mask, mask));
     }
 
-    if (GR_GL_SUPPORT_DESKTOP) {
-        // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
-        // smooth lines.
-        if (fDirtyFlags.fRenderTargetChanged ||
-            (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
-            (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
-            GrGLint msaa = 0;
-            // only perform query if we know MSAA is supported.
-            // calling on non-MSAA target caused a crash in one environment,
-            // though I don't think it should.
-            if (fAASamples[kHigh_AALevel]) {
-                GR_GL_GetIntegerv(GR_GL_SAMPLE_BUFFERS, &msaa);
-            }
-            if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
-                if (msaa) {
-                    GR_GL(Enable(GR_GL_MULTISAMPLE));
-                } else {
-                    GR_GL(Enable(GR_GL_LINE_SMOOTH));
-                }
-            } else {
-                if (msaa) {
-                    GR_GL(Disable(GR_GL_MULTISAMPLE));
-                }
-                GR_GL(Disable(GR_GL_LINE_SMOOTH));
-            }
-        }
-    }
-
     bool blendOff = canDisableBlend();
     if (fHWBlendDisabled != blendOff) {
         if (blendOff) {
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 3eedabf..6d600e0 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -39,6 +39,11 @@
         bool                    fArrayPtrsDirty;
     } fHWGeometryState;
 
+    struct AAState {
+        bool fMSAAEnabled;
+        bool fSmoothLineEnabled;
+    } fHWAAState;
+
     DrState   fHWDrawState;
     bool      fHWStencilClip;
 
@@ -78,6 +83,7 @@
     virtual GrRenderTarget* createPlatformRenderTargetHelper(
                                                  intptr_t platformRenderTarget,
                                                  int stencilBits,
+                                                 bool isMultisampled,
                                                  int width, int height);
 
     virtual GrRenderTarget* createRenderTargetFrom3DApiStateHelper();
@@ -147,6 +153,7 @@
 
     void flushRenderTarget();
     void flushStencil();
+    void flushAAState(GrPrimitiveType type);
     void resolveTextureRenderTarget(GrGLTexture* texture);
 
     bool canBeTexture(GrPixelConfig config,