blob: 6bffec9a529742f83d58e091d572ca367f9088e6 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com4834ee22013-01-11 04:06:16 +00002//
3// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
9// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
10
11#include "libGLESv2/renderer/TextureStorage11.h"
12
13#include "libGLESv2/renderer/Renderer11.h"
14#include "libGLESv2/renderer/RenderTarget11.h"
15#include "libGLESv2/renderer/SwapChain11.h"
16#include "libGLESv2/renderer/renderer11_utils.h"
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +000017#include "libGLESv2/renderer/formatutils11.h"
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000018
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000019#include "common/utilities.h"
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000020#include "libGLESv2/main.h"
21
22namespace rx
23{
24
25TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
26 : mBindFlags(bindFlags),
daniel@transgaming.comb1154552013-01-11 04:11:02 +000027 mLodOffset(0),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000028 mMipLevels(0),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000029 mTextureFormat(DXGI_FORMAT_UNKNOWN),
30 mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
31 mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
32 mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
shannon.woods@transgaming.com96c21ee2013-02-28 23:13:45 +000033 mSRV(NULL),
shannon.woods@transgaming.com53b0ecb2013-02-28 23:13:21 +000034 mTextureWidth(0),
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +000035 mTextureHeight(0),
36 mTextureDepth(0)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000037{
38 mRenderer = Renderer11::makeRenderer11(renderer);
39}
40
41TextureStorage11::~TextureStorage11()
42{
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +000043}
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000044
45TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
46{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000047 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000048 return static_cast<TextureStorage11*>(storage);
49}
50
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +000051DWORD TextureStorage11::GetTextureBindFlags(GLint internalFormat, GLuint clientVersion, GLenum glusage)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000052{
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +000053 UINT bindFlags = 0;
54
55 if (gl_d3d11::GetSRVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN)
56 {
57 bindFlags |= D3D11_BIND_SHADER_RESOURCE;
58 }
59 if (gl_d3d11::GetDSVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000060 {
61 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
62 }
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +000063 if (gl_d3d11::GetRTVFormat(internalFormat, clientVersion) != DXGI_FORMAT_UNKNOWN &&
64 glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000065 {
66 bindFlags |= D3D11_BIND_RENDER_TARGET;
67 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000068
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +000069 return bindFlags;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000070}
71
72UINT TextureStorage11::getBindFlags() const
73{
74 return mBindFlags;
75}
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000076int TextureStorage11::getLodOffset() const
77{
78 return mLodOffset;
79}
80
81bool TextureStorage11::isRenderTarget() const
82{
83 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
84}
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +000085
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000086bool TextureStorage11::isManaged() const
87{
88 return false;
89}
90
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000091int TextureStorage11::levelCount()
92{
93 int levels = 0;
94 if (getBaseTexture())
95 {
daniel@transgaming.comb1154552013-01-11 04:11:02 +000096 levels = mMipLevels - getLodOffset();
daniel@transgaming.com4834ee22013-01-11 04:06:16 +000097 }
98 return levels;
99}
100
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000101UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget)
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000102{
103 UINT index = 0;
104 if (getBaseTexture())
105 {
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000106 index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000107 }
108 return index;
109}
110
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000111bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000112 int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000113 GLsizei width, GLsizei height, GLsizei depth)
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000114{
115 if (srcTexture)
116 {
117 D3D11_BOX srcBox;
118 srcBox.left = xoffset;
119 srcBox.top = yoffset;
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000120 srcBox.right = xoffset + roundUp((unsigned int)width, d3d11::GetBlockWidth(mTextureFormat));
121 srcBox.bottom = yoffset + roundUp((unsigned int)height, d3d11::GetBlockHeight(mTextureFormat));
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000122 srcBox.front = zoffset;
123 srcBox.back = zoffset + depth;
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000124
125 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000126
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000127 ASSERT(getBaseTexture());
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000128 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, layerTarget),
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000129 xoffset, yoffset, zoffset, srcTexture, sourceSubresource, &srcBox);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000130 return true;
131 }
132
133 return false;
134}
135
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000136void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
137{
138 if (source && dest)
139 {
140 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
141 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
142
143 if (sourceSRV && destRTV)
144 {
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000145 gl::Box sourceArea;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000146 sourceArea.x = 0;
147 sourceArea.y = 0;
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000148 sourceArea.z = 0;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000149 sourceArea.width = source->getWidth();
150 sourceArea.height = source->getHeight();
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000151 sourceArea.depth = source->getDepth();
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000152
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000153 gl::Box destArea;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000154 destArea.x = 0;
155 destArea.y = 0;
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000156 destArea.z = 0;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000157 destArea.width = dest->getWidth();
158 destArea.height = dest->getHeight();
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000159 destArea.depth = dest->getDepth();
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000160
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000161 mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), source->getDepth(),
162 destRTV, destArea, dest->getWidth(), dest->getHeight(), dest->getDepth(),
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000163 GL_RGBA);
164 }
165
166 if (sourceSRV)
167 {
168 sourceSRV->Release();
169 }
170 if (destRTV)
171 {
172 destRTV->Release();
173 }
174 }
175}
176
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000177TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
178 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
179{
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000180 mTexture = swapchain->getOffscreenTexture();
181 mSRV = swapchain->getRenderTargetShaderResource();
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000182
183 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
184 {
185 mRenderTarget[i] = NULL;
186 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000187
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000188 D3D11_TEXTURE2D_DESC texDesc;
189 mTexture->GetDesc(&texDesc);
190 mMipLevels = texDesc.MipLevels;
191 mTextureFormat = texDesc.Format;
192 mTextureWidth = texDesc.Width;
193 mTextureHeight = texDesc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000194 mTextureDepth = 1;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000195
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000196 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
197 mSRV->GetDesc(&srvDesc);
198 mShaderResourceFormat = srvDesc.Format;
199
200 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
201 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
202 offscreenRTV->GetDesc(&rtvDesc);
203 mRenderTargetFormat = rtvDesc.Format;
204 offscreenRTV->Release();
205
206 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000207}
208
209TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +0000210 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000211{
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000212 mTexture = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000213 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
214 {
215 mRenderTarget[i] = NULL;
216 }
217
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000218 GLuint clientVersion = mRenderer->getCurrentClientVersion();
219
220 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion);
221 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion);
222 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion);
223 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000224
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000225 // if the width or height is not positive this should be treated as an incomplete texture
226 // we handle that here by skipping the d3d texture creation
227 if (width > 0 && height > 0)
228 {
229 // adjust size if needed for compressed textures
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000230 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mLodOffset);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000231
232 ID3D11Device *device = mRenderer->getDevice();
233
234 D3D11_TEXTURE2D_DESC desc;
235 desc.Width = width; // Compressed texture size constraints?
236 desc.Height = height;
shannon.woods@transgaming.comc22e3602013-02-28 23:20:39 +0000237 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000238 desc.ArraySize = 1;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000239 desc.Format = mTextureFormat;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000240 desc.SampleDesc.Count = 1;
241 desc.SampleDesc.Quality = 0;
242 desc.Usage = D3D11_USAGE_DEFAULT;
243 desc.BindFlags = getBindFlags();
244 desc.CPUAccessFlags = 0;
245 desc.MiscFlags = 0;
246
247 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
248
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000249 // this can happen from windows TDR
250 if (d3d11::isDeviceLostError(result))
251 {
252 mRenderer->notifyDeviceLost();
253 gl::error(GL_OUT_OF_MEMORY);
254 }
255 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000256 {
257 ASSERT(result == E_OUTOFMEMORY);
258 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000259 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000260 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000261 else
262 {
263 mTexture->GetDesc(&desc);
264 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000265 mTextureWidth = desc.Width;
266 mTextureHeight = desc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000267 mTextureDepth = 1;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000268 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000269 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000270}
271
272TextureStorage11_2D::~TextureStorage11_2D()
273{
274 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000275 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000276 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000277 mTexture = NULL;
278 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000279
280 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000281 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000282 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000283 mSRV = NULL;
284 }
285
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000286 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000287 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000288 delete mRenderTarget[i];
289 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000290 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000291}
292
293TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
294{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000295 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000296 return static_cast<TextureStorage11_2D*>(storage);
297}
298
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000299ID3D11Resource *TextureStorage11_2D::getBaseTexture() const
300{
301 return mTexture;
302}
303
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000304RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000305{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000306 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000307 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000308 if (!mRenderTarget[level])
309 {
310 ID3D11Device *device = mRenderer->getDevice();
311 HRESULT result;
312
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000313 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000314 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000315 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
316 srvDesc.Texture2D.MostDetailedMip = level;
317 srvDesc.Texture2D.MipLevels = 1;
318
319 ID3D11ShaderResourceView *srv;
320 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
321
322 if (result == E_OUTOFMEMORY)
323 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000324 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000325 }
326 ASSERT(SUCCEEDED(result));
327
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000328 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
329 {
330 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
331 rtvDesc.Format = mRenderTargetFormat;
332 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
333 rtvDesc.Texture2D.MipSlice = level;
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000334
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000335 ID3D11RenderTargetView *rtv;
336 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
337
338 if (result == E_OUTOFMEMORY)
339 {
340 srv->Release();
341 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
342 }
343 ASSERT(SUCCEEDED(result));
344
345 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
346 // also needs to keep a reference to the texture.
347 mTexture->AddRef();
348
349 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
350 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000351 std::max(mTextureHeight >> level, 1U),
352 1);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000353 }
354 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
355 {
356 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
357 dsvDesc.Format = mDepthStencilFormat;
358 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
359 dsvDesc.Texture2D.MipSlice = level;
360 dsvDesc.Flags = 0;
361
362 ID3D11DepthStencilView *dsv;
363 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
364
365 if (result == E_OUTOFMEMORY)
366 {
367 srv->Release();
368 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
369 }
370 ASSERT(SUCCEEDED(result));
371
372 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
373 // also needs to keep a reference to the texture.
374 mTexture->AddRef();
375
376 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
377 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000378 std::max(mTextureHeight >> level, 1U),
379 1);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000380 }
381 else
382 {
383 UNREACHABLE();
384 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000385 }
386
387 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000388 }
389 else
390 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000391 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000392 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000393}
394
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000395ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000396{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000397 if (!mSRV)
398 {
399 ID3D11Device *device = mRenderer->getDevice();
400
401 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000402 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000403 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
404 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
405 srvDesc.Texture2D.MostDetailedMip = 0;
406
407 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
408
409 if (result == E_OUTOFMEMORY)
410 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000411 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000412 }
413 ASSERT(SUCCEEDED(result));
414 }
415
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000416 return mSRV;
417}
418
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000419void TextureStorage11_2D::generateMipmap(int level)
420{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000421 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
422 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
423
424 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000425}
426
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000427TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +0000428 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000429{
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000430 mTexture = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000431 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000432 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000433 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
434 {
435 mRenderTarget[i][j] = NULL;
436 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000437 }
438
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000439 GLuint clientVersion = mRenderer->getCurrentClientVersion();
440
441 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion);
442 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion);
443 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion);
444 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000445
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000446 // if the size is not positive this should be treated as an incomplete texture
447 // we handle that here by skipping the d3d texture creation
448 if (size > 0)
449 {
450 // adjust size if needed for compressed textures
451 int height = size;
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000452 d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mLodOffset);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000453
454 ID3D11Device *device = mRenderer->getDevice();
455
456 D3D11_TEXTURE2D_DESC desc;
457 desc.Width = size;
458 desc.Height = size;
shannon.woods@transgaming.comc22e3602013-02-28 23:20:39 +0000459 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000460 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000461 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000462 desc.SampleDesc.Count = 1;
463 desc.SampleDesc.Quality = 0;
464 desc.Usage = D3D11_USAGE_DEFAULT;
465 desc.BindFlags = getBindFlags();
466 desc.CPUAccessFlags = 0;
467 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
468
469 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
470
471 if (FAILED(result))
472 {
473 ASSERT(result == E_OUTOFMEMORY);
474 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000475 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000476 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000477 else
478 {
479 mTexture->GetDesc(&desc);
480 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000481 mTextureWidth = desc.Width;
482 mTextureHeight = desc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000483 mTextureDepth = 1;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000484 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000485 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000486}
487
488TextureStorage11_Cube::~TextureStorage11_Cube()
489{
490 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000491 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000492 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000493 mTexture = NULL;
494 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000495
496 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000497 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000498 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000499 mSRV = NULL;
500 }
501
502 for (unsigned int i = 0; i < 6; i++)
503 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000504 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000505 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000506 delete mRenderTarget[i][j];
507 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000508 }
509 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000510}
511
512TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
513{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000514 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000515 return static_cast<TextureStorage11_Cube*>(storage);
516}
517
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000518ID3D11Resource *TextureStorage11_Cube::getBaseTexture() const
519{
520 return mTexture;
521}
522
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000523RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000524{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000525 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
526 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000527 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000528 if (!mRenderTarget[faceIdx][level])
529 {
530 ID3D11Device *device = mRenderer->getDevice();
531 HRESULT result;
532
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000533 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
534 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.comd89f1942013-02-28 23:18:27 +0000535 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000536 srvDesc.Texture2DArray.MostDetailedMip = level;
537 srvDesc.Texture2DArray.MipLevels = 1;
538 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
539 srvDesc.Texture2DArray.ArraySize = 1;
540
541 ID3D11ShaderResourceView *srv;
542 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
543
544 if (result == E_OUTOFMEMORY)
545 {
546 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
547 }
548 ASSERT(SUCCEEDED(result));
549
550 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000551 {
552 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000553 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000554 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
555 rtvDesc.Texture2DArray.MipSlice = level;
556 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
557 rtvDesc.Texture2DArray.ArraySize = 1;
558
559 ID3D11RenderTargetView *rtv;
560 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
561
562 if (result == E_OUTOFMEMORY)
563 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000564 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000565 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000566 }
567 ASSERT(SUCCEEDED(result));
568
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000569 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
570 // also needs to keep a reference to the texture.
571 mTexture->AddRef();
572
573 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000574 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000575 std::max(mTextureHeight >> level, 1U),
576 1);
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000577 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000578 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000579 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000580 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
581 dsvDesc.Format = mRenderTargetFormat;
582 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
583 dsvDesc.Texture2DArray.MipSlice = level;
584 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
585 dsvDesc.Texture2DArray.ArraySize = 1;
586
587 ID3D11DepthStencilView *dsv;
588 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
589
590 if (result == E_OUTOFMEMORY)
591 {
592 srv->Release();
593 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
594 }
595 ASSERT(SUCCEEDED(result));
596
597 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
598 // also needs to keep a reference to the texture.
599 mTexture->AddRef();
600
601 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
602 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000603 std::max(mTextureHeight >> level, 1U),
604 1);
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000605 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000606 else
607 {
608 UNREACHABLE();
609 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000610 }
611
612 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000613 }
614 else
615 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000616 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000617 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000618}
619
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000620ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000621{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000622 if (!mSRV)
623 {
624 ID3D11Device *device = mRenderer->getDevice();
625
626 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000627 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000628 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
629 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
630 srvDesc.TextureCube.MostDetailedMip = 0;
631
632 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
633
634 if (result == E_OUTOFMEMORY)
635 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000636 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000637 }
638 ASSERT(SUCCEEDED(result));
639 }
640
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000641 return mSRV;
642}
643
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000644void TextureStorage11_Cube::generateMipmap(int face, int level)
645{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000646 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
647 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
648
649 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000650}
651
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000652TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
653 GLsizei width, GLsizei height, GLsizei depth)
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +0000654 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000655{
656 mTexture = NULL;
657
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000658 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
659 {
660 mLevelRenderTargets[i] = NULL;
661 }
662
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000663 GLuint clientVersion = mRenderer->getCurrentClientVersion();
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000664
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000665 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion);
666 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion);
667 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion);
668 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion);
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000669
670 // If the width, height or depth are not positive this should be treated as an incomplete texture
671 // we handle that here by skipping the d3d texture creation
672 if (width > 0 && height > 0 && depth > 0)
673 {
674 // adjust size if needed for compressed textures
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000675 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mLodOffset);
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000676
677 ID3D11Device *device = mRenderer->getDevice();
678
679 D3D11_TEXTURE3D_DESC desc;
680 desc.Width = width;
681 desc.Height = height;
682 desc.Depth = depth;
683 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
684 desc.Format = mTextureFormat;
685 desc.Usage = D3D11_USAGE_DEFAULT;
686 desc.BindFlags = getBindFlags();
687 desc.CPUAccessFlags = 0;
688 desc.MiscFlags = 0;
689
690 HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
691
692 // this can happen from windows TDR
693 if (d3d11::isDeviceLostError(result))
694 {
695 mRenderer->notifyDeviceLost();
696 gl::error(GL_OUT_OF_MEMORY);
697 }
698 else if (FAILED(result))
699 {
700 ASSERT(result == E_OUTOFMEMORY);
701 ERR("Creating image failed.");
702 gl::error(GL_OUT_OF_MEMORY);
703 }
704 else
705 {
706 mTexture->GetDesc(&desc);
707 mMipLevels = desc.MipLevels;
708 mTextureWidth = desc.Width;
709 mTextureHeight = desc.Height;
710 mTextureDepth = desc.Depth;
711 }
712 }
713}
714
715TextureStorage11_3D::~TextureStorage11_3D()
716{
717 if (mTexture)
718 {
719 mTexture->Release();
720 mTexture = NULL;
721 }
722
723 if (mSRV)
724 {
725 mSRV->Release();
726 mSRV = NULL;
727 }
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000728
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000729 for (RenderTargetMap::const_iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++)
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000730 {
731 RenderTarget11* renderTarget = i->second;
732 delete renderTarget;
733 }
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000734 mLevelLayerRenderTargets.clear();
735
736 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
737 {
738 delete mLevelRenderTargets[i];
739 mLevelRenderTargets[i] = NULL;
740 }
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000741}
742
743TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage)
744{
745 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage));
746 return static_cast<TextureStorage11_3D*>(storage);
747}
748
749ID3D11Resource *TextureStorage11_3D::getBaseTexture() const
750{
751 return mTexture;
752}
753
754ID3D11ShaderResourceView *TextureStorage11_3D::getSRV()
755{
756 if (!mSRV)
757 {
758 ID3D11Device *device = mRenderer->getDevice();
759
760 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
761 srvDesc.Format = mShaderResourceFormat;
762 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
763 srvDesc.Texture3D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
764 srvDesc.Texture3D.MostDetailedMip = 0;
765
766 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
767
768 if (result == E_OUTOFMEMORY)
769 {
770 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
771 }
772 ASSERT(SUCCEEDED(result));
773 }
774
775 return mSRV;
776}
777
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000778RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel)
779{
780 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
781 {
782 if (!mLevelRenderTargets[mipLevel])
783 {
784 ID3D11Device *device = mRenderer->getDevice();
785 HRESULT result;
786
787 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
788 srvDesc.Format = mShaderResourceFormat;
789 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
790 srvDesc.Texture3D.MostDetailedMip = mipLevel;
791 srvDesc.Texture3D.MipLevels = 1;
792
793 ID3D11ShaderResourceView *srv;
794 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
795
796 if (result == E_OUTOFMEMORY)
797 {
798 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
799 }
800 ASSERT(SUCCEEDED(result));
801
802 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
803 {
804 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
805 rtvDesc.Format = mRenderTargetFormat;
806 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
807 rtvDesc.Texture3D.MipSlice = mipLevel;
808 rtvDesc.Texture3D.FirstWSlice = 0;
809 rtvDesc.Texture3D.WSize = -1;
810
811 ID3D11RenderTargetView *rtv;
812 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
813
814 if (result == E_OUTOFMEMORY)
815 {
816 srv->Release();
817 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
818 }
819 ASSERT(SUCCEEDED(result));
820
821 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
822 // also needs to keep a reference to the texture.
823 mTexture->AddRef();
824
825 mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
826 std::max(mTextureWidth >> mipLevel, 1U),
827 std::max(mTextureHeight >> mipLevel, 1U),
828 std::max(mTextureDepth >> mipLevel, 1U));
829 }
830 else
831 {
832 UNREACHABLE();
833 }
834 }
835
836 return mLevelRenderTargets[mipLevel];
837 }
838 else
839 {
840 return NULL;
841 }
842}
843
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000844RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer)
845{
846 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
847 {
848 LevelLayerKey key(mipLevel, layer);
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000849 if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000850 {
851 ID3D11Device *device = mRenderer->getDevice();
852 HRESULT result;
853
854 // TODO, what kind of SRV is expected here?
855 ID3D11ShaderResourceView *srv = NULL;
856
857 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
858 {
859 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
860 rtvDesc.Format = mRenderTargetFormat;
861 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
862 rtvDesc.Texture3D.MipSlice = mipLevel;
863 rtvDesc.Texture3D.FirstWSlice = layer;
864 rtvDesc.Texture3D.WSize = 1;
865
866 ID3D11RenderTargetView *rtv;
867 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
868
869 if (result == E_OUTOFMEMORY)
870 {
871 srv->Release();
872 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
873 }
874 ASSERT(SUCCEEDED(result));
875
876 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
877 // also needs to keep a reference to the texture.
878 mTexture->AddRef();
879
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000880 mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
881 std::max(mTextureWidth >> mipLevel, 1U),
882 std::max(mTextureHeight >> mipLevel, 1U),
883 1);
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000884 }
885 else
886 {
887 UNREACHABLE();
888 }
889 }
890
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000891 return mLevelLayerRenderTargets[key];
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000892 }
893 else
894 {
895 return NULL;
896 }
897}
898
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000899void TextureStorage11_3D::generateMipmap(int level)
900{
shannonwoods@chromium.org37b8a912013-05-30 00:04:21 +0000901 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
902 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
903
904 generateMipmapLayer(source, dest);
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000905}
906
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000907TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
908 GLsizei width, GLsizei height, GLsizei depth)
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +0000909 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000910{
911 mTexture = NULL;
912
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000913 GLuint clientVersion = mRenderer->getCurrentClientVersion();
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000914
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000915 mTextureFormat = gl_d3d11::GetTexFormat(internalformat, clientVersion);
916 mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat, clientVersion);
917 mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat, clientVersion);
918 mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat, clientVersion);
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000919
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000920 // if the width, height or depth is not positive this should be treated as an incomplete texture
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000921 // we handle that here by skipping the d3d texture creation
922 if (width > 0 && height > 0 && depth > 0)
923 {
924 // adjust size if needed for compressed textures
shannonwoods@chromium.orgd38d66e2013-05-30 00:09:16 +0000925 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mLodOffset);
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000926
927 ID3D11Device *device = mRenderer->getDevice();
928
929 D3D11_TEXTURE2D_DESC desc;
930 desc.Width = width;
931 desc.Height = height;
932 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
933 desc.ArraySize = depth;
934 desc.Format = mTextureFormat;
935 desc.SampleDesc.Count = 1;
936 desc.SampleDesc.Quality = 0;
937 desc.Usage = D3D11_USAGE_DEFAULT;
938 desc.BindFlags = getBindFlags();
939 desc.CPUAccessFlags = 0;
940 desc.MiscFlags = 0;
941
942 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
943
944 // this can happen from windows TDR
945 if (d3d11::isDeviceLostError(result))
946 {
947 mRenderer->notifyDeviceLost();
948 gl::error(GL_OUT_OF_MEMORY);
949 }
950 else if (FAILED(result))
951 {
952 ASSERT(result == E_OUTOFMEMORY);
953 ERR("Creating image failed.");
954 gl::error(GL_OUT_OF_MEMORY);
955 }
956 else
957 {
958 mTexture->GetDesc(&desc);
959 mMipLevels = desc.MipLevels;
960 mTextureWidth = desc.Width;
961 mTextureHeight = desc.Height;
962 mTextureDepth = desc.ArraySize;
963 }
964 }
965}
966
967TextureStorage11_2DArray::~TextureStorage11_2DArray()
968{
969 if (mTexture)
970 {
971 mTexture->Release();
972 mTexture = NULL;
973 }
974
975 if (mSRV)
976 {
977 mSRV->Release();
978 mSRV = NULL;
979 }
980
981 for (RenderTargetMap::const_iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
982 {
983 RenderTarget11* renderTarget = i->second;
984 delete renderTarget;
985 }
986 mRenderTargets.clear();
987}
988
989TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage)
990{
991 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage));
992 return static_cast<TextureStorage11_2DArray*>(storage);
993}
994
995ID3D11Resource *TextureStorage11_2DArray::getBaseTexture() const
996{
997 return mTexture;
998}
999
1000ID3D11ShaderResourceView *TextureStorage11_2DArray::getSRV()
1001{
1002 if (!mSRV)
1003 {
1004 ID3D11Device *device = mRenderer->getDevice();
1005
1006 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1007 srvDesc.Format = mShaderResourceFormat;
1008 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1009 srvDesc.Texture2DArray.MostDetailedMip = 0;
1010 srvDesc.Texture2DArray.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
1011 srvDesc.Texture2DArray.FirstArraySlice = 0;
1012 srvDesc.Texture2DArray.ArraySize = mTextureDepth;
1013
1014 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
1015
1016 if (result == E_OUTOFMEMORY)
1017 {
1018 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
1019 }
1020 ASSERT(SUCCEEDED(result));
1021 }
1022
1023 return mSRV;
1024}
1025
1026RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer)
1027{
1028 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
1029 {
1030 LevelLayerKey key(mipLevel, layer);
1031 if (mRenderTargets.find(key) == mRenderTargets.end())
1032 {
1033 ID3D11Device *device = mRenderer->getDevice();
1034 HRESULT result;
1035
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +00001036 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1037 srvDesc.Format = mShaderResourceFormat;
1038 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1039 srvDesc.Texture2DArray.MostDetailedMip = mipLevel;
1040 srvDesc.Texture2DArray.MipLevels = 1;
1041 srvDesc.Texture2DArray.FirstArraySlice = layer;
1042 srvDesc.Texture2DArray.ArraySize = 1;
1043
1044 ID3D11ShaderResourceView *srv;
1045 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
1046
1047 if (result == E_OUTOFMEMORY)
1048 {
1049 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1050 }
1051 ASSERT(SUCCEEDED(result));
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001052
1053 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
1054 {
1055 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1056 rtvDesc.Format = mRenderTargetFormat;
1057 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1058 rtvDesc.Texture2DArray.MipSlice = mipLevel;
1059 rtvDesc.Texture2DArray.FirstArraySlice = layer;
1060 rtvDesc.Texture2DArray.ArraySize = 1;
1061
1062 ID3D11RenderTargetView *rtv;
1063 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
1064
1065 if (result == E_OUTOFMEMORY)
1066 {
1067 SafeRelease(srv);
1068 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1069 }
1070 ASSERT(SUCCEEDED(result));
1071
1072 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
1073 // also needs to keep a reference to the texture.
1074 mTexture->AddRef();
1075
1076 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
1077 std::max(mTextureWidth >> mipLevel, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +00001078 std::max(mTextureHeight >> mipLevel, 1U),
1079 1);
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001080 }
1081 else
1082 {
1083 UNREACHABLE();
1084 }
1085 }
1086
1087 return mRenderTargets[key];
1088 }
1089 else
1090 {
1091 return NULL;
1092 }
1093}
1094
1095void TextureStorage11_2DArray::generateMipmap(int level)
1096{
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +00001097 for (unsigned int layer = 0; layer < mTextureDepth; layer++)
1098 {
1099 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer));
1100 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer));
1101
1102 generateMipmapLayer(source, dest);
1103 }
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001104}
1105
daniel@transgaming.comb2151e52013-01-11 04:06:24 +00001106}