1#include "precompiled.h"
2//
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// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
9// retained by Renderbuffers.
10
11#include "libGLESv2/renderer/RenderTarget11.h"
12#include "libGLESv2/renderer/Renderer11.h"
13
14#include "libGLESv2/renderer/renderer11_utils.h"
15#include "libGLESv2/main.h"
16
17namespace rx
18{
19
20static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view)
21{
22    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
23    view->GetDesc(&rtvDesc);
24
25    D3D11_TEXTURE2D_DESC texDesc;
26    texture->GetDesc(&texDesc);
27
28    unsigned int mipSlice = 0;
29    unsigned int arraySlice = 0;
30    unsigned int mipLevels = texDesc.MipLevels;
31
32    switch (rtvDesc.ViewDimension)
33    {
34      case D3D11_RTV_DIMENSION_TEXTURE1D:
35        mipSlice = rtvDesc.Texture1D.MipSlice;
36        arraySlice = 0;
37        break;
38
39      case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
40        mipSlice = rtvDesc.Texture1DArray.MipSlice;
41        arraySlice = rtvDesc.Texture1DArray.FirstArraySlice;
42        break;
43
44      case D3D11_RTV_DIMENSION_TEXTURE2D:
45        mipSlice = rtvDesc.Texture2D.MipSlice;
46        arraySlice = 0;
47        break;
48
49      case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
50        mipSlice = rtvDesc.Texture2DArray.MipSlice;
51        arraySlice = rtvDesc.Texture2DArray.FirstArraySlice;
52        break;
53
54      case D3D11_RTV_DIMENSION_TEXTURE2DMS:
55        mipSlice = 0;
56        arraySlice = 0;
57        break;
58
59      case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
60        mipSlice = 0;
61        arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice;
62        break;
63
64      case D3D11_RTV_DIMENSION_TEXTURE3D:
65        mipSlice = rtvDesc.Texture3D.MipSlice;
66        arraySlice = 0;
67        break;
68
69      case D3D11_RTV_DIMENSION_UNKNOWN:
70      case D3D11_RTV_DIMENSION_BUFFER:
71        UNIMPLEMENTED();
72        break;
73
74      default:
75        UNREACHABLE();
76        break;
77    }
78
79    return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
80}
81
82static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view)
83{
84    D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
85    view->GetDesc(&dsvDesc);
86
87    D3D11_TEXTURE2D_DESC texDesc;
88    texture->GetDesc(&texDesc);
89
90    unsigned int mipSlice = 0;
91    unsigned int arraySlice = 0;
92    unsigned int mipLevels = texDesc.MipLevels;
93
94    switch (dsvDesc.ViewDimension)
95    {
96      case D3D11_DSV_DIMENSION_TEXTURE1D:
97        mipSlice = dsvDesc.Texture1D.MipSlice;
98        arraySlice = 0;
99        break;
100
101      case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
102        mipSlice = dsvDesc.Texture1DArray.MipSlice;
103        arraySlice = dsvDesc.Texture1DArray.FirstArraySlice;
104        break;
105
106      case D3D11_DSV_DIMENSION_TEXTURE2D:
107        mipSlice = dsvDesc.Texture2D.MipSlice;
108        arraySlice = 0;
109        break;
110
111      case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
112        mipSlice = dsvDesc.Texture2DArray.MipSlice;
113        arraySlice = dsvDesc.Texture2DArray.FirstArraySlice;
114        break;
115
116      case D3D11_DSV_DIMENSION_TEXTURE2DMS:
117        mipSlice = 0;
118        arraySlice = 0;
119        break;
120
121      case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
122        mipSlice = 0;
123        arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
124        break;
125
126      case D3D11_RTV_DIMENSION_UNKNOWN:
127        UNIMPLEMENTED();
128        break;
129
130      default:
131        UNREACHABLE();
132        break;
133    }
134
135    return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
136}
137
138RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
139{
140    mRenderer = Renderer11::makeRenderer11(renderer);
141    mTexture = tex;
142    mRenderTarget = rtv;
143    mDepthStencil = NULL;
144    mShaderResource = srv;
145    mSubresourceIndex = 0;
146
147    if (mRenderTarget && mTexture)
148    {
149        D3D11_RENDER_TARGET_VIEW_DESC desc;
150        mRenderTarget->GetDesc(&desc);
151
152        D3D11_TEXTURE2D_DESC texDesc;
153        mTexture->GetDesc(&texDesc);
154
155        mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
156        mWidth = width;
157        mHeight = height;
158        mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
159
160        mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
161        mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
162    }
163}
164
165RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
166{
167    mRenderer = Renderer11::makeRenderer11(renderer);
168    mTexture = tex;
169    mRenderTarget = NULL;
170    mDepthStencil = dsv;
171    mShaderResource = srv;
172    mSubresourceIndex = 0;
173
174    if (mDepthStencil && mTexture)
175    {
176        D3D11_DEPTH_STENCIL_VIEW_DESC desc;
177        mDepthStencil->GetDesc(&desc);
178
179        D3D11_TEXTURE2D_DESC texDesc;
180        mTexture->GetDesc(&texDesc);
181
182        mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
183        mWidth = width;
184        mHeight = height;
185        mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
186
187        mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
188        mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
189    }
190}
191
192RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth)
193{
194    mRenderer = Renderer11::makeRenderer11(renderer);
195    mTexture = NULL;
196    mRenderTarget = NULL;
197    mDepthStencil = NULL;
198    mShaderResource = NULL;
199
200    DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format);
201
202    int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples);
203    if (supportedSamples < 0)
204    {
205        gl::error(GL_OUT_OF_MEMORY);
206        return;
207    }
208
209    if (width > 0 && height > 0)
210    {
211        // Create texture resource
212        D3D11_TEXTURE2D_DESC desc;
213        desc.Width = width;
214        desc.Height = height;
215        desc.MipLevels = 1;
216        desc.ArraySize = 1;
217        desc.Format = requestedFormat;
218        desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
219        desc.SampleDesc.Quality = 0;
220        desc.Usage = D3D11_USAGE_DEFAULT;
221        desc.CPUAccessFlags = 0;
222        desc.MiscFlags = 0;
223        desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE));
224
225        ID3D11Device *device = mRenderer->getDevice();
226        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
227
228        if (result == E_OUTOFMEMORY)
229        {
230            gl::error(GL_OUT_OF_MEMORY);
231            return;
232        }
233        ASSERT(SUCCEEDED(result));
234
235        if (depth)
236        {
237            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
238            dsvDesc.Format = requestedFormat;
239            dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
240            dsvDesc.Texture2D.MipSlice = 0;
241            dsvDesc.Flags = 0;
242            result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil);
243
244            if (result == E_OUTOFMEMORY)
245            {
246                mTexture->Release();
247                mTexture = NULL;
248                gl::error(GL_OUT_OF_MEMORY);
249            }
250            ASSERT(SUCCEEDED(result));
251        }
252        else
253        {
254            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
255            rtvDesc.Format = requestedFormat;
256            rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
257            rtvDesc.Texture2D.MipSlice = 0;
258            result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget);
259
260            if (result == E_OUTOFMEMORY)
261            {
262                mTexture->Release();
263                mTexture = NULL;
264                gl::error(GL_OUT_OF_MEMORY);
265                return;
266            }
267            ASSERT(SUCCEEDED(result));
268
269            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
270            srvDesc.Format = requestedFormat;
271            srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
272            srvDesc.Texture2D.MostDetailedMip = 0;
273            srvDesc.Texture2D.MipLevels = 1;
274            result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource);
275
276            if (result == E_OUTOFMEMORY)
277            {
278                mTexture->Release();
279                mTexture = NULL;
280                mRenderTarget->Release();
281                mRenderTarget = NULL;
282                gl::error(GL_OUT_OF_MEMORY);
283                return;
284            }
285            ASSERT(SUCCEEDED(result));
286        }
287    }
288
289    mWidth = width;
290    mHeight = height;
291    mInternalFormat = format;
292    mSamples = supportedSamples;
293    mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat);
294    mSubresourceIndex = D3D11CalcSubresource(0, 0, 1);
295}
296
297RenderTarget11::~RenderTarget11()
298{
299    if (mTexture)
300    {
301        mTexture->Release();
302        mTexture = NULL;
303    }
304
305    if (mRenderTarget)
306    {
307        mRenderTarget->Release();
308        mRenderTarget = NULL;
309    }
310
311    if (mDepthStencil)
312    {
313        mDepthStencil->Release();
314        mDepthStencil = NULL;
315    }
316
317    if (mShaderResource)
318    {
319        mShaderResource->Release();
320        mShaderResource = NULL;
321    }
322}
323
324RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
325{
326    ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target));
327    return static_cast<rx::RenderTarget11*>(target);
328}
329
330ID3D11Texture2D *RenderTarget11::getTexture() const
331{
332    return mTexture;
333}
334
335ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const
336{
337    return mRenderTarget;
338}
339
340ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const
341{
342    return mDepthStencil;
343}
344
345ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const
346{
347    return mShaderResource;
348}
349
350unsigned int RenderTarget11::getSubresourceIndex() const
351{
352    return mSubresourceIndex;
353}
354
355}
356