-#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
// 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))
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)
{
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)
{
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()
// 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]);
}
// 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
+}