Implemented Renderer11::blitRect for render targets.

TRAC #22416

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

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1868 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 12e5627..c5d4612 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -2730,9 +2730,17 @@
 bool Renderer11::blitRect(gl::Framebuffer *readTarget, gl::Rectangle *readRect, gl::Framebuffer *drawTarget, gl::Rectangle *drawRect,
                           bool blitRenderTarget, bool blitDepthStencil)
 {
-    // TODO
-    UNIMPLEMENTED();
-    return false;
+    if (blitRenderTarget && !blitRect(readTarget, *readRect, drawTarget, *drawRect, BLIT_RENDERTARGET))
+    {
+        return false;
+    }
+
+    if (blitDepthStencil && !blitRect(readTarget, *readRect, drawTarget, *drawRect, BLIT_DEPTHSTENCIL))
+    {
+        return false;
+    }
+
+    return true;
 }
 
 void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
@@ -3155,6 +3163,125 @@
     stagingTex = NULL;
 }
 
+bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget,
+                          const gl::Rectangle &drawRect, BlitTarget target)
+{
+    ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
+
+    gl::Renderbuffer *readBuffer = NULL;
+    switch (target)
+    {
+      case BLIT_RENDERTARGET:
+        readBuffer = readTarget->getColorbuffer();
+        break;
+      case BLIT_DEPTHSTENCIL:
+        readBuffer = readTarget->getDepthOrStencilbuffer();
+        break;
+      default: UNREACHABLE();
+    }
+    if (!readBuffer)
+    {
+        ERR("Failed to retrieve the color buffer from the read target.");
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+    RenderTarget11 *sourceRenderTarget = NULL;
+    switch (target)
+    {
+      case BLIT_RENDERTARGET:
+        sourceRenderTarget = RenderTarget11::makeRenderTarget11(readBuffer->getRenderTarget());
+        break;
+      case BLIT_DEPTHSTENCIL:
+        sourceRenderTarget = RenderTarget11::makeRenderTarget11(readBuffer->getDepthStencil());
+        break;
+      default: UNREACHABLE();
+    }
+    if (!sourceRenderTarget)
+    {
+        ERR("Failed to retrieve the render target from the frame buffer.");
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+    ID3D11Texture2D *source = NULL;
+    unsigned int sourceSubresource = 0;
+    if (sourceRenderTarget->getSamples() > 0)
+    {
+        ID3D11Texture2D *unresolvedTexture = sourceRenderTarget->getTexture();
+
+        source = resolveMultisampledTexture(unresolvedTexture, sourceRenderTarget->getSubresourceIndex());
+        sourceSubresource = 0;
+
+        unresolvedTexture->Release();
+    }
+    else
+    {
+        source = sourceRenderTarget->getTexture();
+        sourceSubresource = sourceRenderTarget->getSubresourceIndex();
+    }
+
+    if (!source)
+    {
+        ERR("Failed to retrieve the render target view from the render target.");
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+
+    gl::Renderbuffer *drawBuffer = NULL;
+    switch (target)
+    {
+      case BLIT_RENDERTARGET:
+        drawBuffer = drawTarget->getColorbuffer();
+        break;
+      case BLIT_DEPTHSTENCIL:
+        drawBuffer = drawTarget->getDepthOrStencilbuffer();
+        break;
+      default: UNREACHABLE();
+    }
+    if (!drawBuffer)
+    {
+        source->Release();
+        ERR("Failed to retrieve the color buffer from the draw buffer.");
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+    RenderTarget11 *drawRenderTarget = NULL;
+    switch (target)
+    {
+      case BLIT_RENDERTARGET:
+        drawRenderTarget = RenderTarget11::makeRenderTarget11(drawBuffer->getRenderTarget());
+        break;
+      case BLIT_DEPTHSTENCIL:
+        drawRenderTarget = RenderTarget11::makeRenderTarget11(drawBuffer->getDepthStencil());
+        break;
+      default: UNREACHABLE();
+    }
+    if (!drawRenderTarget)
+    {
+        source->Release();
+        ERR("Failed to retrieve the render target from the render buffer.");
+        return error(GL_OUT_OF_MEMORY, false);
+    }
+
+    ID3D11Texture2D *dest = drawRenderTarget->getTexture();
+    unsigned int destSubresource = drawRenderTarget->getSubresourceIndex();
+
+    D3D11_BOX srcBox;
+    srcBox.left = readRect.x;
+    srcBox.right = readRect.x + readRect.width;
+    srcBox.top = readRect.y;
+    srcBox.bottom = readRect.y + readRect.height;
+    srcBox.front = 0;
+    srcBox.back = 1;
+
+    mDeviceContext->CopySubresourceRegion(dest, destSubresource, drawRect.x, drawRect.y, 0,
+                                          source, sourceSubresource, &srcBox);
+
+    source->Release();
+    dest->Release();
+
+    return true;
+}
+
 ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
 {
     D3D11_TEXTURE2D_DESC textureDesc;
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index 0c26112..45c38ad 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -179,6 +179,12 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer11);
 
+    enum BlitTarget
+    {
+        BLIT_RENDERTARGET,
+        BLIT_DEPTHSTENCIL,
+    };
+
     void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
     void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
 
@@ -188,6 +194,8 @@
 
     void maskedClear(const gl::ClearParameters &clearParams);
 
+    bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget,
+                  const gl::Rectangle &drawRect, BlitTarget target);
     ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
 
     HMODULE mD3d11Module;