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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial