Add support for IMG's MSAA extension.
Review URL: https://codereview.chromium.org/12875005

git-svn-id: http://skia.googlecode.com/svn/trunk@8241 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 8882934..e202a14 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -285,11 +285,12 @@
         caps->fGeometryShaderSupport = this->glVersion() >= GR_GL_VER(3,2) &&
                                        this->glslGeneration() >= k150_GrGLSLGeneration;
     } else {
-        caps->fShaderDerivativeSupport =
-                            this->hasExtension("GL_OES_standard_derivatives");
+        caps->fShaderDerivativeSupport = this->hasExtension("GL_OES_standard_derivatives");
     }
 
-    if (GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType()) {
+    if (GrGLCaps::kImaginationES_MSFBOType == this->glCaps().msFBOType()) {
+        GR_GL_GetIntegerv(this->glInterface(), GR_GL_MAX_SAMPLES_IMG, &caps->fMaxSampleCount);
+    } else if (GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType()) {
         GR_GL_GetIntegerv(this->glInterface(), GR_GL_MAX_SAMPLES, &caps->fMaxSampleCount);
     }
 }
@@ -879,9 +880,11 @@
     }
 
 
-    // If we are using multisampling we will create two FBOS. We render
-    // to one and then resolve to the texture bound to the other.
-    if (desc->fSampleCnt > 0) {
+    // If we are using multisampling we will create two FBOS. We render to one and then resolve to
+    // the texture bound to the other. The exception is the IMG multisample extension. With this
+    // extension the texture is multisampled when rendered to and then auto-resolves it when it is
+    // rendered from.
+    if (desc->fSampleCnt > 0 && GrGLCaps::kImaginationES_MSFBOType != this->glCaps().msFBOType()) {
         if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
             goto FAILED;
         }
@@ -921,16 +924,22 @@
             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
                 goto FAILED;
             }
-            fGLContext.info().caps().markConfigAsValidColorAttachment(
-                                                                desc->fConfig);
+            fGLContext.info().caps().markConfigAsValidColorAttachment(desc->fConfig);
         }
     }
     GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID));
 
-    GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
-                                 GR_GL_COLOR_ATTACHMENT0,
-                                 GR_GL_TEXTURE_2D,
-                                 texID, 0));
+    if (GrGLCaps::kImaginationES_MSFBOType == this->glCaps().msFBOType() && desc->fSampleCnt > 0) {
+        GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
+                                                GR_GL_COLOR_ATTACHMENT0,
+                                                GR_GL_TEXTURE_2D,
+                                                texID, 0, desc->fSampleCnt));
+    } else {
+        GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
+                                     GR_GL_COLOR_ATTACHMENT0,
+                                     GR_GL_TEXTURE_2D,
+                                     texID, 0));
+    }
     if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) {
         GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
         if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
@@ -1172,8 +1181,7 @@
     return false;
 }
 
-bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb,
-                                                GrRenderTarget* rt) {
+bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget* rt) {
     GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt;
 
     GrGLuint fbo = glrt->renderFBOID();
@@ -1181,11 +1189,11 @@
     if (NULL == sb) {
         if (NULL != rt->getStencilBuffer()) {
             GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
-                                          GR_GL_STENCIL_ATTACHMENT,
-                                          GR_GL_RENDERBUFFER, 0));
+                                            GR_GL_STENCIL_ATTACHMENT,
+                                            GR_GL_RENDERBUFFER, 0));
             GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
-                                          GR_GL_DEPTH_ATTACHMENT,
-                                          GR_GL_RENDERBUFFER, 0));
+                                            GR_GL_DEPTH_ATTACHMENT,
+                                            GR_GL_RENDERBUFFER, 0));
 #if GR_DEBUG
             GrGLenum status;
             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
@@ -1194,27 +1202,26 @@
         }
         return true;
     } else {
-        GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb;
+        GrGLStencilBuffer* glsb = static_cast<GrGLStencilBuffer*>(sb);
         GrGLuint rb = glsb->renderbufferID();
 
         fHWBoundRenderTarget = NULL;
         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
-                                      GR_GL_STENCIL_ATTACHMENT,
-                                      GR_GL_RENDERBUFFER, rb));
+                                        GR_GL_STENCIL_ATTACHMENT,
+                                        GR_GL_RENDERBUFFER, rb));
         if (glsb->format().fPacked) {
             GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
-                                          GR_GL_DEPTH_ATTACHMENT,
-                                          GR_GL_RENDERBUFFER, rb));
+                                            GR_GL_DEPTH_ATTACHMENT,
+                                            GR_GL_RENDERBUFFER, rb));
         } else {
             GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
-                                          GR_GL_DEPTH_ATTACHMENT,
-                                          GR_GL_RENDERBUFFER, 0));
+                                            GR_GL_DEPTH_ATTACHMENT,
+                                            GR_GL_RENDERBUFFER, 0));
         }
 
         GrGLenum status;
-        if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(),
-                                                           glsb->format())) {
+        if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(), glsb->format())) {
             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
                 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
@@ -1767,47 +1774,45 @@
 }
 
 void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
-
     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
-
     if (rt->needsResolve()) {
-        GrAssert(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType());
-        GrAssert(rt->textureFBOID() != rt->renderFBOID());
-        GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
-                                rt->renderFBOID()));
-        GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
-                                rt->textureFBOID()));
-        // make sure we go through flushRenderTarget() since we've modified
-        // the bound DRAW FBO ID.
-        fHWBoundRenderTarget = NULL;
-        const GrGLIRect& vp = rt->getViewport();
-        const GrIRect dirtyRect = rt->getResolveRect();
-        GrGLIRect r;
-        r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
-                        dirtyRect.width(), dirtyRect.height(), target->origin());
+        // The IMG extension automatically resolves the texture when it is read.
+        if (GrGLCaps::kImaginationES_MSFBOType != this->glCaps().msFBOType()) {
+            GrAssert(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType());
+            GrAssert(rt->textureFBOID() != rt->renderFBOID());
+            GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID()));
+            GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID()));
+            // make sure we go through flushRenderTarget() since we've modified
+            // the bound DRAW FBO ID.
+            fHWBoundRenderTarget = NULL;
+            const GrGLIRect& vp = rt->getViewport();
+            const GrIRect dirtyRect = rt->getResolveRect();
+            GrGLIRect r;
+            r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
+                            dirtyRect.width(), dirtyRect.height(), target->origin());
 
-        GrAutoTRestore<ScissorState> asr;
-        if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {
-            // Apple's extension uses the scissor as the blit bounds.
-            asr.reset(&fScissorState);
-            fScissorState.fEnabled = true;
-            fScissorState.fRect = dirtyRect;
-            this->flushScissor();
-            GL_CALL(ResolveMultisampleFramebuffer());
-        } else {
-            if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) {
-                // this respects the scissor during the blit, so disable it.
-                GrAssert(GrGLCaps::kDesktopEXT_MSFBOType ==
-                         this->glCaps().msFBOType());
+            GrAutoTRestore<ScissorState> asr;
+            if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {
+                // Apple's extension uses the scissor as the blit bounds.
                 asr.reset(&fScissorState);
-                fScissorState.fEnabled = false;
+                fScissorState.fEnabled = true;
+                fScissorState.fRect = dirtyRect;
                 this->flushScissor();
+                GL_CALL(ResolveMultisampleFramebuffer());
+            } else {
+                if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) {
+                    // this respects the scissor during the blit, so disable it.
+                    GrAssert(GrGLCaps::kDesktopEXT_MSFBOType == this->glCaps().msFBOType());
+                    asr.reset(&fScissorState);
+                    fScissorState.fEnabled = false;
+                    this->flushScissor();
+                }
+                int right = r.fLeft + r.fWidth;
+                int top = r.fBottom + r.fHeight;
+                GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
+                                        r.fLeft, r.fBottom, right, top,
+                                        GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
             }
-            int right = r.fLeft + r.fWidth;
-            int top = r.fBottom + r.fHeight;
-            GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
-                                    r.fLeft, r.fBottom, right, top,
-                                    GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
         }
         rt->flagAsResolved();
     }