blob: b957d84796fb524f243046d6ee0e852e12a72d31 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com4834ee22013-01-11 04:06:16 +00002//
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
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000018#include "libGLESv2/utilities.h"
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000019#include "libGLESv2/main.h"
20
21namespace rx
22{
23
24TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
25 : mBindFlags(bindFlags),
daniel@transgaming.comb1154552013-01-11 04:11:02 +000026 mLodOffset(0),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000027 mMipLevels(0),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000028 mTextureFormat(DXGI_FORMAT_UNKNOWN),
29 mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
30 mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
31 mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
shannon.woods@transgaming.com96c21ee2013-02-28 23:13:45 +000032 mSRV(NULL),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000033 mTextureWidth(0),
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +000034 mTextureHeight(0),
35 mTextureDepth(0)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000036{
37 mRenderer = Renderer11::makeRenderer11(renderer);
38}
39
40TextureStorage11::~TextureStorage11()
41{
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +000042}
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000043
44TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
45{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000046 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000047 return static_cast<TextureStorage11*>(storage);
48}
49
50DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
51{
52 UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
53
shannon.woods@transgaming.comeec5c632013-02-28 23:04:21 +000054 if (d3d11::IsDepthStencilFormat(format))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000055 {
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
65bool 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_R32G32B32_FLOAT:
73 case DXGI_FORMAT_R16G16B16A16_FLOAT:
74 case DXGI_FORMAT_B8G8R8A8_UNORM:
75 case DXGI_FORMAT_R8_UNORM:
76 case DXGI_FORMAT_R8G8_UNORM:
77 case DXGI_FORMAT_R16_FLOAT:
78 case DXGI_FORMAT_R16G16_FLOAT:
79 return true;
80 case DXGI_FORMAT_BC1_UNORM:
81 case DXGI_FORMAT_BC2_UNORM:
82 case DXGI_FORMAT_BC3_UNORM:
83 return false;
84 default:
85 UNREACHABLE();
86 return false;
87 }
88}
89
90UINT TextureStorage11::getBindFlags() const
91{
92 return mBindFlags;
93}
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000094int TextureStorage11::getLodOffset() const
95{
96 return mLodOffset;
97}
98
99bool TextureStorage11::isRenderTarget() const
100{
101 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
102}
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000103
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000104bool TextureStorage11::isManaged() const
105{
106 return false;
107}
108
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000109int TextureStorage11::levelCount()
110{
111 int levels = 0;
112 if (getBaseTexture())
113 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000114 levels = mMipLevels - getLodOffset();
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000115 }
116 return levels;
117}
118
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000119UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget)
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000120{
121 UINT index = 0;
122 if (getBaseTexture())
123 {
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000124 index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000125 }
126 return index;
127}
128
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000129bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000130 int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000131 GLsizei width, GLsizei height, GLsizei depth)
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000132{
133 if (srcTexture)
134 {
shannon.woods@transgaming.com7ae9e7f2013-02-28 23:13:27 +0000135 // Round up the width and height to the nearest multiple of dimension alignment
136 unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
137 width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
138 height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
139
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000140 D3D11_BOX srcBox;
141 srcBox.left = xoffset;
142 srcBox.top = yoffset;
143 srcBox.right = xoffset + width;
144 srcBox.bottom = yoffset + height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000145 srcBox.front = zoffset;
146 srcBox.back = zoffset + depth;
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000147
148 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000149
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000150 ASSERT(getBaseTexture());
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000151 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, layerTarget),
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000152 xoffset, yoffset, zoffset, srcTexture, sourceSubresource, &srcBox);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000153 return true;
154 }
155
156 return false;
157}
158
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000159void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
160{
161 if (source && dest)
162 {
163 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
164 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
165
166 if (sourceSRV && destRTV)
167 {
168 gl::Rectangle sourceArea;
169 sourceArea.x = 0;
170 sourceArea.y = 0;
171 sourceArea.width = source->getWidth();
172 sourceArea.height = source->getHeight();
173
174 gl::Rectangle destArea;
175 destArea.x = 0;
176 destArea.y = 0;
177 destArea.width = dest->getWidth();
178 destArea.height = dest->getHeight();
179
180 mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
181 destRTV, destArea, dest->getWidth(), dest->getHeight(),
182 GL_RGBA);
183 }
184
185 if (sourceSRV)
186 {
187 sourceSRV->Release();
188 }
189 if (destRTV)
190 {
191 destRTV->Release();
192 }
193 }
194}
195
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000196TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
197 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
198{
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000199 mTexture = swapchain->getOffscreenTexture();
200 mSRV = swapchain->getRenderTargetShaderResource();
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000201
202 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
203 {
204 mRenderTarget[i] = NULL;
205 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000206
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000207 D3D11_TEXTURE2D_DESC texDesc;
208 mTexture->GetDesc(&texDesc);
209 mMipLevels = texDesc.MipLevels;
210 mTextureFormat = texDesc.Format;
211 mTextureWidth = texDesc.Width;
212 mTextureHeight = texDesc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000213 mTextureDepth = 1;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000214
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000215 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
216 mSRV->GetDesc(&srvDesc);
217 mShaderResourceFormat = srvDesc.Format;
218
219 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
220 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
221 offscreenRTV->GetDesc(&rtvDesc);
222 mRenderTargetFormat = rtvDesc.Format;
223 offscreenRTV->Release();
224
225 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000226}
227
228TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
229 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
230{
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000231 mTexture = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000232 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
233 {
234 mRenderTarget[i] = NULL;
235 }
236
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000237 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
238 if (d3d11::IsDepthStencilFormat(convertedFormat))
239 {
240 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
241 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
242 mDepthStencilFormat = convertedFormat;
243 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
244 }
245 else
246 {
247 mTextureFormat = convertedFormat;
248 mShaderResourceFormat = convertedFormat;
249 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
250 mRenderTargetFormat = convertedFormat;
251 }
252
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000253 // if the width or height is not positive this should be treated as an incomplete texture
254 // we handle that here by skipping the d3d texture creation
255 if (width > 0 && height > 0)
256 {
257 // adjust size if needed for compressed textures
258 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
259
260 ID3D11Device *device = mRenderer->getDevice();
261
262 D3D11_TEXTURE2D_DESC desc;
263 desc.Width = width; // Compressed texture size constraints?
264 desc.Height = height;
shannon.woods@transgaming.comc22e3602013-02-28 23:20:39 +0000265 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000266 desc.ArraySize = 1;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000267 desc.Format = mTextureFormat;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000268 desc.SampleDesc.Count = 1;
269 desc.SampleDesc.Quality = 0;
270 desc.Usage = D3D11_USAGE_DEFAULT;
271 desc.BindFlags = getBindFlags();
272 desc.CPUAccessFlags = 0;
273 desc.MiscFlags = 0;
274
275 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
276
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000277 // this can happen from windows TDR
278 if (d3d11::isDeviceLostError(result))
279 {
280 mRenderer->notifyDeviceLost();
281 gl::error(GL_OUT_OF_MEMORY);
282 }
283 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000284 {
285 ASSERT(result == E_OUTOFMEMORY);
286 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000287 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000288 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000289 else
290 {
291 mTexture->GetDesc(&desc);
292 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000293 mTextureWidth = desc.Width;
294 mTextureHeight = desc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000295 mTextureDepth = 1;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000296 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000297 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000298}
299
300TextureStorage11_2D::~TextureStorage11_2D()
301{
302 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000303 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000304 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000305 mTexture = NULL;
306 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000307
308 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000309 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000310 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000311 mSRV = NULL;
312 }
313
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000314 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000315 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000316 delete mRenderTarget[i];
317 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000318 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000319}
320
321TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
322{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000323 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000324 return static_cast<TextureStorage11_2D*>(storage);
325}
326
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000327ID3D11Resource *TextureStorage11_2D::getBaseTexture() const
328{
329 return mTexture;
330}
331
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000332RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000333{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000334 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000335 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000336 if (!mRenderTarget[level])
337 {
338 ID3D11Device *device = mRenderer->getDevice();
339 HRESULT result;
340
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000341 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000342 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000343 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
344 srvDesc.Texture2D.MostDetailedMip = level;
345 srvDesc.Texture2D.MipLevels = 1;
346
347 ID3D11ShaderResourceView *srv;
348 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
349
350 if (result == E_OUTOFMEMORY)
351 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000352 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000353 }
354 ASSERT(SUCCEEDED(result));
355
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000356 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
357 {
358 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
359 rtvDesc.Format = mRenderTargetFormat;
360 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
361 rtvDesc.Texture2D.MipSlice = level;
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000362
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000363 ID3D11RenderTargetView *rtv;
364 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
365
366 if (result == E_OUTOFMEMORY)
367 {
368 srv->Release();
369 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
370 }
371 ASSERT(SUCCEEDED(result));
372
373 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
374 // also needs to keep a reference to the texture.
375 mTexture->AddRef();
376
377 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
378 std::max(mTextureWidth >> level, 1U),
379 std::max(mTextureHeight >> level, 1U));
380 }
381 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
382 {
383 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
384 dsvDesc.Format = mDepthStencilFormat;
385 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
386 dsvDesc.Texture2D.MipSlice = level;
387 dsvDesc.Flags = 0;
388
389 ID3D11DepthStencilView *dsv;
390 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
391
392 if (result == E_OUTOFMEMORY)
393 {
394 srv->Release();
395 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
396 }
397 ASSERT(SUCCEEDED(result));
398
399 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
400 // also needs to keep a reference to the texture.
401 mTexture->AddRef();
402
403 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
404 std::max(mTextureWidth >> level, 1U),
405 std::max(mTextureHeight >> level, 1U));
406 }
407 else
408 {
409 UNREACHABLE();
410 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000411 }
412
413 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000414 }
415 else
416 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000417 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000418 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000419}
420
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000421ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000422{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000423 if (!mSRV)
424 {
425 ID3D11Device *device = mRenderer->getDevice();
426
427 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000428 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000429 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
430 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
431 srvDesc.Texture2D.MostDetailedMip = 0;
432
433 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
434
435 if (result == E_OUTOFMEMORY)
436 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000437 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000438 }
439 ASSERT(SUCCEEDED(result));
440 }
441
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000442 return mSRV;
443}
444
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000445void TextureStorage11_2D::generateMipmap(int level)
446{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000447 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
448 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
449
450 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000451}
452
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000453TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
454 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
455{
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000456 mTexture = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000457 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000458 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000459 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
460 {
461 mRenderTarget[i][j] = NULL;
462 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000463 }
464
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000465 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
466 if (d3d11::IsDepthStencilFormat(convertedFormat))
467 {
468 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
469 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
470 mDepthStencilFormat = convertedFormat;
471 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
472 }
473 else
474 {
475 mTextureFormat = convertedFormat;
476 mShaderResourceFormat = convertedFormat;
477 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
478 mRenderTargetFormat = convertedFormat;
479 }
480
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000481 // if the size is not positive this should be treated as an incomplete texture
482 // we handle that here by skipping the d3d texture creation
483 if (size > 0)
484 {
485 // adjust size if needed for compressed textures
486 int height = size;
487 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
488
489 ID3D11Device *device = mRenderer->getDevice();
490
491 D3D11_TEXTURE2D_DESC desc;
492 desc.Width = size;
493 desc.Height = size;
shannon.woods@transgaming.comc22e3602013-02-28 23:20:39 +0000494 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000495 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000496 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000497 desc.SampleDesc.Count = 1;
498 desc.SampleDesc.Quality = 0;
499 desc.Usage = D3D11_USAGE_DEFAULT;
500 desc.BindFlags = getBindFlags();
501 desc.CPUAccessFlags = 0;
502 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
503
504 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
505
506 if (FAILED(result))
507 {
508 ASSERT(result == E_OUTOFMEMORY);
509 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000510 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000511 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000512 else
513 {
514 mTexture->GetDesc(&desc);
515 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000516 mTextureWidth = desc.Width;
517 mTextureHeight = desc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000518 mTextureDepth = 1;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000519 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000520 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000521}
522
523TextureStorage11_Cube::~TextureStorage11_Cube()
524{
525 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000526 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000527 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000528 mTexture = NULL;
529 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000530
531 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000532 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000533 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000534 mSRV = NULL;
535 }
536
537 for (unsigned int i = 0; i < 6; i++)
538 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000539 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000540 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000541 delete mRenderTarget[i][j];
542 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000543 }
544 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000545}
546
547TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
548{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000549 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000550 return static_cast<TextureStorage11_Cube*>(storage);
551}
552
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000553ID3D11Resource *TextureStorage11_Cube::getBaseTexture() const
554{
555 return mTexture;
556}
557
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000558RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000559{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000560 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
561 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000562 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000563 if (!mRenderTarget[faceIdx][level])
564 {
565 ID3D11Device *device = mRenderer->getDevice();
566 HRESULT result;
567
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000568 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
569 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.comd89f1942013-02-28 23:18:27 +0000570 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000571 srvDesc.Texture2DArray.MostDetailedMip = level;
572 srvDesc.Texture2DArray.MipLevels = 1;
573 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
574 srvDesc.Texture2DArray.ArraySize = 1;
575
576 ID3D11ShaderResourceView *srv;
577 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
578
579 if (result == E_OUTOFMEMORY)
580 {
581 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
582 }
583 ASSERT(SUCCEEDED(result));
584
585 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000586 {
587 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000588 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000589 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
590 rtvDesc.Texture2DArray.MipSlice = level;
591 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
592 rtvDesc.Texture2DArray.ArraySize = 1;
593
594 ID3D11RenderTargetView *rtv;
595 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
596
597 if (result == E_OUTOFMEMORY)
598 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000599 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000600 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000601 }
602 ASSERT(SUCCEEDED(result));
603
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000604 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
605 // also needs to keep a reference to the texture.
606 mTexture->AddRef();
607
608 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000609 std::max(mTextureWidth >> level, 1U),
610 std::max(mTextureHeight >> level, 1U));
611 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000612 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000613 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000614 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
615 dsvDesc.Format = mRenderTargetFormat;
616 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
617 dsvDesc.Texture2DArray.MipSlice = level;
618 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
619 dsvDesc.Texture2DArray.ArraySize = 1;
620
621 ID3D11DepthStencilView *dsv;
622 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
623
624 if (result == E_OUTOFMEMORY)
625 {
626 srv->Release();
627 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
628 }
629 ASSERT(SUCCEEDED(result));
630
631 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
632 // also needs to keep a reference to the texture.
633 mTexture->AddRef();
634
635 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
636 std::max(mTextureWidth >> level, 1U),
637 std::max(mTextureHeight >> level, 1U));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000638 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000639 else
640 {
641 UNREACHABLE();
642 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000643 }
644
645 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000646 }
647 else
648 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000649 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000650 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000651}
652
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000653ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000654{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000655 if (!mSRV)
656 {
657 ID3D11Device *device = mRenderer->getDevice();
658
659 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000660 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000661 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
662 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
663 srvDesc.TextureCube.MostDetailedMip = 0;
664
665 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
666
667 if (result == E_OUTOFMEMORY)
668 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000669 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000670 }
671 ASSERT(SUCCEEDED(result));
672 }
673
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000674 return mSRV;
675}
676
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000677void TextureStorage11_Cube::generateMipmap(int face, int level)
678{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000679 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
680 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
681
682 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000683}
684
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000685TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
686 GLsizei width, GLsizei height, GLsizei depth)
687 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, false))
688{
689 mTexture = NULL;
690
691 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
692 ASSERT(!d3d11::IsDepthStencilFormat(convertedFormat));
693
694 mTextureFormat = convertedFormat;
695 mShaderResourceFormat = convertedFormat;
696 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
697 mRenderTargetFormat = convertedFormat;
698
699 // If the width, height or depth are not positive this should be treated as an incomplete texture
700 // we handle that here by skipping the d3d texture creation
701 if (width > 0 && height > 0 && depth > 0)
702 {
703 // adjust size if needed for compressed textures
704 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
705
706 ID3D11Device *device = mRenderer->getDevice();
707
708 D3D11_TEXTURE3D_DESC desc;
709 desc.Width = width;
710 desc.Height = height;
711 desc.Depth = depth;
712 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
713 desc.Format = mTextureFormat;
714 desc.Usage = D3D11_USAGE_DEFAULT;
715 desc.BindFlags = getBindFlags();
716 desc.CPUAccessFlags = 0;
717 desc.MiscFlags = 0;
718
719 HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
720
721 // this can happen from windows TDR
722 if (d3d11::isDeviceLostError(result))
723 {
724 mRenderer->notifyDeviceLost();
725 gl::error(GL_OUT_OF_MEMORY);
726 }
727 else if (FAILED(result))
728 {
729 ASSERT(result == E_OUTOFMEMORY);
730 ERR("Creating image failed.");
731 gl::error(GL_OUT_OF_MEMORY);
732 }
733 else
734 {
735 mTexture->GetDesc(&desc);
736 mMipLevels = desc.MipLevels;
737 mTextureWidth = desc.Width;
738 mTextureHeight = desc.Height;
739 mTextureDepth = desc.Depth;
740 }
741 }
742}
743
744TextureStorage11_3D::~TextureStorage11_3D()
745{
746 if (mTexture)
747 {
748 mTexture->Release();
749 mTexture = NULL;
750 }
751
752 if (mSRV)
753 {
754 mSRV->Release();
755 mSRV = NULL;
756 }
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000757
758 for (RenderTargetMap::const_iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
759 {
760 RenderTarget11* renderTarget = i->second;
761 delete renderTarget;
762 }
763 mRenderTargets.clear();
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000764}
765
766TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage)
767{
768 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage));
769 return static_cast<TextureStorage11_3D*>(storage);
770}
771
772ID3D11Resource *TextureStorage11_3D::getBaseTexture() const
773{
774 return mTexture;
775}
776
777ID3D11ShaderResourceView *TextureStorage11_3D::getSRV()
778{
779 if (!mSRV)
780 {
781 ID3D11Device *device = mRenderer->getDevice();
782
783 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
784 srvDesc.Format = mShaderResourceFormat;
785 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
786 srvDesc.Texture3D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
787 srvDesc.Texture3D.MostDetailedMip = 0;
788
789 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
790
791 if (result == E_OUTOFMEMORY)
792 {
793 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
794 }
795 ASSERT(SUCCEEDED(result));
796 }
797
798 return mSRV;
799}
800
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000801RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer)
802{
803 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
804 {
805 LevelLayerKey key(mipLevel, layer);
806 if (mRenderTargets.find(key) == mRenderTargets.end())
807 {
808 ID3D11Device *device = mRenderer->getDevice();
809 HRESULT result;
810
811 // TODO, what kind of SRV is expected here?
812 ID3D11ShaderResourceView *srv = NULL;
813
814 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
815 {
816 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
817 rtvDesc.Format = mRenderTargetFormat;
818 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
819 rtvDesc.Texture3D.MipSlice = mipLevel;
820 rtvDesc.Texture3D.FirstWSlice = layer;
821 rtvDesc.Texture3D.WSize = 1;
822
823 ID3D11RenderTargetView *rtv;
824 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
825
826 if (result == E_OUTOFMEMORY)
827 {
828 srv->Release();
829 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
830 }
831 ASSERT(SUCCEEDED(result));
832
833 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
834 // also needs to keep a reference to the texture.
835 mTexture->AddRef();
836
837 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
838 std::max(mTextureWidth >> mipLevel, 1U),
839 std::max(mTextureHeight >> mipLevel, 1U));
840 }
841 else
842 {
843 UNREACHABLE();
844 }
845 }
846
847 return mRenderTargets[key];
848 }
849 else
850 {
851 return NULL;
852 }
853}
854
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000855void TextureStorage11_3D::generateMipmap(int level)
856{
857 UNIMPLEMENTED();
858}
859
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000860TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
861 GLsizei width, GLsizei height, GLsizei depth)
862 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, false))
863{
864 mTexture = NULL;
865
866 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
867 ASSERT(!d3d11::IsDepthStencilFormat(convertedFormat));
868
869 mTextureFormat = convertedFormat;
870 mShaderResourceFormat = convertedFormat;
871 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
872 mRenderTargetFormat = convertedFormat;
873
874 // if the width, height or depth is not positive this should be treated as an incomplete texture
875 // we handle that here by skipping the d3d texture creation
876 if (width > 0 && height > 0 && depth > 0)
877 {
878 // adjust size if needed for compressed textures
879 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
880
881 ID3D11Device *device = mRenderer->getDevice();
882
883 D3D11_TEXTURE2D_DESC desc;
884 desc.Width = width;
885 desc.Height = height;
886 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
887 desc.ArraySize = depth;
888 desc.Format = mTextureFormat;
889 desc.SampleDesc.Count = 1;
890 desc.SampleDesc.Quality = 0;
891 desc.Usage = D3D11_USAGE_DEFAULT;
892 desc.BindFlags = getBindFlags();
893 desc.CPUAccessFlags = 0;
894 desc.MiscFlags = 0;
895
896 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
897
898 // this can happen from windows TDR
899 if (d3d11::isDeviceLostError(result))
900 {
901 mRenderer->notifyDeviceLost();
902 gl::error(GL_OUT_OF_MEMORY);
903 }
904 else if (FAILED(result))
905 {
906 ASSERT(result == E_OUTOFMEMORY);
907 ERR("Creating image failed.");
908 gl::error(GL_OUT_OF_MEMORY);
909 }
910 else
911 {
912 mTexture->GetDesc(&desc);
913 mMipLevels = desc.MipLevels;
914 mTextureWidth = desc.Width;
915 mTextureHeight = desc.Height;
916 mTextureDepth = desc.ArraySize;
917 }
918 }
919}
920
921TextureStorage11_2DArray::~TextureStorage11_2DArray()
922{
923 if (mTexture)
924 {
925 mTexture->Release();
926 mTexture = NULL;
927 }
928
929 if (mSRV)
930 {
931 mSRV->Release();
932 mSRV = NULL;
933 }
934
935 for (RenderTargetMap::const_iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
936 {
937 RenderTarget11* renderTarget = i->second;
938 delete renderTarget;
939 }
940 mRenderTargets.clear();
941}
942
943TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage)
944{
945 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage));
946 return static_cast<TextureStorage11_2DArray*>(storage);
947}
948
949ID3D11Resource *TextureStorage11_2DArray::getBaseTexture() const
950{
951 return mTexture;
952}
953
954ID3D11ShaderResourceView *TextureStorage11_2DArray::getSRV()
955{
956 if (!mSRV)
957 {
958 ID3D11Device *device = mRenderer->getDevice();
959
960 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
961 srvDesc.Format = mShaderResourceFormat;
962 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
963 srvDesc.Texture2DArray.MostDetailedMip = 0;
964 srvDesc.Texture2DArray.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
965 srvDesc.Texture2DArray.FirstArraySlice = 0;
966 srvDesc.Texture2DArray.ArraySize = mTextureDepth;
967
968 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
969
970 if (result == E_OUTOFMEMORY)
971 {
972 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
973 }
974 ASSERT(SUCCEEDED(result));
975 }
976
977 return mSRV;
978}
979
980RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer)
981{
982 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
983 {
984 LevelLayerKey key(mipLevel, layer);
985 if (mRenderTargets.find(key) == mRenderTargets.end())
986 {
987 ID3D11Device *device = mRenderer->getDevice();
988 HRESULT result;
989
990 // TODO, what kind of SRV is expected here?
991 ID3D11ShaderResourceView *srv = NULL;
992
993 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
994 {
995 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
996 rtvDesc.Format = mRenderTargetFormat;
997 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
998 rtvDesc.Texture2DArray.MipSlice = mipLevel;
999 rtvDesc.Texture2DArray.FirstArraySlice = layer;
1000 rtvDesc.Texture2DArray.ArraySize = 1;
1001
1002 ID3D11RenderTargetView *rtv;
1003 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
1004
1005 if (result == E_OUTOFMEMORY)
1006 {
1007 SafeRelease(srv);
1008 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1009 }
1010 ASSERT(SUCCEEDED(result));
1011
1012 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
1013 // also needs to keep a reference to the texture.
1014 mTexture->AddRef();
1015
1016 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
1017 std::max(mTextureWidth >> mipLevel, 1U),
1018 std::max(mTextureHeight >> mipLevel, 1U));
1019 }
1020 else
1021 {
1022 UNREACHABLE();
1023 }
1024 }
1025
1026 return mRenderTargets[key];
1027 }
1028 else
1029 {
1030 return NULL;
1031 }
1032}
1033
1034void TextureStorage11_2DArray::generateMipmap(int level)
1035{
1036 UNIMPLEMENTED();
1037}
1038
daniel@transgaming.comb2151e52013-01-11 04:06:24 +00001039}