gfx/angle/src/libGLESv2/renderer/TextureStorage11.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/libGLESv2/renderer/TextureStorage11.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,667 @@
     1.4 +#include "precompiled.h"
     1.5 +//
     1.6 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
     1.7 +// Use of this source code is governed by a BSD-style license that can be
     1.8 +// found in the LICENSE file.
     1.9 +//
    1.10 +
    1.11 +// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
    1.12 +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
    1.13 +
    1.14 +#include "libGLESv2/renderer/TextureStorage11.h"
    1.15 +
    1.16 +#include "libGLESv2/renderer/Renderer11.h"
    1.17 +#include "libGLESv2/renderer/RenderTarget11.h"
    1.18 +#include "libGLESv2/renderer/SwapChain11.h"
    1.19 +#include "libGLESv2/renderer/renderer11_utils.h"
    1.20 +
    1.21 +#include "libGLESv2/utilities.h"
    1.22 +#include "libGLESv2/main.h"
    1.23 +
    1.24 +namespace rx
    1.25 +{
    1.26 +
    1.27 +TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
    1.28 +    : mBindFlags(bindFlags),
    1.29 +      mLodOffset(0),
    1.30 +      mMipLevels(0),
    1.31 +      mTexture(NULL),
    1.32 +      mTextureFormat(DXGI_FORMAT_UNKNOWN),
    1.33 +      mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
    1.34 +      mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
    1.35 +      mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
    1.36 +      mSRV(NULL),
    1.37 +      mTextureWidth(0),
    1.38 +      mTextureHeight(0)
    1.39 +{
    1.40 +    mRenderer = Renderer11::makeRenderer11(renderer);
    1.41 +}
    1.42 +
    1.43 +TextureStorage11::~TextureStorage11()
    1.44 +{
    1.45 +}
    1.46 +
    1.47 +TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
    1.48 +{
    1.49 +    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
    1.50 +    return static_cast<TextureStorage11*>(storage);
    1.51 +}
    1.52 +
    1.53 +DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
    1.54 +{
    1.55 +    UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
    1.56 +    
    1.57 +    if (d3d11::IsDepthStencilFormat(format))
    1.58 +    {
    1.59 +        bindFlags |= D3D11_BIND_DEPTH_STENCIL;
    1.60 +    }
    1.61 +    else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
    1.62 +    {
    1.63 +        bindFlags |= D3D11_BIND_RENDER_TARGET;
    1.64 +    }
    1.65 +    return bindFlags;
    1.66 +}
    1.67 +
    1.68 +bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
    1.69 +{
    1.70 +    switch(format)
    1.71 +    {
    1.72 +      case DXGI_FORMAT_R8G8B8A8_UNORM:
    1.73 +      case DXGI_FORMAT_A8_UNORM:
    1.74 +      case DXGI_FORMAT_R32G32B32A32_FLOAT:
    1.75 +      case DXGI_FORMAT_R16G16B16A16_FLOAT:
    1.76 +      case DXGI_FORMAT_B8G8R8A8_UNORM:
    1.77 +      case DXGI_FORMAT_R8_UNORM:
    1.78 +      case DXGI_FORMAT_R8G8_UNORM:
    1.79 +      case DXGI_FORMAT_R16_FLOAT:
    1.80 +      case DXGI_FORMAT_R16G16_FLOAT:
    1.81 +        return true;
    1.82 +      case DXGI_FORMAT_BC1_UNORM:
    1.83 +      case DXGI_FORMAT_BC2_UNORM: 
    1.84 +      case DXGI_FORMAT_BC3_UNORM:
    1.85 +      case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices
    1.86 +        return false;
    1.87 +      default:
    1.88 +        UNREACHABLE();
    1.89 +        return false;
    1.90 +    }
    1.91 +}
    1.92 +
    1.93 +UINT TextureStorage11::getBindFlags() const
    1.94 +{
    1.95 +    return mBindFlags;
    1.96 +}
    1.97 +
    1.98 +ID3D11Texture2D *TextureStorage11::getBaseTexture() const
    1.99 +{
   1.100 +    return mTexture;
   1.101 +}
   1.102 +
   1.103 +int TextureStorage11::getLodOffset() const
   1.104 +{
   1.105 +    return mLodOffset;
   1.106 +}
   1.107 +
   1.108 +bool TextureStorage11::isRenderTarget() const
   1.109 +{
   1.110 +    return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
   1.111 +}
   1.112 +    
   1.113 +bool TextureStorage11::isManaged() const
   1.114 +{
   1.115 +    return false;
   1.116 +}
   1.117 +
   1.118 +int TextureStorage11::levelCount()
   1.119 +{
   1.120 +    int levels = 0;
   1.121 +    if (getBaseTexture())
   1.122 +    {
   1.123 +        levels = mMipLevels - getLodOffset();
   1.124 +    }
   1.125 +    return levels;
   1.126 +}
   1.127 +
   1.128 +UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
   1.129 +{
   1.130 +    UINT index = 0;
   1.131 +    if (getBaseTexture())
   1.132 +    {
   1.133 +        index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
   1.134 +    }
   1.135 +    return index;
   1.136 +}
   1.137 +
   1.138 +bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource,
   1.139 +                                              int level, int face, GLint xoffset, GLint yoffset,
   1.140 +                                              GLsizei width, GLsizei height)
   1.141 +{
   1.142 +    if (srcTexture)
   1.143 +    {
   1.144 +        // Round up the width and height to the nearest multiple of dimension alignment
   1.145 +        unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
   1.146 +        width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
   1.147 +        height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
   1.148 +
   1.149 +        D3D11_BOX srcBox;
   1.150 +        srcBox.left = xoffset;
   1.151 +        srcBox.top = yoffset;
   1.152 +        srcBox.right = xoffset + width;
   1.153 +        srcBox.bottom = yoffset + height;
   1.154 +        srcBox.front = 0;
   1.155 +        srcBox.back = 1;
   1.156 +
   1.157 +        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
   1.158 +        
   1.159 +        ASSERT(getBaseTexture());
   1.160 +        context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face),
   1.161 +                                       xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox);
   1.162 +        return true;
   1.163 +    }
   1.164 +
   1.165 +    return false;
   1.166 +}
   1.167 +
   1.168 +void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
   1.169 +{
   1.170 +    if (source && dest)
   1.171 +    {
   1.172 +        ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
   1.173 +        ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
   1.174 +
   1.175 +        if (sourceSRV && destRTV)
   1.176 +        {
   1.177 +            gl::Rectangle sourceArea;
   1.178 +            sourceArea.x = 0;
   1.179 +            sourceArea.y = 0;
   1.180 +            sourceArea.width = source->getWidth();
   1.181 +            sourceArea.height = source->getHeight();
   1.182 +
   1.183 +            gl::Rectangle destArea;
   1.184 +            destArea.x = 0;
   1.185 +            destArea.y = 0;
   1.186 +            destArea.width = dest->getWidth();
   1.187 +            destArea.height = dest->getHeight();
   1.188 +
   1.189 +            mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
   1.190 +                                   destRTV, destArea, dest->getWidth(), dest->getHeight(),
   1.191 +                                   GL_RGBA);
   1.192 +        }
   1.193 +    }
   1.194 +}
   1.195 +
   1.196 +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
   1.197 +    : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
   1.198 +{
   1.199 +    mTexture = swapchain->getOffscreenTexture();
   1.200 +    mSRV = swapchain->getRenderTargetShaderResource();
   1.201 +
   1.202 +    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
   1.203 +    {
   1.204 +        mRenderTarget[i] = NULL;
   1.205 +    }
   1.206 +
   1.207 +    D3D11_TEXTURE2D_DESC texDesc;
   1.208 +    mTexture->GetDesc(&texDesc);
   1.209 +    mMipLevels = texDesc.MipLevels;
   1.210 +    mTextureFormat = texDesc.Format;
   1.211 +    mTextureWidth = texDesc.Width;
   1.212 +    mTextureHeight = texDesc.Height;
   1.213 +
   1.214 +    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1.215 +    mSRV->GetDesc(&srvDesc);
   1.216 +    mShaderResourceFormat = srvDesc.Format;
   1.217 +
   1.218 +    ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
   1.219 +    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1.220 +    offscreenRTV->GetDesc(&rtvDesc);
   1.221 +    mRenderTargetFormat = rtvDesc.Format;
   1.222 +    offscreenRTV->Release();
   1.223 +
   1.224 +    mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
   1.225 +}
   1.226 +
   1.227 +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
   1.228 +    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
   1.229 +{
   1.230 +    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
   1.231 +    {
   1.232 +        mRenderTarget[i] = NULL;
   1.233 +    }
   1.234 +
   1.235 +    DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
   1.236 +    if (d3d11::IsDepthStencilFormat(convertedFormat))
   1.237 +    {
   1.238 +        mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
   1.239 +        mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
   1.240 +        mDepthStencilFormat = convertedFormat;
   1.241 +        mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
   1.242 +    }
   1.243 +    else
   1.244 +    {
   1.245 +        mTextureFormat = convertedFormat;
   1.246 +        mShaderResourceFormat = convertedFormat;
   1.247 +        mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
   1.248 +        mRenderTargetFormat = convertedFormat;
   1.249 +    }
   1.250 +
   1.251 +    // if the width or height is not positive this should be treated as an incomplete texture
   1.252 +    // we handle that here by skipping the d3d texture creation
   1.253 +    if (width > 0 && height > 0)
   1.254 +    {
   1.255 +        // adjust size if needed for compressed textures
   1.256 +        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
   1.257 +
   1.258 +        ID3D11Device *device = mRenderer->getDevice();
   1.259 +
   1.260 +        D3D11_TEXTURE2D_DESC desc;
   1.261 +        desc.Width = width;      // Compressed texture size constraints?
   1.262 +        desc.Height = height;
   1.263 +        desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
   1.264 +        desc.ArraySize = 1;
   1.265 +        desc.Format = mTextureFormat;
   1.266 +        desc.SampleDesc.Count = 1;
   1.267 +        desc.SampleDesc.Quality = 0;
   1.268 +        desc.Usage = D3D11_USAGE_DEFAULT;
   1.269 +        desc.BindFlags = getBindFlags();
   1.270 +        desc.CPUAccessFlags = 0;
   1.271 +        desc.MiscFlags = 0;
   1.272 +
   1.273 +        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
   1.274 +
   1.275 +        // this can happen from windows TDR
   1.276 +        if (d3d11::isDeviceLostError(result))
   1.277 +        {
   1.278 +            mRenderer->notifyDeviceLost();
   1.279 +            gl::error(GL_OUT_OF_MEMORY);
   1.280 +        }
   1.281 +        else if (FAILED(result))
   1.282 +        {
   1.283 +            ASSERT(result == E_OUTOFMEMORY);
   1.284 +            ERR("Creating image failed.");
   1.285 +            gl::error(GL_OUT_OF_MEMORY);
   1.286 +        }
   1.287 +        else
   1.288 +        {
   1.289 +            mTexture->GetDesc(&desc);
   1.290 +            mMipLevels = desc.MipLevels;
   1.291 +            mTextureWidth = desc.Width;
   1.292 +            mTextureHeight = desc.Height;
   1.293 +        }
   1.294 +    }
   1.295 +}
   1.296 +
   1.297 +TextureStorage11_2D::~TextureStorage11_2D()
   1.298 +{
   1.299 +    if (mTexture)
   1.300 +    {
   1.301 +        mTexture->Release();
   1.302 +        mTexture = NULL;
   1.303 +    }
   1.304 +
   1.305 +    if (mSRV)
   1.306 +    {
   1.307 +        mSRV->Release();
   1.308 +        mSRV = NULL;
   1.309 +    }
   1.310 +
   1.311 +    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
   1.312 +    {
   1.313 +        delete mRenderTarget[i];
   1.314 +        mRenderTarget[i] = NULL;
   1.315 +    }
   1.316 +}
   1.317 +
   1.318 +TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
   1.319 +{
   1.320 +    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
   1.321 +    return static_cast<TextureStorage11_2D*>(storage);
   1.322 +}
   1.323 +
   1.324 +RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
   1.325 +{
   1.326 +    if (level >= 0 && level < static_cast<int>(mMipLevels))
   1.327 +    {
   1.328 +        if (!mRenderTarget[level])
   1.329 +        {
   1.330 +            ID3D11Device *device = mRenderer->getDevice();
   1.331 +            HRESULT result;
   1.332 +
   1.333 +            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1.334 +            srvDesc.Format = mShaderResourceFormat;
   1.335 +            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
   1.336 +            srvDesc.Texture2D.MostDetailedMip = level;
   1.337 +            srvDesc.Texture2D.MipLevels = 1;
   1.338 +
   1.339 +            ID3D11ShaderResourceView *srv;
   1.340 +            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
   1.341 +
   1.342 +            if (result == E_OUTOFMEMORY)
   1.343 +            {
   1.344 +                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1.345 +            }
   1.346 +            ASSERT(SUCCEEDED(result));
   1.347 +
   1.348 +            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
   1.349 +            {
   1.350 +                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1.351 +                rtvDesc.Format = mRenderTargetFormat;
   1.352 +                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
   1.353 +                rtvDesc.Texture2D.MipSlice = level;
   1.354 +
   1.355 +                ID3D11RenderTargetView *rtv;
   1.356 +                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
   1.357 +
   1.358 +                if (result == E_OUTOFMEMORY)
   1.359 +                {
   1.360 +                    srv->Release();
   1.361 +                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1.362 +                }
   1.363 +                ASSERT(SUCCEEDED(result));
   1.364 +
   1.365 +                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
   1.366 +                // also needs to keep a reference to the texture.
   1.367 +                mTexture->AddRef();
   1.368 +
   1.369 +                mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
   1.370 +                                                          std::max(mTextureWidth >> level, 1U),
   1.371 +                                                          std::max(mTextureHeight >> level, 1U));
   1.372 +            }
   1.373 +            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
   1.374 +            {
   1.375 +                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
   1.376 +                dsvDesc.Format = mDepthStencilFormat;
   1.377 +                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
   1.378 +                dsvDesc.Texture2D.MipSlice = level;
   1.379 +                dsvDesc.Flags = 0;
   1.380 +
   1.381 +                ID3D11DepthStencilView *dsv;
   1.382 +                result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
   1.383 +
   1.384 +                if (result == E_OUTOFMEMORY)
   1.385 +                {
   1.386 +                    srv->Release();
   1.387 +                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1.388 +                }
   1.389 +                ASSERT(SUCCEEDED(result));
   1.390 +
   1.391 +                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
   1.392 +                // also needs to keep a reference to the texture.
   1.393 +                mTexture->AddRef();
   1.394 +
   1.395 +                mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
   1.396 +                                                          std::max(mTextureWidth >> level, 1U),
   1.397 +                                                          std::max(mTextureHeight >> level, 1U));
   1.398 +            }
   1.399 +            else
   1.400 +            {
   1.401 +                UNREACHABLE();
   1.402 +            }
   1.403 +        }
   1.404 +
   1.405 +        return mRenderTarget[level];
   1.406 +    }
   1.407 +    else
   1.408 +    {
   1.409 +        return NULL;
   1.410 +    }
   1.411 +}
   1.412 +
   1.413 +ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
   1.414 +{
   1.415 +    if (!mSRV)
   1.416 +    {
   1.417 +        ID3D11Device *device = mRenderer->getDevice();
   1.418 +
   1.419 +        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1.420 +        srvDesc.Format = mShaderResourceFormat;
   1.421 +        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
   1.422 +        srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
   1.423 +        srvDesc.Texture2D.MostDetailedMip = 0;
   1.424 +
   1.425 +        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
   1.426 +
   1.427 +        if (result == E_OUTOFMEMORY)
   1.428 +        {
   1.429 +            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
   1.430 +        }
   1.431 +        ASSERT(SUCCEEDED(result));
   1.432 +    }
   1.433 +
   1.434 +    return mSRV;
   1.435 +}
   1.436 +
   1.437 +void TextureStorage11_2D::generateMipmap(int level)
   1.438 +{
   1.439 +    RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
   1.440 +    RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
   1.441 +
   1.442 +    generateMipmapLayer(source, dest);
   1.443 +}
   1.444 +
   1.445 +TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
   1.446 +    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
   1.447 +{
   1.448 +    for (unsigned int i = 0; i < 6; i++)
   1.449 +    {
   1.450 +        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
   1.451 +        {
   1.452 +            mRenderTarget[i][j] = NULL;
   1.453 +        }
   1.454 +    }
   1.455 +
   1.456 +    DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
   1.457 +    if (d3d11::IsDepthStencilFormat(convertedFormat))
   1.458 +    {
   1.459 +        mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
   1.460 +        mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
   1.461 +        mDepthStencilFormat = convertedFormat;
   1.462 +        mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
   1.463 +    }
   1.464 +    else
   1.465 +    {
   1.466 +        mTextureFormat = convertedFormat;
   1.467 +        mShaderResourceFormat = convertedFormat;
   1.468 +        mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
   1.469 +        mRenderTargetFormat = convertedFormat;
   1.470 +    }
   1.471 +
   1.472 +    // if the size is not positive this should be treated as an incomplete texture
   1.473 +    // we handle that here by skipping the d3d texture creation
   1.474 +    if (size > 0)
   1.475 +    {
   1.476 +        // adjust size if needed for compressed textures
   1.477 +        int height = size;
   1.478 +        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
   1.479 +
   1.480 +        ID3D11Device *device = mRenderer->getDevice();
   1.481 +
   1.482 +        D3D11_TEXTURE2D_DESC desc;
   1.483 +        desc.Width = size;
   1.484 +        desc.Height = size;
   1.485 +        desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
   1.486 +        desc.ArraySize = 6;
   1.487 +        desc.Format = mTextureFormat;
   1.488 +        desc.SampleDesc.Count = 1;
   1.489 +        desc.SampleDesc.Quality = 0;
   1.490 +        desc.Usage = D3D11_USAGE_DEFAULT;
   1.491 +        desc.BindFlags = getBindFlags();
   1.492 +        desc.CPUAccessFlags = 0;
   1.493 +        desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
   1.494 +
   1.495 +        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
   1.496 +
   1.497 +        if (FAILED(result))
   1.498 +        {
   1.499 +            ASSERT(result == E_OUTOFMEMORY);
   1.500 +            ERR("Creating image failed.");
   1.501 +            gl::error(GL_OUT_OF_MEMORY);
   1.502 +        }
   1.503 +        else
   1.504 +        {
   1.505 +            mTexture->GetDesc(&desc);
   1.506 +            mMipLevels = desc.MipLevels;
   1.507 +            mTextureWidth = desc.Width;
   1.508 +            mTextureHeight = desc.Height;
   1.509 +        }
   1.510 +    }
   1.511 +}
   1.512 +
   1.513 +TextureStorage11_Cube::~TextureStorage11_Cube()
   1.514 +{
   1.515 +    if (mTexture)
   1.516 +    {
   1.517 +        mTexture->Release();
   1.518 +        mTexture = NULL;
   1.519 +    }
   1.520 +
   1.521 +    if (mSRV)
   1.522 +    {
   1.523 +        mSRV->Release();
   1.524 +        mSRV = NULL;
   1.525 +    }
   1.526 +
   1.527 +    for (unsigned int i = 0; i < 6; i++)
   1.528 +    {
   1.529 +        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
   1.530 +        {
   1.531 +            delete mRenderTarget[i][j];
   1.532 +            mRenderTarget[i][j] = NULL;
   1.533 +        }
   1.534 +    }
   1.535 +}
   1.536 +
   1.537 +TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
   1.538 +{
   1.539 +    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
   1.540 +    return static_cast<TextureStorage11_Cube*>(storage);
   1.541 +}
   1.542 +
   1.543 +RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
   1.544 +{
   1.545 +    unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
   1.546 +    if (level >= 0 && level < static_cast<int>(mMipLevels))
   1.547 +    {
   1.548 +        if (!mRenderTarget[faceIdx][level])
   1.549 +        {
   1.550 +            ID3D11Device *device = mRenderer->getDevice();
   1.551 +            HRESULT result;
   1.552 +
   1.553 +            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1.554 +            srvDesc.Format = mShaderResourceFormat;
   1.555 +            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
   1.556 +            srvDesc.Texture2DArray.MostDetailedMip = level;
   1.557 +            srvDesc.Texture2DArray.MipLevels = 1;
   1.558 +            srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
   1.559 +            srvDesc.Texture2DArray.ArraySize = 1;
   1.560 +
   1.561 +            ID3D11ShaderResourceView *srv;
   1.562 +            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
   1.563 +
   1.564 +            if (result == E_OUTOFMEMORY)
   1.565 +            {
   1.566 +                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1.567 +            }
   1.568 +            ASSERT(SUCCEEDED(result));
   1.569 +
   1.570 +            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
   1.571 +            {
   1.572 +                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
   1.573 +                rtvDesc.Format = mRenderTargetFormat;
   1.574 +                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
   1.575 +                rtvDesc.Texture2DArray.MipSlice = level;
   1.576 +                rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
   1.577 +                rtvDesc.Texture2DArray.ArraySize = 1;
   1.578 +
   1.579 +                ID3D11RenderTargetView *rtv;
   1.580 +                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
   1.581 +
   1.582 +                if (result == E_OUTOFMEMORY)
   1.583 +                {
   1.584 +                    srv->Release();
   1.585 +                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1.586 +                }
   1.587 +                ASSERT(SUCCEEDED(result));
   1.588 +
   1.589 +                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
   1.590 +                // also needs to keep a reference to the texture.
   1.591 +                mTexture->AddRef();
   1.592 +
   1.593 +                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
   1.594 +                                                                   std::max(mTextureWidth >> level, 1U),
   1.595 +                                                                   std::max(mTextureHeight >> level, 1U));
   1.596 +            }
   1.597 +            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
   1.598 +            {
   1.599 +                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
   1.600 +                dsvDesc.Format = mRenderTargetFormat;
   1.601 +                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
   1.602 +                dsvDesc.Texture2DArray.MipSlice = level;
   1.603 +                dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
   1.604 +                dsvDesc.Texture2DArray.ArraySize = 1;
   1.605 +
   1.606 +                ID3D11DepthStencilView *dsv;
   1.607 +                result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
   1.608 +
   1.609 +                if (result == E_OUTOFMEMORY)
   1.610 +                {
   1.611 +                    srv->Release();
   1.612 +                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
   1.613 +                }
   1.614 +                ASSERT(SUCCEEDED(result));
   1.615 +
   1.616 +                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
   1.617 +                // also needs to keep a reference to the texture.
   1.618 +                mTexture->AddRef();
   1.619 +
   1.620 +                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
   1.621 +                                                                   std::max(mTextureWidth >> level, 1U),
   1.622 +                                                                   std::max(mTextureHeight >> level, 1U));
   1.623 +            }
   1.624 +            else
   1.625 +            {
   1.626 +                UNREACHABLE();
   1.627 +            }
   1.628 +        }
   1.629 +
   1.630 +        return mRenderTarget[faceIdx][level];
   1.631 +    }
   1.632 +    else
   1.633 +    {
   1.634 +        return NULL;
   1.635 +    }
   1.636 +}
   1.637 +
   1.638 +ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
   1.639 +{
   1.640 +    if (!mSRV)
   1.641 +    {
   1.642 +        ID3D11Device *device = mRenderer->getDevice();
   1.643 +
   1.644 +        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
   1.645 +        srvDesc.Format = mShaderResourceFormat;
   1.646 +        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
   1.647 +        srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
   1.648 +        srvDesc.TextureCube.MostDetailedMip = 0;
   1.649 +
   1.650 +        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
   1.651 +
   1.652 +        if (result == E_OUTOFMEMORY)
   1.653 +        {
   1.654 +            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
   1.655 +        }
   1.656 +        ASSERT(SUCCEEDED(result));
   1.657 +    }
   1.658 +
   1.659 +    return mSRV;
   1.660 +}
   1.661 +
   1.662 +void TextureStorage11_Cube::generateMipmap(int face, int level)
   1.663 +{
   1.664 +    RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
   1.665 +    RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
   1.666 +
   1.667 +    generateMipmapLayer(source, dest);
   1.668 +}
   1.669 +
   1.670 +}

mercurial