17ec681f3Smrg/**************************************************************************
27ec681f3Smrg *
37ec681f3Smrg * Copyright 2012-2021 VMware, Inc.
47ec681f3Smrg * All Rights Reserved.
57ec681f3Smrg *
67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77ec681f3Smrg * copy of this software and associated documentation files (the
87ec681f3Smrg * "Software"), to deal in the Software without restriction, including
97ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish,
107ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to
117ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to
127ec681f3Smrg * the following conditions:
137ec681f3Smrg *
147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
177ec681f3Smrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
187ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
197ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
207ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
217ec681f3Smrg *
227ec681f3Smrg * The above copyright notice and this permission notice (including the
237ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions
247ec681f3Smrg * of the Software.
257ec681f3Smrg *
267ec681f3Smrg **************************************************************************/
277ec681f3Smrg
287ec681f3Smrg/*
297ec681f3Smrg * OutputMerger.cpp --
307ec681f3Smrg *    Functions that manipulate the output merger state.
317ec681f3Smrg */
327ec681f3Smrg
337ec681f3Smrg
347ec681f3Smrg#include "OutputMerger.h"
357ec681f3Smrg#include "State.h"
367ec681f3Smrg
377ec681f3Smrg#include "Debug.h"
387ec681f3Smrg#include "Format.h"
397ec681f3Smrg
407ec681f3Smrg#include "util/u_framebuffer.h"
417ec681f3Smrg#include "util/format/u_format.h"
427ec681f3Smrg
437ec681f3Smrg
447ec681f3Smrg/*
457ec681f3Smrg * ----------------------------------------------------------------------
467ec681f3Smrg *
477ec681f3Smrg * CalcPrivateRenderTargetViewSize --
487ec681f3Smrg *
497ec681f3Smrg *    The CalcPrivateRenderTargetViewSize function determines the size
507ec681f3Smrg *    of the user-mode display driver's private region of memory
517ec681f3Smrg *    (that is, the size of internal driver structures, not the size
527ec681f3Smrg *    of the resource video memory) for a render target view.
537ec681f3Smrg *
547ec681f3Smrg * ----------------------------------------------------------------------
557ec681f3Smrg */
567ec681f3Smrg
577ec681f3Smrg
587ec681f3SmrgSIZE_T APIENTRY
597ec681f3SmrgCalcPrivateRenderTargetViewSize(
607ec681f3Smrg   D3D10DDI_HDEVICE hDevice,                                               // IN
617ec681f3Smrg   __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView) // IN
627ec681f3Smrg{
637ec681f3Smrg   return sizeof(RenderTargetView);
647ec681f3Smrg}
657ec681f3Smrg
667ec681f3Smrg
677ec681f3Smrg/*
687ec681f3Smrg * ----------------------------------------------------------------------
697ec681f3Smrg *
707ec681f3Smrg * CreateRenderTargetView --
717ec681f3Smrg *
727ec681f3Smrg *    The CreateRenderTargetView function creates a render target view.
737ec681f3Smrg *
747ec681f3Smrg * ----------------------------------------------------------------------
757ec681f3Smrg */
767ec681f3Smrg
777ec681f3Smrgvoid APIENTRY
787ec681f3SmrgCreateRenderTargetView(
797ec681f3Smrg   D3D10DDI_HDEVICE hDevice,                                               // IN
807ec681f3Smrg   __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView, // IN
817ec681f3Smrg   D3D10DDI_HRENDERTARGETVIEW hRenderTargetView,                           // IN
827ec681f3Smrg   D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView)                       // IN
837ec681f3Smrg{
847ec681f3Smrg   LOG_ENTRYPOINT();
857ec681f3Smrg
867ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
877ec681f3Smrg   struct pipe_resource *resource = CastPipeResource(pCreateRenderTargetView->hDrvResource);
887ec681f3Smrg   RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);
897ec681f3Smrg
907ec681f3Smrg   struct pipe_surface desc;
917ec681f3Smrg
927ec681f3Smrg   memset(&desc, 0, sizeof desc);
937ec681f3Smrg   desc.format = FormatTranslate(pCreateRenderTargetView->Format, FALSE);
947ec681f3Smrg
957ec681f3Smrg   switch (pCreateRenderTargetView->ResourceDimension) {
967ec681f3Smrg   case D3D10DDIRESOURCE_BUFFER:
977ec681f3Smrg      desc.u.buf.first_element = pCreateRenderTargetView->Buffer.FirstElement;
987ec681f3Smrg      desc.u.buf.last_element = pCreateRenderTargetView->Buffer.NumElements - 1 +
997ec681f3Smrg                                   desc.u.buf.first_element;
1007ec681f3Smrg      break;
1017ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE1D:
1027ec681f3Smrg      ASSERT(pCreateRenderTargetView->Tex1D.ArraySize != (UINT)-1);
1037ec681f3Smrg      desc.u.tex.level = pCreateRenderTargetView->Tex1D.MipSlice;
1047ec681f3Smrg      desc.u.tex.first_layer = pCreateRenderTargetView->Tex1D.FirstArraySlice;
1057ec681f3Smrg      desc.u.tex.last_layer = pCreateRenderTargetView->Tex1D.ArraySize - 1 +
1067ec681f3Smrg                                 desc.u.tex.first_layer;
1077ec681f3Smrg      break;
1087ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE2D:
1097ec681f3Smrg      ASSERT(pCreateRenderTargetView->Tex2D.ArraySize != (UINT)-1);
1107ec681f3Smrg      desc.u.tex.level = pCreateRenderTargetView->Tex2D.MipSlice;
1117ec681f3Smrg      desc.u.tex.first_layer = pCreateRenderTargetView->Tex2D.FirstArraySlice;
1127ec681f3Smrg      desc.u.tex.last_layer = pCreateRenderTargetView->Tex2D.ArraySize - 1 +
1137ec681f3Smrg                                 desc.u.tex.first_layer;
1147ec681f3Smrg      break;
1157ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE3D:
1167ec681f3Smrg      desc.u.tex.level = pCreateRenderTargetView->Tex3D.MipSlice;
1177ec681f3Smrg      desc.u.tex.first_layer = pCreateRenderTargetView->Tex3D.FirstW;
1187ec681f3Smrg      desc.u.tex.last_layer = pCreateRenderTargetView->Tex3D.WSize - 1 +
1197ec681f3Smrg                                 desc.u.tex.first_layer;
1207ec681f3Smrg      break;
1217ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURECUBE:
1227ec681f3Smrg      ASSERT(pCreateRenderTargetView->TexCube.ArraySize != (UINT)-1);
1237ec681f3Smrg      desc.u.tex.level = pCreateRenderTargetView->TexCube.MipSlice;
1247ec681f3Smrg      desc.u.tex.first_layer = pCreateRenderTargetView->TexCube.FirstArraySlice;
1257ec681f3Smrg      desc.u.tex.last_layer = pCreateRenderTargetView->TexCube.ArraySize - 1 +
1267ec681f3Smrg                                 desc.u.tex.first_layer;;
1277ec681f3Smrg      break;
1287ec681f3Smrg   default:
1297ec681f3Smrg      ASSERT(0);
1307ec681f3Smrg      return;
1317ec681f3Smrg   }
1327ec681f3Smrg
1337ec681f3Smrg   pRTView->surface = pipe->create_surface(pipe, resource, &desc);
1347ec681f3Smrg   assert(pRTView->surface);
1357ec681f3Smrg}
1367ec681f3Smrg
1377ec681f3Smrg
1387ec681f3Smrg/*
1397ec681f3Smrg * ----------------------------------------------------------------------
1407ec681f3Smrg *
1417ec681f3Smrg * DestroyRenderTargetView --
1427ec681f3Smrg *
1437ec681f3Smrg *    The DestroyRenderTargetView function destroys the specified
1447ec681f3Smrg *    render target view object. The render target view object can
1457ec681f3Smrg *    be destoyed only if it is not currently bound to a display device.
1467ec681f3Smrg *
1477ec681f3Smrg * ----------------------------------------------------------------------
1487ec681f3Smrg */
1497ec681f3Smrg
1507ec681f3Smrgvoid APIENTRY
1517ec681f3SmrgDestroyRenderTargetView(D3D10DDI_HDEVICE hDevice,                       // IN
1527ec681f3Smrg                        D3D10DDI_HRENDERTARGETVIEW hRenderTargetView)   // IN
1537ec681f3Smrg{
1547ec681f3Smrg   LOG_ENTRYPOINT();
1557ec681f3Smrg
1567ec681f3Smrg   RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);
1577ec681f3Smrg
1587ec681f3Smrg   pipe_surface_reference(&pRTView->surface, NULL);
1597ec681f3Smrg}
1607ec681f3Smrg
1617ec681f3Smrg
1627ec681f3Smrg/*
1637ec681f3Smrg * ----------------------------------------------------------------------
1647ec681f3Smrg *
1657ec681f3Smrg * ClearRenderTargetView --
1667ec681f3Smrg *
1677ec681f3Smrg *    The ClearRenderTargetView function clears the specified
1687ec681f3Smrg *    render target view by setting it to a constant value.
1697ec681f3Smrg *
1707ec681f3Smrg * ----------------------------------------------------------------------
1717ec681f3Smrg */
1727ec681f3Smrg
1737ec681f3Smrgvoid APIENTRY
1747ec681f3SmrgClearRenderTargetView(D3D10DDI_HDEVICE hDevice,                      // IN
1757ec681f3Smrg                      D3D10DDI_HRENDERTARGETVIEW hRenderTargetView,  // IN
1767ec681f3Smrg                      FLOAT pColorRGBA[4])                           // IN
1777ec681f3Smrg{
1787ec681f3Smrg   LOG_ENTRYPOINT();
1797ec681f3Smrg
1807ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
1817ec681f3Smrg   struct pipe_surface *surface = CastPipeRenderTargetView(hRenderTargetView);
1827ec681f3Smrg   union pipe_color_union clear_color;
1837ec681f3Smrg
1847ec681f3Smrg   /*
1857ec681f3Smrg    * DX10 always uses float clear color but gallium does not.
1867ec681f3Smrg    * Conversion should just be ordinary conversion. Actual clamping will
1877ec681f3Smrg    * be done later but need to make sure values exceeding int/uint range
1887ec681f3Smrg    * are handled correctly.
1897ec681f3Smrg    */
1907ec681f3Smrg   if (util_format_is_pure_integer(surface->format)) {
1917ec681f3Smrg      if (util_format_is_pure_sint(surface->format)) {
1927ec681f3Smrg         unsigned i;
1937ec681f3Smrg         /* If only MIN_INT/UINT32 in c++ code would work... */
1947ec681f3Smrg         int min_int32 = 0x80000000;
1957ec681f3Smrg         int max_int32 = 0x7fffffff;
1967ec681f3Smrg         for (i = 0; i < 4; i++) {
1977ec681f3Smrg            float value = pColorRGBA[i];
1987ec681f3Smrg            /* This is an expanded clamp to handle NaN and integer conversion. */
1997ec681f3Smrg            if (util_is_nan(value)) {
2007ec681f3Smrg               clear_color.i[i] = 0;
2017ec681f3Smrg            } else if (value <= (float)min_int32) {
2027ec681f3Smrg               clear_color.i[i] = min_int32;
2037ec681f3Smrg            } else if (value >= (float)max_int32) {
2047ec681f3Smrg               clear_color.i[i] = max_int32;
2057ec681f3Smrg            } else {
2067ec681f3Smrg               clear_color.i[i] = value;
2077ec681f3Smrg            }
2087ec681f3Smrg         }
2097ec681f3Smrg      }
2107ec681f3Smrg      else {
2117ec681f3Smrg         assert(util_format_is_pure_uint(surface->format));
2127ec681f3Smrg         unsigned i;
2137ec681f3Smrg         unsigned max_uint32 = 0xffffffffU;
2147ec681f3Smrg         for (i = 0; i < 4; i++) {
2157ec681f3Smrg            float value = pColorRGBA[i];
2167ec681f3Smrg            /* This is an expanded clamp to handle NaN and integer conversion. */
2177ec681f3Smrg            if (!(value >= 0.0f)) {
2187ec681f3Smrg               /* Handles NaN. */
2197ec681f3Smrg               clear_color.ui[i] = 0;
2207ec681f3Smrg            } else if (value >= (float)max_uint32) {
2217ec681f3Smrg               clear_color.ui[i] = max_uint32;
2227ec681f3Smrg            } else {
2237ec681f3Smrg               clear_color.ui[i] = value;
2247ec681f3Smrg            }
2257ec681f3Smrg         }
2267ec681f3Smrg      }
2277ec681f3Smrg   }
2287ec681f3Smrg   else {
2297ec681f3Smrg      clear_color.f[0] = pColorRGBA[0];
2307ec681f3Smrg      clear_color.f[1] = pColorRGBA[1];
2317ec681f3Smrg      clear_color.f[2] = pColorRGBA[2];
2327ec681f3Smrg      clear_color.f[3] = pColorRGBA[3];
2337ec681f3Smrg   }
2347ec681f3Smrg
2357ec681f3Smrg   pipe->clear_render_target(pipe,
2367ec681f3Smrg                             surface,
2377ec681f3Smrg                             &clear_color,
2387ec681f3Smrg                             0, 0,
2397ec681f3Smrg                             surface->width,
2407ec681f3Smrg                             surface->height,
2417ec681f3Smrg                             TRUE);
2427ec681f3Smrg}
2437ec681f3Smrg
2447ec681f3Smrg
2457ec681f3Smrg/*
2467ec681f3Smrg * ----------------------------------------------------------------------
2477ec681f3Smrg *
2487ec681f3Smrg * CalcPrivateDepthStencilViewSize --
2497ec681f3Smrg *
2507ec681f3Smrg *    The CalcPrivateDepthStencilViewSize function determines the size
2517ec681f3Smrg *    of the user-mode display driver's private region of memory
2527ec681f3Smrg *    (that is, the size of internal driver structures, not the size
2537ec681f3Smrg *    of the resource video memory) for a depth stencil view.
2547ec681f3Smrg *
2557ec681f3Smrg * ----------------------------------------------------------------------
2567ec681f3Smrg */
2577ec681f3Smrg
2587ec681f3SmrgSIZE_T APIENTRY
2597ec681f3SmrgCalcPrivateDepthStencilViewSize(
2607ec681f3Smrg   D3D10DDI_HDEVICE hDevice,                                               // IN
2617ec681f3Smrg   __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView) // IN
2627ec681f3Smrg{
2637ec681f3Smrg   return sizeof(DepthStencilView);
2647ec681f3Smrg}
2657ec681f3Smrg
2667ec681f3Smrg
2677ec681f3Smrg/*
2687ec681f3Smrg * ----------------------------------------------------------------------
2697ec681f3Smrg *
2707ec681f3Smrg * CreateDepthStencilView --
2717ec681f3Smrg *
2727ec681f3Smrg *    The CreateDepthStencilView function creates a depth stencil view.
2737ec681f3Smrg *
2747ec681f3Smrg * ----------------------------------------------------------------------
2757ec681f3Smrg */
2767ec681f3Smrg
2777ec681f3Smrgvoid APIENTRY
2787ec681f3SmrgCreateDepthStencilView(
2797ec681f3Smrg   D3D10DDI_HDEVICE hDevice,                                               // IN
2807ec681f3Smrg   __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView, // IN
2817ec681f3Smrg   D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView,                           // IN
2827ec681f3Smrg   D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView)                       // IN
2837ec681f3Smrg{
2847ec681f3Smrg   LOG_ENTRYPOINT();
2857ec681f3Smrg
2867ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
2877ec681f3Smrg   struct pipe_resource *resource = CastPipeResource(pCreateDepthStencilView->hDrvResource);
2887ec681f3Smrg   DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);
2897ec681f3Smrg
2907ec681f3Smrg   struct pipe_surface desc;
2917ec681f3Smrg
2927ec681f3Smrg   memset(&desc, 0, sizeof desc);
2937ec681f3Smrg   desc.format = FormatTranslate(pCreateDepthStencilView->Format, TRUE);
2947ec681f3Smrg
2957ec681f3Smrg   switch (pCreateDepthStencilView->ResourceDimension) {
2967ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE1D:
2977ec681f3Smrg      ASSERT(pCreateDepthStencilView->Tex1D.ArraySize != (UINT)-1);
2987ec681f3Smrg      desc.u.tex.level = pCreateDepthStencilView->Tex1D.MipSlice;
2997ec681f3Smrg      desc.u.tex.first_layer = pCreateDepthStencilView->Tex1D.FirstArraySlice;
3007ec681f3Smrg      desc.u.tex.last_layer = pCreateDepthStencilView->Tex1D.ArraySize - 1 +
3017ec681f3Smrg                                 desc.u.tex.first_layer;
3027ec681f3Smrg      break;
3037ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE2D:
3047ec681f3Smrg      ASSERT(pCreateDepthStencilView->Tex2D.ArraySize != (UINT)-1);
3057ec681f3Smrg      desc.u.tex.level = pCreateDepthStencilView->Tex2D.MipSlice;
3067ec681f3Smrg      desc.u.tex.first_layer = pCreateDepthStencilView->Tex2D.FirstArraySlice;
3077ec681f3Smrg      desc.u.tex.last_layer = pCreateDepthStencilView->Tex2D.ArraySize - 1 +
3087ec681f3Smrg                                 desc.u.tex.first_layer;
3097ec681f3Smrg      break;
3107ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURECUBE:
3117ec681f3Smrg      ASSERT(pCreateDepthStencilView->TexCube.ArraySize != (UINT)-1);
3127ec681f3Smrg      desc.u.tex.level = pCreateDepthStencilView->TexCube.MipSlice;
3137ec681f3Smrg      desc.u.tex.first_layer = pCreateDepthStencilView->TexCube.FirstArraySlice;
3147ec681f3Smrg      desc.u.tex.last_layer = pCreateDepthStencilView->TexCube.ArraySize - 1 +
3157ec681f3Smrg                                 desc.u.tex.first_layer;
3167ec681f3Smrg      break;
3177ec681f3Smrg   default:
3187ec681f3Smrg      ASSERT(0);
3197ec681f3Smrg      return;
3207ec681f3Smrg   }
3217ec681f3Smrg
3227ec681f3Smrg   pDSView->surface = pipe->create_surface(pipe, resource, &desc);
3237ec681f3Smrg   assert(pDSView->surface);
3247ec681f3Smrg}
3257ec681f3Smrg
3267ec681f3Smrg
3277ec681f3Smrg/*
3287ec681f3Smrg * ----------------------------------------------------------------------
3297ec681f3Smrg *
3307ec681f3Smrg * DestroyDepthStencilView --
3317ec681f3Smrg *
3327ec681f3Smrg *    The DestroyDepthStencilView function destroys the specified
3337ec681f3Smrg *    depth stencil view object. The depth stencil view object can
3347ec681f3Smrg *    be destoyed only if it is not currently bound to a display device.
3357ec681f3Smrg *
3367ec681f3Smrg * ----------------------------------------------------------------------
3377ec681f3Smrg */
3387ec681f3Smrg
3397ec681f3Smrgvoid APIENTRY
3407ec681f3SmrgDestroyDepthStencilView(D3D10DDI_HDEVICE hDevice,                       // IN
3417ec681f3Smrg                        D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView)   // IN
3427ec681f3Smrg{
3437ec681f3Smrg   LOG_ENTRYPOINT();
3447ec681f3Smrg
3457ec681f3Smrg   DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);
3467ec681f3Smrg
3477ec681f3Smrg   pipe_surface_reference(&pDSView->surface, NULL);
3487ec681f3Smrg}
3497ec681f3Smrg
3507ec681f3Smrg
3517ec681f3Smrg/*
3527ec681f3Smrg * ----------------------------------------------------------------------
3537ec681f3Smrg *
3547ec681f3Smrg * ClearDepthStencilView --
3557ec681f3Smrg *
3567ec681f3Smrg *    The ClearDepthStencilView function clears the specified
3577ec681f3Smrg *    currently bound depth-stencil view.
3587ec681f3Smrg *
3597ec681f3Smrg * ----------------------------------------------------------------------
3607ec681f3Smrg */
3617ec681f3Smrg
3627ec681f3Smrgvoid APIENTRY
3637ec681f3SmrgClearDepthStencilView(D3D10DDI_HDEVICE hDevice,                      // IN
3647ec681f3Smrg                      D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView,  // IN
3657ec681f3Smrg                      UINT Flags,                                    // IN
3667ec681f3Smrg                      FLOAT Depth,                                   // IN
3677ec681f3Smrg                      UINT8 Stencil)                                 // IN
3687ec681f3Smrg{
3697ec681f3Smrg   LOG_ENTRYPOINT();
3707ec681f3Smrg
3717ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
3727ec681f3Smrg   struct pipe_surface *surface = CastPipeDepthStencilView(hDepthStencilView);
3737ec681f3Smrg
3747ec681f3Smrg   unsigned flags = 0;
3757ec681f3Smrg   if (Flags & D3D10_DDI_CLEAR_DEPTH) {
3767ec681f3Smrg      flags |= PIPE_CLEAR_DEPTH;
3777ec681f3Smrg   }
3787ec681f3Smrg   if (Flags & D3D10_DDI_CLEAR_STENCIL) {
3797ec681f3Smrg      flags |= PIPE_CLEAR_STENCIL;
3807ec681f3Smrg   }
3817ec681f3Smrg
3827ec681f3Smrg   pipe->clear_depth_stencil(pipe,
3837ec681f3Smrg                             surface,
3847ec681f3Smrg                             flags,
3857ec681f3Smrg                             Depth,
3867ec681f3Smrg                             Stencil,
3877ec681f3Smrg                             0, 0,
3887ec681f3Smrg                             surface->width,
3897ec681f3Smrg                             surface->height,
3907ec681f3Smrg                             TRUE);
3917ec681f3Smrg}
3927ec681f3Smrg
3937ec681f3Smrg
3947ec681f3Smrg/*
3957ec681f3Smrg * ----------------------------------------------------------------------
3967ec681f3Smrg *
3977ec681f3Smrg * CalcPrivateBlendStateSize --
3987ec681f3Smrg *
3997ec681f3Smrg *    The CalcPrivateBlendStateSize function determines the size of
4007ec681f3Smrg *    the user-mode display driver's private region of memory (that
4017ec681f3Smrg *    is, the size of internal driver structures, not the size of
4027ec681f3Smrg *    the resource video memory) for a blend state.
4037ec681f3Smrg *
4047ec681f3Smrg * ----------------------------------------------------------------------
4057ec681f3Smrg */
4067ec681f3Smrg
4077ec681f3SmrgSIZE_T APIENTRY
4087ec681f3SmrgCalcPrivateBlendStateSize(D3D10DDI_HDEVICE hDevice,                     // IN
4097ec681f3Smrg                          __in const D3D10_DDI_BLEND_DESC *pBlendDesc)  // IN
4107ec681f3Smrg{
4117ec681f3Smrg   return sizeof(BlendState);
4127ec681f3Smrg}
4137ec681f3Smrg
4147ec681f3Smrg
4157ec681f3Smrg/*
4167ec681f3Smrg * ----------------------------------------------------------------------
4177ec681f3Smrg *
4187ec681f3Smrg * CalcPrivateBlendStateSize1 --
4197ec681f3Smrg *
4207ec681f3Smrg *    The CalcPrivateBlendStateSize function determines the size of
4217ec681f3Smrg *    the user-mode display driver's private region of memory (that
4227ec681f3Smrg *    is, the size of internal driver structures, not the size of
4237ec681f3Smrg *    the resource video memory) for a blend state.
4247ec681f3Smrg *
4257ec681f3Smrg * ----------------------------------------------------------------------
4267ec681f3Smrg */
4277ec681f3Smrg
4287ec681f3SmrgSIZE_T APIENTRY
4297ec681f3SmrgCalcPrivateBlendStateSize1(D3D10DDI_HDEVICE hDevice,                     // IN
4307ec681f3Smrg                           __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc)  // IN
4317ec681f3Smrg{
4327ec681f3Smrg   return sizeof(BlendState);
4337ec681f3Smrg}
4347ec681f3Smrg
4357ec681f3Smrg
4367ec681f3Smrg/*
4377ec681f3Smrg * ----------------------------------------------------------------------
4387ec681f3Smrg *
4397ec681f3Smrg * translateBlend --
4407ec681f3Smrg *
4417ec681f3Smrg *   Translate blend function from svga3d to gallium representation.
4427ec681f3Smrg *
4437ec681f3Smrg * ----------------------------------------------------------------------
4447ec681f3Smrg */
4457ec681f3Smrgstatic uint
4467ec681f3SmrgtranslateBlendOp(D3D10_DDI_BLEND_OP op)
4477ec681f3Smrg{
4487ec681f3Smrg   switch (op) {
4497ec681f3Smrg   case D3D10_DDI_BLEND_OP_ADD:
4507ec681f3Smrg      return PIPE_BLEND_ADD;
4517ec681f3Smrg   case D3D10_DDI_BLEND_OP_SUBTRACT:
4527ec681f3Smrg      return PIPE_BLEND_SUBTRACT;
4537ec681f3Smrg   case D3D10_DDI_BLEND_OP_REV_SUBTRACT:
4547ec681f3Smrg      return PIPE_BLEND_REVERSE_SUBTRACT;
4557ec681f3Smrg   case D3D10_DDI_BLEND_OP_MIN:
4567ec681f3Smrg      return PIPE_BLEND_MIN;
4577ec681f3Smrg   case D3D10_DDI_BLEND_OP_MAX:
4587ec681f3Smrg      return PIPE_BLEND_MAX;
4597ec681f3Smrg   default:
4607ec681f3Smrg      assert(0);
4617ec681f3Smrg      return PIPE_BLEND_ADD;
4627ec681f3Smrg   }
4637ec681f3Smrg}
4647ec681f3Smrg
4657ec681f3Smrg
4667ec681f3Smrg/*
4677ec681f3Smrg * ----------------------------------------------------------------------
4687ec681f3Smrg *
4697ec681f3Smrg * translateBlend --
4707ec681f3Smrg *
4717ec681f3Smrg *   Translate blend factor from svga3d to gallium representation.
4727ec681f3Smrg *
4737ec681f3Smrg * ----------------------------------------------------------------------
4747ec681f3Smrg */
4757ec681f3Smrgstatic uint
4767ec681f3SmrgtranslateBlend(Device *pDevice,
4777ec681f3Smrg               D3D10_DDI_BLEND blend)
4787ec681f3Smrg{
4797ec681f3Smrg   if (!pDevice->max_dual_source_render_targets) {
4807ec681f3Smrg      switch (blend) {
4817ec681f3Smrg      case D3D10_DDI_BLEND_SRC1_COLOR:
4827ec681f3Smrg      case D3D10_DDI_BLEND_SRC1_ALPHA:
4837ec681f3Smrg         LOG_UNSUPPORTED(TRUE);
4847ec681f3Smrg         return D3D10_DDI_BLEND_ZERO;
4857ec681f3Smrg      case D3D10_DDI_BLEND_INV_SRC1_COLOR:
4867ec681f3Smrg      case D3D10_DDI_BLEND_INV_SRC1_ALPHA:
4877ec681f3Smrg         LOG_UNSUPPORTED(TRUE);
4887ec681f3Smrg         return D3D10_DDI_BLEND_ONE;
4897ec681f3Smrg      default:
4907ec681f3Smrg         break;
4917ec681f3Smrg      }
4927ec681f3Smrg   }
4937ec681f3Smrg
4947ec681f3Smrg   switch (blend) {
4957ec681f3Smrg   case D3D10_DDI_BLEND_ZERO:
4967ec681f3Smrg      return PIPE_BLENDFACTOR_ZERO;
4977ec681f3Smrg   case D3D10_DDI_BLEND_ONE:
4987ec681f3Smrg      return PIPE_BLENDFACTOR_ONE;
4997ec681f3Smrg   case D3D10_DDI_BLEND_SRC_COLOR:
5007ec681f3Smrg      return PIPE_BLENDFACTOR_SRC_COLOR;
5017ec681f3Smrg   case D3D10_DDI_BLEND_INV_SRC_COLOR:
5027ec681f3Smrg      return PIPE_BLENDFACTOR_INV_SRC_COLOR;
5037ec681f3Smrg   case D3D10_DDI_BLEND_SRC_ALPHA:
5047ec681f3Smrg      return PIPE_BLENDFACTOR_SRC_ALPHA;
5057ec681f3Smrg   case D3D10_DDI_BLEND_INV_SRC_ALPHA:
5067ec681f3Smrg      return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
5077ec681f3Smrg   case D3D10_DDI_BLEND_DEST_ALPHA:
5087ec681f3Smrg      return PIPE_BLENDFACTOR_DST_ALPHA;
5097ec681f3Smrg   case D3D10_DDI_BLEND_INV_DEST_ALPHA:
5107ec681f3Smrg      return PIPE_BLENDFACTOR_INV_DST_ALPHA;
5117ec681f3Smrg   case D3D10_DDI_BLEND_DEST_COLOR:
5127ec681f3Smrg      return PIPE_BLENDFACTOR_DST_COLOR;
5137ec681f3Smrg   case D3D10_DDI_BLEND_INV_DEST_COLOR:
5147ec681f3Smrg      return PIPE_BLENDFACTOR_INV_DST_COLOR;
5157ec681f3Smrg   case D3D10_DDI_BLEND_SRC_ALPHASAT:
5167ec681f3Smrg      return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
5177ec681f3Smrg   case D3D10_DDI_BLEND_BLEND_FACTOR:
5187ec681f3Smrg      return PIPE_BLENDFACTOR_CONST_COLOR;
5197ec681f3Smrg   case D3D10_DDI_BLEND_INVBLEND_FACTOR:
5207ec681f3Smrg      return PIPE_BLENDFACTOR_INV_CONST_COLOR;
5217ec681f3Smrg   case D3D10_DDI_BLEND_SRC1_COLOR:
5227ec681f3Smrg      return PIPE_BLENDFACTOR_SRC1_COLOR;
5237ec681f3Smrg   case D3D10_DDI_BLEND_INV_SRC1_COLOR:
5247ec681f3Smrg      return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
5257ec681f3Smrg   case D3D10_DDI_BLEND_SRC1_ALPHA:
5267ec681f3Smrg      return PIPE_BLENDFACTOR_SRC1_ALPHA;
5277ec681f3Smrg   case D3D10_DDI_BLEND_INV_SRC1_ALPHA:
5287ec681f3Smrg      return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
5297ec681f3Smrg   default:
5307ec681f3Smrg      assert(0);
5317ec681f3Smrg      return PIPE_BLENDFACTOR_ONE;
5327ec681f3Smrg   }
5337ec681f3Smrg}
5347ec681f3Smrg
5357ec681f3Smrg
5367ec681f3Smrg/*
5377ec681f3Smrg * ----------------------------------------------------------------------
5387ec681f3Smrg *
5397ec681f3Smrg * CreateBlendState --
5407ec681f3Smrg *
5417ec681f3Smrg *    The CreateBlendState function creates a blend state.
5427ec681f3Smrg *
5437ec681f3Smrg * ----------------------------------------------------------------------
5447ec681f3Smrg */
5457ec681f3Smrg
5467ec681f3Smrgvoid APIENTRY
5477ec681f3SmrgCreateBlendState(D3D10DDI_HDEVICE hDevice,                     // IN
5487ec681f3Smrg                 __in const D3D10_DDI_BLEND_DESC *pBlendDesc,  // IN
5497ec681f3Smrg                 D3D10DDI_HBLENDSTATE hBlendState,             // IN
5507ec681f3Smrg                 D3D10DDI_HRTBLENDSTATE hRTBlendState)         // IN
5517ec681f3Smrg{
5527ec681f3Smrg   unsigned i;
5537ec681f3Smrg
5547ec681f3Smrg   LOG_ENTRYPOINT();
5557ec681f3Smrg
5567ec681f3Smrg   Device *pDevice = CastDevice(hDevice);
5577ec681f3Smrg   struct pipe_context *pipe = pDevice->pipe;
5587ec681f3Smrg   BlendState *pBlendState = CastBlendState(hBlendState);
5597ec681f3Smrg
5607ec681f3Smrg   struct pipe_blend_state state;
5617ec681f3Smrg   memset(&state, 0, sizeof state);
5627ec681f3Smrg
5637ec681f3Smrg   for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
5647ec681f3Smrg      state.rt[i].blend_enable = pBlendDesc->BlendEnable[i];
5657ec681f3Smrg      state.rt[i].colormask = pBlendDesc->RenderTargetWriteMask[i];
5667ec681f3Smrg
5677ec681f3Smrg      if (pBlendDesc->BlendEnable[0] != pBlendDesc->BlendEnable[i] ||
5687ec681f3Smrg          pBlendDesc->RenderTargetWriteMask[0] != pBlendDesc->RenderTargetWriteMask[i]) {
5697ec681f3Smrg         state.independent_blend_enable = 1;
5707ec681f3Smrg      }
5717ec681f3Smrg   }
5727ec681f3Smrg
5737ec681f3Smrg   state.rt[0].rgb_func = translateBlendOp(pBlendDesc->BlendOp);
5747ec681f3Smrg   if (pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MIN ||
5757ec681f3Smrg       pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MAX) {
5767ec681f3Smrg      state.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
5777ec681f3Smrg      state.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
5787ec681f3Smrg   } else {
5797ec681f3Smrg      state.rt[0].rgb_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlend);
5807ec681f3Smrg      state.rt[0].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlend);
5817ec681f3Smrg   }
5827ec681f3Smrg
5837ec681f3Smrg   state.rt[0].alpha_func = translateBlendOp(pBlendDesc->BlendOpAlpha);
5847ec681f3Smrg   if (pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||
5857ec681f3Smrg       pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {
5867ec681f3Smrg      state.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
5877ec681f3Smrg      state.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
5887ec681f3Smrg   } else {
5897ec681f3Smrg      state.rt[0].alpha_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlendAlpha);
5907ec681f3Smrg      state.rt[0].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlendAlpha);
5917ec681f3Smrg   }
5927ec681f3Smrg
5937ec681f3Smrg   /*
5947ec681f3Smrg    * Propagate to all the other rendertargets
5957ec681f3Smrg    */
5967ec681f3Smrg   for (i = 1; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
5977ec681f3Smrg      state.rt[i].rgb_func = state.rt[0].rgb_func;
5987ec681f3Smrg      state.rt[i].rgb_src_factor = state.rt[0].rgb_src_factor;
5997ec681f3Smrg      state.rt[i].rgb_dst_factor = state.rt[0].rgb_dst_factor;
6007ec681f3Smrg      state.rt[i].alpha_func = state.rt[0].alpha_func;
6017ec681f3Smrg      state.rt[i].alpha_src_factor = state.rt[0].alpha_src_factor;
6027ec681f3Smrg      state.rt[i].alpha_dst_factor = state.rt[0].alpha_dst_factor;
6037ec681f3Smrg   }
6047ec681f3Smrg
6057ec681f3Smrg   state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;
6067ec681f3Smrg
6077ec681f3Smrg   pBlendState->handle = pipe->create_blend_state(pipe, &state);
6087ec681f3Smrg}
6097ec681f3Smrg
6107ec681f3Smrg
6117ec681f3Smrg/*
6127ec681f3Smrg * ----------------------------------------------------------------------
6137ec681f3Smrg *
6147ec681f3Smrg * CreateBlendState1 --
6157ec681f3Smrg *
6167ec681f3Smrg *    The CreateBlendState function creates a blend state.
6177ec681f3Smrg *
6187ec681f3Smrg * ----------------------------------------------------------------------
6197ec681f3Smrg */
6207ec681f3Smrg
6217ec681f3Smrgvoid APIENTRY
6227ec681f3SmrgCreateBlendState1(D3D10DDI_HDEVICE hDevice,                     // IN
6237ec681f3Smrg                  __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc,  // IN
6247ec681f3Smrg                  D3D10DDI_HBLENDSTATE hBlendState,             // IN
6257ec681f3Smrg                  D3D10DDI_HRTBLENDSTATE hRTBlendState)         // IN
6267ec681f3Smrg{
6277ec681f3Smrg   unsigned i;
6287ec681f3Smrg
6297ec681f3Smrg   LOG_ENTRYPOINT();
6307ec681f3Smrg
6317ec681f3Smrg   Device *pDevice = CastDevice(hDevice);
6327ec681f3Smrg   struct pipe_context *pipe = pDevice->pipe;
6337ec681f3Smrg   BlendState *pBlendState = CastBlendState(hBlendState);
6347ec681f3Smrg
6357ec681f3Smrg   struct pipe_blend_state state;
6367ec681f3Smrg   memset(&state, 0, sizeof state);
6377ec681f3Smrg
6387ec681f3Smrg   state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;
6397ec681f3Smrg   state.independent_blend_enable = pBlendDesc->IndependentBlendEnable;
6407ec681f3Smrg
6417ec681f3Smrg   for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
6427ec681f3Smrg      state.rt[i].blend_enable = pBlendDesc->RenderTarget[i].BlendEnable;
6437ec681f3Smrg      state.rt[i].colormask = pBlendDesc->RenderTarget[i].RenderTargetWriteMask;
6447ec681f3Smrg
6457ec681f3Smrg      state.rt[i].rgb_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOp);
6467ec681f3Smrg      if (pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MIN ||
6477ec681f3Smrg          pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MAX) {
6487ec681f3Smrg         state.rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
6497ec681f3Smrg         state.rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
6507ec681f3Smrg      } else {
6517ec681f3Smrg         state.rt[i].rgb_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlend);
6527ec681f3Smrg         state.rt[i].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlend);
6537ec681f3Smrg      }
6547ec681f3Smrg
6557ec681f3Smrg      state.rt[i].alpha_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOpAlpha);
6567ec681f3Smrg      if (pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||
6577ec681f3Smrg          pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {
6587ec681f3Smrg         state.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
6597ec681f3Smrg         state.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
6607ec681f3Smrg      } else {
6617ec681f3Smrg         state.rt[i].alpha_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlendAlpha);
6627ec681f3Smrg         state.rt[i].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlendAlpha);
6637ec681f3Smrg      }
6647ec681f3Smrg   }
6657ec681f3Smrg
6667ec681f3Smrg   pBlendState->handle = pipe->create_blend_state(pipe, &state);
6677ec681f3Smrg}
6687ec681f3Smrg
6697ec681f3Smrg
6707ec681f3Smrg/*
6717ec681f3Smrg * ----------------------------------------------------------------------
6727ec681f3Smrg *
6737ec681f3Smrg * DestroyBlendState --
6747ec681f3Smrg *
6757ec681f3Smrg *    The DestroyBlendState function destroys the specified blend
6767ec681f3Smrg *    state object. The blend state object can be destoyed only if
6777ec681f3Smrg *    it is not currently bound to a display device.
6787ec681f3Smrg *
6797ec681f3Smrg * ----------------------------------------------------------------------
6807ec681f3Smrg */
6817ec681f3Smrg
6827ec681f3Smrgvoid APIENTRY
6837ec681f3SmrgDestroyBlendState(D3D10DDI_HDEVICE hDevice,           // IN
6847ec681f3Smrg                  D3D10DDI_HBLENDSTATE hBlendState)   // IN
6857ec681f3Smrg{
6867ec681f3Smrg   LOG_ENTRYPOINT();
6877ec681f3Smrg
6887ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
6897ec681f3Smrg   BlendState *pBlendState = CastBlendState(hBlendState);
6907ec681f3Smrg
6917ec681f3Smrg   pipe->delete_blend_state(pipe, pBlendState->handle);
6927ec681f3Smrg}
6937ec681f3Smrg
6947ec681f3Smrg
6957ec681f3Smrg/*
6967ec681f3Smrg * ----------------------------------------------------------------------
6977ec681f3Smrg *
6987ec681f3Smrg * SetBlendState --
6997ec681f3Smrg *
7007ec681f3Smrg *    The SetBlendState function sets a blend state.
7017ec681f3Smrg *
7027ec681f3Smrg * ----------------------------------------------------------------------
7037ec681f3Smrg */
7047ec681f3Smrg
7057ec681f3Smrgvoid APIENTRY
7067ec681f3SmrgSetBlendState(D3D10DDI_HDEVICE hDevice,      // IN
7077ec681f3Smrg              D3D10DDI_HBLENDSTATE hState,   // IN
7087ec681f3Smrg              const FLOAT pBlendFactor[4],   // IN
7097ec681f3Smrg              UINT SampleMask)               // IN
7107ec681f3Smrg{
7117ec681f3Smrg   LOG_ENTRYPOINT();
7127ec681f3Smrg
7137ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
7147ec681f3Smrg   void *state = CastPipeBlendState(hState);
7157ec681f3Smrg
7167ec681f3Smrg   pipe->bind_blend_state(pipe, state);
7177ec681f3Smrg
7187ec681f3Smrg   struct pipe_blend_color color;
7197ec681f3Smrg   color.color[0] = pBlendFactor[0];
7207ec681f3Smrg   color.color[1] = pBlendFactor[1];
7217ec681f3Smrg   color.color[2] = pBlendFactor[2];
7227ec681f3Smrg   color.color[3] = pBlendFactor[3];
7237ec681f3Smrg
7247ec681f3Smrg   pipe->set_blend_color(pipe, &color);
7257ec681f3Smrg
7267ec681f3Smrg   pipe->set_sample_mask(pipe, SampleMask);
7277ec681f3Smrg}
7287ec681f3Smrg
7297ec681f3Smrg
7307ec681f3Smrg/*
7317ec681f3Smrg * ----------------------------------------------------------------------
7327ec681f3Smrg *
7337ec681f3Smrg * SetRenderTargets --
7347ec681f3Smrg *
7357ec681f3Smrg *    Set the rendertargets.
7367ec681f3Smrg *
7377ec681f3Smrg * ----------------------------------------------------------------------
7387ec681f3Smrg */
7397ec681f3Smrg
7407ec681f3Smrgvoid APIENTRY
7417ec681f3SmrgSetRenderTargets(D3D10DDI_HDEVICE hDevice,                              // IN
7427ec681f3Smrg                 __in_ecount (NumViews)
7437ec681f3Smrg                  const D3D10DDI_HRENDERTARGETVIEW *phRenderTargetView, // IN
7447ec681f3Smrg                 UINT RTargets,                                         // IN
7457ec681f3Smrg                 UINT ClearTargets,                                     // IN
7467ec681f3Smrg                 D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView)          // IN
7477ec681f3Smrg{
7487ec681f3Smrg   LOG_ENTRYPOINT();
7497ec681f3Smrg
7507ec681f3Smrg   Device *pDevice = CastDevice(hDevice);
7517ec681f3Smrg
7527ec681f3Smrg   struct pipe_context *pipe = pDevice->pipe;
7537ec681f3Smrg
7547ec681f3Smrg   pDevice->fb.nr_cbufs = 0;
7557ec681f3Smrg   for (unsigned i = 0; i < RTargets; ++i) {
7567ec681f3Smrg      pipe_surface_reference(&pDevice->fb.cbufs[i],
7577ec681f3Smrg                             CastPipeRenderTargetView(phRenderTargetView[i]));
7587ec681f3Smrg      if (pDevice->fb.cbufs[i]) {
7597ec681f3Smrg         pDevice->fb.nr_cbufs = i + 1;
7607ec681f3Smrg      }
7617ec681f3Smrg   }
7627ec681f3Smrg
7637ec681f3Smrg   for (unsigned i = RTargets; i < PIPE_MAX_COLOR_BUFS; ++i) {
7647ec681f3Smrg      pipe_surface_reference(&pDevice->fb.cbufs[i], NULL);
7657ec681f3Smrg   }
7667ec681f3Smrg
7677ec681f3Smrg   pipe_surface_reference(&pDevice->fb.zsbuf,
7687ec681f3Smrg                          CastPipeDepthStencilView(hDepthStencilView));
7697ec681f3Smrg
7707ec681f3Smrg   /*
7717ec681f3Smrg    * Calculate the width/height fields for this framebuffer.  D3D10
7727ec681f3Smrg    * actually specifies that they be identical for all bound views.
7737ec681f3Smrg    */
7747ec681f3Smrg   unsigned width, height;
7757ec681f3Smrg   util_framebuffer_min_size(&pDevice->fb, &width, &height);
7767ec681f3Smrg   pDevice->fb.width = width;
7777ec681f3Smrg   pDevice->fb.height = height;
7787ec681f3Smrg
7797ec681f3Smrg   pipe->set_framebuffer_state(pipe, &pDevice->fb);
7807ec681f3Smrg}
7817ec681f3Smrg
7827ec681f3Smrg
7837ec681f3Smrg/*
7847ec681f3Smrg * ----------------------------------------------------------------------
7857ec681f3Smrg *
7867ec681f3Smrg * CalcPrivateDepthStencilStateSize --
7877ec681f3Smrg *
7887ec681f3Smrg *    The CalcPrivateDepthStencilStateSize function determines the size
7897ec681f3Smrg *    of the user-mode display driver's private region of memory (that
7907ec681f3Smrg *    is, the size of internal driver structures, not the size of the
7917ec681f3Smrg *    resource video memory) for a depth stencil state.
7927ec681f3Smrg *
7937ec681f3Smrg * ----------------------------------------------------------------------
7947ec681f3Smrg */
7957ec681f3Smrg
7967ec681f3SmrgSIZE_T APIENTRY
7977ec681f3SmrgCalcPrivateDepthStencilStateSize(
7987ec681f3Smrg   D3D10DDI_HDEVICE hDevice,                                   // IN
7997ec681f3Smrg   __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc) // IN
8007ec681f3Smrg{
8017ec681f3Smrg   return sizeof(DepthStencilState);
8027ec681f3Smrg}
8037ec681f3Smrg
8047ec681f3Smrg
8057ec681f3Smrg/*
8067ec681f3Smrg * ----------------------------------------------------------------------
8077ec681f3Smrg *
8087ec681f3Smrg * translateComparison --
8097ec681f3Smrg *
8107ec681f3Smrg *   Translate comparison function from DX10 to gallium representation.
8117ec681f3Smrg *
8127ec681f3Smrg * ----------------------------------------------------------------------
8137ec681f3Smrg */
8147ec681f3Smrgstatic uint
8157ec681f3SmrgtranslateComparison(D3D10_DDI_COMPARISON_FUNC Func)
8167ec681f3Smrg{
8177ec681f3Smrg   switch (Func) {
8187ec681f3Smrg   case D3D10_DDI_COMPARISON_NEVER:
8197ec681f3Smrg      return PIPE_FUNC_NEVER;
8207ec681f3Smrg   case D3D10_DDI_COMPARISON_LESS:
8217ec681f3Smrg      return PIPE_FUNC_LESS;
8227ec681f3Smrg   case D3D10_DDI_COMPARISON_EQUAL:
8237ec681f3Smrg      return PIPE_FUNC_EQUAL;
8247ec681f3Smrg   case D3D10_DDI_COMPARISON_LESS_EQUAL:
8257ec681f3Smrg      return PIPE_FUNC_LEQUAL;
8267ec681f3Smrg   case D3D10_DDI_COMPARISON_GREATER:
8277ec681f3Smrg      return PIPE_FUNC_GREATER;
8287ec681f3Smrg   case D3D10_DDI_COMPARISON_NOT_EQUAL:
8297ec681f3Smrg      return PIPE_FUNC_NOTEQUAL;
8307ec681f3Smrg   case D3D10_DDI_COMPARISON_GREATER_EQUAL:
8317ec681f3Smrg      return PIPE_FUNC_GEQUAL;
8327ec681f3Smrg   case D3D10_DDI_COMPARISON_ALWAYS:
8337ec681f3Smrg      return PIPE_FUNC_ALWAYS;
8347ec681f3Smrg   default:
8357ec681f3Smrg      assert(0);
8367ec681f3Smrg      return PIPE_FUNC_ALWAYS;
8377ec681f3Smrg   }
8387ec681f3Smrg}
8397ec681f3Smrg
8407ec681f3Smrg
8417ec681f3Smrg/*
8427ec681f3Smrg * ----------------------------------------------------------------------
8437ec681f3Smrg *
8447ec681f3Smrg * translateStencilOp --
8457ec681f3Smrg *
8467ec681f3Smrg *   Translate stencil op from DX10 to gallium representation.
8477ec681f3Smrg *
8487ec681f3Smrg * ----------------------------------------------------------------------
8497ec681f3Smrg */
8507ec681f3Smrgstatic uint
8517ec681f3SmrgtranslateStencilOp(D3D10_DDI_STENCIL_OP StencilOp)
8527ec681f3Smrg{
8537ec681f3Smrg   switch (StencilOp) {
8547ec681f3Smrg   case D3D10_DDI_STENCIL_OP_KEEP:
8557ec681f3Smrg      return PIPE_STENCIL_OP_KEEP;
8567ec681f3Smrg   case D3D10_DDI_STENCIL_OP_ZERO:
8577ec681f3Smrg      return PIPE_STENCIL_OP_ZERO;
8587ec681f3Smrg   case D3D10_DDI_STENCIL_OP_REPLACE:
8597ec681f3Smrg      return PIPE_STENCIL_OP_REPLACE;
8607ec681f3Smrg   case D3D10_DDI_STENCIL_OP_INCR_SAT:
8617ec681f3Smrg      return PIPE_STENCIL_OP_INCR;
8627ec681f3Smrg   case D3D10_DDI_STENCIL_OP_DECR_SAT:
8637ec681f3Smrg      return PIPE_STENCIL_OP_DECR;
8647ec681f3Smrg   case D3D10_DDI_STENCIL_OP_INVERT:
8657ec681f3Smrg      return PIPE_STENCIL_OP_INVERT;
8667ec681f3Smrg   case D3D10_DDI_STENCIL_OP_INCR:
8677ec681f3Smrg      return PIPE_STENCIL_OP_INCR_WRAP;
8687ec681f3Smrg   case D3D10_DDI_STENCIL_OP_DECR:
8697ec681f3Smrg      return PIPE_STENCIL_OP_DECR_WRAP;
8707ec681f3Smrg   default:
8717ec681f3Smrg      assert(0);
8727ec681f3Smrg      return PIPE_STENCIL_OP_KEEP;
8737ec681f3Smrg   }
8747ec681f3Smrg}
8757ec681f3Smrg
8767ec681f3Smrg
8777ec681f3Smrg/*
8787ec681f3Smrg * ----------------------------------------------------------------------
8797ec681f3Smrg *
8807ec681f3Smrg * CreateDepthStencilState --
8817ec681f3Smrg *
8827ec681f3Smrg *    The CreateDepthStencilState function creates a depth stencil state.
8837ec681f3Smrg *
8847ec681f3Smrg * ----------------------------------------------------------------------
8857ec681f3Smrg */
8867ec681f3Smrg
8877ec681f3Smrgvoid APIENTRY
8887ec681f3SmrgCreateDepthStencilState(
8897ec681f3Smrg   D3D10DDI_HDEVICE hDevice,                                   // IN
8907ec681f3Smrg   __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc, // IN
8917ec681f3Smrg   D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState,             // IN
8927ec681f3Smrg   D3D10DDI_HRTDEPTHSTENCILSTATE hRTDepthStencilState)         // IN
8937ec681f3Smrg{
8947ec681f3Smrg   LOG_ENTRYPOINT();
8957ec681f3Smrg
8967ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
8977ec681f3Smrg   DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);
8987ec681f3Smrg
8997ec681f3Smrg   struct pipe_depth_stencil_alpha_state state;
9007ec681f3Smrg   memset(&state, 0, sizeof state);
9017ec681f3Smrg
9027ec681f3Smrg   /* Depth. */
9037ec681f3Smrg   state.depth_enabled = (pDepthStencilDesc->DepthEnable ? 1 : 0);
9047ec681f3Smrg   state.depth_writemask = (pDepthStencilDesc->DepthWriteMask ? 1 : 0);
9057ec681f3Smrg   state.depth_func = translateComparison(pDepthStencilDesc->DepthFunc);
9067ec681f3Smrg
9077ec681f3Smrg   /* Stencil. */
9087ec681f3Smrg   if (pDepthStencilDesc->StencilEnable) {
9097ec681f3Smrg      struct pipe_stencil_state *face0 = &state.stencil[0];
9107ec681f3Smrg      struct pipe_stencil_state *face1 = &state.stencil[1];
9117ec681f3Smrg
9127ec681f3Smrg      face0->enabled   = 1;
9137ec681f3Smrg      face0->func      = translateComparison(pDepthStencilDesc->FrontFace.StencilFunc);
9147ec681f3Smrg      face0->fail_op   = translateStencilOp(pDepthStencilDesc->FrontFace.StencilFailOp);
9157ec681f3Smrg      face0->zpass_op  = translateStencilOp(pDepthStencilDesc->FrontFace.StencilPassOp);
9167ec681f3Smrg      face0->zfail_op  = translateStencilOp(pDepthStencilDesc->FrontFace.StencilDepthFailOp);
9177ec681f3Smrg      face0->valuemask = pDepthStencilDesc->StencilReadMask;
9187ec681f3Smrg      face0->writemask = pDepthStencilDesc->StencilWriteMask;
9197ec681f3Smrg
9207ec681f3Smrg      face1->enabled   = 1;
9217ec681f3Smrg      face1->func      = translateComparison(pDepthStencilDesc->BackFace.StencilFunc);
9227ec681f3Smrg      face1->fail_op   = translateStencilOp(pDepthStencilDesc->BackFace.StencilFailOp);
9237ec681f3Smrg      face1->zpass_op  = translateStencilOp(pDepthStencilDesc->BackFace.StencilPassOp);
9247ec681f3Smrg      face1->zfail_op  = translateStencilOp(pDepthStencilDesc->BackFace.StencilDepthFailOp);
9257ec681f3Smrg      face1->valuemask = pDepthStencilDesc->StencilReadMask;
9267ec681f3Smrg      face1->writemask = pDepthStencilDesc->StencilWriteMask;
9277ec681f3Smrg#ifdef DEBUG
9287ec681f3Smrg      if (!pDepthStencilDesc->FrontEnable) {
9297ec681f3Smrg         ASSERT(face0->func == PIPE_FUNC_ALWAYS);
9307ec681f3Smrg         ASSERT(face0->fail_op == PIPE_STENCIL_OP_KEEP);
9317ec681f3Smrg         ASSERT(face0->zpass_op == PIPE_STENCIL_OP_KEEP);
9327ec681f3Smrg         ASSERT(face0->zfail_op == PIPE_STENCIL_OP_KEEP);
9337ec681f3Smrg      }
9347ec681f3Smrg
9357ec681f3Smrg      if (!pDepthStencilDesc->BackEnable) {
9367ec681f3Smrg         ASSERT(face1->func == PIPE_FUNC_ALWAYS);
9377ec681f3Smrg         ASSERT(face1->fail_op == PIPE_STENCIL_OP_KEEP);
9387ec681f3Smrg         ASSERT(face1->zpass_op == PIPE_STENCIL_OP_KEEP);
9397ec681f3Smrg         ASSERT(face1->zfail_op == PIPE_STENCIL_OP_KEEP);
9407ec681f3Smrg      }
9417ec681f3Smrg#endif
9427ec681f3Smrg   }
9437ec681f3Smrg
9447ec681f3Smrg   pDepthStencilState->handle =
9457ec681f3Smrg      pipe->create_depth_stencil_alpha_state(pipe, &state);
9467ec681f3Smrg}
9477ec681f3Smrg
9487ec681f3Smrg
9497ec681f3Smrg/*
9507ec681f3Smrg * ----------------------------------------------------------------------
9517ec681f3Smrg *
9527ec681f3Smrg * DestroyDepthStencilState --
9537ec681f3Smrg *
9547ec681f3Smrg *    The CreateDepthStencilState function creates a depth stencil state.
9557ec681f3Smrg *
9567ec681f3Smrg * ----------------------------------------------------------------------
9577ec681f3Smrg */
9587ec681f3Smrg
9597ec681f3Smrgvoid APIENTRY
9607ec681f3SmrgDestroyDepthStencilState(D3D10DDI_HDEVICE hDevice,                         // IN
9617ec681f3Smrg                         D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState)   // IN
9627ec681f3Smrg{
9637ec681f3Smrg   LOG_ENTRYPOINT();
9647ec681f3Smrg
9657ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
9667ec681f3Smrg   DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);
9677ec681f3Smrg
9687ec681f3Smrg   pipe->delete_depth_stencil_alpha_state(pipe, pDepthStencilState->handle);
9697ec681f3Smrg}
9707ec681f3Smrg
9717ec681f3Smrg
9727ec681f3Smrg/*
9737ec681f3Smrg * ----------------------------------------------------------------------
9747ec681f3Smrg *
9757ec681f3Smrg * SetDepthStencilState --
9767ec681f3Smrg *
9777ec681f3Smrg *    The SetDepthStencilState function sets a depth-stencil state.
9787ec681f3Smrg *
9797ec681f3Smrg * ----------------------------------------------------------------------
9807ec681f3Smrg */
9817ec681f3Smrg
9827ec681f3Smrgvoid APIENTRY
9837ec681f3SmrgSetDepthStencilState(D3D10DDI_HDEVICE hDevice,           // IN
9847ec681f3Smrg                     D3D10DDI_HDEPTHSTENCILSTATE hState, // IN
9857ec681f3Smrg                     UINT StencilRef)                    // IN
9867ec681f3Smrg{
9877ec681f3Smrg   LOG_ENTRYPOINT();
9887ec681f3Smrg
9897ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
9907ec681f3Smrg   void *state = CastPipeDepthStencilState(hState);
9917ec681f3Smrg   struct pipe_stencil_ref psr;
9927ec681f3Smrg
9937ec681f3Smrg   psr.ref_value[0] = StencilRef;
9947ec681f3Smrg   psr.ref_value[1] = StencilRef;
9957ec681f3Smrg
9967ec681f3Smrg   pipe->bind_depth_stencil_alpha_state(pipe, state);
9977ec681f3Smrg   pipe->set_stencil_ref(pipe, psr);
9987ec681f3Smrg}
999