blob: c53a519b77fa02756c3dde7019c9f0ad2f2e735f [file] [log] [blame]
daniel@transgaming.com4834ee22013-01-11 04:06:16 +00001//
2// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
8// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
9
10#include "libGLESv2/renderer/TextureStorage11.h"
11
12#include "libGLESv2/renderer/Renderer11.h"
13#include "libGLESv2/renderer/RenderTarget11.h"
14#include "libGLESv2/renderer/SwapChain11.h"
15#include "libGLESv2/renderer/renderer11_utils.h"
16
17#include "libGLESv2/main.h"
18
19namespace rx
20{
21
22TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
23 : mBindFlags(bindFlags),
daniel@transgaming.comb1154552013-01-11 04:11:02 +000024 mLodOffset(0),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000025 mMipLevels(0),
26 mTexture(NULL),
27 mTextureFormat(DXGI_FORMAT_UNKNOWN),
28 mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
29 mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
30 mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
31 mTextureWidth(0),
32 mTextureHeight(0)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000033{
34 mRenderer = Renderer11::makeRenderer11(renderer);
35}
36
37TextureStorage11::~TextureStorage11()
38{
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +000039}
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000040
41TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
42{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000043 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000044 return static_cast<TextureStorage11*>(storage);
45}
46
47DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
48{
49 UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
50
shannon.woods@transgaming.comeec5c632013-02-28 23:04:21 +000051 if (d3d11::IsDepthStencilFormat(format))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000052 {
53 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
54 }
55 else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
56 {
57 bindFlags |= D3D11_BIND_RENDER_TARGET;
58 }
59 return bindFlags;
60}
61
62bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
63{
64 switch(format)
65 {
66 case DXGI_FORMAT_R8G8B8A8_UNORM:
67 case DXGI_FORMAT_A8_UNORM:
68 case DXGI_FORMAT_R32G32B32A32_FLOAT:
69 case DXGI_FORMAT_R32G32B32_FLOAT:
70 case DXGI_FORMAT_R16G16B16A16_FLOAT:
71 case DXGI_FORMAT_B8G8R8A8_UNORM:
72 case DXGI_FORMAT_R8_UNORM:
73 case DXGI_FORMAT_R8G8_UNORM:
74 case DXGI_FORMAT_R16_FLOAT:
75 case DXGI_FORMAT_R16G16_FLOAT:
76 return true;
77 case DXGI_FORMAT_BC1_UNORM:
78 case DXGI_FORMAT_BC2_UNORM:
79 case DXGI_FORMAT_BC3_UNORM:
80 return false;
81 default:
82 UNREACHABLE();
83 return false;
84 }
85}
86
87UINT TextureStorage11::getBindFlags() const
88{
89 return mBindFlags;
90}
91
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000092ID3D11Texture2D *TextureStorage11::getBaseTexture() const
93{
94 return mTexture;
95}
96
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000097int TextureStorage11::getLodOffset() const
98{
99 return mLodOffset;
100}
101
102bool TextureStorage11::isRenderTarget() const
103{
104 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
105}
106
107bool TextureStorage11::isManaged() const
108{
109 return false;
110}
111
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000112int TextureStorage11::levelCount()
113{
114 int levels = 0;
115 if (getBaseTexture())
116 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000117 levels = mMipLevels - getLodOffset();
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000118 }
119 return levels;
120}
121
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000122UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
123{
124 UINT index = 0;
125 if (getBaseTexture())
126 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000127 index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000128 }
129 return index;
130}
131
132bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, int level, int face, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
133{
134 if (srcTexture)
135 {
shannon.woods@transgaming.com7ae9e7f2013-02-28 23:13:27 +0000136 // Round up the width and height to the nearest multiple of dimension alignment
137 unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
138 width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
139 height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
140
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000141 D3D11_BOX srcBox;
142 srcBox.left = xoffset;
143 srcBox.top = yoffset;
144 srcBox.right = xoffset + width;
145 srcBox.bottom = yoffset + height;
146 srcBox.front = 0;
147 srcBox.back = 1;
148
149 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
150
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000151 ASSERT(getBaseTexture());
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000152 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level, face), xoffset, yoffset, 0, srcTexture, 0, &srcBox);
153 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;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000213
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000214 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
215 mSRV->GetDesc(&srvDesc);
216 mShaderResourceFormat = srvDesc.Format;
217
218 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
219 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
220 offscreenRTV->GetDesc(&rtvDesc);
221 mRenderTargetFormat = rtvDesc.Format;
222 offscreenRTV->Release();
223
224 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000225}
226
227TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
228 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
229{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000230 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
231 {
232 mRenderTarget[i] = NULL;
233 }
234
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000235 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
236 if (d3d11::IsDepthStencilFormat(convertedFormat))
237 {
238 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
239 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
240 mDepthStencilFormat = convertedFormat;
241 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
242 }
243 else
244 {
245 mTextureFormat = convertedFormat;
246 mShaderResourceFormat = convertedFormat;
247 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
248 mRenderTargetFormat = convertedFormat;
249 }
250
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000251 // if the width or height is not positive this should be treated as an incomplete texture
252 // we handle that here by skipping the d3d texture creation
253 if (width > 0 && height > 0)
254 {
255 // adjust size if needed for compressed textures
256 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
257
258 ID3D11Device *device = mRenderer->getDevice();
259
260 D3D11_TEXTURE2D_DESC desc;
261 desc.Width = width; // Compressed texture size constraints?
262 desc.Height = height;
263 desc.MipLevels = levels + mLodOffset;
264 desc.ArraySize = 1;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000265 desc.Format = mTextureFormat;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000266 desc.SampleDesc.Count = 1;
267 desc.SampleDesc.Quality = 0;
268 desc.Usage = D3D11_USAGE_DEFAULT;
269 desc.BindFlags = getBindFlags();
270 desc.CPUAccessFlags = 0;
271 desc.MiscFlags = 0;
272
273 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
274
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000275 // this can happen from windows TDR
276 if (d3d11::isDeviceLostError(result))
277 {
278 mRenderer->notifyDeviceLost();
279 gl::error(GL_OUT_OF_MEMORY);
280 }
281 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000282 {
283 ASSERT(result == E_OUTOFMEMORY);
284 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000285 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000286 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000287 else
288 {
289 mTexture->GetDesc(&desc);
290 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000291 mTextureWidth = desc.Width;
292 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000293 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000294 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000295}
296
297TextureStorage11_2D::~TextureStorage11_2D()
298{
299 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000300 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000301 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000302 mTexture = NULL;
303 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000304
305 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000306 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000307 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000308 mSRV = NULL;
309 }
310
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000311 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000312 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000313 delete mRenderTarget[i];
314 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000315 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000316}
317
318TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
319{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000320 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000321 return static_cast<TextureStorage11_2D*>(storage);
322}
323
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000324RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000325{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000326 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000327 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000328 if (!mRenderTarget[level])
329 {
330 ID3D11Device *device = mRenderer->getDevice();
331 HRESULT result;
332
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000333 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000334 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000335 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
336 srvDesc.Texture2D.MostDetailedMip = level;
337 srvDesc.Texture2D.MipLevels = 1;
338
339 ID3D11ShaderResourceView *srv;
340 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
341
342 if (result == E_OUTOFMEMORY)
343 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000344 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000345 }
346 ASSERT(SUCCEEDED(result));
347
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000348 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
349 {
350 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
351 rtvDesc.Format = mRenderTargetFormat;
352 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
353 rtvDesc.Texture2D.MipSlice = level;
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000354
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000355 ID3D11RenderTargetView *rtv;
356 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
357
358 if (result == E_OUTOFMEMORY)
359 {
360 srv->Release();
361 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
362 }
363 ASSERT(SUCCEEDED(result));
364
365 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
366 // also needs to keep a reference to the texture.
367 mTexture->AddRef();
368
369 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
370 std::max(mTextureWidth >> level, 1U),
371 std::max(mTextureHeight >> level, 1U));
372 }
373 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
374 {
375 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
376 dsvDesc.Format = mDepthStencilFormat;
377 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
378 dsvDesc.Texture2D.MipSlice = level;
379 dsvDesc.Flags = 0;
380
381 ID3D11DepthStencilView *dsv;
382 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
383
384 if (result == E_OUTOFMEMORY)
385 {
386 srv->Release();
387 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
388 }
389 ASSERT(SUCCEEDED(result));
390
391 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
392 // also needs to keep a reference to the texture.
393 mTexture->AddRef();
394
395 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
396 std::max(mTextureWidth >> level, 1U),
397 std::max(mTextureHeight >> level, 1U));
398 }
399 else
400 {
401 UNREACHABLE();
402 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000403 }
404
405 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000406 }
407 else
408 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000409 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000410 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000411}
412
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000413ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000414{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000415 if (!mSRV)
416 {
417 ID3D11Device *device = mRenderer->getDevice();
418
419 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000420 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000421 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
422 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
423 srvDesc.Texture2D.MostDetailedMip = 0;
424
425 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
426
427 if (result == E_OUTOFMEMORY)
428 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000429 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000430 }
431 ASSERT(SUCCEEDED(result));
432 }
433
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000434 return mSRV;
435}
436
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000437void TextureStorage11_2D::generateMipmap(int level)
438{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000439 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
440 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
441
442 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000443}
444
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000445TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
446 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
447{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000448 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000449 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000450 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
451 {
452 mRenderTarget[i][j] = NULL;
453 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000454 }
455
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000456 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
457 if (d3d11::IsDepthStencilFormat(convertedFormat))
458 {
459 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
460 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
461 mDepthStencilFormat = convertedFormat;
462 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
463 }
464 else
465 {
466 mTextureFormat = convertedFormat;
467 mShaderResourceFormat = convertedFormat;
468 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
469 mRenderTargetFormat = convertedFormat;
470 }
471
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000472 // if the size is not positive this should be treated as an incomplete texture
473 // we handle that here by skipping the d3d texture creation
474 if (size > 0)
475 {
476 // adjust size if needed for compressed textures
477 int height = size;
478 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
479
480 ID3D11Device *device = mRenderer->getDevice();
481
482 D3D11_TEXTURE2D_DESC desc;
483 desc.Width = size;
484 desc.Height = size;
485 desc.MipLevels = levels + mLodOffset;
486 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000487 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000488 desc.SampleDesc.Count = 1;
489 desc.SampleDesc.Quality = 0;
490 desc.Usage = D3D11_USAGE_DEFAULT;
491 desc.BindFlags = getBindFlags();
492 desc.CPUAccessFlags = 0;
493 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
494
495 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
496
497 if (FAILED(result))
498 {
499 ASSERT(result == E_OUTOFMEMORY);
500 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000501 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000502 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000503 else
504 {
505 mTexture->GetDesc(&desc);
506 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000507 mTextureWidth = desc.Width;
508 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000509 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000510 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000511}
512
513TextureStorage11_Cube::~TextureStorage11_Cube()
514{
515 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000516 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000517 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000518 mTexture = NULL;
519 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000520
521 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000522 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000523 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000524 mSRV = NULL;
525 }
526
527 for (unsigned int i = 0; i < 6; i++)
528 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000529 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000530 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000531 delete mRenderTarget[i][j];
532 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000533 }
534 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000535}
536
537TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
538{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000539 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000540 return static_cast<TextureStorage11_Cube*>(storage);
541}
542
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000543RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000544{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000545 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
546 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000547 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000548 if (!mRenderTarget[faceIdx][level])
549 {
550 ID3D11Device *device = mRenderer->getDevice();
551 HRESULT result;
552
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000553 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
554 srvDesc.Format = mShaderResourceFormat;
555 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
556 srvDesc.Texture2DArray.MostDetailedMip = level;
557 srvDesc.Texture2DArray.MipLevels = 1;
558 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
559 srvDesc.Texture2DArray.ArraySize = 1;
560
561 ID3D11ShaderResourceView *srv;
562 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
563
564 if (result == E_OUTOFMEMORY)
565 {
566 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
567 }
568 ASSERT(SUCCEEDED(result));
569
570 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000571 {
572 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000573 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000574 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
575 rtvDesc.Texture2DArray.MipSlice = level;
576 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
577 rtvDesc.Texture2DArray.ArraySize = 1;
578
579 ID3D11RenderTargetView *rtv;
580 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
581
582 if (result == E_OUTOFMEMORY)
583 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000584 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000585 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000586 }
587 ASSERT(SUCCEEDED(result));
588
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000589 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
590 // also needs to keep a reference to the texture.
591 mTexture->AddRef();
592
593 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000594 std::max(mTextureWidth >> level, 1U),
595 std::max(mTextureHeight >> level, 1U));
596 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000597 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000598 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000599 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
600 dsvDesc.Format = mRenderTargetFormat;
601 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
602 dsvDesc.Texture2DArray.MipSlice = level;
603 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
604 dsvDesc.Texture2DArray.ArraySize = 1;
605
606 ID3D11DepthStencilView *dsv;
607 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
608
609 if (result == E_OUTOFMEMORY)
610 {
611 srv->Release();
612 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
613 }
614 ASSERT(SUCCEEDED(result));
615
616 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
617 // also needs to keep a reference to the texture.
618 mTexture->AddRef();
619
620 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
621 std::max(mTextureWidth >> level, 1U),
622 std::max(mTextureHeight >> level, 1U));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000623 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000624 else
625 {
626 UNREACHABLE();
627 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000628 }
629
630 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000631 }
632 else
633 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000634 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000635 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000636}
637
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000638ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000639{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000640 if (!mSRV)
641 {
642 ID3D11Device *device = mRenderer->getDevice();
643
644 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000645 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000646 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
647 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
648 srvDesc.TextureCube.MostDetailedMip = 0;
649
650 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
651
652 if (result == E_OUTOFMEMORY)
653 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000654 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000655 }
656 ASSERT(SUCCEEDED(result));
657 }
658
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000659 return mSRV;
660}
661
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000662void TextureStorage11_Cube::generateMipmap(int face, int level)
663{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000664 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
665 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
666
667 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000668}
669
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000670}