blob: 9a3db01468a0a8bdfaff134473593bb9699dcd37 [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
327 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000328 std::max(mTextureWidth >> level, 1U),
329 std::max(mTextureHeight >> level, 1U));
330 }
331
332 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000333 }
334 else
335 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000336 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000337 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000338}
339
340ID3D11Texture2D *TextureStorage11_2D::getBaseTexture() const
341{
342 return mTexture;
343}
344
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000345ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000346{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000347 if (!mSRV)
348 {
349 ID3D11Device *device = mRenderer->getDevice();
350
351 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
352 srvDesc.Format = mTextureFormat;
353 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
354 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
355 srvDesc.Texture2D.MostDetailedMip = 0;
356
357 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
358
359 if (result == E_OUTOFMEMORY)
360 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000361 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000362 }
363 ASSERT(SUCCEEDED(result));
364 }
365
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000366 return mSRV;
367}
368
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000369void TextureStorage11_2D::generateMipmap(int level)
370{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000371 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
372 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
373
374 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000375}
376
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000377TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
378 : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
379{
380 mTexture = NULL;
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000381 mSRV = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000382 mTextureWidth = 0;
383 mTextureHeight = 0;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000384
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000385 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000386 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000387 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
388 {
389 mRenderTarget[i][j] = NULL;
390 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000391 }
392
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000393 DXGI_FORMAT format = gl_d3d11::ConvertTextureFormat(internalformat);
394 // if the size is not positive this should be treated as an incomplete texture
395 // we handle that here by skipping the d3d texture creation
396 if (size > 0)
397 {
398 // adjust size if needed for compressed textures
399 int height = size;
400 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
401
402 ID3D11Device *device = mRenderer->getDevice();
403
404 D3D11_TEXTURE2D_DESC desc;
405 desc.Width = size;
406 desc.Height = size;
407 desc.MipLevels = levels + mLodOffset;
408 desc.ArraySize = 6;
409 desc.Format = format;
410 desc.SampleDesc.Count = 1;
411 desc.SampleDesc.Quality = 0;
412 desc.Usage = D3D11_USAGE_DEFAULT;
413 desc.BindFlags = getBindFlags();
414 desc.CPUAccessFlags = 0;
415 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
416
417 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
418
419 if (FAILED(result))
420 {
421 ASSERT(result == E_OUTOFMEMORY);
422 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000423 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000424 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000425 else
426 {
427 mTexture->GetDesc(&desc);
428 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000429 mTextureFormat = desc.Format;
430 mTextureWidth = desc.Width;
431 mTextureHeight = desc.Height;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000432 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000433 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000434}
435
436TextureStorage11_Cube::~TextureStorage11_Cube()
437{
438 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000439 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000440 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000441 mTexture = NULL;
442 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000443
444 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000445 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000446 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000447 mSRV = NULL;
448 }
449
450 for (unsigned int i = 0; i < 6; i++)
451 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000452 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000453 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000454 delete mRenderTarget[i][j];
455 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000456 }
457 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000458}
459
460TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
461{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000462 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000463 return static_cast<TextureStorage11_Cube*>(storage);
464}
465
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000466RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000467{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000468 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
469 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000470 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000471 if (!mRenderTarget[faceIdx][level])
472 {
473 ID3D11Device *device = mRenderer->getDevice();
474 HRESULT result;
475
476 if (getBindFlags() & D3D11_BIND_RENDER_TARGET)
477 {
478 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
479 rtvDesc.Format = mTextureFormat;
480 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
481 rtvDesc.Texture2DArray.MipSlice = level;
482 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
483 rtvDesc.Texture2DArray.ArraySize = 1;
484
485 ID3D11RenderTargetView *rtv;
486 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
487
488 if (result == E_OUTOFMEMORY)
489 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000490 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000491 }
492 ASSERT(SUCCEEDED(result));
493
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000494 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
495 srvDesc.Format = mTextureFormat;
496 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
497 srvDesc.Texture2DArray.MostDetailedMip = level;
498 srvDesc.Texture2DArray.MipLevels = 1;
499 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
500 srvDesc.Texture2DArray.ArraySize = 1;
501
502 ID3D11ShaderResourceView *srv;
503 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
504
505 if (result == E_OUTOFMEMORY)
506 {
507 rtv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000508 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000509 }
510 ASSERT(SUCCEEDED(result));
511
512 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000513 std::max(mTextureWidth >> level, 1U),
514 std::max(mTextureHeight >> level, 1U));
515 }
516 else if (getBindFlags() & D3D11_BIND_DEPTH_STENCIL)
517 {
518 // TODO
519 UNIMPLEMENTED();
520 }
521 else UNREACHABLE();
522 }
523
524 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000525 }
526 else
527 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000528 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000529 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000530}
531
532ID3D11Texture2D *TextureStorage11_Cube::getBaseTexture() const
533{
534 return mTexture;
535}
536
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000537ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000538{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000539 if (!mSRV)
540 {
541 ID3D11Device *device = mRenderer->getDevice();
542
543 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
544 srvDesc.Format = mTextureFormat;
545 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
546 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
547 srvDesc.TextureCube.MostDetailedMip = 0;
548
549 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
550
551 if (result == E_OUTOFMEMORY)
552 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000553 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000554 }
555 ASSERT(SUCCEEDED(result));
556 }
557
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000558 return mSRV;
559}
560
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000561void TextureStorage11_Cube::generateMipmap(int face, int level)
562{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000563 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
564 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
565
566 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000567}
568
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000569}