blob: ecb2b3a20753cb37d5cb8ebdbe92b989861c546d [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),
shannon.woods@transgaming.com96c21ee2013-02-28 23:13:45 +000031 mSRV(NULL),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000032 mTextureWidth(0),
33 mTextureHeight(0)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000034{
35 mRenderer = Renderer11::makeRenderer11(renderer);
36}
37
38TextureStorage11::~TextureStorage11()
39{
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +000040}
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000041
42TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
43{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000044 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000045 return static_cast<TextureStorage11*>(storage);
46}
47
48DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
49{
50 UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
51
shannon.woods@transgaming.comeec5c632013-02-28 23:04:21 +000052 if (d3d11::IsDepthStencilFormat(format))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000053 {
54 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
55 }
56 else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
57 {
58 bindFlags |= D3D11_BIND_RENDER_TARGET;
59 }
60 return bindFlags;
61}
62
63bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
64{
65 switch(format)
66 {
67 case DXGI_FORMAT_R8G8B8A8_UNORM:
68 case DXGI_FORMAT_A8_UNORM:
69 case DXGI_FORMAT_R32G32B32A32_FLOAT:
70 case DXGI_FORMAT_R32G32B32_FLOAT:
71 case DXGI_FORMAT_R16G16B16A16_FLOAT:
72 case DXGI_FORMAT_B8G8R8A8_UNORM:
73 case DXGI_FORMAT_R8_UNORM:
74 case DXGI_FORMAT_R8G8_UNORM:
75 case DXGI_FORMAT_R16_FLOAT:
76 case DXGI_FORMAT_R16G16_FLOAT:
77 return true;
78 case DXGI_FORMAT_BC1_UNORM:
79 case DXGI_FORMAT_BC2_UNORM:
80 case DXGI_FORMAT_BC3_UNORM:
81 return false;
82 default:
83 UNREACHABLE();
84 return false;
85 }
86}
87
88UINT TextureStorage11::getBindFlags() const
89{
90 return mBindFlags;
91}
92
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000093ID3D11Texture2D *TextureStorage11::getBaseTexture() const
94{
95 return mTexture;
96}
97
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000098int TextureStorage11::getLodOffset() const
99{
100 return mLodOffset;
101}
102
103bool TextureStorage11::isRenderTarget() const
104{
105 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
106}
107
108bool TextureStorage11::isManaged() const
109{
110 return false;
111}
112
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000113int TextureStorage11::levelCount()
114{
115 int levels = 0;
116 if (getBaseTexture())
117 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000118 levels = mMipLevels - getLodOffset();
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000119 }
120 return levels;
121}
122
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000123UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
124{
125 UINT index = 0;
126 if (getBaseTexture())
127 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000128 index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000129 }
130 return index;
131}
132
133bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, int level, int face, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
134{
135 if (srcTexture)
136 {
shannon.woods@transgaming.com7ae9e7f2013-02-28 23:13:27 +0000137 // Round up the width and height to the nearest multiple of dimension alignment
138 unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
139 width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
140 height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
141
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000142 D3D11_BOX srcBox;
143 srcBox.left = xoffset;
144 srcBox.top = yoffset;
145 srcBox.right = xoffset + width;
146 srcBox.bottom = yoffset + height;
147 srcBox.front = 0;
148 srcBox.back = 1;
149
150 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
151
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000152 ASSERT(getBaseTexture());
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000153 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level, face), xoffset, yoffset, 0, srcTexture, 0, &srcBox);
154 return true;
155 }
156
157 return false;
158}
159
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000160void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
161{
162 if (source && dest)
163 {
164 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
165 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
166
167 if (sourceSRV && destRTV)
168 {
169 gl::Rectangle sourceArea;
170 sourceArea.x = 0;
171 sourceArea.y = 0;
172 sourceArea.width = source->getWidth();
173 sourceArea.height = source->getHeight();
174
175 gl::Rectangle destArea;
176 destArea.x = 0;
177 destArea.y = 0;
178 destArea.width = dest->getWidth();
179 destArea.height = dest->getHeight();
180
181 mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
182 destRTV, destArea, dest->getWidth(), dest->getHeight(),
183 GL_RGBA);
184 }
185
186 if (sourceSRV)
187 {
188 sourceSRV->Release();
189 }
190 if (destRTV)
191 {
192 destRTV->Release();
193 }
194 }
195}
196
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000197TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
198 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
199{
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000200 mTexture = swapchain->getOffscreenTexture();
201 mSRV = swapchain->getRenderTargetShaderResource();
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000202
203 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
204 {
205 mRenderTarget[i] = NULL;
206 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000207
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000208 D3D11_TEXTURE2D_DESC texDesc;
209 mTexture->GetDesc(&texDesc);
210 mMipLevels = texDesc.MipLevels;
211 mTextureFormat = texDesc.Format;
212 mTextureWidth = texDesc.Width;
213 mTextureHeight = texDesc.Height;
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.com858d32f2013-01-25 21:49:59 +0000231 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
232 {
233 mRenderTarget[i] = NULL;
234 }
235
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000236 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
237 if (d3d11::IsDepthStencilFormat(convertedFormat))
238 {
239 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
240 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
241 mDepthStencilFormat = convertedFormat;
242 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
243 }
244 else
245 {
246 mTextureFormat = convertedFormat;
247 mShaderResourceFormat = convertedFormat;
248 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
249 mRenderTargetFormat = convertedFormat;
250 }
251
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000252 // if the width or height is not positive this should be treated as an incomplete texture
253 // we handle that here by skipping the d3d texture creation
254 if (width > 0 && height > 0)
255 {
256 // adjust size if needed for compressed textures
257 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
258
259 ID3D11Device *device = mRenderer->getDevice();
260
261 D3D11_TEXTURE2D_DESC desc;
262 desc.Width = width; // Compressed texture size constraints?
263 desc.Height = height;
264 desc.MipLevels = levels + mLodOffset;
265 desc.ArraySize = 1;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000266 desc.Format = mTextureFormat;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000267 desc.SampleDesc.Count = 1;
268 desc.SampleDesc.Quality = 0;
269 desc.Usage = D3D11_USAGE_DEFAULT;
270 desc.BindFlags = getBindFlags();
271 desc.CPUAccessFlags = 0;
272 desc.MiscFlags = 0;
273
274 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
275
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000276 // this can happen from windows TDR
277 if (d3d11::isDeviceLostError(result))
278 {
279 mRenderer->notifyDeviceLost();
280 gl::error(GL_OUT_OF_MEMORY);
281 }
282 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000283 {
284 ASSERT(result == E_OUTOFMEMORY);
285 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000286 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000287 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000288 else
289 {
290 mTexture->GetDesc(&desc);
291 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000292 mTextureWidth = desc.Width;
293 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000294 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000295 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000296}
297
298TextureStorage11_2D::~TextureStorage11_2D()
299{
300 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000301 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000302 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000303 mTexture = NULL;
304 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000305
306 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000307 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000308 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000309 mSRV = NULL;
310 }
311
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000312 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000313 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000314 delete mRenderTarget[i];
315 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000316 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000317}
318
319TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
320{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000321 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000322 return static_cast<TextureStorage11_2D*>(storage);
323}
324
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000325RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000326{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000327 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000328 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000329 if (!mRenderTarget[level])
330 {
331 ID3D11Device *device = mRenderer->getDevice();
332 HRESULT result;
333
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000334 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000335 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000336 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
337 srvDesc.Texture2D.MostDetailedMip = level;
338 srvDesc.Texture2D.MipLevels = 1;
339
340 ID3D11ShaderResourceView *srv;
341 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
342
343 if (result == E_OUTOFMEMORY)
344 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000345 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000346 }
347 ASSERT(SUCCEEDED(result));
348
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000349 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
350 {
351 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
352 rtvDesc.Format = mRenderTargetFormat;
353 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
354 rtvDesc.Texture2D.MipSlice = level;
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000355
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000356 ID3D11RenderTargetView *rtv;
357 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
358
359 if (result == E_OUTOFMEMORY)
360 {
361 srv->Release();
362 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
363 }
364 ASSERT(SUCCEEDED(result));
365
366 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
367 // also needs to keep a reference to the texture.
368 mTexture->AddRef();
369
370 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
371 std::max(mTextureWidth >> level, 1U),
372 std::max(mTextureHeight >> level, 1U));
373 }
374 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
375 {
376 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
377 dsvDesc.Format = mDepthStencilFormat;
378 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
379 dsvDesc.Texture2D.MipSlice = level;
380 dsvDesc.Flags = 0;
381
382 ID3D11DepthStencilView *dsv;
383 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
384
385 if (result == E_OUTOFMEMORY)
386 {
387 srv->Release();
388 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
389 }
390 ASSERT(SUCCEEDED(result));
391
392 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
393 // also needs to keep a reference to the texture.
394 mTexture->AddRef();
395
396 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
397 std::max(mTextureWidth >> level, 1U),
398 std::max(mTextureHeight >> level, 1U));
399 }
400 else
401 {
402 UNREACHABLE();
403 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000404 }
405
406 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000407 }
408 else
409 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000410 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000411 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000412}
413
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000414ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000415{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000416 if (!mSRV)
417 {
418 ID3D11Device *device = mRenderer->getDevice();
419
420 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000421 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000422 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
423 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
424 srvDesc.Texture2D.MostDetailedMip = 0;
425
426 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
427
428 if (result == E_OUTOFMEMORY)
429 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000430 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000431 }
432 ASSERT(SUCCEEDED(result));
433 }
434
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000435 return mSRV;
436}
437
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000438void TextureStorage11_2D::generateMipmap(int level)
439{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000440 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
441 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
442
443 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000444}
445
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000446TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
447 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
448{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000449 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000450 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000451 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
452 {
453 mRenderTarget[i][j] = NULL;
454 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000455 }
456
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000457 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
458 if (d3d11::IsDepthStencilFormat(convertedFormat))
459 {
460 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
461 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
462 mDepthStencilFormat = convertedFormat;
463 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
464 }
465 else
466 {
467 mTextureFormat = convertedFormat;
468 mShaderResourceFormat = convertedFormat;
469 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
470 mRenderTargetFormat = convertedFormat;
471 }
472
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000473 // if the size is not positive this should be treated as an incomplete texture
474 // we handle that here by skipping the d3d texture creation
475 if (size > 0)
476 {
477 // adjust size if needed for compressed textures
478 int height = size;
479 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
480
481 ID3D11Device *device = mRenderer->getDevice();
482
483 D3D11_TEXTURE2D_DESC desc;
484 desc.Width = size;
485 desc.Height = size;
486 desc.MipLevels = levels + mLodOffset;
487 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000488 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000489 desc.SampleDesc.Count = 1;
490 desc.SampleDesc.Quality = 0;
491 desc.Usage = D3D11_USAGE_DEFAULT;
492 desc.BindFlags = getBindFlags();
493 desc.CPUAccessFlags = 0;
494 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
495
496 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
497
498 if (FAILED(result))
499 {
500 ASSERT(result == E_OUTOFMEMORY);
501 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000502 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000503 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000504 else
505 {
506 mTexture->GetDesc(&desc);
507 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000508 mTextureWidth = desc.Width;
509 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000510 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000511 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000512}
513
514TextureStorage11_Cube::~TextureStorage11_Cube()
515{
516 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000517 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000518 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000519 mTexture = NULL;
520 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000521
522 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000523 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000524 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000525 mSRV = NULL;
526 }
527
528 for (unsigned int i = 0; i < 6; i++)
529 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000530 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000531 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000532 delete mRenderTarget[i][j];
533 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000534 }
535 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000536}
537
538TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
539{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000540 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000541 return static_cast<TextureStorage11_Cube*>(storage);
542}
543
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000544RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000545{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000546 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
547 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000548 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000549 if (!mRenderTarget[faceIdx][level])
550 {
551 ID3D11Device *device = mRenderer->getDevice();
552 HRESULT result;
553
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000554 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
555 srvDesc.Format = mShaderResourceFormat;
556 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
557 srvDesc.Texture2DArray.MostDetailedMip = level;
558 srvDesc.Texture2DArray.MipLevels = 1;
559 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
560 srvDesc.Texture2DArray.ArraySize = 1;
561
562 ID3D11ShaderResourceView *srv;
563 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
564
565 if (result == E_OUTOFMEMORY)
566 {
567 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
568 }
569 ASSERT(SUCCEEDED(result));
570
571 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000572 {
573 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000574 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000575 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
576 rtvDesc.Texture2DArray.MipSlice = level;
577 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
578 rtvDesc.Texture2DArray.ArraySize = 1;
579
580 ID3D11RenderTargetView *rtv;
581 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
582
583 if (result == E_OUTOFMEMORY)
584 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000585 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000586 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000587 }
588 ASSERT(SUCCEEDED(result));
589
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000590 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
591 // also needs to keep a reference to the texture.
592 mTexture->AddRef();
593
594 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000595 std::max(mTextureWidth >> level, 1U),
596 std::max(mTextureHeight >> level, 1U));
597 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000598 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000599 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000600 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
601 dsvDesc.Format = mRenderTargetFormat;
602 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
603 dsvDesc.Texture2DArray.MipSlice = level;
604 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
605 dsvDesc.Texture2DArray.ArraySize = 1;
606
607 ID3D11DepthStencilView *dsv;
608 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
609
610 if (result == E_OUTOFMEMORY)
611 {
612 srv->Release();
613 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
614 }
615 ASSERT(SUCCEEDED(result));
616
617 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
618 // also needs to keep a reference to the texture.
619 mTexture->AddRef();
620
621 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
622 std::max(mTextureWidth >> level, 1U),
623 std::max(mTextureHeight >> level, 1U));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000624 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000625 else
626 {
627 UNREACHABLE();
628 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000629 }
630
631 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000632 }
633 else
634 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000635 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000636 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000637}
638
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000639ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000640{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000641 if (!mSRV)
642 {
643 ID3D11Device *device = mRenderer->getDevice();
644
645 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000646 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000647 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
648 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
649 srvDesc.TextureCube.MostDetailedMip = 0;
650
651 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
652
653 if (result == E_OUTOFMEMORY)
654 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000655 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000656 }
657 ASSERT(SUCCEEDED(result));
658 }
659
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000660 return mSRV;
661}
662
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000663void TextureStorage11_Cube::generateMipmap(int face, int level)
664{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000665 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
666 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
667
668 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000669}
670
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000671}