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// 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"
17
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/main.h"
20
21namespace rx
22{
23
24TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
25    : mBindFlags(bindFlags),
26      mLodOffset(0),
27      mMipLevels(0),
28      mTexture(NULL),
29      mTextureFormat(DXGI_FORMAT_UNKNOWN),
30      mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
31      mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
32      mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
33      mSRV(NULL),
34      mTextureWidth(0),
35      mTextureHeight(0)
36{
37    mRenderer = Renderer11::makeRenderer11(renderer);
38}
39
40TextureStorage11::~TextureStorage11()
41{
42}
43
44TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
45{
46    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
47    return static_cast<TextureStorage11*>(storage);
48}
49
50DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
51{
52    UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
53
54    if (d3d11::IsDepthStencilFormat(format))
55    {
56        bindFlags |= D3D11_BIND_DEPTH_STENCIL;
57    }
58    else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
59    {
60        bindFlags |= D3D11_BIND_RENDER_TARGET;
61    }
62    return bindFlags;
63}
64
65bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
66{
67    switch(format)
68    {
69      case DXGI_FORMAT_R8G8B8A8_UNORM:
70      case DXGI_FORMAT_A8_UNORM:
71      case DXGI_FORMAT_R32G32B32A32_FLOAT:
72      case DXGI_FORMAT_R16G16B16A16_FLOAT:
73      case DXGI_FORMAT_B8G8R8A8_UNORM:
74      case DXGI_FORMAT_R8_UNORM:
75      case DXGI_FORMAT_R8G8_UNORM:
76      case DXGI_FORMAT_R16_FLOAT:
77      case DXGI_FORMAT_R16G16_FLOAT:
78        return true;
79      case DXGI_FORMAT_BC1_UNORM:
80      case DXGI_FORMAT_BC2_UNORM:
81      case DXGI_FORMAT_BC3_UNORM:
82      case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices
83        return false;
84      default:
85        UNREACHABLE();
86        return false;
87    }
88}
89
90UINT TextureStorage11::getBindFlags() const
91{
92    return mBindFlags;
93}
94
95ID3D11Texture2D *TextureStorage11::getBaseTexture() const
96{
97    return mTexture;
98}
99
100int TextureStorage11::getLodOffset() const
101{
102    return mLodOffset;
103}
104
105bool TextureStorage11::isRenderTarget() const
106{
107    return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
108}
109
110bool TextureStorage11::isManaged() const
111{
112    return false;
113}
114
115int TextureStorage11::levelCount()
116{
117    int levels = 0;
118    if (getBaseTexture())
119    {
120        levels = mMipLevels - getLodOffset();
121    }
122    return levels;
123}
124
125UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
126{
127    UINT index = 0;
128    if (getBaseTexture())
129    {
130        index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
131    }
132    return index;
133}
134
135bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource,
136                                              int level, int face, GLint xoffset, GLint yoffset,
137                                              GLsizei width, GLsizei height)
138{
139    if (srcTexture)
140    {
141        // Round up the width and height to the nearest multiple of dimension alignment
142        unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
143        width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
144        height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
145
146        D3D11_BOX srcBox;
147        srcBox.left = xoffset;
148        srcBox.top = yoffset;
149        srcBox.right = xoffset + width;
150        srcBox.bottom = yoffset + height;
151        srcBox.front = 0;
152        srcBox.back = 1;
153
154        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
155
156        ASSERT(getBaseTexture());
157        context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face),
158                                       xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox);
159        return true;
160    }
161
162    return false;
163}
164
165void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
166{
167    if (source && dest)
168    {
169        ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
170        ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
171
172        if (sourceSRV && destRTV)
173        {
174            gl::Rectangle sourceArea;
175            sourceArea.x = 0;
176            sourceArea.y = 0;
177            sourceArea.width = source->getWidth();
178            sourceArea.height = source->getHeight();
179
180            gl::Rectangle destArea;
181            destArea.x = 0;
182            destArea.y = 0;
183            destArea.width = dest->getWidth();
184            destArea.height = dest->getHeight();
185
186            mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
187                                   destRTV, destArea, dest->getWidth(), dest->getHeight(),
188                                   GL_RGBA);
189        }
190    }
191}
192
193TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
194    : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
195{
196    mTexture = swapchain->getOffscreenTexture();
197    mSRV = swapchain->getRenderTargetShaderResource();
198
199    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
200    {
201        mRenderTarget[i] = NULL;
202    }
203
204    D3D11_TEXTURE2D_DESC texDesc;
205    mTexture->GetDesc(&texDesc);
206    mMipLevels = texDesc.MipLevels;
207    mTextureFormat = texDesc.Format;
208    mTextureWidth = texDesc.Width;
209    mTextureHeight = texDesc.Height;
210
211    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
212    mSRV->GetDesc(&srvDesc);
213    mShaderResourceFormat = srvDesc.Format;
214
215    ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
216    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
217    offscreenRTV->GetDesc(&rtvDesc);
218    mRenderTargetFormat = rtvDesc.Format;
219    offscreenRTV->Release();
220
221    mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
222}
223
224TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
225    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
226{
227    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
228    {
229        mRenderTarget[i] = NULL;
230    }
231
232    DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
233    if (d3d11::IsDepthStencilFormat(convertedFormat))
234    {
235        mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
236        mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
237        mDepthStencilFormat = convertedFormat;
238        mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
239    }
240    else
241    {
242        mTextureFormat = convertedFormat;
243        mShaderResourceFormat = convertedFormat;
244        mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
245        mRenderTargetFormat = convertedFormat;
246    }
247
248    // if the width or height is not positive this should be treated as an incomplete texture
249    // we handle that here by skipping the d3d texture creation
250    if (width > 0 && height > 0)
251    {
252        // adjust size if needed for compressed textures
253        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
254
255        ID3D11Device *device = mRenderer->getDevice();
256
257        D3D11_TEXTURE2D_DESC desc;
258        desc.Width = width;      // Compressed texture size constraints?
259        desc.Height = height;
260        desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
261        desc.ArraySize = 1;
262        desc.Format = mTextureFormat;
263        desc.SampleDesc.Count = 1;
264        desc.SampleDesc.Quality = 0;
265        desc.Usage = D3D11_USAGE_DEFAULT;
266        desc.BindFlags = getBindFlags();
267        desc.CPUAccessFlags = 0;
268        desc.MiscFlags = 0;
269
270        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
271
272        // this can happen from windows TDR
273        if (d3d11::isDeviceLostError(result))
274        {
275            mRenderer->notifyDeviceLost();
276            gl::error(GL_OUT_OF_MEMORY);
277        }
278        else if (FAILED(result))
279        {
280            ASSERT(result == E_OUTOFMEMORY);
281            ERR("Creating image failed.");
282            gl::error(GL_OUT_OF_MEMORY);
283        }
284        else
285        {
286            mTexture->GetDesc(&desc);
287            mMipLevels = desc.MipLevels;
288            mTextureWidth = desc.Width;
289            mTextureHeight = desc.Height;
290        }
291    }
292}
293
294TextureStorage11_2D::~TextureStorage11_2D()
295{
296    if (mTexture)
297    {
298        mTexture->Release();
299        mTexture = NULL;
300    }
301
302    if (mSRV)
303    {
304        mSRV->Release();
305        mSRV = NULL;
306    }
307
308    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
309    {
310        delete mRenderTarget[i];
311        mRenderTarget[i] = NULL;
312    }
313}
314
315TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
316{
317    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
318    return static_cast<TextureStorage11_2D*>(storage);
319}
320
321RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
322{
323    if (level >= 0 && level < static_cast<int>(mMipLevels))
324    {
325        if (!mRenderTarget[level])
326        {
327            ID3D11Device *device = mRenderer->getDevice();
328            HRESULT result;
329
330            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
331            srvDesc.Format = mShaderResourceFormat;
332            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
333            srvDesc.Texture2D.MostDetailedMip = level;
334            srvDesc.Texture2D.MipLevels = 1;
335
336            ID3D11ShaderResourceView *srv;
337            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
338
339            if (result == E_OUTOFMEMORY)
340            {
341                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
342            }
343            ASSERT(SUCCEEDED(result));
344
345            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
346            {
347                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
348                rtvDesc.Format = mRenderTargetFormat;
349                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
350                rtvDesc.Texture2D.MipSlice = level;
351
352                ID3D11RenderTargetView *rtv;
353                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
354
355                if (result == E_OUTOFMEMORY)
356                {
357                    srv->Release();
358                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
359                }
360                ASSERT(SUCCEEDED(result));
361
362                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
363                // also needs to keep a reference to the texture.
364                mTexture->AddRef();
365
366                mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
367                                                          std::max(mTextureWidth >> level, 1U),
368                                                          std::max(mTextureHeight >> level, 1U));
369            }
370            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
371            {
372                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
373                dsvDesc.Format = mDepthStencilFormat;
374                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
375                dsvDesc.Texture2D.MipSlice = level;
376                dsvDesc.Flags = 0;
377
378                ID3D11DepthStencilView *dsv;
379                result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
380
381                if (result == E_OUTOFMEMORY)
382                {
383                    srv->Release();
384                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
385                }
386                ASSERT(SUCCEEDED(result));
387
388                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
389                // also needs to keep a reference to the texture.
390                mTexture->AddRef();
391
392                mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
393                                                          std::max(mTextureWidth >> level, 1U),
394                                                          std::max(mTextureHeight >> level, 1U));
395            }
396            else
397            {
398                UNREACHABLE();
399            }
400        }
401
402        return mRenderTarget[level];
403    }
404    else
405    {
406        return NULL;
407    }
408}
409
410ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
411{
412    if (!mSRV)
413    {
414        ID3D11Device *device = mRenderer->getDevice();
415
416        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
417        srvDesc.Format = mShaderResourceFormat;
418        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
419        srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
420        srvDesc.Texture2D.MostDetailedMip = 0;
421
422        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
423
424        if (result == E_OUTOFMEMORY)
425        {
426            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
427        }
428        ASSERT(SUCCEEDED(result));
429    }
430
431    return mSRV;
432}
433
434void TextureStorage11_2D::generateMipmap(int level)
435{
436    RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
437    RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
438
439    generateMipmapLayer(source, dest);
440}
441
442TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
443    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
444{
445    for (unsigned int i = 0; i < 6; i++)
446    {
447        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
448        {
449            mRenderTarget[i][j] = NULL;
450        }
451    }
452
453    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
469    // 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;
482        desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
483        desc.ArraySize = 6;
484        desc.Format = mTextureFormat;
485        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.");
498            gl::error(GL_OUT_OF_MEMORY);
499        }
500        else
501        {
502            mTexture->GetDesc(&desc);
503            mMipLevels = desc.MipLevels;
504            mTextureWidth = desc.Width;
505            mTextureHeight = desc.Height;
506        }
507    }
508}
509
510TextureStorage11_Cube::~TextureStorage11_Cube()
511{
512    if (mTexture)
513    {
514        mTexture->Release();
515        mTexture = NULL;
516    }
517
518    if (mSRV)
519    {
520        mSRV->Release();
521        mSRV = NULL;
522    }
523
524    for (unsigned int i = 0; i < 6; i++)
525    {
526        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
527        {
528            delete mRenderTarget[i][j];
529            mRenderTarget[i][j] = NULL;
530        }
531    }
532}
533
534TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
535{
536    ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
537    return static_cast<TextureStorage11_Cube*>(storage);
538}
539
540RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
541{
542    unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
543    if (level >= 0 && level < static_cast<int>(mMipLevels))
544    {
545        if (!mRenderTarget[faceIdx][level])
546        {
547            ID3D11Device *device = mRenderer->getDevice();
548            HRESULT result;
549
550            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
551            srvDesc.Format = mShaderResourceFormat;
552            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
553            srvDesc.Texture2DArray.MostDetailedMip = level;
554            srvDesc.Texture2DArray.MipLevels = 1;
555            srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
556            srvDesc.Texture2DArray.ArraySize = 1;
557
558            ID3D11ShaderResourceView *srv;
559            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
560
561            if (result == E_OUTOFMEMORY)
562            {
563                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
564            }
565            ASSERT(SUCCEEDED(result));
566
567            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
568            {
569                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
570                rtvDesc.Format = mRenderTargetFormat;
571                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
572                rtvDesc.Texture2DArray.MipSlice = level;
573                rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
574                rtvDesc.Texture2DArray.ArraySize = 1;
575
576                ID3D11RenderTargetView *rtv;
577                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
578
579                if (result == E_OUTOFMEMORY)
580                {
581                    srv->Release();
582                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
583                }
584                ASSERT(SUCCEEDED(result));
585
586                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
587                // also needs to keep a reference to the texture.
588                mTexture->AddRef();
589
590                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
591                                                                   std::max(mTextureWidth >> level, 1U),
592                                                                   std::max(mTextureHeight >> level, 1U));
593            }
594            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
595            {
596                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
597                dsvDesc.Format = mRenderTargetFormat;
598                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
599                dsvDesc.Texture2DArray.MipSlice = level;
600                dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
601                dsvDesc.Texture2DArray.ArraySize = 1;
602
603                ID3D11DepthStencilView *dsv;
604                result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
605
606                if (result == E_OUTOFMEMORY)
607                {
608                    srv->Release();
609                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
610                }
611                ASSERT(SUCCEEDED(result));
612
613                // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
614                // also needs to keep a reference to the texture.
615                mTexture->AddRef();
616
617                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
618                                                                   std::max(mTextureWidth >> level, 1U),
619                                                                   std::max(mTextureHeight >> level, 1U));
620            }
621            else
622            {
623                UNREACHABLE();
624            }
625        }
626
627        return mRenderTarget[faceIdx][level];
628    }
629    else
630    {
631        return NULL;
632    }
633}
634
635ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
636{
637    if (!mSRV)
638    {
639        ID3D11Device *device = mRenderer->getDevice();
640
641        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
642        srvDesc.Format = mShaderResourceFormat;
643        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
644        srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
645        srvDesc.TextureCube.MostDetailedMip = 0;
646
647        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
648
649        if (result == E_OUTOFMEMORY)
650        {
651            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
652        }
653        ASSERT(SUCCEEDED(result));
654    }
655
656    return mSRV;
657}
658
659void TextureStorage11_Cube::generateMipmap(int face, int level)
660{
661    RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
662    RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
663
664    generateMipmapLayer(source, dest);
665}
666
667}
668