diff options
Diffstat (limited to 'src/libGLESv2/renderer/d3d/d3d11/Image11.cpp')
-rw-r--r-- | src/libGLESv2/renderer/d3d/d3d11/Image11.cpp | 144 |
1 files changed, 123 insertions, 21 deletions
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp index 08b16ee7..7536713a 100644 --- a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp +++ b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -11,13 +10,13 @@ #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/Image11.h" #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/FramebufferAttachment.h" - #include "libGLESv2/main.h" + #include "common/utilities.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" namespace rx { @@ -27,11 +26,17 @@ Image11::Image11() mStagingTexture = NULL; mRenderer = NULL; mDXGIFormat = DXGI_FORMAT_UNKNOWN; + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedStorageLevel = 0; + mAssociatedStorageLayerTarget = 0; + mRecoveredFromStorageCount = 0; } Image11::~Image11() { - SafeRelease(mStagingTexture); + disassociateStorage(); + releaseStagingTexture(); } Image11 *Image11::makeImage11(Image *img) @@ -82,33 +87,117 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src) bool Image11::isDirty() const { - // Make sure that this image is marked as dirty even if the staging texture hasn't been created yet - // if initialization is required before use. - return (mDirty && (mStagingTexture || d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)); + // If mDirty is true + // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage + // AND the texture doesn't require init data (i.e. a blank new texture will suffice) + // then isDirty should still return false. + if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)) + { + return false; + } + + return mDirty; +} + +bool Image11::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); + return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); } -bool Image11::copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image11::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, 0, width, height, 1); + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); + return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height); +} + +bool Image11::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +{ + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); + return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); +} + +bool Image11::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height) +{ + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); + return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height); +} + +bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times, + // then we should just keep the staging texture around to prevent the copying from impacting perf. + // We allow the Image11 to copy its data to/from TextureStorage once. + // This accounts for an app making a late call to glGenerateMipmap. + bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2); + + if (attemptToReleaseStagingTexture) + { + // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it. + storage11->releaseAssociatedImage(level, layerTarget, this); + } + + bool updateSubresourceSuccess = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget, xoffset, yoffset, 0, width, height, 1); + + // Once the image data has been copied into the Storage, we can release it locally. + if (attemptToReleaseStagingTexture && updateSubresourceSuccess) + { + storage11->associateImage(this, level, layerTarget); + releaseStagingTexture(); + mRecoverFromStorage = true; + mAssociatedStorage = storage11; + mAssociatedStorageLevel = level; + mAssociatedStorageLayerTarget = layerTarget; + } + + return updateSubresourceSuccess; } -bool Image11::copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const { - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, 0, width, height, 1); + return (mAssociatedStorage == textureStorage); } -bool Image11::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +bool Image11::recoverFromAssociatedStorage() { - TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, zoffset, width, height, depth); + if (mRecoverFromStorage) + { + createStagingTexture(); + + bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this); + + // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. + // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten. + ASSERT(textureStorageCorrect); + + if (textureStorageCorrect) + { + // CopySubResource from the Storage to the Staging texture + mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth); + mRecoveredFromStorageCount += 1; + } + + // Reset all the recovery parameters, even if the texture storage association is broken. + disassociateStorage(); + + return textureStorageCorrect; + } + + return false; } -bool Image11::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height) +void Image11::disassociateStorage() { - TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, arrayLayer, xoffset, yoffset, 0, width, height, 1); + if (mRecoverFromStorage) + { + // Make the texturestorage release the Image11 too + mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this); + + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedStorageLevel = 0; + mAssociatedStorageLayerTarget = 0; + } } bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) @@ -118,6 +207,11 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, mInternalFormat != internalformat || forceRelease) { + // End the association with the TextureStorage, since that data will be out of date. + // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined. + disassociateStorage(); + mRecoveredFromStorageCount = 0; + mRenderer = Renderer11::makeRenderer11(renderer); mWidth = width; @@ -296,7 +390,7 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y // determine the offset coordinate into the destination buffer GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset; - void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; + uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); @@ -313,6 +407,11 @@ ID3D11Resource *Image11::getStagingTexture() return mStagingTexture; } +void Image11::releaseStagingTexture() +{ + SafeRelease(mStagingTexture); +} + unsigned int Image11::getStagingSubresource() { createStagingTexture(); @@ -434,6 +533,9 @@ HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { createStagingTexture(); + // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. + recoverFromAssociatedStorage(); + HRESULT result = E_FAIL; if (mStagingTexture) |