blob: f348ca651b020cf639d00a8f0c410c6a61aa727f [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{
182 ID3D11Texture2D *surfaceTexture = swapchain->getOffscreenTexture();
183 mTexture = surfaceTexture;
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000184 mSRV = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000185
186 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
187 {
188 mRenderTarget[i] = NULL;
189 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000190
191 D3D11_TEXTURE2D_DESC desc;
192 surfaceTexture->GetDesc(&desc);
193
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000194 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000195 mTextureFormat = desc.Format;
196 mTextureWidth = desc.Width;
197 mTextureHeight = desc.Height;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000198}
199
200TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
201 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
202{
203 mTexture = NULL;
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000204 mSRV = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000205 mTextureWidth = 0;
206 mTextureHeight = 0;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000207 DXGI_FORMAT format = gl_d3d11::ConvertTextureFormat(internalformat);
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000208
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000209 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
210 {
211 mRenderTarget[i] = NULL;
212 }
213
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000214 // if the width or height is not positive this should be treated as an incomplete texture
215 // we handle that here by skipping the d3d texture creation
216 if (width > 0 && height > 0)
217 {
218 // adjust size if needed for compressed textures
219 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
220
221 ID3D11Device *device = mRenderer->getDevice();
222
223 D3D11_TEXTURE2D_DESC desc;
224 desc.Width = width; // Compressed texture size constraints?
225 desc.Height = height;
226 desc.MipLevels = levels + mLodOffset;
227 desc.ArraySize = 1;
228 desc.Format = format;
229 desc.SampleDesc.Count = 1;
230 desc.SampleDesc.Quality = 0;
231 desc.Usage = D3D11_USAGE_DEFAULT;
232 desc.BindFlags = getBindFlags();
233 desc.CPUAccessFlags = 0;
234 desc.MiscFlags = 0;
235
236 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
237
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000238 // this can happen from windows TDR
239 if (d3d11::isDeviceLostError(result))
240 {
241 mRenderer->notifyDeviceLost();
242 gl::error(GL_OUT_OF_MEMORY);
243 }
244 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000245 {
246 ASSERT(result == E_OUTOFMEMORY);
247 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000248 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000249 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000250 else
251 {
252 mTexture->GetDesc(&desc);
253 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000254 mTextureFormat = desc.Format;
255 mTextureWidth = desc.Width;
256 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000257 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000258 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000259}
260
261TextureStorage11_2D::~TextureStorage11_2D()
262{
263 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000264 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000265 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000266 mTexture = NULL;
267 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000268
269 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000270 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000271 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000272 mSRV = NULL;
273 }
274
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000275 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000276 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000277 delete mRenderTarget[i];
278 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000279 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000280}
281
282TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
283{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000284 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000285 return static_cast<TextureStorage11_2D*>(storage);
286}
287
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000288RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000289{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000290 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000291 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000292 if (!mRenderTarget[level])
293 {
294 ID3D11Device *device = mRenderer->getDevice();
295 HRESULT result;
296
297 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
298 rtvDesc.Format = mTextureFormat;
299 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
300 rtvDesc.Texture2D.MipSlice = level;
301
302 ID3D11RenderTargetView *rtv;
303 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
304
305 if (result == E_OUTOFMEMORY)
306 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000307 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000308 }
309 ASSERT(SUCCEEDED(result));
310
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000311 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
312 srvDesc.Format = mTextureFormat;
313 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
314 srvDesc.Texture2D.MostDetailedMip = level;
315 srvDesc.Texture2D.MipLevels = 1;
316
317 ID3D11ShaderResourceView *srv;
318 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
319
320 if (result == E_OUTOFMEMORY)
321 {
322 rtv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000323 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000324 }
325 ASSERT(SUCCEEDED(result));
326
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000327 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
328 // also needs to keep a reference to the texture.
329 mTexture->AddRef();
330
331 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000332 std::max(mTextureWidth >> level, 1U),
333 std::max(mTextureHeight >> level, 1U));
334 }
335
336 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000337 }
338 else
339 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000340 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000341 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000342}
343
344ID3D11Texture2D *TextureStorage11_2D::getBaseTexture() const
345{
346 return mTexture;
347}
348
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000349ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000350{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000351 if (!mSRV)
352 {
353 ID3D11Device *device = mRenderer->getDevice();
354
355 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
356 srvDesc.Format = mTextureFormat;
357 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
358 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
359 srvDesc.Texture2D.MostDetailedMip = 0;
360
361 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
362
363 if (result == E_OUTOFMEMORY)
364 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000365 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000366 }
367 ASSERT(SUCCEEDED(result));
368 }
369
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000370 return mSRV;
371}
372
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000373void TextureStorage11_2D::generateMipmap(int level)
374{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000375 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
376 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
377
378 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000379}
380
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000381TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
382 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
383{
384 mTexture = NULL;
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000385 mSRV = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000386 mTextureWidth = 0;
387 mTextureHeight = 0;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000388
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000389 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000390 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000391 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
392 {
393 mRenderTarget[i][j] = NULL;
394 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000395 }
396
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000397 DXGI_FORMAT format = gl_d3d11::ConvertTextureFormat(internalformat);
398 // if the size is not positive this should be treated as an incomplete texture
399 // we handle that here by skipping the d3d texture creation
400 if (size > 0)
401 {
402 // adjust size if needed for compressed textures
403 int height = size;
404 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
405
406 ID3D11Device *device = mRenderer->getDevice();
407
408 D3D11_TEXTURE2D_DESC desc;
409 desc.Width = size;
410 desc.Height = size;
411 desc.MipLevels = levels + mLodOffset;
412 desc.ArraySize = 6;
413 desc.Format = format;
414 desc.SampleDesc.Count = 1;
415 desc.SampleDesc.Quality = 0;
416 desc.Usage = D3D11_USAGE_DEFAULT;
417 desc.BindFlags = getBindFlags();
418 desc.CPUAccessFlags = 0;
419 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
420
421 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
422
423 if (FAILED(result))
424 {
425 ASSERT(result == E_OUTOFMEMORY);
426 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000427 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000428 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000429 else
430 {
431 mTexture->GetDesc(&desc);
432 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000433 mTextureFormat = desc.Format;
434 mTextureWidth = desc.Width;
435 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000436 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000437 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000438}
439
440TextureStorage11_Cube::~TextureStorage11_Cube()
441{
442 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000443 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000444 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000445 mTexture = NULL;
446 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000447
448 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000449 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000450 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000451 mSRV = NULL;
452 }
453
454 for (unsigned int i = 0; i < 6; i++)
455 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000456 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000457 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000458 delete mRenderTarget[i][j];
459 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000460 }
461 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000462}
463
464TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
465{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000466 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000467 return static_cast<TextureStorage11_Cube*>(storage);
468}
469
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000470RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000471{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000472 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
473 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000474 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000475 if (!mRenderTarget[faceIdx][level])
476 {
477 ID3D11Device *device = mRenderer->getDevice();
478 HRESULT result;
479
480 if (getBindFlags() & D3D11_BIND_RENDER_TARGET)
481 {
482 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
483 rtvDesc.Format = mTextureFormat;
484 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
485 rtvDesc.Texture2DArray.MipSlice = level;
486 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
487 rtvDesc.Texture2DArray.ArraySize = 1;
488
489 ID3D11RenderTargetView *rtv;
490 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
491
492 if (result == E_OUTOFMEMORY)
493 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000494 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000495 }
496 ASSERT(SUCCEEDED(result));
497
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000498 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
499 srvDesc.Format = mTextureFormat;
500 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
501 srvDesc.Texture2DArray.MostDetailedMip = level;
502 srvDesc.Texture2DArray.MipLevels = 1;
503 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
504 srvDesc.Texture2DArray.ArraySize = 1;
505
506 ID3D11ShaderResourceView *srv;
507 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
508
509 if (result == E_OUTOFMEMORY)
510 {
511 rtv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000512 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000513 }
514 ASSERT(SUCCEEDED(result));
515
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000516 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
517 // also needs to keep a reference to the texture.
518 mTexture->AddRef();
519
520 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000521 std::max(mTextureWidth >> level, 1U),
522 std::max(mTextureHeight >> level, 1U));
523 }
524 else if (getBindFlags() & D3D11_BIND_DEPTH_STENCIL)
525 {
526 // TODO
527 UNIMPLEMENTED();
528 }
529 else UNREACHABLE();
530 }
531
532 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000533 }
534 else
535 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000536 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000537 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000538}
539
540ID3D11Texture2D *TextureStorage11_Cube::getBaseTexture() const
541{
542 return mTexture;
543}
544
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000545ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000546{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000547 if (!mSRV)
548 {
549 ID3D11Device *device = mRenderer->getDevice();
550
551 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
552 srvDesc.Format = mTextureFormat;
553 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
554 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
555 srvDesc.TextureCube.MostDetailedMip = 0;
556
557 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
558
559 if (result == E_OUTOFMEMORY)
560 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000561 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000562 }
563 ASSERT(SUCCEEDED(result));
564 }
565
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000566 return mSRV;
567}
568
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000569void TextureStorage11_Cube::generateMipmap(int face, int level)
570{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000571 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
572 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
573
574 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000575}
576
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000577}