Home | History | Annotate | Download | only in d3d11
      1 //
      2 // Copyright (c) 2012-2014 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 // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
      8 // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
      9 
     10 #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
     11 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
     12 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
     13 #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
     14 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
     15 #include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
     16 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
     17 #include "libGLESv2/renderer/d3d/d3d11/Image11.h"
     18 #include "libGLESv2/renderer/d3d/TextureD3D.h"
     19 #include "libGLESv2/main.h"
     20 #include "libGLESv2/ImageIndex.h"
     21 
     22 #include "common/utilities.h"
     23 
     24 namespace rx
     25 {
     26 
     27 TextureStorage11::SwizzleCacheValue::SwizzleCacheValue()
     28     : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE)
     29 {
     30 }
     31 
     32 TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha)
     33     : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
     34 {
     35 }
     36 
     37 bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const
     38 {
     39     return swizzleRed == other.swizzleRed &&
     40            swizzleGreen == other.swizzleGreen &&
     41            swizzleBlue == other.swizzleBlue &&
     42            swizzleAlpha == other.swizzleAlpha;
     43 }
     44 
     45 bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const
     46 {
     47     return !(*this == other);
     48 }
     49 
     50 TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle)
     51     : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle)
     52 {
     53 }
     54 
     55 bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const
     56 {
     57     return baseLevel == rhs.baseLevel &&
     58            mipLevels == rhs.mipLevels &&
     59            swizzle == rhs.swizzle;
     60 }
     61 
     62 TextureStorage11::SRVCache::~SRVCache()
     63 {
     64     for (size_t i = 0; i < cache.size(); i++)
     65     {
     66         SafeRelease(cache[i].srv);
     67     }
     68 }
     69 
     70 ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const
     71 {
     72     for (size_t i = 0; i < cache.size(); i++)
     73     {
     74         if (cache[i].key == key)
     75         {
     76             return cache[i].srv;
     77         }
     78     }
     79 
     80     return NULL;
     81 }
     82 
     83 ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv)
     84 {
     85     SRVPair pair = {key, srv};
     86     cache.push_back(pair);
     87 
     88     return srv;
     89 }
     90 
     91 TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
     92     : mBindFlags(bindFlags),
     93       mTopLevel(0),
     94       mMipLevels(0),
     95       mTextureFormat(DXGI_FORMAT_UNKNOWN),
     96       mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
     97       mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
     98       mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
     99       mTextureWidth(0),
    100       mTextureHeight(0),
    101       mTextureDepth(0)
    102 {
    103     mRenderer = Renderer11::makeRenderer11(renderer);
    104 
    105     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    106     {
    107         mLevelSRVs[i] = NULL;
    108     }
    109 }
    110 
    111 TextureStorage11::~TextureStorage11()
    112 {
    113     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    114     {
    115         SafeRelease(mLevelSRVs[level]);
    116     }
    117 }
    118 
    119 TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
    120 {
    121     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
    122     return static_cast<TextureStorage11*>(storage);
    123 }
    124 
    125 DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget)
    126 {
    127     UINT bindFlags = 0;
    128 
    129     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
    130     if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
    131     {
    132         bindFlags |= D3D11_BIND_SHADER_RESOURCE;
    133     }
    134     if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
    135     {
    136         bindFlags |= D3D11_BIND_DEPTH_STENCIL;
    137     }
    138     if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget)
    139     {
    140         bindFlags |= D3D11_BIND_RENDER_TARGET;
    141     }
    142 
    143     return bindFlags;
    144 }
    145 
    146 UINT TextureStorage11::getBindFlags() const
    147 {
    148     return mBindFlags;
    149 }
    150 
    151 int TextureStorage11::getTopLevel() const
    152 {
    153     return mTopLevel;
    154 }
    155 
    156 bool TextureStorage11::isRenderTarget() const
    157 {
    158     return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
    159 }
    160 
    161 bool TextureStorage11::isManaged() const
    162 {
    163     return false;
    164 }
    165 
    166 int TextureStorage11::getLevelCount() const
    167 {
    168     return mMipLevels - mTopLevel;
    169 }
    170 
    171 int TextureStorage11::getLevelWidth(int mipLevel) const
    172 {
    173     return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1);
    174 }
    175 
    176 int TextureStorage11::getLevelHeight(int mipLevel) const
    177 {
    178     return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1);
    179 }
    180 
    181 int TextureStorage11::getLevelDepth(int mipLevel) const
    182 {
    183     return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
    184 }
    185 
    186 UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const
    187 {
    188     UINT index = 0;
    189     if (getResource())
    190     {
    191         index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels);
    192     }
    193     return index;
    194 }
    195 
    196 ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState)
    197 {
    198     bool swizzleRequired = samplerState.swizzleRequired();
    199     bool mipmapping = gl::IsMipmapFiltered(samplerState);
    200     unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1;
    201 
    202     // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,  which corresponds to GL level 0)
    203     mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel);
    204 
    205     if (swizzleRequired)
    206     {
    207         verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha);
    208     }
    209 
    210     SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired);
    211     ID3D11ShaderResourceView *srv = srvCache.find(key);
    212 
    213     if(srv)
    214     {
    215         return srv;
    216     }
    217 
    218     DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat);
    219     ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource();
    220 
    221     srv = createSRV(samplerState.baseLevel, mipLevels, format, texture);
    222 
    223     return srvCache.add(key, srv);
    224 }
    225 
    226 ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel)
    227 {
    228     if (mipLevel >= 0 && mipLevel < getLevelCount())
    229     {
    230         if (!mLevelSRVs[mipLevel])
    231         {
    232             mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource());
    233         }
    234 
    235         return mLevelSRVs[mipLevel];
    236     }
    237     else
    238     {
    239         return NULL;
    240     }
    241 }
    242 
    243 void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
    244 {
    245     SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
    246     for (int level = 0; level < getLevelCount(); level++)
    247     {
    248         // Check if the swizzle for this level is out of date
    249         if (mSwizzleCache[level] != swizzleTarget)
    250         {
    251             // Need to re-render the swizzle for this level
    252             ID3D11ShaderResourceView *sourceSRV = getSRVLevel(level);
    253             ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level);
    254 
    255             gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
    256 
    257             Blit11 *blitter = mRenderer->getBlitter();
    258 
    259             if (blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha))
    260             {
    261                 mSwizzleCache[level] = swizzleTarget;
    262             }
    263             else
    264             {
    265                 ERR("Failed to swizzle texture.");
    266             }
    267         }
    268     }
    269 }
    270 
    271 void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel)
    272 {
    273     if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache))
    274     {
    275         // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a
    276         // valid swizzle combination
    277         mSwizzleCache[mipLevel] = SwizzleCacheValue();
    278     }
    279 }
    280 
    281 void TextureStorage11::invalidateSwizzleCache()
    282 {
    283     for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++)
    284     {
    285         invalidateSwizzleCacheLevel(mipLevel);
    286     }
    287 }
    288 
    289 bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
    290                                               int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
    291                                               GLsizei width, GLsizei height, GLsizei depth)
    292 {
    293     if (srcTexture)
    294     {
    295         invalidateSwizzleCacheLevel(level);
    296 
    297         gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
    298         gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth);
    299 
    300         bool fullCopy = copyArea.x == 0 &&
    301                         copyArea.y == 0 &&
    302                         copyArea.z == 0 &&
    303                         copyArea.width  == texSize.width &&
    304                         copyArea.height == texSize.height &&
    305                         copyArea.depth  == texSize.depth;
    306 
    307         ID3D11Resource *dstTexture = getResource();
    308         unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget);
    309 
    310         ASSERT(dstTexture);
    311 
    312         const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
    313         if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0))
    314         {
    315             // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
    316             Blit11 *blitter = mRenderer->getBlitter();
    317 
    318             return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
    319                                              dstTexture, dstSubresource, copyArea, texSize,
    320                                              NULL);
    321         }
    322         else
    323         {
    324             const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
    325 
    326             D3D11_BOX srcBox;
    327             srcBox.left = copyArea.x;
    328             srcBox.top = copyArea.y;
    329             srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth);
    330             srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight);
    331             srcBox.front = copyArea.z;
    332             srcBox.back = copyArea.z + copyArea.depth;
    333 
    334             ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    335 
    336             context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z,
    337                                            srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox);
    338             return true;
    339         }
    340     }
    341 
    342     return false;
    343 }
    344 
    345 bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
    346                                             int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
    347                                             GLsizei width, GLsizei height, GLsizei depth)
    348 {
    349     if (dstTexture)
    350     {
    351         ID3D11Resource *srcTexture = getResource();
    352         unsigned int srcSubresource = getSubresourceIndex(level + mTopLevel, layerTarget);
    353 
    354         ASSERT(srcTexture);
    355 
    356         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    357 
    358         context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset,
    359                                        srcTexture, srcSubresource, NULL);
    360         return true;
    361     }
    362 
    363     return false;
    364 }
    365 
    366 void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
    367 {
    368     if (source && dest)
    369     {
    370         ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
    371         ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
    372 
    373         if (sourceSRV && destRTV)
    374         {
    375             gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
    376             gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
    377 
    378             gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
    379             gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
    380 
    381             Blit11 *blitter = mRenderer->getBlitter();
    382 
    383             blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
    384                                  gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
    385         }
    386     }
    387 }
    388 
    389 void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
    390 {
    391     SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
    392     for (unsigned int level = 0; level < mMipLevels; level++)
    393     {
    394         ASSERT(mSwizzleCache[level] == swizzleTarget);
    395     }
    396 }
    397 
    398 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
    399     : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
    400       mTexture(swapchain->getOffscreenTexture()),
    401       mSwizzleTexture(NULL)
    402 {
    403     mTexture->AddRef();
    404 
    405     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    406     {
    407         mAssociatedImages[i] = NULL;
    408         mRenderTarget[i] = NULL;
    409         mSwizzleRenderTargets[i] = NULL;
    410     }
    411 
    412     D3D11_TEXTURE2D_DESC texDesc;
    413     mTexture->GetDesc(&texDesc);
    414     mMipLevels = texDesc.MipLevels;
    415     mTextureFormat = texDesc.Format;
    416     mTextureWidth = texDesc.Width;
    417     mTextureHeight = texDesc.Height;
    418     mTextureDepth = 1;
    419 
    420     ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource();
    421     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    422     srv->GetDesc(&srvDesc);
    423     mShaderResourceFormat = srvDesc.Format;
    424 
    425     ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
    426     D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
    427     offscreenRTV->GetDesc(&rtvDesc);
    428     mRenderTargetFormat = rtvDesc.Format;
    429 
    430     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
    431     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat);
    432     mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
    433     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
    434     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
    435 
    436     mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
    437 
    438     initializeSerials(1, 1);
    439 }
    440 
    441 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
    442     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)),
    443       mTexture(NULL),
    444       mSwizzleTexture(NULL)
    445 {
    446     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    447     {
    448         mAssociatedImages[i] = NULL;
    449         mRenderTarget[i] = NULL;
    450         mSwizzleRenderTargets[i] = NULL;
    451     }
    452 
    453     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
    454     mTextureFormat = formatInfo.texFormat;
    455     mShaderResourceFormat = formatInfo.srvFormat;
    456     mDepthStencilFormat = formatInfo.dsvFormat;
    457     mRenderTargetFormat = formatInfo.rtvFormat;
    458     mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
    459     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
    460     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
    461 
    462     // if the width or height is not positive this should be treated as an incomplete texture
    463     // we handle that here by skipping the d3d texture creation
    464     if (width > 0 && height > 0)
    465     {
    466         // adjust size if needed for compressed textures
    467         d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
    468 
    469         ID3D11Device *device = mRenderer->getDevice();
    470 
    471         D3D11_TEXTURE2D_DESC desc;
    472         desc.Width = width;      // Compressed texture size constraints?
    473         desc.Height = height;
    474         desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
    475         desc.ArraySize = 1;
    476         desc.Format = mTextureFormat;
    477         desc.SampleDesc.Count = 1;
    478         desc.SampleDesc.Quality = 0;
    479         desc.Usage = D3D11_USAGE_DEFAULT;
    480         desc.BindFlags = getBindFlags();
    481         desc.CPUAccessFlags = 0;
    482         desc.MiscFlags = 0;
    483 
    484         HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
    485 
    486         // this can happen from windows TDR
    487         if (d3d11::isDeviceLostError(result))
    488         {
    489             mRenderer->notifyDeviceLost();
    490             gl::error(GL_OUT_OF_MEMORY);
    491         }
    492         else if (FAILED(result))
    493         {
    494             ASSERT(result == E_OUTOFMEMORY);
    495             ERR("Creating image failed.");
    496             gl::error(GL_OUT_OF_MEMORY);
    497         }
    498         else
    499         {
    500             mTexture->GetDesc(&desc);
    501             mMipLevels = desc.MipLevels;
    502             mTextureWidth = desc.Width;
    503             mTextureHeight = desc.Height;
    504             mTextureDepth = 1;
    505         }
    506     }
    507 
    508     initializeSerials(getLevelCount(), 1);
    509 }
    510 
    511 TextureStorage11_2D::~TextureStorage11_2D()
    512 {
    513     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    514     {
    515         if (mAssociatedImages[i] != NULL)
    516         {
    517             bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this);
    518             ASSERT(imageAssociationCorrect);
    519 
    520             if (imageAssociationCorrect)
    521             {
    522                 // We must let the Images recover their data before we delete it from the TextureStorage.
    523                 mAssociatedImages[i]->recoverFromAssociatedStorage();
    524             }
    525         }
    526     }
    527 
    528     SafeRelease(mTexture);
    529     SafeRelease(mSwizzleTexture);
    530 
    531     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    532     {
    533         SafeDelete(mRenderTarget[i]);
    534         SafeRelease(mSwizzleRenderTargets[i]);
    535     }
    536 }
    537 
    538 TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
    539 {
    540     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
    541     return static_cast<TextureStorage11_2D*>(storage);
    542 }
    543 
    544 void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget)
    545 {
    546     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    547 
    548     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    549     {
    550         mAssociatedImages[level] = image;
    551     }
    552 }
    553 
    554 bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
    555 {
    556     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    557     {
    558         // This validation check should never return false. It means the Image/TextureStorage association is broken.
    559         bool retValue = (mAssociatedImages[level] == expectedImage);
    560         ASSERT(retValue);
    561         return retValue;
    562     }
    563 
    564     return false;
    565 }
    566 
    567 // disassociateImage allows an Image to end its association with a Storage.
    568 void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11* expectedImage)
    569 {
    570     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    571 
    572     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    573     {
    574         ASSERT(mAssociatedImages[level] == expectedImage);
    575 
    576         if (mAssociatedImages[level] == expectedImage)
    577         {
    578             mAssociatedImages[level] = NULL;
    579         }
    580     }
    581 }
    582 
    583 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
    584 void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
    585 {
    586     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    587 
    588     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    589     {
    590         // No need to let the old Image recover its data, if it is also the incoming Image.
    591         if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage)
    592         {
    593             // Ensure that the Image is still associated with this TextureStorage. This should be true.
    594             bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this);
    595             ASSERT(imageAssociationCorrect);
    596 
    597             if (imageAssociationCorrect)
    598             {
    599                 // Force the image to recover from storage before its data is overwritten.
    600                 // This will reset mAssociatedImages[level] to NULL too.
    601                 mAssociatedImages[level]->recoverFromAssociatedStorage();
    602             }
    603         }
    604     }
    605 }
    606 
    607 ID3D11Resource *TextureStorage11_2D::getResource() const
    608 {
    609     return mTexture;
    610 }
    611 
    612 RenderTarget *TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index)
    613 {
    614     ASSERT(!index.hasLayer());
    615 
    616     int level = index.mipIndex;
    617 
    618     if (level >= 0 && level < getLevelCount())
    619     {
    620         if (!mRenderTarget[level])
    621         {
    622             ID3D11ShaderResourceView *srv = getSRVLevel(level);
    623             if (!srv)
    624             {
    625                 return NULL;
    626             }
    627 
    628             if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
    629             {
    630                 ID3D11Device *device = mRenderer->getDevice();
    631 
    632                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
    633                 rtvDesc.Format = mRenderTargetFormat;
    634                 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    635                 rtvDesc.Texture2D.MipSlice = mTopLevel + level;
    636 
    637                 ID3D11RenderTargetView *rtv;
    638                 HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
    639 
    640                 if (result == E_OUTOFMEMORY)
    641                 {
    642                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    643                 }
    644                 ASSERT(SUCCEEDED(result));
    645 
    646                 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
    647 
    648                 // RenderTarget will take ownership of these resources
    649                 SafeRelease(rtv);
    650             }
    651             else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
    652             {
    653                 ID3D11Device *device = mRenderer->getDevice();
    654 
    655                 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
    656                 dsvDesc.Format = mDepthStencilFormat;
    657                 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    658                 dsvDesc.Texture2D.MipSlice = mTopLevel + level;
    659                 dsvDesc.Flags = 0;
    660 
    661                 ID3D11DepthStencilView *dsv;
    662                 HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
    663 
    664                 if (result == E_OUTOFMEMORY)
    665                 {
    666                     SafeRelease(srv);
    667                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    668                 }
    669                 ASSERT(SUCCEEDED(result));
    670 
    671                 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
    672 
    673                 // RenderTarget will take ownership of these resources
    674                 SafeRelease(dsv);
    675             }
    676             else
    677             {
    678                 UNREACHABLE();
    679             }
    680         }
    681 
    682         return mRenderTarget[level];
    683     }
    684     else
    685     {
    686         return NULL;
    687     }
    688 }
    689 
    690 ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
    691 {
    692     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    693     srvDesc.Format = format;
    694     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    695     srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
    696     srvDesc.Texture2D.MipLevels = mipLevels;
    697 
    698     ID3D11ShaderResourceView *SRV = NULL;
    699 
    700     ID3D11Device *device = mRenderer->getDevice();
    701     HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
    702 
    703     if (result == E_OUTOFMEMORY)
    704     {
    705         gl::error(GL_OUT_OF_MEMORY);
    706     }
    707     ASSERT(SUCCEEDED(result));
    708 
    709     return SRV;
    710 }
    711 
    712 void TextureStorage11_2D::generateMipmaps()
    713 {
    714     // Base level must already be defined
    715 
    716     for (int level = 1; level < getLevelCount(); level++)
    717     {
    718         invalidateSwizzleCacheLevel(level);
    719 
    720         gl::ImageIndex srcIndex = gl::ImageIndex::Make2D(level - 1);
    721         gl::ImageIndex destIndex = gl::ImageIndex::Make2D(level);
    722 
    723         RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
    724         RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
    725 
    726         generateMipmapLayer(source, dest);
    727     }
    728 }
    729 
    730 ID3D11Resource *TextureStorage11_2D::getSwizzleTexture()
    731 {
    732     if (!mSwizzleTexture)
    733     {
    734         ID3D11Device *device = mRenderer->getDevice();
    735 
    736         D3D11_TEXTURE2D_DESC desc;
    737         desc.Width = mTextureWidth;
    738         desc.Height = mTextureHeight;
    739         desc.MipLevels = mMipLevels;
    740         desc.ArraySize = 1;
    741         desc.Format = mSwizzleTextureFormat;
    742         desc.SampleDesc.Count = 1;
    743         desc.SampleDesc.Quality = 0;
    744         desc.Usage = D3D11_USAGE_DEFAULT;
    745         desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    746         desc.CPUAccessFlags = 0;
    747         desc.MiscFlags = 0;
    748 
    749         HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
    750 
    751         if (result == E_OUTOFMEMORY)
    752         {
    753             return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
    754         }
    755         ASSERT(SUCCEEDED(result));
    756     }
    757 
    758     return mSwizzleTexture;
    759 }
    760 
    761 ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel)
    762 {
    763     if (mipLevel >= 0 && mipLevel < getLevelCount())
    764     {
    765         if (!mSwizzleRenderTargets[mipLevel])
    766         {
    767             ID3D11Resource *swizzleTexture = getSwizzleTexture();
    768             if (!swizzleTexture)
    769             {
    770                 return NULL;
    771             }
    772 
    773             ID3D11Device *device = mRenderer->getDevice();
    774 
    775             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
    776             rtvDesc.Format = mSwizzleRenderTargetFormat;
    777             rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    778             rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
    779 
    780             HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
    781             if (result == E_OUTOFMEMORY)
    782             {
    783                 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
    784             }
    785             ASSERT(SUCCEEDED(result));
    786         }
    787 
    788         return mSwizzleRenderTargets[mipLevel];
    789     }
    790     else
    791     {
    792         return NULL;
    793     }
    794 }
    795 
    796 TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
    797     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
    798 {
    799     mTexture = NULL;
    800     mSwizzleTexture = NULL;
    801 
    802     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    803     {
    804         mSwizzleRenderTargets[level] = NULL;
    805         for (unsigned int face = 0; face < 6; face++)
    806         {
    807             mAssociatedImages[face][level] = NULL;
    808             mRenderTarget[face][level] = NULL;
    809         }
    810     }
    811 
    812     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
    813     mTextureFormat = formatInfo.texFormat;
    814     mShaderResourceFormat = formatInfo.srvFormat;
    815     mDepthStencilFormat = formatInfo.dsvFormat;
    816     mRenderTargetFormat = formatInfo.rtvFormat;
    817     mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
    818     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
    819     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
    820 
    821     // if the size is not positive this should be treated as an incomplete texture
    822     // we handle that here by skipping the d3d texture creation
    823     if (size > 0)
    824     {
    825         // adjust size if needed for compressed textures
    826         int height = size;
    827         d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel);
    828 
    829         ID3D11Device *device = mRenderer->getDevice();
    830 
    831         D3D11_TEXTURE2D_DESC desc;
    832         desc.Width = size;
    833         desc.Height = size;
    834         desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
    835         desc.ArraySize = 6;
    836         desc.Format = mTextureFormat;
    837         desc.SampleDesc.Count = 1;
    838         desc.SampleDesc.Quality = 0;
    839         desc.Usage = D3D11_USAGE_DEFAULT;
    840         desc.BindFlags = getBindFlags();
    841         desc.CPUAccessFlags = 0;
    842         desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
    843 
    844         HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
    845 
    846         if (FAILED(result))
    847         {
    848             ASSERT(result == E_OUTOFMEMORY);
    849             ERR("Creating image failed.");
    850             gl::error(GL_OUT_OF_MEMORY);
    851         }
    852         else
    853         {
    854             mTexture->GetDesc(&desc);
    855             mMipLevels = desc.MipLevels;
    856             mTextureWidth = desc.Width;
    857             mTextureHeight = desc.Height;
    858             mTextureDepth = 1;
    859         }
    860     }
    861 
    862     initializeSerials(getLevelCount() * 6, 6);
    863 }
    864 
    865 
    866 TextureStorage11_Cube::~TextureStorage11_Cube()
    867 {
    868     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    869     {
    870         for (unsigned int face = 0; face < 6; face++)
    871         {
    872             if (mAssociatedImages[face][level] != NULL)
    873             {
    874                 bool imageAssociationCorrect = mAssociatedImages[face][level]->isAssociatedStorageValid(this);
    875                 ASSERT(imageAssociationCorrect);
    876 
    877                 if (imageAssociationCorrect)
    878                 {
    879                     // We must let the Images recover their data before we delete it from the TextureStorage.
    880                     mAssociatedImages[face][level]->recoverFromAssociatedStorage();
    881                 }
    882             }
    883         }
    884     }
    885 
    886     SafeRelease(mTexture);
    887     SafeRelease(mSwizzleTexture);
    888 
    889     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    890     {
    891         SafeRelease(mSwizzleRenderTargets[level]);
    892         for (unsigned int face = 0; face < 6; face++)
    893         {
    894             SafeDelete(mRenderTarget[face][level]);
    895         }
    896     }
    897 }
    898 
    899 TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
    900 {
    901     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
    902     return static_cast<TextureStorage11_Cube*>(storage);
    903 }
    904 
    905 void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget)
    906 {
    907     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    908     ASSERT(0 <= layerTarget && layerTarget < 6);
    909 
    910     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    911     {
    912         if (0 <= layerTarget && layerTarget < 6)
    913         {
    914             mAssociatedImages[layerTarget][level] = image;
    915         }
    916     }
    917 }
    918 
    919 bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
    920 {
    921     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    922     {
    923         if (0 <= layerTarget && layerTarget < 6)
    924         {
    925             // This validation check should never return false. It means the Image/TextureStorage association is broken.
    926             bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage);
    927             ASSERT(retValue);
    928             return retValue;
    929         }
    930     }
    931 
    932     return false;
    933 }
    934 
    935 // disassociateImage allows an Image to end its association with a Storage.
    936 void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image11* expectedImage)
    937 {
    938     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    939     ASSERT(0 <= layerTarget && layerTarget < 6);
    940 
    941     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    942     {
    943         if (0 <= layerTarget && layerTarget < 6)
    944         {
    945             ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
    946 
    947             if (mAssociatedImages[layerTarget][level] == expectedImage)
    948             {
    949                 mAssociatedImages[layerTarget][level] = NULL;
    950             }
    951         }
    952     }
    953 }
    954 
    955 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
    956 void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
    957 {
    958     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    959     ASSERT(0 <= layerTarget && layerTarget < 6);
    960 
    961     if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
    962     {
    963         if (0 <= layerTarget && layerTarget < 6)
    964         {
    965             // No need to let the old Image recover its data, if it is also the incoming Image.
    966             if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage)
    967             {
    968                 // Ensure that the Image is still associated with this TextureStorage. This should be true.
    969                 bool imageAssociationCorrect = mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this);
    970                 ASSERT(imageAssociationCorrect);
    971 
    972                 if (imageAssociationCorrect)
    973                 {
    974                     // Force the image to recover from storage before its data is overwritten.
    975                     // This will reset mAssociatedImages[level] to NULL too.
    976                     mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage();
    977                 }
    978             }
    979         }
    980     }
    981 }
    982 
    983 ID3D11Resource *TextureStorage11_Cube::getResource() const
    984 {
    985     return mTexture;
    986 }
    987 
    988 RenderTarget *TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index)
    989 {
    990     int faceIndex = index.layerIndex;
    991     int level = index.mipIndex;
    992 
    993     if (level >= 0 && level < getLevelCount())
    994     {
    995         if (!mRenderTarget[faceIndex][level])
    996         {
    997             ID3D11Device *device = mRenderer->getDevice();
    998             HRESULT result;
    999 
   1000             D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1001             srvDesc.Format = mShaderResourceFormat;
   1002             srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
   1003             srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
   1004             srvDesc.Texture2DArray.MipLevels = 1;
   1005             srvDesc.Texture2DArray.FirstArraySlice = faceIndex;
   1006             srvDesc.Texture2DArray.ArraySize = 1;
   1007 
   1008             ID3D11ShaderResourceView *srv;
   1009             result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
   1010 
   1011             if (result == E_OUTOFMEMORY)
   1012             {
   1013                 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1014             }
   1015             ASSERT(SUCCEEDED(result));
   1016 
   1017             if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
   1018             {
   1019                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1020                 rtvDesc.Format = mRenderTargetFormat;
   1021                 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
   1022                 rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
   1023                 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
   1024                 rtvDesc.Texture2DArray.ArraySize = 1;
   1025 
   1026                 ID3D11RenderTargetView *rtv;
   1027                 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
   1028 
   1029                 if (result == E_OUTOFMEMORY)
   1030                 {
   1031                     SafeRelease(srv);
   1032                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1033                 }
   1034                 ASSERT(SUCCEEDED(result));
   1035 
   1036                 mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
   1037 
   1038                 // RenderTarget will take ownership of these resources
   1039                 SafeRelease(rtv);
   1040                 SafeRelease(srv);
   1041             }
   1042             else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
   1043             {
   1044                 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
   1045                 dsvDesc.Format = mDepthStencilFormat;
   1046                 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
   1047                 dsvDesc.Flags = 0;
   1048                 dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
   1049                 dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
   1050                 dsvDesc.Texture2DArray.ArraySize = 1;
   1051 
   1052                 ID3D11DepthStencilView *dsv;
   1053                 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
   1054 
   1055                 if (result == E_OUTOFMEMORY)
   1056                 {
   1057                     SafeRelease(srv);
   1058                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1059                 }
   1060                 ASSERT(SUCCEEDED(result));
   1061 
   1062                 mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
   1063 
   1064                 // RenderTarget will take ownership of these resources
   1065                 SafeRelease(dsv);
   1066                 SafeRelease(srv);
   1067             }
   1068             else
   1069             {
   1070                 UNREACHABLE();
   1071             }
   1072         }
   1073 
   1074         return mRenderTarget[faceIndex][level];
   1075     }
   1076     else
   1077     {
   1078         return NULL;
   1079     }
   1080 }
   1081 
   1082 ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
   1083 {
   1084     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1085     srvDesc.Format = format;
   1086 
   1087     // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures
   1088     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
   1089     if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT)
   1090     {
   1091         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
   1092         srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
   1093         srvDesc.Texture2DArray.MipLevels = 1;
   1094         srvDesc.Texture2DArray.FirstArraySlice = 0;
   1095         srvDesc.Texture2DArray.ArraySize = 6;
   1096     }
   1097     else
   1098     {
   1099         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
   1100         srvDesc.TextureCube.MipLevels = mipLevels;
   1101         srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
   1102     }
   1103 
   1104     ID3D11ShaderResourceView *SRV = NULL;
   1105 
   1106     ID3D11Device *device = mRenderer->getDevice();
   1107     HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
   1108 
   1109     if (result == E_OUTOFMEMORY)
   1110     {
   1111         gl::error(GL_OUT_OF_MEMORY);
   1112     }
   1113     ASSERT(SUCCEEDED(result));
   1114 
   1115     return SRV;
   1116 }
   1117 
   1118 void TextureStorage11_Cube::generateMipmaps()
   1119 {
   1120     // Base level must already be defined
   1121 
   1122     for (int faceIndex = 0; faceIndex < 6; faceIndex++)
   1123     {
   1124         for (int level = 1; level < getLevelCount(); level++)
   1125         {
   1126             invalidateSwizzleCacheLevel(level);
   1127 
   1128             gl::ImageIndex srcIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1);
   1129             gl::ImageIndex destIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level);
   1130 
   1131             RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
   1132             RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
   1133 
   1134             generateMipmapLayer(source, dest);
   1135         }
   1136     }
   1137 }
   1138 
   1139 ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture()
   1140 {
   1141     if (!mSwizzleTexture)
   1142     {
   1143         ID3D11Device *device = mRenderer->getDevice();
   1144 
   1145         D3D11_TEXTURE2D_DESC desc;
   1146         desc.Width = mTextureWidth;
   1147         desc.Height = mTextureHeight;
   1148         desc.MipLevels = mMipLevels;
   1149         desc.ArraySize = 6;
   1150         desc.Format = mSwizzleTextureFormat;
   1151         desc.SampleDesc.Count = 1;
   1152         desc.SampleDesc.Quality = 0;
   1153         desc.Usage = D3D11_USAGE_DEFAULT;
   1154         desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
   1155         desc.CPUAccessFlags = 0;
   1156         desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
   1157 
   1158         HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
   1159 
   1160         if (result == E_OUTOFMEMORY)
   1161         {
   1162             return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
   1163         }
   1164         ASSERT(SUCCEEDED(result));
   1165     }
   1166 
   1167     return mSwizzleTexture;
   1168 }
   1169 
   1170 ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel)
   1171 {
   1172     if (mipLevel >= 0 && mipLevel < getLevelCount())
   1173     {
   1174         if (!mSwizzleRenderTargets[mipLevel])
   1175         {
   1176             ID3D11Resource *swizzleTexture = getSwizzleTexture();
   1177             if (!swizzleTexture)
   1178             {
   1179                 return NULL;
   1180             }
   1181 
   1182             ID3D11Device *device = mRenderer->getDevice();
   1183 
   1184             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1185             rtvDesc.Format = mSwizzleRenderTargetFormat;
   1186             rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
   1187             rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
   1188             rtvDesc.Texture2DArray.FirstArraySlice = 0;
   1189             rtvDesc.Texture2DArray.ArraySize = 6;
   1190 
   1191             HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
   1192 
   1193             if (result == E_OUTOFMEMORY)
   1194             {
   1195                 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
   1196             }
   1197             ASSERT(SUCCEEDED(result));
   1198         }
   1199 
   1200         return mSwizzleRenderTargets[mipLevel];
   1201     }
   1202     else
   1203     {
   1204         return NULL;
   1205     }
   1206 }
   1207 
   1208 TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget,
   1209                                          GLsizei width, GLsizei height, GLsizei depth, int levels)
   1210     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
   1211 {
   1212     mTexture = NULL;
   1213     mSwizzleTexture = NULL;
   1214 
   1215     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
   1216     {
   1217         mAssociatedImages[i] = NULL;
   1218         mLevelRenderTargets[i] = NULL;
   1219         mSwizzleRenderTargets[i] = NULL;
   1220     }
   1221 
   1222     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
   1223     mTextureFormat = formatInfo.texFormat;
   1224     mShaderResourceFormat = formatInfo.srvFormat;
   1225     mDepthStencilFormat = formatInfo.dsvFormat;
   1226     mRenderTargetFormat = formatInfo.rtvFormat;
   1227     mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
   1228     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
   1229     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
   1230 
   1231     // If the width, height or depth are not positive this should be treated as an incomplete texture
   1232     // we handle that here by skipping the d3d texture creation
   1233     if (width > 0 && height > 0 && depth > 0)
   1234     {
   1235         // adjust size if needed for compressed textures
   1236         d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
   1237 
   1238         ID3D11Device *device = mRenderer->getDevice();
   1239 
   1240         D3D11_TEXTURE3D_DESC desc;
   1241         desc.Width = width;
   1242         desc.Height = height;
   1243         desc.Depth = depth;
   1244         desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
   1245         desc.Format = mTextureFormat;
   1246         desc.Usage = D3D11_USAGE_DEFAULT;
   1247         desc.BindFlags = getBindFlags();
   1248         desc.CPUAccessFlags = 0;
   1249         desc.MiscFlags = 0;
   1250 
   1251         HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
   1252 
   1253         // this can happen from windows TDR
   1254         if (d3d11::isDeviceLostError(result))
   1255         {
   1256             mRenderer->notifyDeviceLost();
   1257             gl::error(GL_OUT_OF_MEMORY);
   1258         }
   1259         else if (FAILED(result))
   1260         {
   1261             ASSERT(result == E_OUTOFMEMORY);
   1262             ERR("Creating image failed.");
   1263             gl::error(GL_OUT_OF_MEMORY);
   1264         }
   1265         else
   1266         {
   1267             mTexture->GetDesc(&desc);
   1268             mMipLevels = desc.MipLevels;
   1269             mTextureWidth = desc.Width;
   1270             mTextureHeight = desc.Height;
   1271             mTextureDepth = desc.Depth;
   1272         }
   1273     }
   1274 
   1275     initializeSerials(getLevelCount() * depth, depth);
   1276 }
   1277 
   1278 TextureStorage11_3D::~TextureStorage11_3D()
   1279 {
   1280     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
   1281     {
   1282         if (mAssociatedImages[i] != NULL)
   1283         {
   1284             bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this);
   1285             ASSERT(imageAssociationCorrect);
   1286 
   1287             if (imageAssociationCorrect)
   1288             {
   1289                 // We must let the Images recover their data before we delete it from the TextureStorage.
   1290                 mAssociatedImages[i]->recoverFromAssociatedStorage();
   1291             }
   1292         }
   1293     }
   1294 
   1295     SafeRelease(mTexture);
   1296     SafeRelease(mSwizzleTexture);
   1297 
   1298     for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++)
   1299     {
   1300         SafeDelete(i->second);
   1301     }
   1302     mLevelLayerRenderTargets.clear();
   1303 
   1304     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
   1305     {
   1306         SafeDelete(mLevelRenderTargets[i]);
   1307         SafeRelease(mSwizzleRenderTargets[i]);
   1308     }
   1309 }
   1310 
   1311 TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage)
   1312 {
   1313     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage));
   1314     return static_cast<TextureStorage11_3D*>(storage);
   1315 }
   1316 
   1317 void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget)
   1318 {
   1319     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
   1320 
   1321     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1322     {
   1323         mAssociatedImages[level] = image;
   1324     }
   1325 }
   1326 
   1327 bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
   1328 {
   1329     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1330     {
   1331         // This validation check should never return false. It means the Image/TextureStorage association is broken.
   1332         bool retValue = (mAssociatedImages[level] == expectedImage);
   1333         ASSERT(retValue);
   1334         return retValue;
   1335     }
   1336 
   1337     return false;
   1338 }
   1339 
   1340 // disassociateImage allows an Image to end its association with a Storage.
   1341 void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11* expectedImage)
   1342 {
   1343     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
   1344 
   1345     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1346     {
   1347         ASSERT(mAssociatedImages[level] == expectedImage);
   1348 
   1349         if (mAssociatedImages[level] == expectedImage)
   1350         {
   1351             mAssociatedImages[level] = NULL;
   1352         }
   1353     }
   1354 }
   1355 
   1356 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
   1357 void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
   1358 {
   1359     ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
   1360 
   1361     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1362     {
   1363         // No need to let the old Image recover its data, if it is also the incoming Image.
   1364         if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage)
   1365         {
   1366             // Ensure that the Image is still associated with this TextureStorage. This should be true.
   1367             bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this);
   1368             ASSERT(imageAssociationCorrect);
   1369 
   1370             if (imageAssociationCorrect)
   1371             {
   1372                 // Force the image to recover from storage before its data is overwritten.
   1373                 // This will reset mAssociatedImages[level] to NULL too.
   1374                 mAssociatedImages[level]->recoverFromAssociatedStorage();
   1375             }
   1376         }
   1377     }
   1378 }
   1379 
   1380 ID3D11Resource *TextureStorage11_3D::getResource() const
   1381 {
   1382     return mTexture;
   1383 }
   1384 
   1385 ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
   1386 {
   1387     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1388     srvDesc.Format = format;
   1389     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
   1390     srvDesc.Texture3D.MostDetailedMip = baseLevel;
   1391     srvDesc.Texture3D.MipLevels = mipLevels;
   1392 
   1393     ID3D11ShaderResourceView *SRV = NULL;
   1394 
   1395     ID3D11Device *device = mRenderer->getDevice();
   1396     HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
   1397 
   1398     if (result == E_OUTOFMEMORY)
   1399     {
   1400         gl::error(GL_OUT_OF_MEMORY);
   1401     }
   1402     ASSERT(SUCCEEDED(result));
   1403 
   1404     return SRV;
   1405 }
   1406 
   1407 RenderTarget *TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index)
   1408 {
   1409     int mipLevel = index.mipIndex;
   1410 
   1411     if (mipLevel >= 0 && mipLevel < getLevelCount())
   1412     {
   1413         ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN);
   1414 
   1415         if (!index.hasLayer())
   1416         {
   1417             if (!mLevelRenderTargets[mipLevel])
   1418             {
   1419                 ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel);
   1420                 if (!srv)
   1421                 {
   1422                     return NULL;
   1423                 }
   1424 
   1425                 ID3D11Device *device = mRenderer->getDevice();
   1426 
   1427                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1428                 rtvDesc.Format = mRenderTargetFormat;
   1429                 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
   1430                 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
   1431                 rtvDesc.Texture3D.FirstWSlice = 0;
   1432                 rtvDesc.Texture3D.WSize = -1;
   1433 
   1434                 ID3D11RenderTargetView *rtv;
   1435                 HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
   1436 
   1437                 if (result == E_OUTOFMEMORY)
   1438                 {
   1439                     SafeRelease(srv);
   1440                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1441                 }
   1442                 ASSERT(SUCCEEDED(result));
   1443 
   1444                 mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel));
   1445 
   1446                 // RenderTarget will take ownership of these resources
   1447                 SafeRelease(rtv);
   1448             }
   1449 
   1450             return mLevelRenderTargets[mipLevel];
   1451         }
   1452         else
   1453         {
   1454             int layer = index.layerIndex;
   1455 
   1456             LevelLayerKey key(mipLevel, layer);
   1457             if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
   1458             {
   1459                 ID3D11Device *device = mRenderer->getDevice();
   1460                 HRESULT result;
   1461 
   1462                 // TODO, what kind of SRV is expected here?
   1463                 ID3D11ShaderResourceView *srv = NULL;
   1464 
   1465                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1466                 rtvDesc.Format = mRenderTargetFormat;
   1467                 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
   1468                 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
   1469                 rtvDesc.Texture3D.FirstWSlice = layer;
   1470                 rtvDesc.Texture3D.WSize = 1;
   1471 
   1472                 ID3D11RenderTargetView *rtv;
   1473                 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
   1474 
   1475                 if (result == E_OUTOFMEMORY)
   1476                 {
   1477                     SafeRelease(srv);
   1478                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1479                 }
   1480                 ASSERT(SUCCEEDED(result));
   1481 
   1482                 mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
   1483 
   1484                 // RenderTarget will take ownership of these resources
   1485                 SafeRelease(rtv);
   1486                 SafeRelease(srv);
   1487             }
   1488 
   1489             return mLevelLayerRenderTargets[key];
   1490         }
   1491     }
   1492 
   1493     return NULL;
   1494 }
   1495 
   1496 void TextureStorage11_3D::generateMipmaps()
   1497 {
   1498     // Base level must already be defined
   1499 
   1500     for (int level = 1; level < getLevelCount(); level++)
   1501     {
   1502         invalidateSwizzleCacheLevel(level);
   1503 
   1504         gl::ImageIndex srcIndex = gl::ImageIndex::Make3D(level - 1);
   1505         gl::ImageIndex destIndex = gl::ImageIndex::Make3D(level);
   1506 
   1507         RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
   1508         RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
   1509 
   1510         generateMipmapLayer(source, dest);
   1511     }
   1512 }
   1513 
   1514 ID3D11Resource *TextureStorage11_3D::getSwizzleTexture()
   1515 {
   1516     if (!mSwizzleTexture)
   1517     {
   1518         ID3D11Device *device = mRenderer->getDevice();
   1519 
   1520         D3D11_TEXTURE3D_DESC desc;
   1521         desc.Width = mTextureWidth;
   1522         desc.Height = mTextureHeight;
   1523         desc.Depth = mTextureDepth;
   1524         desc.MipLevels = mMipLevels;
   1525         desc.Format = mSwizzleTextureFormat;
   1526         desc.Usage = D3D11_USAGE_DEFAULT;
   1527         desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
   1528         desc.CPUAccessFlags = 0;
   1529         desc.MiscFlags = 0;
   1530 
   1531         HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture);
   1532 
   1533         if (result == E_OUTOFMEMORY)
   1534         {
   1535             return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture3D*>(NULL));
   1536         }
   1537         ASSERT(SUCCEEDED(result));
   1538     }
   1539 
   1540     return mSwizzleTexture;
   1541 }
   1542 
   1543 ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel)
   1544 {
   1545     if (mipLevel >= 0 && mipLevel < getLevelCount())
   1546     {
   1547         if (!mSwizzleRenderTargets[mipLevel])
   1548         {
   1549             ID3D11Resource *swizzleTexture = getSwizzleTexture();
   1550             if (!swizzleTexture)
   1551             {
   1552                 return NULL;
   1553             }
   1554 
   1555             ID3D11Device *device = mRenderer->getDevice();
   1556 
   1557             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1558             rtvDesc.Format = mSwizzleRenderTargetFormat;
   1559             rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
   1560             rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
   1561             rtvDesc.Texture3D.FirstWSlice = 0;
   1562             rtvDesc.Texture3D.WSize = -1;
   1563 
   1564             HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
   1565 
   1566             if (result == E_OUTOFMEMORY)
   1567             {
   1568                 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
   1569             }
   1570             ASSERT(SUCCEEDED(result));
   1571         }
   1572 
   1573         return mSwizzleRenderTargets[mipLevel];
   1574     }
   1575     else
   1576     {
   1577         return NULL;
   1578     }
   1579 }
   1580 
   1581 TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget,
   1582                                                    GLsizei width, GLsizei height, GLsizei depth, int levels)
   1583     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
   1584 {
   1585     mTexture = NULL;
   1586     mSwizzleTexture = NULL;
   1587 
   1588     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
   1589     {
   1590         mSwizzleRenderTargets[level] = NULL;
   1591     }
   1592 
   1593     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
   1594     mTextureFormat = formatInfo.texFormat;
   1595     mShaderResourceFormat = formatInfo.srvFormat;
   1596     mDepthStencilFormat = formatInfo.dsvFormat;
   1597     mRenderTargetFormat = formatInfo.rtvFormat;
   1598     mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
   1599     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
   1600     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
   1601 
   1602     // if the width, height or depth is not positive this should be treated as an incomplete texture
   1603     // we handle that here by skipping the d3d texture creation
   1604     if (width > 0 && height > 0 && depth > 0)
   1605     {
   1606         // adjust size if needed for compressed textures
   1607         d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
   1608 
   1609         ID3D11Device *device = mRenderer->getDevice();
   1610 
   1611         D3D11_TEXTURE2D_DESC desc;
   1612         desc.Width = width;
   1613         desc.Height = height;
   1614         desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
   1615         desc.ArraySize = depth;
   1616         desc.Format = mTextureFormat;
   1617         desc.SampleDesc.Count = 1;
   1618         desc.SampleDesc.Quality = 0;
   1619         desc.Usage = D3D11_USAGE_DEFAULT;
   1620         desc.BindFlags = getBindFlags();
   1621         desc.CPUAccessFlags = 0;
   1622         desc.MiscFlags = 0;
   1623 
   1624         HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
   1625 
   1626         // this can happen from windows TDR
   1627         if (d3d11::isDeviceLostError(result))
   1628         {
   1629             mRenderer->notifyDeviceLost();
   1630             gl::error(GL_OUT_OF_MEMORY);
   1631         }
   1632         else if (FAILED(result))
   1633         {
   1634             ASSERT(result == E_OUTOFMEMORY);
   1635             ERR("Creating image failed.");
   1636             gl::error(GL_OUT_OF_MEMORY);
   1637         }
   1638         else
   1639         {
   1640             mTexture->GetDesc(&desc);
   1641             mMipLevels = desc.MipLevels;
   1642             mTextureWidth = desc.Width;
   1643             mTextureHeight = desc.Height;
   1644             mTextureDepth = desc.ArraySize;
   1645         }
   1646     }
   1647 
   1648     initializeSerials(getLevelCount() * depth, depth);
   1649 }
   1650 
   1651 TextureStorage11_2DArray::~TextureStorage11_2DArray()
   1652 {
   1653     for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++)
   1654     {
   1655         bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this);
   1656         ASSERT(imageAssociationCorrect);
   1657 
   1658         if (imageAssociationCorrect)
   1659         {
   1660             // We must let the Images recover their data before we delete it from the TextureStorage.
   1661             i->second->recoverFromAssociatedStorage();
   1662         }
   1663     }
   1664     mAssociatedImages.clear();
   1665 
   1666     SafeRelease(mTexture);
   1667     SafeRelease(mSwizzleTexture);
   1668 
   1669     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
   1670     {
   1671         SafeRelease(mSwizzleRenderTargets[level]);
   1672     }
   1673 
   1674     for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
   1675     {
   1676         SafeDelete(i->second);
   1677     }
   1678     mRenderTargets.clear();
   1679 }
   1680 
   1681 TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage)
   1682 {
   1683     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage));
   1684     return static_cast<TextureStorage11_2DArray*>(storage);
   1685 }
   1686 
   1687 void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget)
   1688 {
   1689     ASSERT(0 <= level && level < getLevelCount());
   1690 
   1691     if (0 <= level && level < getLevelCount())
   1692     {
   1693         LevelLayerKey key(level, layerTarget);
   1694         mAssociatedImages[key] = image;
   1695     }
   1696 }
   1697 
   1698 bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
   1699 {
   1700     LevelLayerKey key(level, layerTarget);
   1701 
   1702     // This validation check should never return false. It means the Image/TextureStorage association is broken.
   1703     bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage));
   1704     ASSERT(retValue);
   1705     return retValue;
   1706 }
   1707 
   1708 // disassociateImage allows an Image to end its association with a Storage.
   1709 void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Image11* expectedImage)
   1710 {
   1711     LevelLayerKey key(level, layerTarget);
   1712 
   1713     bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage));
   1714     ASSERT(imageAssociationCorrect);
   1715 
   1716     if (imageAssociationCorrect)
   1717     {
   1718         mAssociatedImages[key] = NULL;
   1719     }
   1720 }
   1721 
   1722 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
   1723 void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
   1724 {
   1725     LevelLayerKey key(level, layerTarget);
   1726 
   1727     ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end());
   1728 
   1729     if (mAssociatedImages.find(key) != mAssociatedImages.end())
   1730     {
   1731         if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage)
   1732         {
   1733             // Ensure that the Image is still associated with this TextureStorage. This should be true.
   1734             bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this);
   1735             ASSERT(imageAssociationCorrect);
   1736 
   1737             if (imageAssociationCorrect)
   1738             {
   1739                 // Force the image to recover from storage before its data is overwritten.
   1740                 // This will reset mAssociatedImages[level] to NULL too.
   1741                 mAssociatedImages[key]->recoverFromAssociatedStorage();
   1742             }
   1743         }
   1744     }
   1745 }
   1746 
   1747 ID3D11Resource *TextureStorage11_2DArray::getResource() const
   1748 {
   1749     return mTexture;
   1750 }
   1751 
   1752 ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
   1753 {
   1754     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1755     srvDesc.Format = format;
   1756     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
   1757     srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
   1758     srvDesc.Texture2DArray.MipLevels = mipLevels;
   1759     srvDesc.Texture2DArray.FirstArraySlice = 0;
   1760     srvDesc.Texture2DArray.ArraySize = mTextureDepth;
   1761 
   1762     ID3D11ShaderResourceView *SRV = NULL;
   1763 
   1764     ID3D11Device *device = mRenderer->getDevice();
   1765     HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
   1766 
   1767     if (result == E_OUTOFMEMORY)
   1768     {
   1769         gl::error(GL_OUT_OF_MEMORY);
   1770     }
   1771     ASSERT(SUCCEEDED(result));
   1772 
   1773     return SRV;
   1774 }
   1775 
   1776 RenderTarget *TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index)
   1777 {
   1778     ASSERT(index.hasLayer());
   1779 
   1780     int mipLevel = index.mipIndex;
   1781     int layer = index.layerIndex;
   1782 
   1783     if (mipLevel >= 0 && mipLevel < getLevelCount())
   1784     {
   1785         LevelLayerKey key(mipLevel, layer);
   1786         if (mRenderTargets.find(key) == mRenderTargets.end())
   1787         {
   1788             ID3D11Device *device = mRenderer->getDevice();
   1789             HRESULT result;
   1790 
   1791             D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1792             srvDesc.Format = mShaderResourceFormat;
   1793             srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
   1794             srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel;
   1795             srvDesc.Texture2DArray.MipLevels = 1;
   1796             srvDesc.Texture2DArray.FirstArraySlice = layer;
   1797             srvDesc.Texture2DArray.ArraySize = 1;
   1798 
   1799             ID3D11ShaderResourceView *srv;
   1800             result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
   1801 
   1802             if (result == E_OUTOFMEMORY)
   1803             {
   1804                 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1805             }
   1806             ASSERT(SUCCEEDED(result));
   1807 
   1808             if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
   1809             {
   1810                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1811                 rtvDesc.Format = mRenderTargetFormat;
   1812                 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
   1813                 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
   1814                 rtvDesc.Texture2DArray.FirstArraySlice = layer;
   1815                 rtvDesc.Texture2DArray.ArraySize = 1;
   1816 
   1817                 ID3D11RenderTargetView *rtv;
   1818                 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
   1819 
   1820                 if (result == E_OUTOFMEMORY)
   1821                 {
   1822                     SafeRelease(srv);
   1823                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1824                 }
   1825                 ASSERT(SUCCEEDED(result));
   1826 
   1827                 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
   1828 
   1829                 // RenderTarget will take ownership of these resources
   1830                 SafeRelease(rtv);
   1831                 SafeRelease(srv);
   1832             }
   1833             else
   1834             {
   1835                 UNREACHABLE();
   1836             }
   1837         }
   1838 
   1839         return mRenderTargets[key];
   1840     }
   1841     else
   1842     {
   1843         return NULL;
   1844     }
   1845 }
   1846 
   1847 void TextureStorage11_2DArray::generateMipmaps()
   1848 {
   1849     // Base level must already be defined
   1850 
   1851     for (int level = 0; level < getLevelCount(); level++)
   1852     {
   1853         invalidateSwizzleCacheLevel(level);
   1854         for (unsigned int layer = 0; layer < mTextureDepth; layer++)
   1855         {
   1856             gl::ImageIndex sourceIndex = gl::ImageIndex::Make2DArray(level - 1, layer);
   1857             gl::ImageIndex destIndex = gl::ImageIndex::Make2DArray(level, layer);
   1858 
   1859             RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(sourceIndex));
   1860             RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
   1861 
   1862             generateMipmapLayer(source, dest);
   1863         }
   1864     }
   1865 }
   1866 
   1867 ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture()
   1868 {
   1869     if (!mSwizzleTexture)
   1870     {
   1871         ID3D11Device *device = mRenderer->getDevice();
   1872 
   1873         D3D11_TEXTURE2D_DESC desc;
   1874         desc.Width = mTextureWidth;
   1875         desc.Height = mTextureHeight;
   1876         desc.MipLevels = mMipLevels;
   1877         desc.ArraySize = mTextureDepth;
   1878         desc.Format = mSwizzleTextureFormat;
   1879         desc.SampleDesc.Count = 1;
   1880         desc.SampleDesc.Quality = 0;
   1881         desc.Usage = D3D11_USAGE_DEFAULT;
   1882         desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
   1883         desc.CPUAccessFlags = 0;
   1884         desc.MiscFlags = 0;
   1885 
   1886         HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
   1887 
   1888         if (result == E_OUTOFMEMORY)
   1889         {
   1890             return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
   1891         }
   1892         ASSERT(SUCCEEDED(result));
   1893     }
   1894 
   1895     return mSwizzleTexture;
   1896 }
   1897 
   1898 ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel)
   1899 {
   1900     if (mipLevel >= 0 && mipLevel < getLevelCount())
   1901     {
   1902         if (!mSwizzleRenderTargets[mipLevel])
   1903         {
   1904             ID3D11Resource *swizzleTexture = getSwizzleTexture();
   1905             if (!swizzleTexture)
   1906             {
   1907                 return NULL;
   1908             }
   1909 
   1910             ID3D11Device *device = mRenderer->getDevice();
   1911 
   1912             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1913             rtvDesc.Format = mSwizzleRenderTargetFormat;
   1914             rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
   1915             rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
   1916             rtvDesc.Texture2DArray.FirstArraySlice = 0;
   1917             rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
   1918 
   1919             HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
   1920 
   1921             if (result == E_OUTOFMEMORY)
   1922             {
   1923                 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
   1924             }
   1925             ASSERT(SUCCEEDED(result));
   1926         }
   1927 
   1928         return mSwizzleRenderTargets[mipLevel];
   1929     }
   1930     else
   1931     {
   1932         return NULL;
   1933     }
   1934 }
   1935 
   1936 }
   1937