diff options
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp | 377 |
1 files changed, 263 insertions, 114 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp index f44e33db18..0ff4fd3b0f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp @@ -20,8 +20,13 @@ namespace rx { -TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) +TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage) : mTopLevel(0), + mMipLevels(0), + mTextureWidth(0), + mTextureHeight(0), + mInternalFormat(GL_NONE), + mTextureFormat(D3DFMT_UNKNOWN), mRenderer(Renderer9::makeRenderer9(renderer)), mD3DUsage(usage), mD3DPool(mRenderer->getTexturePool(usage)) @@ -84,44 +89,52 @@ int TextureStorage9::getTopLevel() const int TextureStorage9::getLevelCount() const { - return getBaseTexture() ? (getBaseTexture()->GetLevelCount() - getTopLevel()) : 0; + return mMipLevels - mTopLevel; } -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) +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(Renderer9 *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) { IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); mTexture = surfaceTexture; + mMipLevels = surfaceTexture->GetLevelCount(); + + mInternalFormat = swapchain->GetBackBufferInternalFormat(); + + 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) +TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { 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); + mInternalFormat = internalformat; - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - gl::error(GL_OUT_OF_MEMORY); - } - } + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mTextureFormat = d3dFormatInfo.texFormat; + + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); + mTextureWidth = width; + mTextureHeight = height; + mMipLevels = mTopLevel + levels; - initializeRenderTarget(); initializeSerials(getLevelCount(), 1); } @@ -139,104 +152,168 @@ 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) + // 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 gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT) +{ + if (!mRenderTarget && isRenderTarget()) + { + IDirect3DSurface9 *surface = NULL; + gl::Error error = getSurfaceLevel(0, false, &surface); + if (error.isError()) { - mTexture->AddDirtyRect(NULL); + return error; } + + mRenderTarget = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); } - return surface; + ASSERT(outRT); + *outRT = mRenderTarget; + return gl::Error(GL_NO_ERROR); } -RenderTarget *TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/) +gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) { - return mRenderTarget; + IDirect3DSurface9 *upper = NULL; + gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getSurfaceLevel(destIndex.mipIndex, true, &lower); + if (error.isError()) + { + SafeRelease(upper); + return error; + } + + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; } -void TextureStorage9_2D::generateMipmaps() +gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture) { - // Base level must already be defined - - for (int level = 1; level < getLevelCount(); level++) + // 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) { - IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); - IDirect3DSurface9 *lower = getSurfaceLevel(level, true); + ASSERT(mMipLevels > 0); - if (upper != NULL && lower != NULL) + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat, + getPool(), &mTexture, NULL); + + if (FAILED(result)) { - mRenderer->boxFilter(upper, lower); + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result); } - - SafeRelease(upper); - SafeRelease(lower); } -} -IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const -{ - return mTexture; + *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_Cube::TextureStorage9_Cube(Renderer9 *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; + mInternalFormat = internalformat; - HRESULT result = device->CreateCubeTexture(size, 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); - } - } + int height = size; + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); + mTextureWidth = size; + mTextureHeight = size; + mMipLevels = mTopLevel + levels; - initializeRenderTarget(); - initializeSerials(getLevelCount() * 6, 6); + 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]); } @@ -250,74 +327,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) + // 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 gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +{ + 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()) { - mTexture->AddDirtyRect(face, NULL); + return error; } + + mRenderTarget[index.layerIndex] = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); } - return surface; + *outRT = mRenderTarget[index.layerIndex]; + return gl::Error(GL_NO_ERROR); } -RenderTarget *TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) { - return mRenderTarget[index.layerIndex]; + IDirect3DSurface9 *upper = NULL; + gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower); + if (error.isError()) + { + SafeRelease(upper); + return error; + } + + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; } -void TextureStorage9_Cube::generateMipmaps() +gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture) { - // Base level must already be defined - - for (int faceIndex = 0; faceIndex < 6; faceIndex++) + // 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) { - for (int level = 1; level < getLevelCount(); level++) - { - 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); + ASSERT(mMipLevels > 0); + ASSERT(mTextureWidth == mTextureHeight); - if (upper != NULL && lower != NULL) - { - mRenderer->boxFilter(upper, lower); - } + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(), + &mTexture, NULL); - SafeRelease(upper); - SafeRelease(lower); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result); } } -} -IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const -{ - return mTexture; + *outTexture = mTexture; + return gl::Error(GL_NO_ERROR); } -void TextureStorage9_Cube::initializeRenderTarget() +gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) { - if (mTexture != NULL && isRenderTarget()) - { - IDirect3DSurface9 *surface = NULL; + ASSERT(destStorage); + + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage); - for (int i = 0; i < 6; ++i) + int levels = getLevelCount(); + for (int f = 0; f < CUBE_FACE_COUNT; f++) + { + for (int i = 0; i < levels; i++) { - ASSERT(mRenderTarget[i] == NULL); + IDirect3DSurface9 *srcSurf = NULL; + gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); + if (error.isError()) + { + return error; + } - surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); + 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()); - mRenderTarget[i] = new RenderTarget9(mRenderer, surface); + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (error.isError()) + { + return error; + } } } + + return gl::Error(GL_NO_ERROR); } -}
\ No newline at end of file +} |