blob: a0921df8b5044bf1941f46244ec23ffdc500967f [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 {
136 D3D11_BOX srcBox;
137 srcBox.left = xoffset;
138 srcBox.top = yoffset;
139 srcBox.right = xoffset + width;
140 srcBox.bottom = yoffset + height;
141 srcBox.front = 0;
142 srcBox.back = 1;
143
144 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
145
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000146 ASSERT(getBaseTexture());
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000147 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level, face), xoffset, yoffset, 0, srcTexture, 0, &srcBox);
148 return true;
149 }
150
151 return false;
152}
153
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000154void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
155{
156 if (source && dest)
157 {
158 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
159 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
160
161 if (sourceSRV && destRTV)
162 {
163 gl::Rectangle sourceArea;
164 sourceArea.x = 0;
165 sourceArea.y = 0;
166 sourceArea.width = source->getWidth();
167 sourceArea.height = source->getHeight();
168
169 gl::Rectangle destArea;
170 destArea.x = 0;
171 destArea.y = 0;
172 destArea.width = dest->getWidth();
173 destArea.height = dest->getHeight();
174
175 mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
176 destRTV, destArea, dest->getWidth(), dest->getHeight(),
177 GL_RGBA);
178 }
179
180 if (sourceSRV)
181 {
182 sourceSRV->Release();
183 }
184 if (destRTV)
185 {
186 destRTV->Release();
187 }
188 }
189}
190
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000191TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
192 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
193{
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000194 mTexture = swapchain->getOffscreenTexture();
195 mSRV = swapchain->getRenderTargetShaderResource();
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000196
197 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
198 {
199 mRenderTarget[i] = NULL;
200 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000201
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000202 D3D11_TEXTURE2D_DESC texDesc;
203 mTexture->GetDesc(&texDesc);
204 mMipLevels = texDesc.MipLevels;
205 mTextureFormat = texDesc.Format;
206 mTextureWidth = texDesc.Width;
207 mTextureHeight = texDesc.Height;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000208
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000209 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
210 mSRV->GetDesc(&srvDesc);
211 mShaderResourceFormat = srvDesc.Format;
212
213 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
214 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
215 offscreenRTV->GetDesc(&rtvDesc);
216 mRenderTargetFormat = rtvDesc.Format;
217 offscreenRTV->Release();
218
219 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000220}
221
222TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
223 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
224{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000225 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
226 {
227 mRenderTarget[i] = NULL;
228 }
229
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000230 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
231 if (d3d11::IsDepthStencilFormat(convertedFormat))
232 {
233 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
234 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
235 mDepthStencilFormat = convertedFormat;
236 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
237 }
238 else
239 {
240 mTextureFormat = convertedFormat;
241 mShaderResourceFormat = convertedFormat;
242 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
243 mRenderTargetFormat = convertedFormat;
244 }
245
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000246 // if the width or height is not positive this should be treated as an incomplete texture
247 // we handle that here by skipping the d3d texture creation
248 if (width > 0 && height > 0)
249 {
250 // adjust size if needed for compressed textures
251 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
252
253 ID3D11Device *device = mRenderer->getDevice();
254
255 D3D11_TEXTURE2D_DESC desc;
256 desc.Width = width; // Compressed texture size constraints?
257 desc.Height = height;
258 desc.MipLevels = levels + mLodOffset;
259 desc.ArraySize = 1;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000260 desc.Format = mTextureFormat;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000261 desc.SampleDesc.Count = 1;
262 desc.SampleDesc.Quality = 0;
263 desc.Usage = D3D11_USAGE_DEFAULT;
264 desc.BindFlags = getBindFlags();
265 desc.CPUAccessFlags = 0;
266 desc.MiscFlags = 0;
267
268 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
269
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000270 // this can happen from windows TDR
271 if (d3d11::isDeviceLostError(result))
272 {
273 mRenderer->notifyDeviceLost();
274 gl::error(GL_OUT_OF_MEMORY);
275 }
276 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000277 {
278 ASSERT(result == E_OUTOFMEMORY);
279 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000280 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000281 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000282 else
283 {
284 mTexture->GetDesc(&desc);
285 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000286 mTextureWidth = desc.Width;
287 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000288 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000289 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000290}
291
292TextureStorage11_2D::~TextureStorage11_2D()
293{
294 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000295 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000296 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000297 mTexture = NULL;
298 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000299
300 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000301 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000302 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000303 mSRV = NULL;
304 }
305
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000306 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000307 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000308 delete mRenderTarget[i];
309 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000310 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000311}
312
313TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
314{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000315 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000316 return static_cast<TextureStorage11_2D*>(storage);
317}
318
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000319RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000320{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000321 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000322 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000323 if (!mRenderTarget[level])
324 {
325 ID3D11Device *device = mRenderer->getDevice();
326 HRESULT result;
327
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000328 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000329 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000330 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
331 srvDesc.Texture2D.MostDetailedMip = level;
332 srvDesc.Texture2D.MipLevels = 1;
333
334 ID3D11ShaderResourceView *srv;
335 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
336
337 if (result == E_OUTOFMEMORY)
338 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000339 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000340 }
341 ASSERT(SUCCEEDED(result));
342
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000343 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
344 {
345 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
346 rtvDesc.Format = mRenderTargetFormat;
347 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
348 rtvDesc.Texture2D.MipSlice = level;
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000349
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000350 ID3D11RenderTargetView *rtv;
351 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
352
353 if (result == E_OUTOFMEMORY)
354 {
355 srv->Release();
356 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
357 }
358 ASSERT(SUCCEEDED(result));
359
360 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
361 // also needs to keep a reference to the texture.
362 mTexture->AddRef();
363
364 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
365 std::max(mTextureWidth >> level, 1U),
366 std::max(mTextureHeight >> level, 1U));
367 }
368 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
369 {
370 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
371 dsvDesc.Format = mDepthStencilFormat;
372 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
373 dsvDesc.Texture2D.MipSlice = level;
374 dsvDesc.Flags = 0;
375
376 ID3D11DepthStencilView *dsv;
377 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
378
379 if (result == E_OUTOFMEMORY)
380 {
381 srv->Release();
382 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
383 }
384 ASSERT(SUCCEEDED(result));
385
386 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
387 // also needs to keep a reference to the texture.
388 mTexture->AddRef();
389
390 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
391 std::max(mTextureWidth >> level, 1U),
392 std::max(mTextureHeight >> level, 1U));
393 }
394 else
395 {
396 UNREACHABLE();
397 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000398 }
399
400 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000401 }
402 else
403 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000404 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000405 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000406}
407
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000408ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000409{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000410 if (!mSRV)
411 {
412 ID3D11Device *device = mRenderer->getDevice();
413
414 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000415 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000416 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
417 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
418 srvDesc.Texture2D.MostDetailedMip = 0;
419
420 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
421
422 if (result == E_OUTOFMEMORY)
423 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000424 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000425 }
426 ASSERT(SUCCEEDED(result));
427 }
428
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000429 return mSRV;
430}
431
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000432void TextureStorage11_2D::generateMipmap(int level)
433{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000434 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
435 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
436
437 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000438}
439
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000440TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
441 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
442{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000443 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000444 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000445 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
446 {
447 mRenderTarget[i][j] = NULL;
448 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000449 }
450
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000451 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
452 if (d3d11::IsDepthStencilFormat(convertedFormat))
453 {
454 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
455 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
456 mDepthStencilFormat = convertedFormat;
457 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
458 }
459 else
460 {
461 mTextureFormat = convertedFormat;
462 mShaderResourceFormat = convertedFormat;
463 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
464 mRenderTargetFormat = convertedFormat;
465 }
466
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000467 // if the size is not positive this should be treated as an incomplete texture
468 // we handle that here by skipping the d3d texture creation
469 if (size > 0)
470 {
471 // adjust size if needed for compressed textures
472 int height = size;
473 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
474
475 ID3D11Device *device = mRenderer->getDevice();
476
477 D3D11_TEXTURE2D_DESC desc;
478 desc.Width = size;
479 desc.Height = size;
480 desc.MipLevels = levels + mLodOffset;
481 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000482 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000483 desc.SampleDesc.Count = 1;
484 desc.SampleDesc.Quality = 0;
485 desc.Usage = D3D11_USAGE_DEFAULT;
486 desc.BindFlags = getBindFlags();
487 desc.CPUAccessFlags = 0;
488 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
489
490 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
491
492 if (FAILED(result))
493 {
494 ASSERT(result == E_OUTOFMEMORY);
495 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000496 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000497 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000498 else
499 {
500 mTexture->GetDesc(&desc);
501 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000502 mTextureWidth = desc.Width;
503 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000504 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000505 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000506}
507
508TextureStorage11_Cube::~TextureStorage11_Cube()
509{
510 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000511 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000512 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000513 mTexture = NULL;
514 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000515
516 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000517 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000518 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000519 mSRV = NULL;
520 }
521
522 for (unsigned int i = 0; i < 6; i++)
523 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000524 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000525 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000526 delete mRenderTarget[i][j];
527 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000528 }
529 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000530}
531
532TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
533{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000534 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000535 return static_cast<TextureStorage11_Cube*>(storage);
536}
537
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000538RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000539{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000540 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
541 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000542 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000543 if (!mRenderTarget[faceIdx][level])
544 {
545 ID3D11Device *device = mRenderer->getDevice();
546 HRESULT result;
547
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000548 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
549 srvDesc.Format = mShaderResourceFormat;
550 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
551 srvDesc.Texture2DArray.MostDetailedMip = level;
552 srvDesc.Texture2DArray.MipLevels = 1;
553 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
554 srvDesc.Texture2DArray.ArraySize = 1;
555
556 ID3D11ShaderResourceView *srv;
557 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
558
559 if (result == E_OUTOFMEMORY)
560 {
561 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
562 }
563 ASSERT(SUCCEEDED(result));
564
565 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000566 {
567 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000568 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000569 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
570 rtvDesc.Texture2DArray.MipSlice = level;
571 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
572 rtvDesc.Texture2DArray.ArraySize = 1;
573
574 ID3D11RenderTargetView *rtv;
575 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
576
577 if (result == E_OUTOFMEMORY)
578 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000579 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000580 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000581 }
582 ASSERT(SUCCEEDED(result));
583
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000584 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
585 // also needs to keep a reference to the texture.
586 mTexture->AddRef();
587
588 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000589 std::max(mTextureWidth >> level, 1U),
590 std::max(mTextureHeight >> level, 1U));
591 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000592 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000593 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000594 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
595 dsvDesc.Format = mRenderTargetFormat;
596 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
597 dsvDesc.Texture2DArray.MipSlice = level;
598 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
599 dsvDesc.Texture2DArray.ArraySize = 1;
600
601 ID3D11DepthStencilView *dsv;
602 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
603
604 if (result == E_OUTOFMEMORY)
605 {
606 srv->Release();
607 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
608 }
609 ASSERT(SUCCEEDED(result));
610
611 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
612 // also needs to keep a reference to the texture.
613 mTexture->AddRef();
614
615 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
616 std::max(mTextureWidth >> level, 1U),
617 std::max(mTextureHeight >> level, 1U));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000618 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000619 else
620 {
621 UNREACHABLE();
622 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000623 }
624
625 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000626 }
627 else
628 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000629 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000630 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000631}
632
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000633ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000634{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000635 if (!mSRV)
636 {
637 ID3D11Device *device = mRenderer->getDevice();
638
639 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000640 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000641 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
642 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
643 srvDesc.TextureCube.MostDetailedMip = 0;
644
645 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
646
647 if (result == E_OUTOFMEMORY)
648 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000649 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000650 }
651 ASSERT(SUCCEEDED(result));
652 }
653
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000654 return mSRV;
655}
656
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000657void TextureStorage11_Cube::generateMipmap(int face, int level)
658{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000659 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
660 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
661
662 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000663}
664
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000665}