blob: c328904227a22527e7c123947a1ed4d997e4635e [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),
25 mMipLevels(0)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000026{
27 mRenderer = Renderer11::makeRenderer11(renderer);
28}
29
30TextureStorage11::~TextureStorage11()
31{
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +000032}
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000033
34TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
35{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000036 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000037 return static_cast<TextureStorage11*>(storage);
38}
39
40DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
41{
42 UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
43
shannon.woods@transgaming.comeec5c632013-02-28 23:04:21 +000044 if (d3d11::IsDepthStencilFormat(format))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000045 {
46 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
47 }
48 else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
49 {
50 bindFlags |= D3D11_BIND_RENDER_TARGET;
51 }
52 return bindFlags;
53}
54
55bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
56{
57 switch(format)
58 {
59 case DXGI_FORMAT_R8G8B8A8_UNORM:
60 case DXGI_FORMAT_A8_UNORM:
61 case DXGI_FORMAT_R32G32B32A32_FLOAT:
62 case DXGI_FORMAT_R32G32B32_FLOAT:
63 case DXGI_FORMAT_R16G16B16A16_FLOAT:
64 case DXGI_FORMAT_B8G8R8A8_UNORM:
65 case DXGI_FORMAT_R8_UNORM:
66 case DXGI_FORMAT_R8G8_UNORM:
67 case DXGI_FORMAT_R16_FLOAT:
68 case DXGI_FORMAT_R16G16_FLOAT:
69 return true;
70 case DXGI_FORMAT_BC1_UNORM:
71 case DXGI_FORMAT_BC2_UNORM:
72 case DXGI_FORMAT_BC3_UNORM:
73 return false;
74 default:
75 UNREACHABLE();
76 return false;
77 }
78}
79
80UINT TextureStorage11::getBindFlags() const
81{
82 return mBindFlags;
83}
84
85int TextureStorage11::getLodOffset() const
86{
87 return mLodOffset;
88}
89
90bool TextureStorage11::isRenderTarget() const
91{
92 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
93}
94
95bool TextureStorage11::isManaged() const
96{
97 return false;
98}
99
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000100int TextureStorage11::levelCount()
101{
102 int levels = 0;
103 if (getBaseTexture())
104 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000105 levels = mMipLevels - getLodOffset();
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000106 }
107 return levels;
108}
109
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000110UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
111{
112 UINT index = 0;
113 if (getBaseTexture())
114 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000115 index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000116 }
117 return index;
118}
119
120bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, int level, int face, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
121{
122 if (srcTexture)
123 {
124 D3D11_BOX srcBox;
125 srcBox.left = xoffset;
126 srcBox.top = yoffset;
127 srcBox.right = xoffset + width;
128 srcBox.bottom = yoffset + height;
129 srcBox.front = 0;
130 srcBox.back = 1;
131
132 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
133
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000134 ASSERT(getBaseTexture());
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000135 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level, face), xoffset, yoffset, 0, srcTexture, 0, &srcBox);
136 return true;
137 }
138
139 return false;
140}
141
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000142void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
143{
144 if (source && dest)
145 {
146 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
147 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
148
149 if (sourceSRV && destRTV)
150 {
151 gl::Rectangle sourceArea;
152 sourceArea.x = 0;
153 sourceArea.y = 0;
154 sourceArea.width = source->getWidth();
155 sourceArea.height = source->getHeight();
156
157 gl::Rectangle destArea;
158 destArea.x = 0;
159 destArea.y = 0;
160 destArea.width = dest->getWidth();
161 destArea.height = dest->getHeight();
162
163 mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
164 destRTV, destArea, dest->getWidth(), dest->getHeight(),
165 GL_RGBA);
166 }
167
168 if (sourceSRV)
169 {
170 sourceSRV->Release();
171 }
172 if (destRTV)
173 {
174 destRTV->Release();
175 }
176 }
177}
178
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000179TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
180 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
181{
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000182 mTexture = swapchain->getOffscreenTexture();
183 mSRV = swapchain->getRenderTargetShaderResource();
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000184
185 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
186 {
187 mRenderTarget[i] = NULL;
188 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000189
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000190 D3D11_TEXTURE2D_DESC texDesc;
191 mTexture->GetDesc(&texDesc);
192 mMipLevels = texDesc.MipLevels;
193 mTextureFormat = texDesc.Format;
194 mTextureWidth = texDesc.Width;
195 mTextureHeight = texDesc.Height;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000196
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000197 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
198 mSRV->GetDesc(&srvDesc);
199 mShaderResourceFormat = srvDesc.Format;
200
201 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
202 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
203 offscreenRTV->GetDesc(&rtvDesc);
204 mRenderTargetFormat = rtvDesc.Format;
205 offscreenRTV->Release();
206
207 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000208}
209
210TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
211 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
212{
213 mTexture = NULL;
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000214 mSRV = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000215 mTextureWidth = 0;
216 mTextureHeight = 0;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000217
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000218 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
219 {
220 mRenderTarget[i] = NULL;
221 }
222
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000223 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
224 if (d3d11::IsDepthStencilFormat(convertedFormat))
225 {
226 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
227 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
228 mDepthStencilFormat = convertedFormat;
229 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
230 }
231 else
232 {
233 mTextureFormat = convertedFormat;
234 mShaderResourceFormat = convertedFormat;
235 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
236 mRenderTargetFormat = convertedFormat;
237 }
238
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000239 // if the width or height is not positive this should be treated as an incomplete texture
240 // we handle that here by skipping the d3d texture creation
241 if (width > 0 && height > 0)
242 {
243 // adjust size if needed for compressed textures
244 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
245
246 ID3D11Device *device = mRenderer->getDevice();
247
248 D3D11_TEXTURE2D_DESC desc;
249 desc.Width = width; // Compressed texture size constraints?
250 desc.Height = height;
251 desc.MipLevels = levels + mLodOffset;
252 desc.ArraySize = 1;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000253 desc.Format = mTextureFormat;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000254 desc.SampleDesc.Count = 1;
255 desc.SampleDesc.Quality = 0;
256 desc.Usage = D3D11_USAGE_DEFAULT;
257 desc.BindFlags = getBindFlags();
258 desc.CPUAccessFlags = 0;
259 desc.MiscFlags = 0;
260
261 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
262
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000263 // this can happen from windows TDR
264 if (d3d11::isDeviceLostError(result))
265 {
266 mRenderer->notifyDeviceLost();
267 gl::error(GL_OUT_OF_MEMORY);
268 }
269 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000270 {
271 ASSERT(result == E_OUTOFMEMORY);
272 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000273 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000274 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000275 else
276 {
277 mTexture->GetDesc(&desc);
278 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000279 mTextureWidth = desc.Width;
280 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000281 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000282 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000283}
284
285TextureStorage11_2D::~TextureStorage11_2D()
286{
287 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000288 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000289 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000290 mTexture = NULL;
291 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000292
293 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000294 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000295 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000296 mSRV = NULL;
297 }
298
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000299 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000300 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000301 delete mRenderTarget[i];
302 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000303 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000304}
305
306TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
307{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000308 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000309 return static_cast<TextureStorage11_2D*>(storage);
310}
311
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000312RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000313{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000314 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000315 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000316 if (!mRenderTarget[level])
317 {
318 ID3D11Device *device = mRenderer->getDevice();
319 HRESULT result;
320
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000321 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000322 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000323 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
324 srvDesc.Texture2D.MostDetailedMip = level;
325 srvDesc.Texture2D.MipLevels = 1;
326
327 ID3D11ShaderResourceView *srv;
328 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
329
330 if (result == E_OUTOFMEMORY)
331 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000332 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000333 }
334 ASSERT(SUCCEEDED(result));
335
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000336 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
337 {
338 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
339 rtvDesc.Format = mRenderTargetFormat;
340 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
341 rtvDesc.Texture2D.MipSlice = level;
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000342
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000343 ID3D11RenderTargetView *rtv;
344 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
345
346 if (result == E_OUTOFMEMORY)
347 {
348 srv->Release();
349 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
350 }
351 ASSERT(SUCCEEDED(result));
352
353 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
354 // also needs to keep a reference to the texture.
355 mTexture->AddRef();
356
357 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
358 std::max(mTextureWidth >> level, 1U),
359 std::max(mTextureHeight >> level, 1U));
360 }
361 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
362 {
363 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
364 dsvDesc.Format = mDepthStencilFormat;
365 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
366 dsvDesc.Texture2D.MipSlice = level;
367 dsvDesc.Flags = 0;
368
369 ID3D11DepthStencilView *dsv;
370 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
371
372 if (result == E_OUTOFMEMORY)
373 {
374 srv->Release();
375 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
376 }
377 ASSERT(SUCCEEDED(result));
378
379 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
380 // also needs to keep a reference to the texture.
381 mTexture->AddRef();
382
383 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
384 std::max(mTextureWidth >> level, 1U),
385 std::max(mTextureHeight >> level, 1U));
386 }
387 else
388 {
389 UNREACHABLE();
390 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000391 }
392
393 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000394 }
395 else
396 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000397 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000398 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000399}
400
401ID3D11Texture2D *TextureStorage11_2D::getBaseTexture() const
402{
403 return mTexture;
404}
405
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000406ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000407{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000408 if (!mSRV)
409 {
410 ID3D11Device *device = mRenderer->getDevice();
411
412 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000413 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000414 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
415 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
416 srvDesc.Texture2D.MostDetailedMip = 0;
417
418 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
419
420 if (result == E_OUTOFMEMORY)
421 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000422 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000423 }
424 ASSERT(SUCCEEDED(result));
425 }
426
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000427 return mSRV;
428}
429
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000430void TextureStorage11_2D::generateMipmap(int level)
431{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000432 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
433 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
434
435 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000436}
437
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000438TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
439 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
440{
441 mTexture = NULL;
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000442 mSRV = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000443 mTextureWidth = 0;
444 mTextureHeight = 0;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000445
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000446 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000447 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000448 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
449 {
450 mRenderTarget[i][j] = NULL;
451 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000452 }
453
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000454 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
455 if (d3d11::IsDepthStencilFormat(convertedFormat))
456 {
457 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
458 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
459 mDepthStencilFormat = convertedFormat;
460 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
461 }
462 else
463 {
464 mTextureFormat = convertedFormat;
465 mShaderResourceFormat = convertedFormat;
466 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
467 mRenderTargetFormat = convertedFormat;
468 }
469
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000470 // if the size is not positive this should be treated as an incomplete texture
471 // we handle that here by skipping the d3d texture creation
472 if (size > 0)
473 {
474 // adjust size if needed for compressed textures
475 int height = size;
476 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
477
478 ID3D11Device *device = mRenderer->getDevice();
479
480 D3D11_TEXTURE2D_DESC desc;
481 desc.Width = size;
482 desc.Height = size;
483 desc.MipLevels = levels + mLodOffset;
484 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000485 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000486 desc.SampleDesc.Count = 1;
487 desc.SampleDesc.Quality = 0;
488 desc.Usage = D3D11_USAGE_DEFAULT;
489 desc.BindFlags = getBindFlags();
490 desc.CPUAccessFlags = 0;
491 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
492
493 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
494
495 if (FAILED(result))
496 {
497 ASSERT(result == E_OUTOFMEMORY);
498 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000499 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000500 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000501 else
502 {
503 mTexture->GetDesc(&desc);
504 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000505 mTextureWidth = desc.Width;
506 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000507 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000508 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000509}
510
511TextureStorage11_Cube::~TextureStorage11_Cube()
512{
513 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000514 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000515 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000516 mTexture = NULL;
517 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000518
519 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000520 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000521 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000522 mSRV = NULL;
523 }
524
525 for (unsigned int i = 0; i < 6; i++)
526 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000527 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000528 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000529 delete mRenderTarget[i][j];
530 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000531 }
532 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000533}
534
535TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
536{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000537 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000538 return static_cast<TextureStorage11_Cube*>(storage);
539}
540
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000541RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000542{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000543 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
544 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000545 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000546 if (!mRenderTarget[faceIdx][level])
547 {
548 ID3D11Device *device = mRenderer->getDevice();
549 HRESULT result;
550
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000551 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
552 srvDesc.Format = mShaderResourceFormat;
553 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
554 srvDesc.Texture2DArray.MostDetailedMip = level;
555 srvDesc.Texture2DArray.MipLevels = 1;
556 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
557 srvDesc.Texture2DArray.ArraySize = 1;
558
559 ID3D11ShaderResourceView *srv;
560 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
561
562 if (result == E_OUTOFMEMORY)
563 {
564 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
565 }
566 ASSERT(SUCCEEDED(result));
567
568 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000569 {
570 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000571 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000572 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
573 rtvDesc.Texture2DArray.MipSlice = level;
574 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
575 rtvDesc.Texture2DArray.ArraySize = 1;
576
577 ID3D11RenderTargetView *rtv;
578 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
579
580 if (result == E_OUTOFMEMORY)
581 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000582 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000583 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000584 }
585 ASSERT(SUCCEEDED(result));
586
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000587 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
588 // also needs to keep a reference to the texture.
589 mTexture->AddRef();
590
591 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000592 std::max(mTextureWidth >> level, 1U),
593 std::max(mTextureHeight >> level, 1U));
594 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000595 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000596 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000597 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
598 dsvDesc.Format = mRenderTargetFormat;
599 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
600 dsvDesc.Texture2DArray.MipSlice = level;
601 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
602 dsvDesc.Texture2DArray.ArraySize = 1;
603
604 ID3D11DepthStencilView *dsv;
605 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
606
607 if (result == E_OUTOFMEMORY)
608 {
609 srv->Release();
610 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
611 }
612 ASSERT(SUCCEEDED(result));
613
614 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
615 // also needs to keep a reference to the texture.
616 mTexture->AddRef();
617
618 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
619 std::max(mTextureWidth >> level, 1U),
620 std::max(mTextureHeight >> level, 1U));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000621 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000622 else
623 {
624 UNREACHABLE();
625 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000626 }
627
628 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000629 }
630 else
631 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000632 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000633 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000634}
635
636ID3D11Texture2D *TextureStorage11_Cube::getBaseTexture() const
637{
638 return mTexture;
639}
640
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000641ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000642{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000643 if (!mSRV)
644 {
645 ID3D11Device *device = mRenderer->getDevice();
646
647 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000648 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000649 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
650 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
651 srvDesc.TextureCube.MostDetailedMip = 0;
652
653 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
654
655 if (result == E_OUTOFMEMORY)
656 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000657 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000658 }
659 ASSERT(SUCCEEDED(result));
660 }
661
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000662 return mSRV;
663}
664
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000665void TextureStorage11_Cube::generateMipmap(int face, int level)
666{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000667 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
668 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
669
670 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000671}
672
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000673}