Refactor storage management in TextureCube.

TRAC #23976

Signed-off-by: Geoff Lang
Signed-off-by: Shannon Woods
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 1a56b27..558410c 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -1275,27 +1275,51 @@
     return GetDepthBits(getInternalFormat(target, level), mRenderer->getCurrentClientVersion()) > 0;
 }
 
-// Constructs a native texture resource from the texture images, or returns an existing one
 void TextureCubeMap::initializeStorage(bool renderTarget)
 {
+    // Only initialize the first time this texture is used as a render target or shader resource
+    if (mTexStorage)
+    {
+        return;
+    }
+
+    // do not attempt to create storage for nonexistant data
+    if (!isFaceLevelComplete(0, 0))
+    {
+        return;
+    }
+
+    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
+
+    setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+    ASSERT(mTexStorage);
+
+    // flush image data to the storage
+    updateStorage();
+}
+
+rx::TextureStorageInterfaceCube *TextureCubeMap::createCompleteStorage(bool renderTarget) const
+{
     GLsizei size = getBaseLevelWidth();
 
-    if (!(size > 0))
-        return; // do not attempt to create native textures for nonexistant data
+    ASSERT(size > 0);
 
-    GLint levels = creationLevels(size);
-    GLenum internalformat = getBaseLevelInternalFormat();
+    // use existing storage level count, when previously specified by TexStorage*D
+    GLint levels = (mTexStorage ? mTexStorage->levelCount() : creationLevels(size));
 
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, IsRenderTargetUsage(mUsage), size);
+    return new rx::TextureStorageInterfaceCube(mRenderer, levels, getBaseLevelInternalFormat(), renderTarget, size);
+}
 
-    if (mTexStorage->isManaged())
+void TextureCubeMap::setCompleteTexStorage(rx::TextureStorageInterfaceCube *newCompleteTexStorage)
+{
+    SafeDelete(mTexStorage);
+    mTexStorage = newCompleteTexStorage;
+
+    if (mTexStorage && mTexStorage->isManaged())
     {
-        int levels = levelCount();
-
         for (int faceIndex = 0; faceIndex < 6; faceIndex++)
         {
-            for (int level = 0; level < levels; level++)
+            for (int level = 0; level < mTexStorage->levelCount(); level++)
             {
                 mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level);
             }
@@ -1334,35 +1358,25 @@
 
 bool TextureCubeMap::ensureRenderTarget()
 {
-    if (mTexStorage && mTexStorage->isRenderTarget())
+    initializeStorage(true);
+
+    if (getBaseLevelWidth() > 0)
     {
-        return true;
-    }
-
-    rx::TextureStorageInterfaceCube *newTexStorage = NULL;
-
-    if (getBaseLevelWidth() != 0)
-    {
-        GLsizei size = getBaseLevelWidth();
-        GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(size);
-        GLenum internalformat = getBaseLevelInternalFormat();
-
-        newTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, true, size);
-
-        if (mTexStorage != NULL)
+        ASSERT(mTexStorage);
+        if (!mTexStorage->isRenderTarget())
         {
-            if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage))
+            rx::TextureStorageInterfaceCube *newRenderTargetStorage = createCompleteStorage(true);
+
+            if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
             {
-                delete newTexStorage;
+                delete newRenderTargetStorage;
                 return gl::error(GL_OUT_OF_MEMORY, false);
             }
+
+            setCompleteTexStorage(newRenderTargetStorage);
         }
     }
 
-    delete mTexStorage;
-    mTexStorage = newTexStorage;
-
-    mDirtyImages = true;
     return (mTexStorage && mTexStorage->isRenderTarget());
 }
 
@@ -1500,10 +1514,6 @@
 
 void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
 {
-    delete mTexStorage;
-    mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, IsRenderTargetUsage(mUsage), size);
-    mImmutable = true;
-
     for (int level = 0; level < levels; level++)
     {
         GLsizei mipSize = std::max(1, size >> level);
@@ -1521,18 +1531,9 @@
         }
     }
 
-    if (mTexStorage->isManaged())
-    {
-        int levels = levelCount();
+    mImmutable = true;
 
-        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
-        {
-            for (int level = 0; level < levels; level++)
-            {
-                mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level);
-            }
-        }
-    }
+    setCompleteTexStorage(new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, IsRenderTargetUsage(mUsage), size));
 }
 
 void TextureCubeMap::generateMipmaps()
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 24a630f..b5ff6bb 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -267,6 +267,9 @@
     DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
 
     virtual void initializeStorage(bool renderTarget);
+    rx::TextureStorageInterfaceCube *createCompleteStorage(bool renderTarget) const;
+    void setCompleteTexStorage(rx::TextureStorageInterfaceCube *newCompleteTexStorage);
+
     virtual void updateStorage();
     virtual bool ensureRenderTarget();
     virtual rx::TextureStorageInterface *getStorage(bool renderTarget);