1 #include "precompiled.h" 2 // 3 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 8 // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived 9 // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. 10 11 #include "libGLESv2/renderer/TextureStorage11.h" 12 13 #include "libGLESv2/renderer/Renderer11.h" 14 #include "libGLESv2/renderer/RenderTarget11.h" 15 #include "libGLESv2/renderer/SwapChain11.h" 16 #include "libGLESv2/renderer/renderer11_utils.h" 17 18 #include "libGLESv2/utilities.h" 19 #include "libGLESv2/main.h" 20 21 namespace rx 22 { 23 24 TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) 25 : mBindFlags(bindFlags), 26 mLodOffset(0), 27 mMipLevels(0), 28 mTexture(NULL), 29 mTextureFormat(DXGI_FORMAT_UNKNOWN), 30 mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), 31 mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), 32 mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), 33 mSRV(NULL), 34 mTextureWidth(0), 35 mTextureHeight(0) 36 { 37 mRenderer = Renderer11::makeRenderer11(renderer); 38 } 39 40 TextureStorage11::~TextureStorage11() 41 { 42 } 43 44 TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) 45 { 46 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); 47 return static_cast<TextureStorage11*>(storage); 48 } 49 50 DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable) 51 { 52 UINT bindFlags = D3D11_BIND_SHADER_RESOURCE; 53 54 if (d3d11::IsDepthStencilFormat(format)) 55 { 56 bindFlags |= D3D11_BIND_DEPTH_STENCIL; 57 } 58 else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) 59 { 60 bindFlags |= D3D11_BIND_RENDER_TARGET; 61 } 62 return bindFlags; 63 } 64 65 bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) 66 { 67 switch(format) 68 { 69 case DXGI_FORMAT_R8G8B8A8_UNORM: 70 case DXGI_FORMAT_A8_UNORM: 71 case DXGI_FORMAT_R32G32B32A32_FLOAT: 72 case DXGI_FORMAT_R16G16B16A16_FLOAT: 73 case DXGI_FORMAT_B8G8R8A8_UNORM: 74 case DXGI_FORMAT_R8_UNORM: 75 case DXGI_FORMAT_R8G8_UNORM: 76 case DXGI_FORMAT_R16_FLOAT: 77 case DXGI_FORMAT_R16G16_FLOAT: 78 return true; 79 case DXGI_FORMAT_BC1_UNORM: 80 case DXGI_FORMAT_BC2_UNORM: 81 case DXGI_FORMAT_BC3_UNORM: 82 case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices 83 return false; 84 default: 85 UNREACHABLE(); 86 return false; 87 } 88 } 89 90 UINT TextureStorage11::getBindFlags() const 91 { 92 return mBindFlags; 93 } 94 95 ID3D11Texture2D *TextureStorage11::getBaseTexture() const 96 { 97 return mTexture; 98 } 99 100 int TextureStorage11::getLodOffset() const 101 { 102 return mLodOffset; 103 } 104 105 bool TextureStorage11::isRenderTarget() const 106 { 107 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; 108 } 109 110 bool TextureStorage11::isManaged() const 111 { 112 return false; 113 } 114 115 int TextureStorage11::levelCount() 116 { 117 int levels = 0; 118 if (getBaseTexture()) 119 { 120 levels = mMipLevels - getLodOffset(); 121 } 122 return levels; 123 } 124 125 UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex) 126 { 127 UINT index = 0; 128 if (getBaseTexture()) 129 { 130 index = D3D11CalcSubresource(level, faceIndex, mMipLevels); 131 } 132 return index; 133 } 134 135 bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource, 136 int level, int face, GLint xoffset, GLint yoffset, 137 GLsizei width, GLsizei height) 138 { 139 if (srcTexture) 140 { 141 // Round up the width and height to the nearest multiple of dimension alignment 142 unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat); 143 width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment; 144 height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment; 145 146 D3D11_BOX srcBox; 147 srcBox.left = xoffset; 148 srcBox.top = yoffset; 149 srcBox.right = xoffset + width; 150 srcBox.bottom = yoffset + height; 151 srcBox.front = 0; 152 srcBox.back = 1; 153 154 ID3D11DeviceContext *context = mRenderer->getDeviceContext(); 155 156 ASSERT(getBaseTexture()); 157 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face), 158 xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox); 159 return true; 160 } 161 162 return false; 163 } 164 165 void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) 166 { 167 if (source && dest) 168 { 169 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); 170 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); 171 172 if (sourceSRV && destRTV) 173 { 174 gl::Rectangle sourceArea; 175 sourceArea.x = 0; 176 sourceArea.y = 0; 177 sourceArea.width = source->getWidth(); 178 sourceArea.height = source->getHeight(); 179 180 gl::Rectangle destArea; 181 destArea.x = 0; 182 destArea.y = 0; 183 destArea.width = dest->getWidth(); 184 destArea.height = dest->getHeight(); 185 186 mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), 187 destRTV, destArea, dest->getWidth(), dest->getHeight(), 188 GL_RGBA); 189 } 190 } 191 } 192 193 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) 194 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) 195 { 196 mTexture = swapchain->getOffscreenTexture(); 197 mSRV = swapchain->getRenderTargetShaderResource(); 198 199 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 200 { 201 mRenderTarget[i] = NULL; 202 } 203 204 D3D11_TEXTURE2D_DESC texDesc; 205 mTexture->GetDesc(&texDesc); 206 mMipLevels = texDesc.MipLevels; 207 mTextureFormat = texDesc.Format; 208 mTextureWidth = texDesc.Width; 209 mTextureHeight = texDesc.Height; 210 211 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 212 mSRV->GetDesc(&srvDesc); 213 mShaderResourceFormat = srvDesc.Format; 214 215 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); 216 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 217 offscreenRTV->GetDesc(&rtvDesc); 218 mRenderTargetFormat = rtvDesc.Format; 219 offscreenRTV->Release(); 220 221 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; 222 } 223 224 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) 225 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) 226 { 227 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 228 { 229 mRenderTarget[i] = NULL; 230 } 231 232 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); 233 if (d3d11::IsDepthStencilFormat(convertedFormat)) 234 { 235 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); 236 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); 237 mDepthStencilFormat = convertedFormat; 238 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; 239 } 240 else 241 { 242 mTextureFormat = convertedFormat; 243 mShaderResourceFormat = convertedFormat; 244 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; 245 mRenderTargetFormat = convertedFormat; 246 } 247 248 // if the width or height is not positive this should be treated as an incomplete texture 249 // we handle that here by skipping the d3d texture creation 250 if (width > 0 && height > 0) 251 { 252 // adjust size if needed for compressed textures 253 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); 254 255 ID3D11Device *device = mRenderer->getDevice(); 256 257 D3D11_TEXTURE2D_DESC desc; 258 desc.Width = width; // Compressed texture size constraints? 259 desc.Height = height; 260 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; 261 desc.ArraySize = 1; 262 desc.Format = mTextureFormat; 263 desc.SampleDesc.Count = 1; 264 desc.SampleDesc.Quality = 0; 265 desc.Usage = D3D11_USAGE_DEFAULT; 266 desc.BindFlags = getBindFlags(); 267 desc.CPUAccessFlags = 0; 268 desc.MiscFlags = 0; 269 270 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); 271 272 // this can happen from windows TDR 273 if (d3d11::isDeviceLostError(result)) 274 { 275 mRenderer->notifyDeviceLost(); 276 gl::error(GL_OUT_OF_MEMORY); 277 } 278 else if (FAILED(result)) 279 { 280 ASSERT(result == E_OUTOFMEMORY); 281 ERR("Creating image failed."); 282 gl::error(GL_OUT_OF_MEMORY); 283 } 284 else 285 { 286 mTexture->GetDesc(&desc); 287 mMipLevels = desc.MipLevels; 288 mTextureWidth = desc.Width; 289 mTextureHeight = desc.Height; 290 } 291 } 292 } 293 294 TextureStorage11_2D::~TextureStorage11_2D() 295 { 296 if (mTexture) 297 { 298 mTexture->Release(); 299 mTexture = NULL; 300 } 301 302 if (mSRV) 303 { 304 mSRV->Release(); 305 mSRV = NULL; 306 } 307 308 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) 309 { 310 delete mRenderTarget[i]; 311 mRenderTarget[i] = NULL; 312 } 313 } 314 315 TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) 316 { 317 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); 318 return static_cast<TextureStorage11_2D*>(storage); 319 } 320 321 RenderTarget *TextureStorage11_2D::getRenderTarget(int level) 322 { 323 if (level >= 0 && level < static_cast<int>(mMipLevels)) 324 { 325 if (!mRenderTarget[level]) 326 { 327 ID3D11Device *device = mRenderer->getDevice(); 328 HRESULT result; 329 330 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 331 srvDesc.Format = mShaderResourceFormat; 332 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 333 srvDesc.Texture2D.MostDetailedMip = level; 334 srvDesc.Texture2D.MipLevels = 1; 335 336 ID3D11ShaderResourceView *srv; 337 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); 338 339 if (result == E_OUTOFMEMORY) 340 { 341 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 342 } 343 ASSERT(SUCCEEDED(result)); 344 345 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) 346 { 347 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 348 rtvDesc.Format = mRenderTargetFormat; 349 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; 350 rtvDesc.Texture2D.MipSlice = level; 351 352 ID3D11RenderTargetView *rtv; 353 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); 354 355 if (result == E_OUTOFMEMORY) 356 { 357 srv->Release(); 358 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 359 } 360 ASSERT(SUCCEEDED(result)); 361 362 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 363 // also needs to keep a reference to the texture. 364 mTexture->AddRef(); 365 366 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, 367 std::max(mTextureWidth >> level, 1U), 368 std::max(mTextureHeight >> level, 1U)); 369 } 370 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) 371 { 372 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; 373 dsvDesc.Format = mDepthStencilFormat; 374 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 375 dsvDesc.Texture2D.MipSlice = level; 376 dsvDesc.Flags = 0; 377 378 ID3D11DepthStencilView *dsv; 379 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); 380 381 if (result == E_OUTOFMEMORY) 382 { 383 srv->Release(); 384 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 385 } 386 ASSERT(SUCCEEDED(result)); 387 388 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 389 // also needs to keep a reference to the texture. 390 mTexture->AddRef(); 391 392 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, 393 std::max(mTextureWidth >> level, 1U), 394 std::max(mTextureHeight >> level, 1U)); 395 } 396 else 397 { 398 UNREACHABLE(); 399 } 400 } 401 402 return mRenderTarget[level]; 403 } 404 else 405 { 406 return NULL; 407 } 408 } 409 410 ID3D11ShaderResourceView *TextureStorage11_2D::getSRV() 411 { 412 if (!mSRV) 413 { 414 ID3D11Device *device = mRenderer->getDevice(); 415 416 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 417 srvDesc.Format = mShaderResourceFormat; 418 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 419 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); 420 srvDesc.Texture2D.MostDetailedMip = 0; 421 422 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); 423 424 if (result == E_OUTOFMEMORY) 425 { 426 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL)); 427 } 428 ASSERT(SUCCEEDED(result)); 429 } 430 431 return mSRV; 432 } 433 434 void TextureStorage11_2D::generateMipmap(int level) 435 { 436 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); 437 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); 438 439 generateMipmapLayer(source, dest); 440 } 441 442 TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) 443 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) 444 { 445 for (unsigned int i = 0; i < 6; i++) 446 { 447 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) 448 { 449 mRenderTarget[i][j] = NULL; 450 } 451 } 452 453 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); 454 if (d3d11::IsDepthStencilFormat(convertedFormat)) 455 { 456 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); 457 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); 458 mDepthStencilFormat = convertedFormat; 459 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; 460 } 461 else 462 { 463 mTextureFormat = convertedFormat; 464 mShaderResourceFormat = convertedFormat; 465 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; 466 mRenderTargetFormat = convertedFormat; 467 } 468 469 // if the size is not positive this should be treated as an incomplete texture 470 // we handle that here by skipping the d3d texture creation 471 if (size > 0) 472 { 473 // adjust size if needed for compressed textures 474 int height = size; 475 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); 476 477 ID3D11Device *device = mRenderer->getDevice(); 478 479 D3D11_TEXTURE2D_DESC desc; 480 desc.Width = size; 481 desc.Height = size; 482 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; 483 desc.ArraySize = 6; 484 desc.Format = mTextureFormat; 485 desc.SampleDesc.Count = 1; 486 desc.SampleDesc.Quality = 0; 487 desc.Usage = D3D11_USAGE_DEFAULT; 488 desc.BindFlags = getBindFlags(); 489 desc.CPUAccessFlags = 0; 490 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; 491 492 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); 493 494 if (FAILED(result)) 495 { 496 ASSERT(result == E_OUTOFMEMORY); 497 ERR("Creating image failed."); 498 gl::error(GL_OUT_OF_MEMORY); 499 } 500 else 501 { 502 mTexture->GetDesc(&desc); 503 mMipLevels = desc.MipLevels; 504 mTextureWidth = desc.Width; 505 mTextureHeight = desc.Height; 506 } 507 } 508 } 509 510 TextureStorage11_Cube::~TextureStorage11_Cube() 511 { 512 if (mTexture) 513 { 514 mTexture->Release(); 515 mTexture = NULL; 516 } 517 518 if (mSRV) 519 { 520 mSRV->Release(); 521 mSRV = NULL; 522 } 523 524 for (unsigned int i = 0; i < 6; i++) 525 { 526 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) 527 { 528 delete mRenderTarget[i][j]; 529 mRenderTarget[i][j] = NULL; 530 } 531 } 532 } 533 534 TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) 535 { 536 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); 537 return static_cast<TextureStorage11_Cube*>(storage); 538 } 539 540 RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level) 541 { 542 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget); 543 if (level >= 0 && level < static_cast<int>(mMipLevels)) 544 { 545 if (!mRenderTarget[faceIdx][level]) 546 { 547 ID3D11Device *device = mRenderer->getDevice(); 548 HRESULT result; 549 550 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 551 srvDesc.Format = mShaderResourceFormat; 552 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube 553 srvDesc.Texture2DArray.MostDetailedMip = level; 554 srvDesc.Texture2DArray.MipLevels = 1; 555 srvDesc.Texture2DArray.FirstArraySlice = faceIdx; 556 srvDesc.Texture2DArray.ArraySize = 1; 557 558 ID3D11ShaderResourceView *srv; 559 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); 560 561 if (result == E_OUTOFMEMORY) 562 { 563 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 564 } 565 ASSERT(SUCCEEDED(result)); 566 567 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) 568 { 569 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; 570 rtvDesc.Format = mRenderTargetFormat; 571 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; 572 rtvDesc.Texture2DArray.MipSlice = level; 573 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx; 574 rtvDesc.Texture2DArray.ArraySize = 1; 575 576 ID3D11RenderTargetView *rtv; 577 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); 578 579 if (result == E_OUTOFMEMORY) 580 { 581 srv->Release(); 582 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 583 } 584 ASSERT(SUCCEEDED(result)); 585 586 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 587 // also needs to keep a reference to the texture. 588 mTexture->AddRef(); 589 590 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, 591 std::max(mTextureWidth >> level, 1U), 592 std::max(mTextureHeight >> level, 1U)); 593 } 594 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) 595 { 596 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; 597 dsvDesc.Format = mRenderTargetFormat; 598 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; 599 dsvDesc.Texture2DArray.MipSlice = level; 600 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx; 601 dsvDesc.Texture2DArray.ArraySize = 1; 602 603 ID3D11DepthStencilView *dsv; 604 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); 605 606 if (result == E_OUTOFMEMORY) 607 { 608 srv->Release(); 609 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); 610 } 611 ASSERT(SUCCEEDED(result)); 612 613 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 614 // also needs to keep a reference to the texture. 615 mTexture->AddRef(); 616 617 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, 618 std::max(mTextureWidth >> level, 1U), 619 std::max(mTextureHeight >> level, 1U)); 620 } 621 else 622 { 623 UNREACHABLE(); 624 } 625 } 626 627 return mRenderTarget[faceIdx][level]; 628 } 629 else 630 { 631 return NULL; 632 } 633 } 634 635 ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV() 636 { 637 if (!mSRV) 638 { 639 ID3D11Device *device = mRenderer->getDevice(); 640 641 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 642 srvDesc.Format = mShaderResourceFormat; 643 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; 644 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); 645 srvDesc.TextureCube.MostDetailedMip = 0; 646 647 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); 648 649 if (result == E_OUTOFMEMORY) 650 { 651 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL)); 652 } 653 ASSERT(SUCCEEDED(result)); 654 } 655 656 return mSRV; 657 } 658 659 void TextureStorage11_Cube::generateMipmap(int face, int level) 660 { 661 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1)); 662 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level)); 663 664 generateMipmapLayer(source, dest); 665 } 666 667 } 668