blob: 1b75a61564e2f81c0a0e6c4e307dfdf9be4d11b1 [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
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000019#include "libGLESv2/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 {
shannon.woods@transgaming.com7ae9e7f2013-02-28 23:13:27 +0000117 // Round up the width and height to the nearest multiple of dimension alignment
118 unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
shannonwoods@chromium.org06d4e842013-05-30 00:04:42 +0000119 width = roundUp(width, (GLsizei)dimensionAlignment);
120 height = roundUp(height, (GLsizei)dimensionAlignment);
shannon.woods@transgaming.com7ae9e7f2013-02-28 23:13:27 +0000121
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000122 D3D11_BOX srcBox;
123 srcBox.left = xoffset;
124 srcBox.top = yoffset;
125 srcBox.right = xoffset + width;
126 srcBox.bottom = yoffset + height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000127 srcBox.front = zoffset;
128 srcBox.back = zoffset + depth;
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000129
130 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000131
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000132 ASSERT(getBaseTexture());
shannon.woods%transgaming.com@gtempaccount.com6c86bd52013-04-13 03:45:45 +0000133 context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, layerTarget),
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000134 xoffset, yoffset, zoffset, srcTexture, sourceSubresource, &srcBox);
daniel@transgaming.com9a2f54d2013-01-11 04:06:36 +0000135 return true;
136 }
137
138 return false;
139}
140
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000141void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
142{
143 if (source && dest)
144 {
145 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
146 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
147
148 if (sourceSRV && destRTV)
149 {
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000150 gl::Box sourceArea;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000151 sourceArea.x = 0;
152 sourceArea.y = 0;
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000153 sourceArea.z = 0;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000154 sourceArea.width = source->getWidth();
155 sourceArea.height = source->getHeight();
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000156 sourceArea.depth = source->getDepth();
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000157
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000158 gl::Box destArea;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000159 destArea.x = 0;
160 destArea.y = 0;
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000161 destArea.z = 0;
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000162 destArea.width = dest->getWidth();
163 destArea.height = dest->getHeight();
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000164 destArea.depth = dest->getDepth();
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000165
shannonwoods@chromium.org7b61d5c2013-05-30 00:04:12 +0000166 mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), source->getDepth(),
167 destRTV, destArea, dest->getWidth(), dest->getHeight(), dest->getDepth(),
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000168 GL_RGBA);
169 }
170
171 if (sourceSRV)
172 {
173 sourceSRV->Release();
174 }
175 if (destRTV)
176 {
177 destRTV->Release();
178 }
179 }
180}
181
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000182TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
183 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
184{
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000185 mTexture = swapchain->getOffscreenTexture();
186 mSRV = swapchain->getRenderTargetShaderResource();
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000187
188 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
189 {
190 mRenderTarget[i] = NULL;
191 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000192
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000193 D3D11_TEXTURE2D_DESC texDesc;
194 mTexture->GetDesc(&texDesc);
195 mMipLevels = texDesc.MipLevels;
196 mTextureFormat = texDesc.Format;
197 mTextureWidth = texDesc.Width;
198 mTextureHeight = texDesc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000199 mTextureDepth = 1;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000200
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000201 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
202 mSRV->GetDesc(&srvDesc);
203 mShaderResourceFormat = srvDesc.Format;
204
205 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
206 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
207 offscreenRTV->GetDesc(&rtvDesc);
208 mRenderTargetFormat = rtvDesc.Format;
209 offscreenRTV->Release();
210
211 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000212}
213
214TextureStorage11_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 +0000215 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000216{
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000217 mTexture = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000218 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
219 {
220 mRenderTarget[i] = NULL;
221 }
222
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000223 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
224 if (d3d11::IsDepthStencilFormat(convertedFormat))
225 {
226 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
227 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
228 mDepthStencilFormat = convertedFormat;
229 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
230 }
231 else
232 {
233 mTextureFormat = convertedFormat;
234 mShaderResourceFormat = convertedFormat;
235 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
236 mRenderTargetFormat = convertedFormat;
237 }
238
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000239 // if the width or height is not positive this should be treated as an incomplete texture
240 // we handle that here by skipping the d3d texture creation
241 if (width > 0 && height > 0)
242 {
243 // adjust size if needed for compressed textures
244 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
245
246 ID3D11Device *device = mRenderer->getDevice();
247
248 D3D11_TEXTURE2D_DESC desc;
249 desc.Width = width; // Compressed texture size constraints?
250 desc.Height = height;
shannon.woods@transgaming.comc22e3602013-02-28 23:20:39 +0000251 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000252 desc.ArraySize = 1;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000253 desc.Format = mTextureFormat;
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000254 desc.SampleDesc.Count = 1;
255 desc.SampleDesc.Quality = 0;
256 desc.Usage = D3D11_USAGE_DEFAULT;
257 desc.BindFlags = getBindFlags();
258 desc.CPUAccessFlags = 0;
259 desc.MiscFlags = 0;
260
261 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
262
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000263 // this can happen from windows TDR
264 if (d3d11::isDeviceLostError(result))
265 {
266 mRenderer->notifyDeviceLost();
267 gl::error(GL_OUT_OF_MEMORY);
268 }
269 else if (FAILED(result))
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000270 {
271 ASSERT(result == E_OUTOFMEMORY);
272 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000273 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000274 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000275 else
276 {
277 mTexture->GetDesc(&desc);
278 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000279 mTextureWidth = desc.Width;
280 mTextureHeight = desc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000281 mTextureDepth = 1;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000282 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000283 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000284}
285
286TextureStorage11_2D::~TextureStorage11_2D()
287{
288 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000289 {
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000290 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000291 mTexture = NULL;
292 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000293
294 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000295 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000296 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000297 mSRV = NULL;
298 }
299
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000300 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000301 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000302 delete mRenderTarget[i];
303 mRenderTarget[i] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000304 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000305}
306
307TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
308{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000309 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000310 return static_cast<TextureStorage11_2D*>(storage);
311}
312
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000313ID3D11Resource *TextureStorage11_2D::getBaseTexture() const
314{
315 return mTexture;
316}
317
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000318RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000319{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000320 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000321 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000322 if (!mRenderTarget[level])
323 {
324 ID3D11Device *device = mRenderer->getDevice();
325 HRESULT result;
326
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000327 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000328 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000329 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
330 srvDesc.Texture2D.MostDetailedMip = level;
331 srvDesc.Texture2D.MipLevels = 1;
332
333 ID3D11ShaderResourceView *srv;
334 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
335
336 if (result == E_OUTOFMEMORY)
337 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000338 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000339 }
340 ASSERT(SUCCEEDED(result));
341
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000342 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
343 {
344 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
345 rtvDesc.Format = mRenderTargetFormat;
346 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
347 rtvDesc.Texture2D.MipSlice = level;
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000348
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000349 ID3D11RenderTargetView *rtv;
350 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
351
352 if (result == E_OUTOFMEMORY)
353 {
354 srv->Release();
355 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
356 }
357 ASSERT(SUCCEEDED(result));
358
359 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
360 // also needs to keep a reference to the texture.
361 mTexture->AddRef();
362
363 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
364 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000365 std::max(mTextureHeight >> level, 1U),
366 1);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000367 }
368 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
369 {
370 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
371 dsvDesc.Format = mDepthStencilFormat;
372 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
373 dsvDesc.Texture2D.MipSlice = level;
374 dsvDesc.Flags = 0;
375
376 ID3D11DepthStencilView *dsv;
377 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
378
379 if (result == E_OUTOFMEMORY)
380 {
381 srv->Release();
382 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
383 }
384 ASSERT(SUCCEEDED(result));
385
386 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
387 // also needs to keep a reference to the texture.
388 mTexture->AddRef();
389
390 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
391 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000392 std::max(mTextureHeight >> level, 1U),
393 1);
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000394 }
395 else
396 {
397 UNREACHABLE();
398 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000399 }
400
401 return mRenderTarget[level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000402 }
403 else
404 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000405 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000406 }
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000407}
408
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000409ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000410{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000411 if (!mSRV)
412 {
413 ID3D11Device *device = mRenderer->getDevice();
414
415 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000416 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000417 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
418 srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
419 srvDesc.Texture2D.MostDetailedMip = 0;
420
421 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
422
423 if (result == E_OUTOFMEMORY)
424 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000425 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000426 }
427 ASSERT(SUCCEEDED(result));
428 }
429
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000430 return mSRV;
431}
432
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000433void TextureStorage11_2D::generateMipmap(int level)
434{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000435 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
436 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
437
438 generateMipmapLayer(source, dest);
daniel@transgaming.com4834ee22013-01-11 04:06:16 +0000439}
440
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000441TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +0000442 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000443{
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000444 mTexture = NULL;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000445 for (unsigned int i = 0; i < 6; i++)
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000446 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000447 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
448 {
449 mRenderTarget[i][j] = NULL;
450 }
daniel@transgaming.com5cdd0582013-01-11 04:07:35 +0000451 }
452
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000453 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
454 if (d3d11::IsDepthStencilFormat(convertedFormat))
455 {
456 mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
457 mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
458 mDepthStencilFormat = convertedFormat;
459 mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
460 }
461 else
462 {
463 mTextureFormat = convertedFormat;
464 mShaderResourceFormat = convertedFormat;
465 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
466 mRenderTargetFormat = convertedFormat;
467 }
468
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000469 // if the size is not positive this should be treated as an incomplete texture
470 // we handle that here by skipping the d3d texture creation
471 if (size > 0)
472 {
473 // adjust size if needed for compressed textures
474 int height = size;
475 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
476
477 ID3D11Device *device = mRenderer->getDevice();
478
479 D3D11_TEXTURE2D_DESC desc;
480 desc.Width = size;
481 desc.Height = size;
shannon.woods@transgaming.comc22e3602013-02-28 23:20:39 +0000482 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000483 desc.ArraySize = 6;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000484 desc.Format = mTextureFormat;
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000485 desc.SampleDesc.Count = 1;
486 desc.SampleDesc.Quality = 0;
487 desc.Usage = D3D11_USAGE_DEFAULT;
488 desc.BindFlags = getBindFlags();
489 desc.CPUAccessFlags = 0;
490 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
491
492 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
493
494 if (FAILED(result))
495 {
496 ASSERT(result == E_OUTOFMEMORY);
497 ERR("Creating image failed.");
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000498 gl::error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000499 }
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000500 else
501 {
502 mTexture->GetDesc(&desc);
503 mMipLevels = desc.MipLevels;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000504 mTextureWidth = desc.Width;
505 mTextureHeight = desc.Height;
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000506 mTextureDepth = 1;
daniel@transgaming.comb1154552013-01-11 04:11:02 +0000507 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000508 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000509}
510
511TextureStorage11_Cube::~TextureStorage11_Cube()
512{
513 if (mTexture)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000514 {
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000515 mTexture->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000516 mTexture = NULL;
517 }
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000518
519 if (mSRV)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000520 {
daniel@transgaming.com1e1b5e92013-01-11 04:11:27 +0000521 mSRV->Release();
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000522 mSRV = NULL;
523 }
524
525 for (unsigned int i = 0; i < 6; i++)
526 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000527 for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000528 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000529 delete mRenderTarget[i][j];
530 mRenderTarget[i][j] = NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000531 }
532 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000533}
534
535TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
536{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000537 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000538 return static_cast<TextureStorage11_Cube*>(storage);
539}
540
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000541ID3D11Resource *TextureStorage11_Cube::getBaseTexture() const
542{
543 return mTexture;
544}
545
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000546RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000547{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000548 unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
549 if (level >= 0 && level < static_cast<int>(mMipLevels))
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000550 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000551 if (!mRenderTarget[faceIdx][level])
552 {
553 ID3D11Device *device = mRenderer->getDevice();
554 HRESULT result;
555
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000556 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
557 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.comd89f1942013-02-28 23:18:27 +0000558 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000559 srvDesc.Texture2DArray.MostDetailedMip = level;
560 srvDesc.Texture2DArray.MipLevels = 1;
561 srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
562 srvDesc.Texture2DArray.ArraySize = 1;
563
564 ID3D11ShaderResourceView *srv;
565 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
566
567 if (result == E_OUTOFMEMORY)
568 {
569 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
570 }
571 ASSERT(SUCCEEDED(result));
572
573 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000574 {
575 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000576 rtvDesc.Format = mRenderTargetFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000577 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
578 rtvDesc.Texture2DArray.MipSlice = level;
579 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
580 rtvDesc.Texture2DArray.ArraySize = 1;
581
582 ID3D11RenderTargetView *rtv;
583 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
584
585 if (result == E_OUTOFMEMORY)
586 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000587 srv->Release();
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000588 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
shannon.woods@transgaming.com183408d2013-01-25 21:50:07 +0000589 }
590 ASSERT(SUCCEEDED(result));
591
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000592 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
593 // also needs to keep a reference to the texture.
594 mTexture->AddRef();
595
596 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000597 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000598 std::max(mTextureHeight >> level, 1U),
599 1);
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000600 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000601 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000602 {
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000603 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
604 dsvDesc.Format = mRenderTargetFormat;
605 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
606 dsvDesc.Texture2DArray.MipSlice = level;
607 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
608 dsvDesc.Texture2DArray.ArraySize = 1;
609
610 ID3D11DepthStencilView *dsv;
611 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
612
613 if (result == E_OUTOFMEMORY)
614 {
615 srv->Release();
616 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
617 }
618 ASSERT(SUCCEEDED(result));
619
620 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
621 // also needs to keep a reference to the texture.
622 mTexture->AddRef();
623
624 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
625 std::max(mTextureWidth >> level, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +0000626 std::max(mTextureHeight >> level, 1U),
627 1);
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000628 }
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000629 else
630 {
631 UNREACHABLE();
632 }
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000633 }
634
635 return mRenderTarget[faceIdx][level];
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000636 }
637 else
638 {
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000639 return NULL;
shannon.woods@transgaming.com4b472352013-01-25 21:14:56 +0000640 }
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000641}
642
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000643ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000644{
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000645 if (!mSRV)
646 {
647 ID3D11Device *device = mRenderer->getDevice();
648
649 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
shannon.woods@transgaming.com5b2d8552013-02-28 23:12:32 +0000650 srvDesc.Format = mShaderResourceFormat;
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000651 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
652 srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
653 srvDesc.TextureCube.MostDetailedMip = 0;
654
655 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
656
657 if (result == E_OUTOFMEMORY)
658 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000659 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
shannon.woods@transgaming.com858d32f2013-01-25 21:49:59 +0000660 }
661 ASSERT(SUCCEEDED(result));
662 }
663
daniel@transgaming.comb50d5302013-01-11 04:07:29 +0000664 return mSRV;
665}
666
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000667void TextureStorage11_Cube::generateMipmap(int face, int level)
668{
shannon.woods@transgaming.com85bdfce2013-01-25 21:51:07 +0000669 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
670 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
671
672 generateMipmapLayer(source, dest);
daniel@transgaming.comb2151e52013-01-11 04:06:24 +0000673}
674
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000675TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
676 GLsizei width, GLsizei height, GLsizei depth)
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +0000677 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000678{
679 mTexture = NULL;
680
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000681 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
682 {
683 mLevelRenderTargets[i] = NULL;
684 }
685
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000686 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
687 ASSERT(!d3d11::IsDepthStencilFormat(convertedFormat));
688
689 mTextureFormat = convertedFormat;
690 mShaderResourceFormat = convertedFormat;
691 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
692 mRenderTargetFormat = convertedFormat;
693
694 // If the width, height or depth are not positive this should be treated as an incomplete texture
695 // we handle that here by skipping the d3d texture creation
696 if (width > 0 && height > 0 && depth > 0)
697 {
698 // adjust size if needed for compressed textures
699 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
700
701 ID3D11Device *device = mRenderer->getDevice();
702
703 D3D11_TEXTURE3D_DESC desc;
704 desc.Width = width;
705 desc.Height = height;
706 desc.Depth = depth;
707 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
708 desc.Format = mTextureFormat;
709 desc.Usage = D3D11_USAGE_DEFAULT;
710 desc.BindFlags = getBindFlags();
711 desc.CPUAccessFlags = 0;
712 desc.MiscFlags = 0;
713
714 HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
715
716 // this can happen from windows TDR
717 if (d3d11::isDeviceLostError(result))
718 {
719 mRenderer->notifyDeviceLost();
720 gl::error(GL_OUT_OF_MEMORY);
721 }
722 else if (FAILED(result))
723 {
724 ASSERT(result == E_OUTOFMEMORY);
725 ERR("Creating image failed.");
726 gl::error(GL_OUT_OF_MEMORY);
727 }
728 else
729 {
730 mTexture->GetDesc(&desc);
731 mMipLevels = desc.MipLevels;
732 mTextureWidth = desc.Width;
733 mTextureHeight = desc.Height;
734 mTextureDepth = desc.Depth;
735 }
736 }
737}
738
739TextureStorage11_3D::~TextureStorage11_3D()
740{
741 if (mTexture)
742 {
743 mTexture->Release();
744 mTexture = NULL;
745 }
746
747 if (mSRV)
748 {
749 mSRV->Release();
750 mSRV = NULL;
751 }
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000752
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000753 for (RenderTargetMap::const_iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++)
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000754 {
755 RenderTarget11* renderTarget = i->second;
756 delete renderTarget;
757 }
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000758 mLevelLayerRenderTargets.clear();
759
760 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
761 {
762 delete mLevelRenderTargets[i];
763 mLevelRenderTargets[i] = NULL;
764 }
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000765}
766
767TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage)
768{
769 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage));
770 return static_cast<TextureStorage11_3D*>(storage);
771}
772
773ID3D11Resource *TextureStorage11_3D::getBaseTexture() const
774{
775 return mTexture;
776}
777
778ID3D11ShaderResourceView *TextureStorage11_3D::getSRV()
779{
780 if (!mSRV)
781 {
782 ID3D11Device *device = mRenderer->getDevice();
783
784 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
785 srvDesc.Format = mShaderResourceFormat;
786 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
787 srvDesc.Texture3D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
788 srvDesc.Texture3D.MostDetailedMip = 0;
789
790 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
791
792 if (result == E_OUTOFMEMORY)
793 {
794 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
795 }
796 ASSERT(SUCCEEDED(result));
797 }
798
799 return mSRV;
800}
801
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000802RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel)
803{
804 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
805 {
806 if (!mLevelRenderTargets[mipLevel])
807 {
808 ID3D11Device *device = mRenderer->getDevice();
809 HRESULT result;
810
811 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
812 srvDesc.Format = mShaderResourceFormat;
813 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
814 srvDesc.Texture3D.MostDetailedMip = mipLevel;
815 srvDesc.Texture3D.MipLevels = 1;
816
817 ID3D11ShaderResourceView *srv;
818 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
819
820 if (result == E_OUTOFMEMORY)
821 {
822 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
823 }
824 ASSERT(SUCCEEDED(result));
825
826 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
827 {
828 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
829 rtvDesc.Format = mRenderTargetFormat;
830 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
831 rtvDesc.Texture3D.MipSlice = mipLevel;
832 rtvDesc.Texture3D.FirstWSlice = 0;
833 rtvDesc.Texture3D.WSize = -1;
834
835 ID3D11RenderTargetView *rtv;
836 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
837
838 if (result == E_OUTOFMEMORY)
839 {
840 srv->Release();
841 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
842 }
843 ASSERT(SUCCEEDED(result));
844
845 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
846 // also needs to keep a reference to the texture.
847 mTexture->AddRef();
848
849 mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
850 std::max(mTextureWidth >> mipLevel, 1U),
851 std::max(mTextureHeight >> mipLevel, 1U),
852 std::max(mTextureDepth >> mipLevel, 1U));
853 }
854 else
855 {
856 UNREACHABLE();
857 }
858 }
859
860 return mLevelRenderTargets[mipLevel];
861 }
862 else
863 {
864 return NULL;
865 }
866}
867
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000868RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer)
869{
870 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
871 {
872 LevelLayerKey key(mipLevel, layer);
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000873 if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000874 {
875 ID3D11Device *device = mRenderer->getDevice();
876 HRESULT result;
877
878 // TODO, what kind of SRV is expected here?
879 ID3D11ShaderResourceView *srv = NULL;
880
881 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
882 {
883 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
884 rtvDesc.Format = mRenderTargetFormat;
885 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
886 rtvDesc.Texture3D.MipSlice = mipLevel;
887 rtvDesc.Texture3D.FirstWSlice = layer;
888 rtvDesc.Texture3D.WSize = 1;
889
890 ID3D11RenderTargetView *rtv;
891 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
892
893 if (result == E_OUTOFMEMORY)
894 {
895 srv->Release();
896 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
897 }
898 ASSERT(SUCCEEDED(result));
899
900 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
901 // also needs to keep a reference to the texture.
902 mTexture->AddRef();
903
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000904 mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
905 std::max(mTextureWidth >> mipLevel, 1U),
906 std::max(mTextureHeight >> mipLevel, 1U),
907 1);
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000908 }
909 else
910 {
911 UNREACHABLE();
912 }
913 }
914
shannonwoods@chromium.org15a8b1f2013-05-30 00:03:54 +0000915 return mLevelLayerRenderTargets[key];
shannon.woods%transgaming.com@gtempaccount.com63b3b8f2013-04-13 03:43:26 +0000916 }
917 else
918 {
919 return NULL;
920 }
921}
922
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000923void TextureStorage11_3D::generateMipmap(int level)
924{
shannonwoods@chromium.org37b8a912013-05-30 00:04:21 +0000925 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
926 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
927
928 generateMipmapLayer(source, dest);
shannon.woods%transgaming.com@gtempaccount.com2058d642013-04-13 03:42:50 +0000929}
930
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000931TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, int levels, GLenum internalformat, GLenum usage,
932 GLsizei width, GLsizei height, GLsizei depth)
shannonwoods@chromium.orgadc56352013-05-30 00:09:08 +0000933 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getCurrentClientVersion(), usage))
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +0000934{
935 mTexture = NULL;
936
937 DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
938 ASSERT(!d3d11::IsDepthStencilFormat(convertedFormat));
939
940 mTextureFormat = convertedFormat;
941 mShaderResourceFormat = convertedFormat;
942 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
943 mRenderTargetFormat = convertedFormat;
944
945 // if the width, height or depth is not positive this should be treated as an incomplete texture
946 // we handle that here by skipping the d3d texture creation
947 if (width > 0 && height > 0 && depth > 0)
948 {
949 // adjust size if needed for compressed textures
950 gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
951
952 ID3D11Device *device = mRenderer->getDevice();
953
954 D3D11_TEXTURE2D_DESC desc;
955 desc.Width = width;
956 desc.Height = height;
957 desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
958 desc.ArraySize = depth;
959 desc.Format = mTextureFormat;
960 desc.SampleDesc.Count = 1;
961 desc.SampleDesc.Quality = 0;
962 desc.Usage = D3D11_USAGE_DEFAULT;
963 desc.BindFlags = getBindFlags();
964 desc.CPUAccessFlags = 0;
965 desc.MiscFlags = 0;
966
967 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
968
969 // this can happen from windows TDR
970 if (d3d11::isDeviceLostError(result))
971 {
972 mRenderer->notifyDeviceLost();
973 gl::error(GL_OUT_OF_MEMORY);
974 }
975 else if (FAILED(result))
976 {
977 ASSERT(result == E_OUTOFMEMORY);
978 ERR("Creating image failed.");
979 gl::error(GL_OUT_OF_MEMORY);
980 }
981 else
982 {
983 mTexture->GetDesc(&desc);
984 mMipLevels = desc.MipLevels;
985 mTextureWidth = desc.Width;
986 mTextureHeight = desc.Height;
987 mTextureDepth = desc.ArraySize;
988 }
989 }
990}
991
992TextureStorage11_2DArray::~TextureStorage11_2DArray()
993{
994 if (mTexture)
995 {
996 mTexture->Release();
997 mTexture = NULL;
998 }
999
1000 if (mSRV)
1001 {
1002 mSRV->Release();
1003 mSRV = NULL;
1004 }
1005
1006 for (RenderTargetMap::const_iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
1007 {
1008 RenderTarget11* renderTarget = i->second;
1009 delete renderTarget;
1010 }
1011 mRenderTargets.clear();
1012}
1013
1014TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage)
1015{
1016 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage));
1017 return static_cast<TextureStorage11_2DArray*>(storage);
1018}
1019
1020ID3D11Resource *TextureStorage11_2DArray::getBaseTexture() const
1021{
1022 return mTexture;
1023}
1024
1025ID3D11ShaderResourceView *TextureStorage11_2DArray::getSRV()
1026{
1027 if (!mSRV)
1028 {
1029 ID3D11Device *device = mRenderer->getDevice();
1030
1031 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1032 srvDesc.Format = mShaderResourceFormat;
1033 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1034 srvDesc.Texture2DArray.MostDetailedMip = 0;
1035 srvDesc.Texture2DArray.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
1036 srvDesc.Texture2DArray.FirstArraySlice = 0;
1037 srvDesc.Texture2DArray.ArraySize = mTextureDepth;
1038
1039 HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
1040
1041 if (result == E_OUTOFMEMORY)
1042 {
1043 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
1044 }
1045 ASSERT(SUCCEEDED(result));
1046 }
1047
1048 return mSRV;
1049}
1050
1051RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer)
1052{
1053 if (mipLevel >= 0 && mipLevel < static_cast<int>(mMipLevels))
1054 {
1055 LevelLayerKey key(mipLevel, layer);
1056 if (mRenderTargets.find(key) == mRenderTargets.end())
1057 {
1058 ID3D11Device *device = mRenderer->getDevice();
1059 HRESULT result;
1060
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +00001061 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1062 srvDesc.Format = mShaderResourceFormat;
1063 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1064 srvDesc.Texture2DArray.MostDetailedMip = mipLevel;
1065 srvDesc.Texture2DArray.MipLevels = 1;
1066 srvDesc.Texture2DArray.FirstArraySlice = layer;
1067 srvDesc.Texture2DArray.ArraySize = 1;
1068
1069 ID3D11ShaderResourceView *srv;
1070 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
1071
1072 if (result == E_OUTOFMEMORY)
1073 {
1074 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1075 }
1076 ASSERT(SUCCEEDED(result));
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001077
1078 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
1079 {
1080 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1081 rtvDesc.Format = mRenderTargetFormat;
1082 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1083 rtvDesc.Texture2DArray.MipSlice = mipLevel;
1084 rtvDesc.Texture2DArray.FirstArraySlice = layer;
1085 rtvDesc.Texture2DArray.ArraySize = 1;
1086
1087 ID3D11RenderTargetView *rtv;
1088 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
1089
1090 if (result == E_OUTOFMEMORY)
1091 {
1092 SafeRelease(srv);
1093 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1094 }
1095 ASSERT(SUCCEEDED(result));
1096
1097 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
1098 // also needs to keep a reference to the texture.
1099 mTexture->AddRef();
1100
1101 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
1102 std::max(mTextureWidth >> mipLevel, 1U),
shannonwoods@chromium.org7faf3ec2013-05-30 00:03:45 +00001103 std::max(mTextureHeight >> mipLevel, 1U),
1104 1);
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001105 }
1106 else
1107 {
1108 UNREACHABLE();
1109 }
1110 }
1111
1112 return mRenderTargets[key];
1113 }
1114 else
1115 {
1116 return NULL;
1117 }
1118}
1119
1120void TextureStorage11_2DArray::generateMipmap(int level)
1121{
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +00001122 for (unsigned int layer = 0; layer < mTextureDepth; layer++)
1123 {
1124 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer));
1125 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer));
1126
1127 generateMipmapLayer(source, dest);
1128 }
shannon.woods%transgaming.com@gtempaccount.com96973372013-04-13 03:45:39 +00001129}
1130
daniel@transgaming.comb2151e52013-01-11 04:06:24 +00001131}