Implement multiple render target support in glBlitFramebufferANGLE.

TRAC #22679

Signed-off-by: Geoff Lang
Signed-off-by: Shannon Woods
Author: Jamie Madill

git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2095 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index f2f5607..24ed55f 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -2655,7 +2655,6 @@
                               GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                               GLbitfield mask)
 {
-    // TODO: mrt support for blit
     Framebuffer *readFramebuffer = getReadFramebuffer();
     Framebuffer *drawFramebuffer = getDrawFramebuffer();
 
@@ -2670,10 +2669,19 @@
         return gl::error(GL_INVALID_OPERATION);
     }
 
-    int readBufferWidth = readFramebuffer->getColorbuffer(0)->getWidth();
-    int readBufferHeight = readFramebuffer->getColorbuffer(0)->getHeight();
-    int drawBufferWidth = drawFramebuffer->getColorbuffer(0)->getWidth();
-    int drawBufferHeight = drawFramebuffer->getColorbuffer(0)->getHeight();
+    Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
+    Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorBuffer();
+
+    if (drawColorBuffer == NULL)
+    {
+        ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE");
+        return gl::error(GL_INVALID_OPERATION);
+    }
+
+    int readBufferWidth = readColorBuffer->getWidth();
+    int readBufferHeight = readColorBuffer->getHeight();
+    int drawBufferWidth = drawColorBuffer->getWidth();
+    int drawBufferHeight = drawColorBuffer->getHeight();
 
     Rectangle sourceRect;
     Rectangle destRect;
@@ -2832,12 +2840,29 @@
 
     if (mask & GL_COLOR_BUFFER_BIT)
     {
-        const bool validReadType = readFramebuffer->getColorbufferType(0) == GL_TEXTURE_2D ||
-            readFramebuffer->getColorbufferType(0) == GL_RENDERBUFFER;
-        const bool validDrawType = drawFramebuffer->getColorbufferType(0) == GL_TEXTURE_2D ||
-            drawFramebuffer->getColorbufferType(0) == GL_RENDERBUFFER;
-        if (!validReadType || !validDrawType ||
-            readFramebuffer->getColorbuffer(0)->getActualFormat() != drawFramebuffer->getColorbuffer(0)->getActualFormat())
+        const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
+        const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER);
+        bool validDrawType = true;
+        bool validDrawFormat = true;
+
+        for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+        {
+            if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
+            {
+                if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
+                    drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
+                {
+                    validDrawType = false;
+                }
+
+                if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
+                {
+                    validDrawFormat = false;
+                }
+            }
+        }
+
+        if (!validReadType || !validDrawType || !validDrawFormat)
         {
             ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
             return gl::error(GL_INVALID_OPERATION);
diff --git a/src/libGLESv2/Framebuffer.cpp b/src/libGLESv2/Framebuffer.cpp
index 98a38b1..2a91163 100644
--- a/src/libGLESv2/Framebuffer.cpp
+++ b/src/libGLESv2/Framebuffer.cpp
@@ -209,6 +209,12 @@
     return mColorbufferPointers[0].get();
 }
 
+GLenum Framebuffer::getReadColorbufferType() const
+{
+    // Will require more logic if glReadBuffers is supported
+    return mColorbufferTypes[0];
+}
+
 Renderbuffer *Framebuffer::getFirstColorBuffer() const
 {
     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
diff --git a/src/libGLESv2/Framebuffer.h b/src/libGLESv2/Framebuffer.h
index 9638e12..2160060 100644
--- a/src/libGLESv2/Framebuffer.h
+++ b/src/libGLESv2/Framebuffer.h
@@ -50,6 +50,7 @@
     Renderbuffer *getStencilbuffer() const;
     Renderbuffer *getDepthOrStencilbuffer() const;
     Renderbuffer *getReadColorbuffer() const;
+    GLenum getReadColorbufferType() const;
     Renderbuffer *getFirstColorBuffer() const;
 
     GLenum getColorbufferType(unsigned int colorAttachment) const;
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index e347677..e978c4e 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -2920,11 +2920,9 @@
 bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
                           bool blitRenderTarget, bool blitDepthStencil)
 {
-    // TODO: mrt blit support
     if (blitRenderTarget)
     {
         gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer();
-        gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(0);
 
         if (!readBuffer)
         {
@@ -2932,18 +2930,27 @@
             return gl::error(GL_OUT_OF_MEMORY, false);
         }
 
-        if (!drawBuffer)
-        {
-            ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
-        }
-
         RenderTarget *readRenderTarget = readBuffer->getRenderTarget();
-        RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
 
-        if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget))
+        for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
         {
-            return false;
+            if (drawTarget->isEnabledColorAttachment(colorAttachment))
+            {
+                gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
+
+                if (!drawBuffer)
+                {
+                    ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
+                    return gl::error(GL_OUT_OF_MEMORY, false);
+                }
+
+                RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
+
+                if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget))
+                {
+                    return false;
+                }
+            }
         }
     }