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/Texture.cpp b/src/libGLESv2/Texture.cpp
index 555590b..a23fcdc 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -502,56 +502,12 @@
     return creationLevels(size, size);
 }
 
-int Texture::levelCount()
-{
-    return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0;
-}
-
 Blit *Texture::getBlitter()
 {
     Context *context = getContext();
     return context->getBlitter();
 }
 
-bool Texture::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;
-}
-
 Texture2D::Texture2D(GLuint id) : Texture(id)
 {
     mTexStorage = NULL;
@@ -961,11 +917,6 @@
     return IsDepthTexture(getInternalFormat(level));
 }
 
-IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
-{
-    return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
-}
-
 // Constructs a native texture resource from the texture images
 void Texture2D::createTexture()
 {
@@ -1026,22 +977,10 @@
 
         if (mTexStorage != NULL)
         {
-            int levels = levelCount();
-            for (int i = 0; i < levels; i++)
-            {
-                IDirect3DSurface9 *source = mTexStorage->getSurfaceLevel(i, false);
-                IDirect3DSurface9 *dest = newTexStorage->getSurfaceLevel(i, true);
-
-                if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
-                {   
-                   delete newTexStorage;
-                   if (source) source->Release();
-                   if (dest) dest->Release();
-                   return error(GL_OUT_OF_MEMORY);
-                }
-
-                if (source) source->Release();
-                if (dest) dest->Release();
+            if (!TextureStorage2D::copyToRenderTarget(newTexStorage, mTexStorage))
+            {   
+                delete newTexStorage;
+                return error(GL_OUT_OF_MEMORY);
             }
         }
     }
@@ -1164,6 +1103,11 @@
     return mTexStorage->getSurfaceLevel(0, false);
 }
 
+int Texture2D::levelCount()
+{
+    return mTexStorage ? mTexStorage->levelCount() - getLodOffset() : 0;
+}
+
 TextureStorage *Texture2D::getStorage(bool renderTarget)
 {
     if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
@@ -1438,11 +1382,6 @@
     return IsCompressed(getInternalFormat(target, level));
 }
 
-IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
-{
-    return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
-}
-
 // Constructs a native texture resource from the texture images, or returns an existing one
 void TextureCubeMap::createTexture()
 {
@@ -1507,25 +1446,10 @@
 
         if (mTexStorage != NULL)
         {
-            int levels = levelCount();
-            for (int f = 0; f < 6; f++)
+            if (!TextureStorageCubeMap::copyToRenderTarget(newTexStorage, mTexStorage))
             {
-                for (int i = 0; i < levels; i++)
-                {
-                    IDirect3DSurface9 *source = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
-                    IDirect3DSurface9 *dest = newTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
-
-                    if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
-                    {
-                       delete newTexStorage;
-                       if (source) source->Release();
-                       if (dest) dest->Release();
-                       return error(GL_OUT_OF_MEMORY);
-                    }
-
-                    if (source) source->Release();
-                    if (dest) dest->Release();
-                }
+                delete newTexStorage;
+                return error(GL_OUT_OF_MEMORY);
             }
         }
     }
@@ -1819,6 +1743,11 @@
     return mTexStorage->getCubeMapSurface(target, 0, false);
 }
 
+int TextureCubeMap::levelCount()
+{
+    return mTexStorage ? mTexStorage->levelCount() - getLodOffset() : 0;
+}
+
 TextureStorage *TextureCubeMap::getStorage(bool renderTarget)
 {
     if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 02c8652..0efedfa 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -111,16 +111,14 @@
     GLint creationLevels(GLsizei width, GLsizei height) const;
     GLint creationLevels(GLsizei size) const;
 
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
     virtual void createTexture() = 0;
     virtual void updateTexture() = 0;
     virtual void convertToRenderTarget() = 0;
     virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0;
 
-    int levelCount();
+    virtual int levelCount() = 0;
 
     static Blit *getBlitter();
-    static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
 
     SamplerState mSamplerState;
     bool mDirtyParameters;
@@ -175,11 +173,11 @@
     friend class RenderbufferTexture2D;
     virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
     virtual IDirect3DSurface9 *getDepthStencil(GLenum target);
+    virtual int levelCount();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture2D);
 
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
     virtual void createTexture();
     virtual void updateTexture();
     virtual void convertToRenderTarget();
@@ -248,11 +246,11 @@
   protected:
     friend class RenderbufferTextureCubeMap;
     virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+    virtual int levelCount();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
 
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
     virtual void createTexture();
     virtual void updateTexture();
     virtual void convertToRenderTarget();
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)
diff --git a/src/libGLESv2/renderer/TextureStorage.h b/src/libGLESv2/renderer/TextureStorage.h
index f0f1a0a..31782e6 100644
--- a/src/libGLESv2/renderer/TextureStorage.h
+++ b/src/libGLESv2/renderer/TextureStorage.h
@@ -44,8 +44,11 @@
     virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
     virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
     int getLodOffset() const;
+    int levelCount();
 
   protected:
+    static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
+
     int mLodOffset;
 
   private:
@@ -68,6 +71,8 @@
 
     virtual ~TextureStorage2D();
 
+    static bool copyToRenderTarget(TextureStorage2D *dest, TextureStorage2D *source);
+
     IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty);
     virtual IDirect3DBaseTexture9 *getBaseTexture() const;
 
@@ -87,6 +92,8 @@
 
     virtual ~TextureStorageCubeMap();
 
+    static bool copyToRenderTarget(TextureStorageCubeMap *dest, TextureStorageCubeMap *source);
+
     IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty);
     virtual IDirect3DBaseTexture9 *getBaseTexture() const;