Home | History | Annotate | Download | only in d3d11
      1 //
      2 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Clear11.cpp: Framebuffer clear utility class.
      8 
      9 #include "libGLESv2/renderer/d3d/d3d11/Clear11.h"
     10 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
     11 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
     12 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
     13 #include "libGLESv2/formatutils.h"
     14 #include "libGLESv2/Framebuffer.h"
     15 #include "libGLESv2/FramebufferAttachment.h"
     16 
     17 // Precompiled shaders
     18 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h"
     19 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h"
     20 
     21 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h"
     22 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h"
     23 
     24 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h"
     25 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h"
     26 
     27 namespace rx
     28 {
     29 
     30 template <typename T>
     31 static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color<T> &color, float depth, void *buffer)
     32 {
     33     d3d11::PositionDepthColorVertex<T> *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex<T>*>(buffer);
     34 
     35     float depthClear = gl::clamp01(depth);
     36     float left = -1.0f;
     37     float right = 1.0f;
     38     float top = -1.0f;
     39     float bottom = 1.0f;
     40 
     41     // Clip the quad coordinates to the scissor if needed
     42     if (scissor != NULL)
     43     {
     44         left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f);
     45         right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f);
     46         top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f);
     47         bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f);
     48     }
     49 
     50     d3d11::SetPositionDepthColorVertex<T>(vertices + 0, left,  bottom, depthClear, color);
     51     d3d11::SetPositionDepthColorVertex<T>(vertices + 1, left,  top,    depthClear, color);
     52     d3d11::SetPositionDepthColorVertex<T>(vertices + 2, right, bottom, depthClear, color);
     53     d3d11::SetPositionDepthColorVertex<T>(vertices + 3, right, top,    depthClear, color);
     54 }
     55 
     56 template <unsigned int vsSize, unsigned int psSize>
     57 Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize])
     58 {
     59     HRESULT result;
     60 
     61     ClearShader shader = { 0 };
     62 
     63     D3D11_INPUT_ELEMENT_DESC quadLayout[] =
     64     {
     65         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     66         { "COLOR",    0, colorType,                   0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     67     };
     68 
     69     result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout);
     70     ASSERT(SUCCEEDED(result));
     71 
     72     result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader);
     73     ASSERT(SUCCEEDED(result));
     74 
     75     result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader);
     76     ASSERT(SUCCEEDED(result));
     77 
     78     return shader;
     79 }
     80 
     81 Clear11::Clear11(Renderer11 *renderer)
     82     : mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
     83       mVertexBuffer(NULL), mRasterizerState(NULL)
     84 {
     85     HRESULT result;
     86     ID3D11Device *device = renderer->getDevice();
     87 
     88     D3D11_BUFFER_DESC vbDesc;
     89     vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex<float>) * 4;
     90     vbDesc.Usage = D3D11_USAGE_DYNAMIC;
     91     vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
     92     vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
     93     vbDesc.MiscFlags = 0;
     94     vbDesc.StructureByteStride = 0;
     95 
     96     result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer);
     97     ASSERT(SUCCEEDED(result));
     98     d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer");
     99 
    100     D3D11_RASTERIZER_DESC rsDesc;
    101     rsDesc.FillMode = D3D11_FILL_SOLID;
    102     rsDesc.CullMode = D3D11_CULL_NONE;
    103     rsDesc.FrontCounterClockwise = FALSE;
    104     rsDesc.DepthBias = 0;
    105     rsDesc.DepthBiasClamp = 0.0f;
    106     rsDesc.SlopeScaledDepthBias = 0.0f;
    107     rsDesc.DepthClipEnable = FALSE;
    108     rsDesc.ScissorEnable = FALSE;
    109     rsDesc.MultisampleEnable = FALSE;
    110     rsDesc.AntialiasedLineEnable = FALSE;
    111 
    112     result = device->CreateRasterizerState(&rsDesc, &mRasterizerState);
    113     ASSERT(SUCCEEDED(result));
    114     d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state");
    115 
    116     mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat);
    117     mUintClearShader  = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT,  g_VS_ClearUint,  g_PS_ClearUint );
    118     mIntClearShader   = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT,  g_VS_ClearSint,  g_PS_ClearSint );
    119 }
    120 
    121 Clear11::~Clear11()
    122 {
    123     for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++)
    124     {
    125         SafeRelease(i->second);
    126     }
    127     mClearBlendStates.clear();
    128 
    129     SafeRelease(mFloatClearShader.inputLayout);
    130     SafeRelease(mFloatClearShader.vertexShader);
    131     SafeRelease(mFloatClearShader.pixelShader);
    132 
    133     SafeRelease(mUintClearShader.inputLayout);
    134     SafeRelease(mUintClearShader.vertexShader);
    135     SafeRelease(mUintClearShader.pixelShader);
    136 
    137     SafeRelease(mIntClearShader.inputLayout);
    138     SafeRelease(mIntClearShader.vertexShader);
    139     SafeRelease(mIntClearShader.pixelShader);
    140 
    141     for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++)
    142     {
    143         SafeRelease(i->second);
    144     }
    145     mClearDepthStencilStates.clear();
    146 
    147     SafeRelease(mVertexBuffer);
    148     SafeRelease(mRasterizerState);
    149 }
    150 
    151 gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
    152 {
    153     // First determine if a scissored clear is needed, this will always require drawing a quad.
    154     //
    155     // Otherwise, iterate over the color buffers which require clearing and determine if they can be
    156     // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires:
    157     // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer
    158     //    render targets as expected but does not work the other way around)
    159     // 2) The format of the render target has no color channels that are currently masked out.
    160     // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work.
    161     //
    162     // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView
    163     // by checking if the stencil write mask covers the entire stencil.
    164     //
    165     // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color
    166     // attribute.
    167 
    168     gl::Extents framebufferSize;
    169     if (frameBuffer->getFirstColorbuffer() != NULL)
    170     {
    171         gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
    172         framebufferSize.width = attachment->getWidth();
    173         framebufferSize.height = attachment->getHeight();
    174         framebufferSize.depth = 1;
    175     }
    176     else if (frameBuffer->getDepthOrStencilbuffer() != NULL)
    177     {
    178         gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
    179         framebufferSize.width = attachment->getWidth();
    180         framebufferSize.height = attachment->getHeight();
    181         framebufferSize.depth = 1;
    182     }
    183     else
    184     {
    185         UNREACHABLE();
    186         return gl::Error(GL_INVALID_OPERATION);
    187     }
    188 
    189     if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width ||
    190                                        clearParams.scissor.y >= framebufferSize.height ||
    191                                        clearParams.scissor.x + clearParams.scissor.width <= 0 ||
    192                                        clearParams.scissor.y + clearParams.scissor.height <= 0))
    193     {
    194         // Scissor is enabled and the scissor rectangle is outside the renderbuffer
    195         return gl::Error(GL_NO_ERROR);
    196     }
    197 
    198     bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 ||
    199                                                              clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
    200                                                              clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height);
    201 
    202     std::vector<MaskedRenderTarget> maskedClearRenderTargets;
    203     RenderTarget11* maskedClearDepthStencil = NULL;
    204 
    205     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    206 
    207     for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    208     {
    209         if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment))
    210         {
    211             gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment);
    212             if (attachment)
    213             {
    214                 RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
    215                 if (!renderTarget)
    216                 {
    217                     return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
    218                 }
    219 
    220                 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
    221 
    222                 if (clearParams.colorClearType == GL_FLOAT &&
    223                     !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED))
    224                 {
    225                     ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-"
    226                         "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment,
    227                         attachment->getInternalFormat());
    228                 }
    229 
    230                 if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
    231                     (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
    232                     (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
    233                     (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
    234                 {
    235                     // Every channel either does not exist in the render target or is masked out
    236                     continue;
    237                 }
    238                 else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT ||
    239                          (formatInfo.redBits   > 0 && !clearParams.colorMaskRed)   ||
    240                          (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
    241                          (formatInfo.blueBits  > 0 && !clearParams.colorMaskBlue) ||
    242                          (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
    243                 {
    244                     // A scissored or masked clear is required
    245                     MaskedRenderTarget maskAndRt;
    246                     bool clearColor = clearParams.clearColor[colorAttachment];
    247                     maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed);
    248                     maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen);
    249                     maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue);
    250                     maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha);
    251                     maskAndRt.renderTarget = renderTarget;
    252                     maskedClearRenderTargets.push_back(maskAndRt);
    253                 }
    254                 else
    255                 {
    256                     // ID3D11DeviceContext::ClearRenderTargetView is possible
    257 
    258                     ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
    259                     if (!framebufferRTV)
    260                     {
    261                         return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
    262                     }
    263 
    264                     const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
    265 
    266                     // Check if the actual format has a channel that the internal format does not and set them to the
    267                     // default values
    268                     const float clearValues[4] =
    269                     {
    270                         ((formatInfo.redBits == 0 && actualFormatInfo.redBits   > 0) ? 0.0f : clearParams.colorFClearValue.red),
    271                         ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
    272                         ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits  > 0) ? 0.0f : clearParams.colorFClearValue.blue),
    273                         ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
    274                     };
    275 
    276                     deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
    277                 }
    278             }
    279         }
    280     }
    281 
    282     if (clearParams.clearDepth || clearParams.clearStencil)
    283     {
    284         gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
    285         if (attachment)
    286         {
    287             RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
    288             if (!renderTarget)
    289             {
    290                 return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
    291             }
    292 
    293             const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
    294 
    295             unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0;
    296             bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
    297 
    298             if (needScissoredClear || needMaskedStencilClear)
    299             {
    300                 maskedClearDepthStencil = renderTarget;
    301             }
    302             else
    303             {
    304                 ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
    305                 if (!framebufferDSV)
    306                 {
    307                     return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
    308                 }
    309 
    310                 UINT clearFlags = (clearParams.clearDepth   ? D3D11_CLEAR_DEPTH   : 0) |
    311                                   (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
    312                 FLOAT depthClear = gl::clamp01(clearParams.depthClearValue);
    313                 UINT8 stencilClear = clearParams.stencilClearValue & 0xFF;
    314 
    315                 deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
    316             }
    317         }
    318     }
    319 
    320     if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil)
    321     {
    322         // To clear the render targets and depth stencil in one pass:
    323         //
    324         // Render a quad clipped to the scissor rectangle which draws the clear color and a blend
    325         // state that will perform the required color masking.
    326         //
    327         // The quad's depth is equal to the depth clear value with a depth stencil state that
    328         // will enable or disable depth test/writes if the depth buffer should be cleared or not.
    329         //
    330         // The rasterizer state's stencil is set to always pass or fail based on if the stencil
    331         // should be cleared or not with a stencil write mask of the stencil clear value.
    332         //
    333         // ======================================================================================
    334         //
    335         // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
    336         // buffer that is not normalized fixed point or floating point with floating point values
    337         // are undefined so we can just write floats to them and D3D11 will bit cast them to
    338         // integers.
    339         //
    340         // Also, we don't have to worry about attempting to clear a normalized fixed/floating point
    341         // buffer with integer values because there is no gl API call which would allow it,
    342         // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
    343         // be a compatible clear type.
    344 
    345         // Bind all the render targets which need clearing
    346         ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers);
    347         std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size());
    348         for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
    349         {
    350             RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
    351             ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
    352             if (!rtv)
    353             {
    354                 return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
    355             }
    356 
    357             rtvs[i] = rtv;
    358         }
    359         ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL;
    360 
    361         ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets);
    362         const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
    363         const UINT sampleMask = 0xFFFFFFFF;
    364 
    365         ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams);
    366         const UINT stencilClear = clearParams.stencilClearValue & 0xFF;
    367 
    368         // Set the vertices
    369         UINT vertexStride = 0;
    370         const UINT startIdx = 0;
    371         const ClearShader* shader = NULL;
    372         D3D11_MAPPED_SUBRESOURCE mappedResource;
    373         HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    374         if (FAILED(result))
    375         {
    376             return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result);
    377         }
    378 
    379         const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL;
    380         switch (clearParams.colorClearType)
    381         {
    382           case GL_FLOAT:
    383             ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData);
    384             vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>);
    385             shader = &mFloatClearShader;
    386             break;
    387 
    388           case GL_UNSIGNED_INT:
    389             ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData);
    390             vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>);
    391             shader = &mUintClearShader;
    392             break;
    393 
    394           case GL_INT:
    395             ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData);
    396             vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>);
    397             shader = &mIntClearShader;
    398             break;
    399 
    400           default:
    401             UNREACHABLE();
    402             break;
    403         }
    404 
    405         deviceContext->Unmap(mVertexBuffer, 0);
    406 
    407         // Set the viewport to be the same size as the framebuffer
    408         D3D11_VIEWPORT viewport;
    409         viewport.TopLeftX = 0;
    410         viewport.TopLeftY = 0;
    411         viewport.Width = framebufferSize.width;
    412         viewport.Height = framebufferSize.height;
    413         viewport.MinDepth = 0;
    414         viewport.MaxDepth = 1;
    415         deviceContext->RSSetViewports(1, &viewport);
    416 
    417         // Apply state
    418         deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
    419         deviceContext->OMSetDepthStencilState(dsState, stencilClear);
    420         deviceContext->RSSetState(mRasterizerState);
    421 
    422         // Apply shaders
    423         deviceContext->IASetInputLayout(shader->inputLayout);
    424         deviceContext->VSSetShader(shader->vertexShader, NULL, 0);
    425         deviceContext->PSSetShader(shader->pixelShader, NULL, 0);
    426         deviceContext->GSSetShader(NULL, NULL, 0);
    427 
    428         // Apply vertex buffer
    429         deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx);
    430         deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
    431 
    432         // Apply render targets
    433         deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv);
    434 
    435         // Draw the clear quad
    436         deviceContext->Draw(4, 0);
    437 
    438         // Clean up
    439         mRenderer->markAllStateDirty();
    440     }
    441 
    442     return gl::Error(GL_NO_ERROR);
    443 }
    444 
    445 ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts)
    446 {
    447     ClearBlendInfo blendKey = { 0 };
    448     for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
    449     {
    450         if (i < rts.size())
    451         {
    452             RenderTarget11 *rt = rts[i].renderTarget;
    453             const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat());
    454 
    455             blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits   > 0);
    456             blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0);
    457             blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits  > 0);
    458             blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0);
    459         }
    460         else
    461         {
    462             blendKey.maskChannels[i][0] = false;
    463             blendKey.maskChannels[i][1] = false;
    464             blendKey.maskChannels[i][2] = false;
    465             blendKey.maskChannels[i][3] = false;
    466         }
    467     }
    468 
    469     ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey);
    470     if (i != mClearBlendStates.end())
    471     {
    472         return i->second;
    473     }
    474     else
    475     {
    476         D3D11_BLEND_DESC blendDesc = { 0 };
    477         blendDesc.AlphaToCoverageEnable = FALSE;
    478         blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE;
    479 
    480         for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
    481         {
    482             blendDesc.RenderTarget[i].BlendEnable = FALSE;
    483             blendDesc.RenderTarget[i].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[i][0],
    484                                                                                          blendKey.maskChannels[i][1],
    485                                                                                          blendKey.maskChannels[i][2],
    486                                                                                          blendKey.maskChannels[i][3]);
    487         }
    488 
    489         ID3D11Device *device = mRenderer->getDevice();
    490         ID3D11BlendState* blendState = NULL;
    491         HRESULT result = device->CreateBlendState(&blendDesc, &blendState);
    492         if (FAILED(result) || !blendState)
    493         {
    494             ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
    495             return NULL;
    496         }
    497 
    498         mClearBlendStates[blendKey] = blendState;
    499 
    500         return blendState;
    501     }
    502 }
    503 
    504 ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::ClearParameters &clearParams)
    505 {
    506     ClearDepthStencilInfo dsKey = { 0 };
    507     dsKey.clearDepth = clearParams.clearDepth;
    508     dsKey.clearStencil = clearParams.clearStencil;
    509     dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF;
    510 
    511     ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey);
    512     if (i != mClearDepthStencilStates.end())
    513     {
    514         return i->second;
    515     }
    516     else
    517     {
    518         D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 };
    519         dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE;
    520         dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
    521         dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
    522         dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE;
    523         dsDesc.StencilReadMask = 0;
    524         dsDesc.StencilWriteMask = dsKey.stencilWriteMask;
    525         dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
    526         dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
    527         dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
    528         dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    529         dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
    530         dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
    531         dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
    532         dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    533 
    534         ID3D11Device *device = mRenderer->getDevice();
    535         ID3D11DepthStencilState* dsState = NULL;
    536         HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState);
    537         if (FAILED(result) || !dsState)
    538         {
    539             ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
    540             return NULL;
    541         }
    542 
    543         mClearDepthStencilStates[dsKey] = dsState;
    544 
    545         return dsState;
    546     }
    547 }
    548 
    549 }
    550