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
27namespace rx
28{
29
30template <typename T>
31static 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
56template <unsigned int vsSize, unsigned int psSize>
57Clear11::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
81Clear11::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
121Clear11::~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
151gl::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
445ID3D11BlendState *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
504ID3D11DepthStencilState *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