blob: 024a778aea44c08f64b9f388ee8089f4f352e25b [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),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000379 std::max(mTextureHeight >> level, 1U),
380 1);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000381 }
382 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
383 {
384 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
385 dsvDesc.Format = mDepthStencilFormat;
386 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
387 dsvDesc.Texture2D.MipSlice = level;
388 dsvDesc.Flags = 0;
389
390 ID3D11DepthStencilView *dsv;
391 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
392
393 if (result == E_OUTOFMEMORY)
394 {
395 srv->Release();
396 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
397 }
398 ASSERT(SUCCEEDED(result));
399
400 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
401 // also needs to keep a reference to the texture.
402 mTexture->AddRef();
403
404 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
405 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000406 std::max(mTextureHeight >> level, 1U),
407 1);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000408 }
409 else
410 {
411 UNREACHABLE();
412 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000413 }
414
415 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000416 }
417 else
418 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000419 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000420 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000421}
422
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000423ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000424{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000425 if (!mSRV)
426 {
427 ID3D11Device *device = mRenderer->getDevice();
428
429 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000430 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000431 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
432 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
433 srvDesc.Texture2D.MostDetailedMip = 0;
434
435 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
436
437 if (result == E_OUTOFMEMORY)
438 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000439 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000440 }
441 ASSERT(SUCCEEDED(result));
442 }
443
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000444 return mSRV;
445}
446
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000447void TextureStorage11_2D::generateMipmap(int level)
448{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000449 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
450 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
451
452 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000453}
454
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000455TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
456 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
457{
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000458 mTexture = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000459 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000460 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000461 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
462 {
463 mRenderTarget[i][j] = NULL;
464 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000465 }
466
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000467 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
468 if (d3d11::IsDepthStencilFormat(convertedFormat))
469 {
470 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
471 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
472 mDepthStencilFormat = convertedFormat;
473 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
474 }
475 else
476 {
477 mTextureFormat = convertedFormat;
478 mShaderResourceFormat = convertedFormat;
479 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
480 mRenderTargetFormat = convertedFormat;
481 }
482
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000483 // if the size is not positive this should be treated as an incomplete texture
484 // we handle that here by skipping the d3d texture creation
485 if (size > 0)
486 {
487 // adjust size if needed for compressed textures
488 int height = size;
489 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
490
491 ID3D11Device *device = mRenderer->getDevice();
492
493 D3D11_TEXTURE2D_DESC desc;
494 desc.Width = size;
495 desc.Height = size;
shannon.woods@transgaming.comc22e3602013-02-28 23:20:39 +0000496 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000497 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000498 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000499 desc.SampleDesc.Count = 1;
500 desc.SampleDesc.Quality = 0;
501 desc.Usage = D3D11_USAGE_DEFAULT;
502 desc.BindFlags = getBindFlags();
503 desc.CPUAccessFlags = 0;
504 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
505
506 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
507
508 if (FAILED(result))
509 {
510 ASSERT(result == E_OUTOFMEMORY);
511 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000512 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000513 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000514 else
515 {
516 mTexture->GetDesc(&desc);
517 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000518 mTextureWidth = desc.Width;
519 mTextureHeight = desc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000520 mTextureDepth = 1;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000521 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000522 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000523}
524
525TextureStorage11_Cube::~TextureStorage11_Cube()
526{
527 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000528 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000529 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000530 mTexture = NULL;
531 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000532
533 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000534 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000535 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000536 mSRV = NULL;
537 }
538
539 for (unsigned int i = 0; i < 6; i++)
540 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000541 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000542 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000543 delete mRenderTarget[i][j];
544 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000545 }
546 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000547}
548
549TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
550{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000551 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000552 return static_cast<TextureStorage11_Cube*>(storage);
553}
554
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000555ID3D11Resource *TextureStorage11_Cube::getBaseTexture() const
556{
557 return mTexture;
558}
559
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000560RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000561{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000562 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
563 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000564 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000565 if (!mRenderTarget[faceIdx][level])
566 {
567 ID3D11Device *device = mRenderer->getDevice();
568 HRESULT result;
569
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000570 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
571 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.comd89f1942013-02-28 23:18:27 +0000572 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000573 srvDesc.Texture2DArray.MostDetailedMip = level;
574 srvDesc.Texture2DArray.MipLevels = 1;
575 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
576 srvDesc.Texture2DArray.ArraySize = 1;
577
578 ID3D11ShaderResourceView *srv;
579 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
580
581 if (result == E_OUTOFMEMORY)
582 {
583 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
584 }
585 ASSERT(SUCCEEDED(result));
586
587 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000588 {
589 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000590 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000591 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
592 rtvDesc.Texture2DArray.MipSlice = level;
593 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
594 rtvDesc.Texture2DArray.ArraySize = 1;
595
596 ID3D11RenderTargetView *rtv;
597 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
598
599 if (result == E_OUTOFMEMORY)
600 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000601 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000602 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000603 }
604 ASSERT(SUCCEEDED(result));
605
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000606 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
607 // also needs to keep a reference to the texture.
608 mTexture->AddRef();
609
610 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000611 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000612 std::max(mTextureHeight >> level, 1U),
613 1);
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000614 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000615 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000616 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000617 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
618 dsvDesc.Format = mRenderTargetFormat;
619 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
620 dsvDesc.Texture2DArray.MipSlice = level;
621 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
622 dsvDesc.Texture2DArray.ArraySize = 1;
623
624 ID3D11DepthStencilView *dsv;
625 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
626
627 if (result == E_OUTOFMEMORY)
628 {
629 srv->Release();
630 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
631 }
632 ASSERT(SUCCEEDED(result));
633
634 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
635 // also needs to keep a reference to the texture.
636 mTexture->AddRef();
637
638 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
639 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000640 std::max(mTextureHeight >> level, 1U),
641 1);
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000642 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000643 else
644 {
645 UNREACHABLE();
646 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000647 }
648
649 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000650 }
651 else
652 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000653 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000654 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000655}
656
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000657ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000658{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000659 if (!mSRV)
660 {
661 ID3D11Device *device = mRenderer->getDevice();
662
663 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000664 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000665 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
666 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
667 srvDesc.TextureCube.MostDetailedMip = 0;
668
669 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
670
671 if (result == E_OUTOFMEMORY)
672 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000673 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000674 }
675 ASSERT(SUCCEEDED(result));
676 }
677
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000678 return mSRV;
679}
680
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000681void TextureStorage11_Cube::generateMipmap(int face, int level)
682{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000683 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
684 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
685
686 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000687}
688
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000689TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
690 GLsizei width, GLsizei height, GLsizei depth)
691 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, false))
692{
693 mTexture = NULL;
694
695 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
696 ASSERT(!d3d11::IsDepthStencilFormat(convertedFormat));
697
698 mTextureFormat = convertedFormat;
699 mShaderResourceFormat = convertedFormat;
700 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
701 mRenderTargetFormat = convertedFormat;
702
703 // If the width, height or depth are not positive this should be treated as an incomplete texture
704 // we handle that here by skipping the d3d texture creation
705 if (width > 0 && height > 0 && depth > 0)
706 {
707 // adjust size if needed for compressed textures
708 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
709
710 ID3D11Device *device = mRenderer->getDevice();
711
712 D3D11_TEXTURE3D_DESC desc;
713 desc.Width = width;
714 desc.Height = height;
715 desc.Depth = depth;
716 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
717 desc.Format = mTextureFormat;
718 desc.Usage = D3D11_USAGE_DEFAULT;
719 desc.BindFlags = getBindFlags();
720 desc.CPUAccessFlags = 0;
721 desc.MiscFlags = 0;
722
723 HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
724
725 // this can happen from windows TDR
726 if (d3d11::isDeviceLostError(result))
727 {
728 mRenderer->notifyDeviceLost();
729 gl::error(GL_OUT_OF_MEMORY);
730 }
731 else if (FAILED(result))
732 {
733 ASSERT(result == E_OUTOFMEMORY);
734 ERR("Creating image failed.");
735 gl::error(GL_OUT_OF_MEMORY);
736 }
737 else
738 {
739 mTexture->GetDesc(&desc);
740 mMipLevels = desc.MipLevels;
741 mTextureWidth = desc.Width;
742 mTextureHeight = desc.Height;
743 mTextureDepth = desc.Depth;
744 }
745 }
746}
747
748TextureStorage11_3D::~TextureStorage11_3D()
749{
750 if (mTexture)
751 {
752 mTexture->Release();
753 mTexture = NULL;
754 }
755
756 if (mSRV)
757 {
758 mSRV->Release();
759 mSRV = NULL;
760 }
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000761
762 for (RenderTargetMap::const_iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
763 {
764 RenderTarget11* renderTarget = i->second;
765 delete renderTarget;
766 }
767 mRenderTargets.clear();
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000768}
769
770TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage)
771{
772 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage));
773 return static_cast<TextureStorage11_3D*>(storage);
774}
775
776ID3D11Resource *TextureStorage11_3D::getBaseTexture() const
777{
778 return mTexture;
779}
780
781ID3D11ShaderResourceView *TextureStorage11_3D::getSRV()
782{
783 if (!mSRV)
784 {
785 ID3D11Device *device = mRenderer->getDevice();
786
787 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
788 srvDesc.Format = mShaderResourceFormat;
789 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
790 srvDesc.Texture3D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
791 srvDesc.Texture3D.MostDetailedMip = 0;
792
793 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
794
795 if (result == E_OUTOFMEMORY)
796 {
797 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
798 }
799 ASSERT(SUCCEEDED(result));
800 }
801
802 return mSRV;
803}
804
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000805RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer)
806{
807 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
808 {
809 LevelLayerKey key(mipLevel, layer);
810 if (mRenderTargets.find(key) == mRenderTargets.end())
811 {
812 ID3D11Device *device = mRenderer->getDevice();
813 HRESULT result;
814
815 // TODO, what kind of SRV is expected here?
816 ID3D11ShaderResourceView *srv = NULL;
817
818 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
819 {
820 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
821 rtvDesc.Format = mRenderTargetFormat;
822 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
823 rtvDesc.Texture3D.MipSlice = mipLevel;
824 rtvDesc.Texture3D.FirstWSlice = layer;
825 rtvDesc.Texture3D.WSize = 1;
826
827 ID3D11RenderTargetView *rtv;
828 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
829
830 if (result == E_OUTOFMEMORY)
831 {
832 srv->Release();
833 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
834 }
835 ASSERT(SUCCEEDED(result));
836
837 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
838 // also needs to keep a reference to the texture.
839 mTexture->AddRef();
840
841 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
842 std::max(mTextureWidth >> mipLevel, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000843 std::max(mTextureHeight >> mipLevel, 1U),
844 1);
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000845 }
846 else
847 {
848 UNREACHABLE();
849 }
850 }
851
852 return mRenderTargets[key];
853 }
854 else
855 {
856 return NULL;
857 }
858}
859
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000860void TextureStorage11_3D::generateMipmap(int level)
861{
862 UNIMPLEMENTED();
863}
864
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000865TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
866 GLsizei width, GLsizei height, GLsizei depth)
867 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, false))
868{
869 mTexture = NULL;
870
871 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
872 ASSERT(!d3d11::IsDepthStencilFormat(convertedFormat));
873
874 mTextureFormat = convertedFormat;
875 mShaderResourceFormat = convertedFormat;
876 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
877 mRenderTargetFormat = convertedFormat;
878
879 // if the width, height or depth is not positive this should be treated as an incomplete texture
880 // we handle that here by skipping the d3d texture creation
881 if (width > 0 && height > 0 && depth > 0)
882 {
883 // adjust size if needed for compressed textures
884 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
885
886 ID3D11Device *device = mRenderer->getDevice();
887
888 D3D11_TEXTURE2D_DESC desc;
889 desc.Width = width;
890 desc.Height = height;
891 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
892 desc.ArraySize = depth;
893 desc.Format = mTextureFormat;
894 desc.SampleDesc.Count = 1;
895 desc.SampleDesc.Quality = 0;
896 desc.Usage = D3D11_USAGE_DEFAULT;
897 desc.BindFlags = getBindFlags();
898 desc.CPUAccessFlags = 0;
899 desc.MiscFlags = 0;
900
901 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
902
903 // this can happen from windows TDR
904 if (d3d11::isDeviceLostError(result))
905 {
906 mRenderer->notifyDeviceLost();
907 gl::error(GL_OUT_OF_MEMORY);
908 }
909 else if (FAILED(result))
910 {
911 ASSERT(result == E_OUTOFMEMORY);
912 ERR("Creating image failed.");
913 gl::error(GL_OUT_OF_MEMORY);
914 }
915 else
916 {
917 mTexture->GetDesc(&desc);
918 mMipLevels = desc.MipLevels;
919 mTextureWidth = desc.Width;
920 mTextureHeight = desc.Height;
921 mTextureDepth = desc.ArraySize;
922 }
923 }
924}
925
926TextureStorage11_2DArray::~TextureStorage11_2DArray()
927{
928 if (mTexture)
929 {
930 mTexture->Release();
931 mTexture = NULL;
932 }
933
934 if (mSRV)
935 {
936 mSRV->Release();
937 mSRV = NULL;
938 }
939
940 for (RenderTargetMap::const_iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
941 {
942 RenderTarget11* renderTarget = i->second;
943 delete renderTarget;
944 }
945 mRenderTargets.clear();
946}
947
948TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage)
949{
950 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage));
951 return static_cast<TextureStorage11_2DArray*>(storage);
952}
953
954ID3D11Resource *TextureStorage11_2DArray::getBaseTexture() const
955{
956 return mTexture;
957}
958
959ID3D11ShaderResourceView *TextureStorage11_2DArray::getSRV()
960{
961 if (!mSRV)
962 {
963 ID3D11Device *device = mRenderer->getDevice();
964
965 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
966 srvDesc.Format = mShaderResourceFormat;
967 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
968 srvDesc.Texture2DArray.MostDetailedMip = 0;
969 srvDesc.Texture2DArray.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
970 srvDesc.Texture2DArray.FirstArraySlice = 0;
971 srvDesc.Texture2DArray.ArraySize = mTextureDepth;
972
973 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
974
975 if (result == E_OUTOFMEMORY)
976 {
977 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
978 }
979 ASSERT(SUCCEEDED(result));
980 }
981
982 return mSRV;
983}
984
985RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer)
986{
987 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
988 {
989 LevelLayerKey key(mipLevel, layer);
990 if (mRenderTargets.find(key) == mRenderTargets.end())
991 {
992 ID3D11Device *device = mRenderer->getDevice();
993 HRESULT result;
994
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +0000995 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
996 srvDesc.Format = mShaderResourceFormat;
997 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
998 srvDesc.Texture2DArray.MostDetailedMip = mipLevel;
999 srvDesc.Texture2DArray.MipLevels = 1;
1000 srvDesc.Texture2DArray.FirstArraySlice = layer;
1001 srvDesc.Texture2DArray.ArraySize = 1;
1002
1003 ID3D11ShaderResourceView *srv;
1004 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
1005
1006 if (result == E_OUTOFMEMORY)
1007 {
1008 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1009 }
1010 ASSERT(SUCCEEDED(result));
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001011
1012 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
1013 {
1014 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1015 rtvDesc.Format = mRenderTargetFormat;
1016 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1017 rtvDesc.Texture2DArray.MipSlice = mipLevel;
1018 rtvDesc.Texture2DArray.FirstArraySlice = layer;
1019 rtvDesc.Texture2DArray.ArraySize = 1;
1020
1021 ID3D11RenderTargetView *rtv;
1022 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
1023
1024 if (result == E_OUTOFMEMORY)
1025 {
1026 SafeRelease(srv);
1027 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1028 }
1029 ASSERT(SUCCEEDED(result));
1030
1031 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
1032 // also needs to keep a reference to the texture.
1033 mTexture->AddRef();
1034
1035 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
1036 std::max(mTextureWidth >> mipLevel, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +00001037 std::max(mTextureHeight >> mipLevel, 1U),
1038 1);
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001039 }
1040 else
1041 {
1042 UNREACHABLE();
1043 }
1044 }
1045
1046 return mRenderTargets[key];
1047 }
1048 else
1049 {
1050 return NULL;
1051 }
1052}
1053
1054void TextureStorage11_2DArray::generateMipmap(int level)
1055{
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +00001056 for (unsigned int layer = 0; layer < mTextureDepth; layer++)
1057 {
1058 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer));
1059 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer));
1060
1061 generateMipmapLayer(source, dest);
1062 }
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001063}
1064
daniel@transgaming.comb2151e52013-01-11 04:06:24 +00001065}