Moves copyToRenderTarget operation into texture storage object.

TRAC #21910

Signed-off-by: Daniel Koch

Author:    Shannon Woods

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1373 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/TextureStorage.cpp b/src/libGLESv2/renderer/TextureStorage.cpp
index 2b10ae8..a2afc3c 100644
--- a/src/libGLESv2/renderer/TextureStorage.cpp
+++ b/src/libGLESv2/renderer/TextureStorage.cpp
@@ -153,6 +153,50 @@
     return mLodOffset;
 }
 
+int TextureStorage::levelCount()
+{
+    return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0;
+}
+
+bool TextureStorage::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+{
+    if (source && dest)
+    {
+        HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
+        renderer::Renderer9 *renderer = getDisplay()->getRenderer();
+        IDirect3DDevice9 *device = renderer->getDevice(); // D3D9_REPLACE
+
+        if (fromManaged)
+        {
+            D3DSURFACE_DESC desc;
+            source->GetDesc(&desc);
+
+            IDirect3DSurface9 *surf = 0;
+            result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+
+            if (SUCCEEDED(result))
+            {
+                Image::CopyLockableSurfaces(surf, source);
+                result = device->UpdateSurface(surf, NULL, dest, NULL);
+                surf->Release();
+            }
+        }
+        else
+        {
+            renderer->endScene();
+            result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+        }
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return false;
+        }
+    }
+
+    return true;
+} 
+
 TextureStorage2D::TextureStorage2D(renderer::SwapChain *swapchain) : TextureStorage(D3DUSAGE_RENDERTARGET), mRenderTargetSerial(RenderbufferStorage::issueSerial())
 {
     IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
@@ -189,6 +233,31 @@
     }
 }
 
+bool TextureStorage2D::copyToRenderTarget(TextureStorage2D *dest, TextureStorage2D *source)
+{
+    bool result = false;
+
+    if (source && dest)
+    {
+        int levels = source->levelCount();
+        for (int i = 0; i < levels; ++i)
+        {
+            IDirect3DSurface9 *srcSurf = source->getSurfaceLevel(i, false);
+            IDirect3DSurface9 *dstSurf = dest->getSurfaceLevel(i, false);
+            
+            result = TextureStorage::copyToRenderTarget(dstSurf, srcSurf, source->isManaged());
+
+            if (srcSurf) srcSurf->Release();
+            if (dstSurf) dstSurf->Release();
+
+            if (!result)
+                return false;
+        }
+    }
+
+    return result;
+}
+
 // Increments refcount on surface.
 // caller must Release() the returned surface
 IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level, bool dirty)
@@ -251,6 +320,34 @@
     }
 }
 
+bool TextureStorageCubeMap::copyToRenderTarget(TextureStorageCubeMap *dest, TextureStorageCubeMap *source)
+{
+    bool result = false;
+
+    if (source && dest)
+    {
+        int levels = source->levelCount();
+        for (int f = 0; f < 6; f++)
+        {
+            for (int i = 0; i < levels; i++)
+            {
+                IDirect3DSurface9 *srcSurf = source->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
+                IDirect3DSurface9 *dstSurf = dest->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
+
+                result = TextureStorage::copyToRenderTarget(dstSurf, srcSurf, source->isManaged());
+
+                if (srcSurf) srcSurf->Release();
+                if (dstSurf) dstSurf->Release();
+
+                if (!result)
+                    return false;
+            }
+        }
+    }
+
+    return result;
+}
+
 // Increments refcount on surface.
 // caller must Release() the returned surface
 IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)