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 +}