Home | History | Annotate | Download | only in d3d11
      1 //
      2 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Image11.h: Implements the rx::Image11 class, which acts as the interface to
      8 // the actual underlying resources of a Texture
      9 
     10 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
     11 #include "libGLESv2/renderer/d3d/d3d11/Image11.h"
     12 #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
     13 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
     14 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
     15 #include "libGLESv2/Framebuffer.h"
     16 #include "libGLESv2/FramebufferAttachment.h"
     17 #include "libGLESv2/main.h"
     18 
     19 #include "common/utilities.h"
     20 
     21 namespace rx
     22 {
     23 
     24 Image11::Image11()
     25 {
     26     mStagingTexture = NULL;
     27     mRenderer = NULL;
     28     mDXGIFormat = DXGI_FORMAT_UNKNOWN;
     29     mRecoverFromStorage = false;
     30     mAssociatedStorage = NULL;
     31     mAssociatedStorageLevel = 0;
     32     mAssociatedStorageLayerTarget = 0;
     33     mRecoveredFromStorageCount = 0;
     34 }
     35 
     36 Image11::~Image11()
     37 {
     38     disassociateStorage();
     39     releaseStagingTexture();
     40 }
     41 
     42 Image11 *Image11::makeImage11(Image *img)
     43 {
     44     ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img));
     45     return static_cast<rx::Image11*>(img);
     46 }
     47 
     48 void Image11::generateMipmap(Image11 *dest, Image11 *src)
     49 {
     50     ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
     51     ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
     52     ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
     53 
     54     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat());
     55     ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL);
     56 
     57     D3D11_MAPPED_SUBRESOURCE destMapped;
     58     HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped);
     59     if (FAILED(destMapResult))
     60     {
     61         ERR("Failed to map destination image for mip map generation. HRESULT:0x%X", destMapResult);
     62         return;
     63     }
     64 
     65     D3D11_MAPPED_SUBRESOURCE srcMapped;
     66     HRESULT srcMapResult = src->map(D3D11_MAP_READ, &srcMapped);
     67     if (FAILED(srcMapResult))
     68     {
     69         ERR("Failed to map source image for mip map generation. HRESULT:0x%X", srcMapResult);
     70 
     71         dest->unmap();
     72         return;
     73     }
     74 
     75     const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(srcMapped.pData);
     76     uint8_t *destData = reinterpret_cast<uint8_t*>(destMapped.pData);
     77 
     78     dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(),
     79                                          sourceData, srcMapped.RowPitch, srcMapped.DepthPitch,
     80                                          destData, destMapped.RowPitch, destMapped.DepthPitch);
     81 
     82     dest->unmap();
     83     src->unmap();
     84 
     85     dest->markDirty();
     86 }
     87 
     88 bool Image11::isDirty() const
     89 {
     90     // If mDirty is true
     91     // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage
     92     // AND the texture doesn't require init data (i.e. a blank new texture will suffice)
     93     // then isDirty should still return false.
     94     if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL))
     95     {
     96         return false;
     97     }
     98 
     99     return mDirty;
    100 }
    101 
    102 bool Image11::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
    103 {
    104     TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage);
    105     return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
    106 }
    107 
    108 bool Image11::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
    109 {
    110     TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage);
    111     return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height);
    112 }
    113 
    114 bool Image11::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
    115 {
    116     TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
    117     return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
    118 }
    119 
    120 bool Image11::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height)
    121 {
    122     TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
    123     return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height);
    124 }
    125 
    126 bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
    127 {
    128     // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times,
    129     // then we should just keep the staging texture around to prevent the copying from impacting perf.
    130     // We allow the Image11 to copy its data to/from TextureStorage once.
    131     // This accounts for an app making a late call to glGenerateMipmap.
    132     bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2);
    133 
    134     if (attemptToReleaseStagingTexture)
    135     {
    136         // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it.
    137         storage11->releaseAssociatedImage(level, layerTarget, this);
    138     }
    139 
    140     bool updateSubresourceSuccess = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget, xoffset, yoffset, 0, width, height, 1);
    141 
    142     // Once the image data has been copied into the Storage, we can release it locally.
    143     if (attemptToReleaseStagingTexture && updateSubresourceSuccess)
    144     {
    145         storage11->associateImage(this, level, layerTarget);
    146         releaseStagingTexture();
    147         mRecoverFromStorage = true;
    148         mAssociatedStorage = storage11;
    149         mAssociatedStorageLevel = level;
    150         mAssociatedStorageLayerTarget = layerTarget;
    151     }
    152 
    153     return updateSubresourceSuccess;
    154 }
    155 
    156 bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const
    157 {
    158     return (mAssociatedStorage == textureStorage);
    159 }
    160 
    161 bool Image11::recoverFromAssociatedStorage()
    162 {
    163     if (mRecoverFromStorage)
    164     {
    165         createStagingTexture();
    166 
    167         bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this);
    168 
    169         // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data.
    170         // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten.
    171         ASSERT(textureStorageCorrect);
    172 
    173         if (textureStorageCorrect)
    174         {
    175             // CopySubResource from the Storage to the Staging texture
    176             mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth);
    177             mRecoveredFromStorageCount += 1;
    178         }
    179 
    180         // Reset all the recovery parameters, even if the texture storage association is broken.
    181         disassociateStorage();
    182 
    183         return textureStorageCorrect;
    184     }
    185 
    186     return false;
    187 }
    188 
    189 void Image11::disassociateStorage()
    190 {
    191     if (mRecoverFromStorage)
    192     {
    193         // Make the texturestorage release the Image11 too
    194         mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this);
    195 
    196         mRecoverFromStorage = false;
    197         mAssociatedStorage = NULL;
    198         mAssociatedStorageLevel = 0;
    199         mAssociatedStorageLayerTarget = 0;
    200     }
    201 }
    202 
    203 bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
    204 {
    205     if (mWidth != width ||
    206         mHeight != height ||
    207         mInternalFormat != internalformat ||
    208         forceRelease)
    209     {
    210         // End the association with the TextureStorage, since that data will be out of date.
    211         // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined.
    212         disassociateStorage();
    213         mRecoveredFromStorageCount = 0;
    214 
    215         mRenderer = Renderer11::makeRenderer11(renderer);
    216 
    217         mWidth = width;
    218         mHeight = height;
    219         mDepth = depth;
    220         mInternalFormat = internalformat;
    221         mTarget = target;
    222 
    223         // compute the d3d format that will be used
    224         const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
    225         const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat);
    226         mDXGIFormat = formatInfo.texFormat;
    227         mActualFormat = dxgiFormatInfo.internalFormat;
    228         mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
    229 
    230         SafeRelease(mStagingTexture);
    231         mDirty = (formatInfo.dataInitializerFunction != NULL);
    232 
    233         return true;
    234     }
    235 
    236     return false;
    237 }
    238 
    239 DXGI_FORMAT Image11::getDXGIFormat() const
    240 {
    241     // this should only happen if the image hasn't been redefined first
    242     // which would be a bug by the caller
    243     ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
    244 
    245     return mDXGIFormat;
    246 }
    247 
    248 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
    249 // into the target pixel rectangle.
    250 void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
    251                        GLint unpackAlignment, GLenum type, const void *input)
    252 {
    253     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
    254     GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
    255     GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment);
    256 
    257     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
    258     GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
    259 
    260     const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat);
    261     LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type);
    262 
    263     D3D11_MAPPED_SUBRESOURCE mappedImage;
    264     HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
    265     if (FAILED(result))
    266     {
    267         ERR("Could not map image for loading.");
    268         return;
    269     }
    270 
    271     uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch));
    272     loadFunction(width, height, depth,
    273                  reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
    274                  offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
    275 
    276     unmap();
    277 }
    278 
    279 void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
    280                                  const void *input)
    281 {
    282     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
    283     GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
    284     GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
    285 
    286     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
    287     GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
    288     GLuint outputBlockWidth = dxgiFormatInfo.blockWidth;
    289     GLuint outputBlockHeight = dxgiFormatInfo.blockHeight;
    290 
    291     ASSERT(xoffset % outputBlockWidth == 0);
    292     ASSERT(yoffset % outputBlockHeight == 0);
    293 
    294     const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat);
    295     LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE);
    296 
    297     D3D11_MAPPED_SUBRESOURCE mappedImage;
    298     HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
    299     if (FAILED(result))
    300     {
    301         ERR("Could not map image for loading.");
    302         return;
    303     }
    304 
    305     uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch +
    306                                                                            (xoffset / outputBlockWidth) * outputPixelSize +
    307                                                                            zoffset * mappedImage.DepthPitch);
    308 
    309     loadFunction(width, height, depth,
    310                  reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
    311                  offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
    312 
    313     unmap();
    314 }
    315 
    316 void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
    317 {
    318     gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();
    319 
    320     if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat)
    321     {
    322         // No conversion needed-- use copyback fastpath
    323         ID3D11Texture2D *colorBufferTexture = NULL;
    324         unsigned int subresourceIndex = 0;
    325 
    326         if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
    327         {
    328             D3D11_TEXTURE2D_DESC textureDesc;
    329             colorBufferTexture->GetDesc(&textureDesc);
    330 
    331             ID3D11Device *device = mRenderer->getDevice();
    332             ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    333 
    334             ID3D11Texture2D* srcTex = NULL;
    335             if (textureDesc.SampleDesc.Count > 1)
    336             {
    337                 D3D11_TEXTURE2D_DESC resolveDesc;
    338                 resolveDesc.Width = textureDesc.Width;
    339                 resolveDesc.Height = textureDesc.Height;
    340                 resolveDesc.MipLevels = 1;
    341                 resolveDesc.ArraySize = 1;
    342                 resolveDesc.Format = textureDesc.Format;
    343                 resolveDesc.SampleDesc.Count = 1;
    344                 resolveDesc.SampleDesc.Quality = 0;
    345                 resolveDesc.Usage = D3D11_USAGE_DEFAULT;
    346                 resolveDesc.BindFlags = 0;
    347                 resolveDesc.CPUAccessFlags = 0;
    348                 resolveDesc.MiscFlags = 0;
    349 
    350                 HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
    351                 if (FAILED(result))
    352                 {
    353                     ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
    354                     return;
    355                 }
    356 
    357                 deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
    358                 subresourceIndex = 0;
    359             }
    360             else
    361             {
    362                 srcTex = colorBufferTexture;
    363                 srcTex->AddRef();
    364             }
    365 
    366             D3D11_BOX srcBox;
    367             srcBox.left = x;
    368             srcBox.right = x + width;
    369             srcBox.top = y;
    370             srcBox.bottom = y + height;
    371             srcBox.front = 0;
    372             srcBox.back = 1;
    373 
    374             deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox);
    375 
    376             SafeRelease(srcTex);
    377             SafeRelease(colorBufferTexture);
    378         }
    379     }
    380     else
    381     {
    382         // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
    383         D3D11_MAPPED_SUBRESOURCE mappedImage;
    384         HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
    385         if (FAILED(result))
    386         {
    387             ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result);
    388             return;
    389         }
    390 
    391         // determine the offset coordinate into the destination buffer
    392         GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset;
    393         uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch;
    394 
    395         const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
    396 
    397         mRenderer->readPixels(source, x, y, width, height, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
    398 
    399         unmap();
    400     }
    401 }
    402 
    403 ID3D11Resource *Image11::getStagingTexture()
    404 {
    405     createStagingTexture();
    406 
    407     return mStagingTexture;
    408 }
    409 
    410 void Image11::releaseStagingTexture()
    411 {
    412     SafeRelease(mStagingTexture);
    413 }
    414 
    415 unsigned int Image11::getStagingSubresource()
    416 {
    417     createStagingTexture();
    418 
    419     return mStagingSubresource;
    420 }
    421 
    422 void Image11::createStagingTexture()
    423 {
    424     if (mStagingTexture)
    425     {
    426         return;
    427     }
    428 
    429     const DXGI_FORMAT dxgiFormat = getDXGIFormat();
    430 
    431     if (mWidth > 0 && mHeight > 0 && mDepth > 0)
    432     {
    433         ID3D11Device *device = mRenderer->getDevice();
    434         HRESULT result;
    435 
    436         int lodOffset = 1;
    437         GLsizei width = mWidth;
    438         GLsizei height = mHeight;
    439 
    440         // adjust size if needed for compressed textures
    441         d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset);
    442 
    443         if (mTarget == GL_TEXTURE_3D)
    444         {
    445             ID3D11Texture3D *newTexture = NULL;
    446 
    447             D3D11_TEXTURE3D_DESC desc;
    448             desc.Width = width;
    449             desc.Height = height;
    450             desc.Depth = mDepth;
    451             desc.MipLevels = lodOffset + 1;
    452             desc.Format = dxgiFormat;
    453             desc.Usage = D3D11_USAGE_STAGING;
    454             desc.BindFlags = 0;
    455             desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    456             desc.MiscFlags = 0;
    457 
    458             if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
    459             {
    460                 std::vector<D3D11_SUBRESOURCE_DATA> initialData;
    461                 std::vector< std::vector<BYTE> > textureData;
    462                 d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth,
    463                                                   lodOffset + 1, &initialData, &textureData);
    464 
    465                 result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
    466             }
    467             else
    468             {
    469                 result = device->CreateTexture3D(&desc, NULL, &newTexture);
    470             }
    471 
    472             if (FAILED(result))
    473             {
    474                 ASSERT(result == E_OUTOFMEMORY);
    475                 ERR("Creating image failed.");
    476                 return gl::error(GL_OUT_OF_MEMORY);
    477             }
    478 
    479             mStagingTexture = newTexture;
    480             mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
    481         }
    482         else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP)
    483         {
    484             ID3D11Texture2D *newTexture = NULL;
    485 
    486             D3D11_TEXTURE2D_DESC desc;
    487             desc.Width = width;
    488             desc.Height = height;
    489             desc.MipLevels = lodOffset + 1;
    490             desc.ArraySize = 1;
    491             desc.Format = dxgiFormat;
    492             desc.SampleDesc.Count = 1;
    493             desc.SampleDesc.Quality = 0;
    494             desc.Usage = D3D11_USAGE_STAGING;
    495             desc.BindFlags = 0;
    496             desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    497             desc.MiscFlags = 0;
    498 
    499             if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
    500             {
    501                 std::vector<D3D11_SUBRESOURCE_DATA> initialData;
    502                 std::vector< std::vector<BYTE> > textureData;
    503                 d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1,
    504                                                   lodOffset + 1, &initialData, &textureData);
    505 
    506                 result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
    507             }
    508             else
    509             {
    510                 result = device->CreateTexture2D(&desc, NULL, &newTexture);
    511             }
    512 
    513             if (FAILED(result))
    514             {
    515                 ASSERT(result == E_OUTOFMEMORY);
    516                 ERR("Creating image failed.");
    517                 return gl::error(GL_OUT_OF_MEMORY);
    518             }
    519 
    520             mStagingTexture = newTexture;
    521             mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
    522         }
    523         else
    524         {
    525             UNREACHABLE();
    526         }
    527     }
    528 
    529     mDirty = false;
    530 }
    531 
    532 HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
    533 {
    534     createStagingTexture();
    535 
    536     // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
    537     recoverFromAssociatedStorage();
    538 
    539     HRESULT result = E_FAIL;
    540 
    541     if (mStagingTexture)
    542     {
    543         ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    544         result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
    545 
    546         // this can fail if the device is removed (from TDR)
    547         if (d3d11::isDeviceLostError(result))
    548         {
    549             mRenderer->notifyDeviceLost();
    550         }
    551         else if (SUCCEEDED(result))
    552         {
    553             mDirty = true;
    554         }
    555     }
    556 
    557     return result;
    558 }
    559 
    560 void Image11::unmap()
    561 {
    562     if (mStagingTexture)
    563     {
    564         ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    565         deviceContext->Unmap(mStagingTexture, mStagingSubresource);
    566     }
    567 }
    568 
    569 }
    570