Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d9 / TextureStorage9.cpp
index 9065bc6..479e05e 100644 (file)
@@ -1,4 +1,3 @@
-#include "precompiled.h"
 //
 // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -9,20 +8,24 @@
 // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
 // D3D9 texture.
 
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
 #include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
 #include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
 #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
 #include "libGLESv2/Texture.h"
+#include "libGLESv2/main.h"
 
 namespace rx
 {
 TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
     : mTopLevel(0),
+      mMipLevels(0),
+      mTextureWidth(0),
+      mTextureHeight(0),
+      mTextureFormat(D3DFMT_UNKNOWN),
       mRenderer(Renderer9::makeRenderer9(renderer)),
       mD3DUsage(usage),
       mD3DPool(mRenderer->getTexturePool(usage))
@@ -85,7 +88,14 @@ int TextureStorage9::getTopLevel() const
 
 int TextureStorage9::getLevelCount() const
 {
-    return getBaseTexture() ? (getBaseTexture()->GetLevelCount() - getTopLevel()) : 0;
+    return mMipLevels - mTopLevel;
+}
+
+gl::Error TextureStorage9::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+                                   const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
 }
 
 TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain)
@@ -93,9 +103,17 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain
 {
     IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
     mTexture = surfaceTexture;
+    mMipLevels = surfaceTexture->GetLevelCount();
+
+    D3DSURFACE_DESC surfaceDesc;
+    surfaceTexture->GetLevelDesc(0, &surfaceDesc);
+    mTextureWidth = surfaceDesc.Width;
+    mTextureHeight = surfaceDesc.Height;
+    mTextureFormat = surfaceDesc.Format;
+
     mRenderTarget = NULL;
 
-    initializeRenderTarget();
+    initializeSerials(1, 1);
 }
 
 TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
@@ -103,25 +121,16 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat
 {
     mTexture = NULL;
     mRenderTarget = NULL;
-    // if the width or height is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (width > 0 && height > 0)
-    {
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-        const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
-        d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
-        UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels;
 
-        HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL);
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+    mTextureFormat = d3dFormatInfo.texFormat;
 
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
+    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
+    mTextureWidth = width;
+    mTextureHeight = height;
+    mMipLevels = mTopLevel + levels;
 
-    initializeRenderTarget();
+    initializeSerials(getLevelCount(), 1);
 }
 
 TextureStorage9_2D::~TextureStorage9_2D()
@@ -138,98 +147,166 @@ TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *s
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
+gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface)
 {
-    IDirect3DSurface9 *surface = NULL;
+    IDirect3DBaseTexture9 *baseTexture = NULL;
+    gl::Error error = getBaseTexture(&baseTexture);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture);
 
-    if (mTexture)
+    HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
+
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
     {
-        HRESULT result = mTexture->GetSurfaceLevel(level + mTopLevel, &surface);
-        UNUSED_ASSERTION_VARIABLE(result);
-        ASSERT(SUCCEEDED(result));
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+    }
 
-        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
-        if (level + mTopLevel != 0 && isManaged() && dirty)
-        {
-            mTexture->AddDirtyRect(NULL);
-        }
+    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+    if (level + mTopLevel != 0 && isManaged() && dirty)
+    {
+        texture->AddDirtyRect(NULL);
     }
 
-    return surface;
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage9_2D::getRenderTarget(int level)
+gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT)
 {
-    return mRenderTarget;
+    if (!mRenderTarget && isRenderTarget())
+    {
+        IDirect3DSurface9 *surface = NULL;
+        gl::Error error = getSurfaceLevel(0, false, &surface);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        mRenderTarget = new RenderTarget9(mRenderer, surface);
+    }
+
+    ASSERT(outRT);
+    *outRT = mRenderTarget;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage9_2D::generateMipmap(int level)
+gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
 {
-    IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false);
-    IDirect3DSurface9 *lower = getSurfaceLevel(level, true);
+    IDirect3DSurface9 *upper = NULL;
+    gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    if (upper != NULL && lower != NULL)
+    IDirect3DSurface9 *lower = NULL;
+    error = getSurfaceLevel(destIndex.mipIndex, true, &lower);
+    if (error.isError())
     {
-        mRenderer->boxFilter(upper, lower);
+        SafeRelease(upper);
+        return error;
     }
 
+    ASSERT(upper && lower);
+    error = mRenderer->boxFilter(upper, lower);
+
     SafeRelease(upper);
     SafeRelease(lower);
+
+    return error;
 }
 
-IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const
+gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
 {
-    return mTexture;
+    // if the width or height is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        IDirect3DDevice9 *device = mRenderer->getDevice();
+        HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat,
+                                               getPool(), &mTexture, NULL);
+
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result);
+        }
+    }
+
+    *outTexture = mTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage9_2D::initializeRenderTarget()
+gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
 {
-    ASSERT(mRenderTarget == NULL);
+    ASSERT(destStorage);
+
+    TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(destStorage);
 
-    if (mTexture != NULL && isRenderTarget())
+    int levels = getLevelCount();
+    for (int i = 0; i < levels; ++i)
     {
-        IDirect3DSurface9 *surface = getSurfaceLevel(0, false);
+        IDirect3DSurface9 *srcSurf = NULL;
+        gl::Error error = getSurfaceLevel(i, false, &srcSurf);
+        if (error.isError())
+        {
+            return error;
+        }
 
-        mRenderTarget = new RenderTarget9(mRenderer, surface);
+        IDirect3DSurface9 *dstSurf = NULL;
+        error = dest9->getSurfaceLevel(i, true, &dstSurf);
+        if (error.isError())
+        {
+            SafeRelease(srcSurf);
+            return error;
+        }
+
+        error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
+
+        SafeRelease(srcSurf);
+        SafeRelease(dstSurf);
+
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
     : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
 {
     mTexture = NULL;
-    for (int i = 0; i < 6; ++i)
+    for (int i = 0; i < CUBE_FACE_COUNT; ++i)
     {
         mRenderTarget[i] = NULL;
     }
 
-    // if the size is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (size > 0)
-    {
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-        int height = size;
-        const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
-        d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
-        UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels;
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+    mTextureFormat = d3dFormatInfo.texFormat;
 
-        HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL);
+    int height = size;
+    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
+    mTextureWidth = size;
+    mTextureHeight = size;
+    mMipLevels = mTopLevel + levels;
 
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
-
-    initializeRenderTarget();
+    initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT);
 }
 
 TextureStorage9_Cube::~TextureStorage9_Cube()
 {
     SafeRelease(mTexture);
 
-    for (int i = 0; i < 6; ++i)
+    for (int i = 0; i < CUBE_FACE_COUNT; ++i)
     {
         SafeDelete(mRenderTarget[i]);
     }
@@ -243,66 +320,146 @@ TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStor
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
+gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface)
 {
-    IDirect3DSurface9 *surface = NULL;
+    IDirect3DBaseTexture9 *baseTexture = NULL;
+    gl::Error error = getBaseTexture(&baseTexture);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture);
 
-    if (mTexture)
+    D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
+    HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface);
+
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
     {
-        D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
-        HRESULT result = mTexture->GetCubeMapSurface(face, level + mTopLevel, &surface);
-        UNUSED_ASSERTION_VARIABLE(result);
-        ASSERT(SUCCEEDED(result));
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+    }
 
-        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
-        if (level != 0 && isManaged() && dirty)
-        {
-            mTexture->AddDirtyRect(face, NULL);
-        }
+    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+    if (level != 0 && isManaged() && dirty)
+    {
+        texture->AddDirtyRect(face, NULL);
     }
 
-    return surface;
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage9_Cube::getRenderTargetFace(GLenum faceTarget, int level)
+gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
-    return mRenderTarget[gl::TextureCubeMap::targetToLayerIndex(faceTarget)];
+    ASSERT(outRT);
+    ASSERT(index.mipIndex == 0);
+    ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT);
+
+    if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget())
+    {
+        IDirect3DSurface9 *surface = NULL;
+        gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, 0, false, &surface);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        mRenderTarget[index.layerIndex] = new RenderTarget9(mRenderer, surface);
+    }
+
+    *outRT = mRenderTarget[index.layerIndex];
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage9_Cube::generateMipmap(int faceIndex, int level)
+gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
 {
-    IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1, false);
-    IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, true);
+    IDirect3DSurface9 *upper = NULL;
+    gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    if (upper != NULL && lower != NULL)
+    IDirect3DSurface9 *lower = NULL;
+    error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower);
+    if (error.isError())
     {
-        mRenderer->boxFilter(upper, lower);
+        SafeRelease(upper);
+        return error;
     }
 
+    ASSERT(upper && lower);
+    error = mRenderer->boxFilter(upper, lower);
+
     SafeRelease(upper);
     SafeRelease(lower);
-}
 
-IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const
-{
-    return mTexture;
+    return error;
 }
 
-void TextureStorage9_Cube::initializeRenderTarget()
+gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
 {
-    if (mTexture != NULL && isRenderTarget())
+    // if the size is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
     {
-        IDirect3DSurface9 *surface = NULL;
+        ASSERT(mMipLevels > 0);
+        ASSERT(mTextureWidth == mTextureHeight);
 
-        for (int i = 0; i < 6; ++i)
+        IDirect3DDevice9 *device = mRenderer->getDevice();
+        HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(),
+                                                   &mTexture, NULL);
+
+        if (FAILED(result))
         {
-            ASSERT(mRenderTarget[i] == NULL);
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result);
+        }
+    }
+
+    *outTexture = mTexture;
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
 
-            surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false);
+    TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage);
 
-            mRenderTarget[i] = new RenderTarget9(mRenderer, surface);
+    int levels = getLevelCount();
+    for (int f = 0; f < CUBE_FACE_COUNT; f++)
+    {
+        for (int i = 0; i < levels; i++)
+        {
+            IDirect3DSurface9 *srcSurf = NULL;
+            gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
+            if (error.isError())
+            {
+                return error;
+            }
+
+            IDirect3DSurface9 *dstSurf = NULL;
+            error = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf);
+            if (error.isError())
+            {
+                SafeRelease(srcSurf);
+                return error;
+            }
+
+            error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
+
+            SafeRelease(srcSurf);
+            SafeRelease(dstSurf);
+
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-}
\ No newline at end of file
+}