1/**************************************************************************
2 *
3 * Copyright 2012-2021 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28/*
29 * OutputMerger.cpp --
30 *    Functions that manipulate the output merger state.
31 */
32
33
34#include "OutputMerger.h"
35#include "State.h"
36
37#include "Debug.h"
38#include "Format.h"
39
40#include "util/u_framebuffer.h"
41#include "util/format/u_format.h"
42
43
44/*
45 * ----------------------------------------------------------------------
46 *
47 * CalcPrivateRenderTargetViewSize --
48 *
49 *    The CalcPrivateRenderTargetViewSize function determines the size
50 *    of the user-mode display driver's private region of memory
51 *    (that is, the size of internal driver structures, not the size
52 *    of the resource video memory) for a render target view.
53 *
54 * ----------------------------------------------------------------------
55 */
56
57
58SIZE_T APIENTRY
59CalcPrivateRenderTargetViewSize(
60   D3D10DDI_HDEVICE hDevice,                                               // IN
61   __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView) // IN
62{
63   return sizeof(RenderTargetView);
64}
65
66
67/*
68 * ----------------------------------------------------------------------
69 *
70 * CreateRenderTargetView --
71 *
72 *    The CreateRenderTargetView function creates a render target view.
73 *
74 * ----------------------------------------------------------------------
75 */
76
77void APIENTRY
78CreateRenderTargetView(
79   D3D10DDI_HDEVICE hDevice,                                               // IN
80   __in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView, // IN
81   D3D10DDI_HRENDERTARGETVIEW hRenderTargetView,                           // IN
82   D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView)                       // IN
83{
84   LOG_ENTRYPOINT();
85
86   struct pipe_context *pipe = CastPipeContext(hDevice);
87   struct pipe_resource *resource = CastPipeResource(pCreateRenderTargetView->hDrvResource);
88   RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);
89
90   struct pipe_surface desc;
91
92   memset(&desc, 0, sizeof desc);
93   desc.format = FormatTranslate(pCreateRenderTargetView->Format, FALSE);
94
95   switch (pCreateRenderTargetView->ResourceDimension) {
96   case D3D10DDIRESOURCE_BUFFER:
97      desc.u.buf.first_element = pCreateRenderTargetView->Buffer.FirstElement;
98      desc.u.buf.last_element = pCreateRenderTargetView->Buffer.NumElements - 1 +
99                                   desc.u.buf.first_element;
100      break;
101   case D3D10DDIRESOURCE_TEXTURE1D:
102      ASSERT(pCreateRenderTargetView->Tex1D.ArraySize != (UINT)-1);
103      desc.u.tex.level = pCreateRenderTargetView->Tex1D.MipSlice;
104      desc.u.tex.first_layer = pCreateRenderTargetView->Tex1D.FirstArraySlice;
105      desc.u.tex.last_layer = pCreateRenderTargetView->Tex1D.ArraySize - 1 +
106                                 desc.u.tex.first_layer;
107      break;
108   case D3D10DDIRESOURCE_TEXTURE2D:
109      ASSERT(pCreateRenderTargetView->Tex2D.ArraySize != (UINT)-1);
110      desc.u.tex.level = pCreateRenderTargetView->Tex2D.MipSlice;
111      desc.u.tex.first_layer = pCreateRenderTargetView->Tex2D.FirstArraySlice;
112      desc.u.tex.last_layer = pCreateRenderTargetView->Tex2D.ArraySize - 1 +
113                                 desc.u.tex.first_layer;
114      break;
115   case D3D10DDIRESOURCE_TEXTURE3D:
116      desc.u.tex.level = pCreateRenderTargetView->Tex3D.MipSlice;
117      desc.u.tex.first_layer = pCreateRenderTargetView->Tex3D.FirstW;
118      desc.u.tex.last_layer = pCreateRenderTargetView->Tex3D.WSize - 1 +
119                                 desc.u.tex.first_layer;
120      break;
121   case D3D10DDIRESOURCE_TEXTURECUBE:
122      ASSERT(pCreateRenderTargetView->TexCube.ArraySize != (UINT)-1);
123      desc.u.tex.level = pCreateRenderTargetView->TexCube.MipSlice;
124      desc.u.tex.first_layer = pCreateRenderTargetView->TexCube.FirstArraySlice;
125      desc.u.tex.last_layer = pCreateRenderTargetView->TexCube.ArraySize - 1 +
126                                 desc.u.tex.first_layer;;
127      break;
128   default:
129      ASSERT(0);
130      return;
131   }
132
133   pRTView->surface = pipe->create_surface(pipe, resource, &desc);
134   assert(pRTView->surface);
135}
136
137
138/*
139 * ----------------------------------------------------------------------
140 *
141 * DestroyRenderTargetView --
142 *
143 *    The DestroyRenderTargetView function destroys the specified
144 *    render target view object. The render target view object can
145 *    be destoyed only if it is not currently bound to a display device.
146 *
147 * ----------------------------------------------------------------------
148 */
149
150void APIENTRY
151DestroyRenderTargetView(D3D10DDI_HDEVICE hDevice,                       // IN
152                        D3D10DDI_HRENDERTARGETVIEW hRenderTargetView)   // IN
153{
154   LOG_ENTRYPOINT();
155
156   RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);
157
158   pipe_surface_reference(&pRTView->surface, NULL);
159}
160
161
162/*
163 * ----------------------------------------------------------------------
164 *
165 * ClearRenderTargetView --
166 *
167 *    The ClearRenderTargetView function clears the specified
168 *    render target view by setting it to a constant value.
169 *
170 * ----------------------------------------------------------------------
171 */
172
173void APIENTRY
174ClearRenderTargetView(D3D10DDI_HDEVICE hDevice,                      // IN
175                      D3D10DDI_HRENDERTARGETVIEW hRenderTargetView,  // IN
176                      FLOAT pColorRGBA[4])                           // IN
177{
178   LOG_ENTRYPOINT();
179
180   struct pipe_context *pipe = CastPipeContext(hDevice);
181   struct pipe_surface *surface = CastPipeRenderTargetView(hRenderTargetView);
182   union pipe_color_union clear_color;
183
184   /*
185    * DX10 always uses float clear color but gallium does not.
186    * Conversion should just be ordinary conversion. Actual clamping will
187    * be done later but need to make sure values exceeding int/uint range
188    * are handled correctly.
189    */
190   if (util_format_is_pure_integer(surface->format)) {
191      if (util_format_is_pure_sint(surface->format)) {
192         unsigned i;
193         /* If only MIN_INT/UINT32 in c++ code would work... */
194         int min_int32 = 0x80000000;
195         int max_int32 = 0x7fffffff;
196         for (i = 0; i < 4; i++) {
197            float value = pColorRGBA[i];
198            /* This is an expanded clamp to handle NaN and integer conversion. */
199            if (util_is_nan(value)) {
200               clear_color.i[i] = 0;
201            } else if (value <= (float)min_int32) {
202               clear_color.i[i] = min_int32;
203            } else if (value >= (float)max_int32) {
204               clear_color.i[i] = max_int32;
205            } else {
206               clear_color.i[i] = value;
207            }
208         }
209      }
210      else {
211         assert(util_format_is_pure_uint(surface->format));
212         unsigned i;
213         unsigned max_uint32 = 0xffffffffU;
214         for (i = 0; i < 4; i++) {
215            float value = pColorRGBA[i];
216            /* This is an expanded clamp to handle NaN and integer conversion. */
217            if (!(value >= 0.0f)) {
218               /* Handles NaN. */
219               clear_color.ui[i] = 0;
220            } else if (value >= (float)max_uint32) {
221               clear_color.ui[i] = max_uint32;
222            } else {
223               clear_color.ui[i] = value;
224            }
225         }
226      }
227   }
228   else {
229      clear_color.f[0] = pColorRGBA[0];
230      clear_color.f[1] = pColorRGBA[1];
231      clear_color.f[2] = pColorRGBA[2];
232      clear_color.f[3] = pColorRGBA[3];
233   }
234
235   pipe->clear_render_target(pipe,
236                             surface,
237                             &clear_color,
238                             0, 0,
239                             surface->width,
240                             surface->height,
241                             TRUE);
242}
243
244
245/*
246 * ----------------------------------------------------------------------
247 *
248 * CalcPrivateDepthStencilViewSize --
249 *
250 *    The CalcPrivateDepthStencilViewSize function determines the size
251 *    of the user-mode display driver's private region of memory
252 *    (that is, the size of internal driver structures, not the size
253 *    of the resource video memory) for a depth stencil view.
254 *
255 * ----------------------------------------------------------------------
256 */
257
258SIZE_T APIENTRY
259CalcPrivateDepthStencilViewSize(
260   D3D10DDI_HDEVICE hDevice,                                               // IN
261   __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView) // IN
262{
263   return sizeof(DepthStencilView);
264}
265
266
267/*
268 * ----------------------------------------------------------------------
269 *
270 * CreateDepthStencilView --
271 *
272 *    The CreateDepthStencilView function creates a depth stencil view.
273 *
274 * ----------------------------------------------------------------------
275 */
276
277void APIENTRY
278CreateDepthStencilView(
279   D3D10DDI_HDEVICE hDevice,                                               // IN
280   __in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView, // IN
281   D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView,                           // IN
282   D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView)                       // IN
283{
284   LOG_ENTRYPOINT();
285
286   struct pipe_context *pipe = CastPipeContext(hDevice);
287   struct pipe_resource *resource = CastPipeResource(pCreateDepthStencilView->hDrvResource);
288   DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);
289
290   struct pipe_surface desc;
291
292   memset(&desc, 0, sizeof desc);
293   desc.format = FormatTranslate(pCreateDepthStencilView->Format, TRUE);
294
295   switch (pCreateDepthStencilView->ResourceDimension) {
296   case D3D10DDIRESOURCE_TEXTURE1D:
297      ASSERT(pCreateDepthStencilView->Tex1D.ArraySize != (UINT)-1);
298      desc.u.tex.level = pCreateDepthStencilView->Tex1D.MipSlice;
299      desc.u.tex.first_layer = pCreateDepthStencilView->Tex1D.FirstArraySlice;
300      desc.u.tex.last_layer = pCreateDepthStencilView->Tex1D.ArraySize - 1 +
301                                 desc.u.tex.first_layer;
302      break;
303   case D3D10DDIRESOURCE_TEXTURE2D:
304      ASSERT(pCreateDepthStencilView->Tex2D.ArraySize != (UINT)-1);
305      desc.u.tex.level = pCreateDepthStencilView->Tex2D.MipSlice;
306      desc.u.tex.first_layer = pCreateDepthStencilView->Tex2D.FirstArraySlice;
307      desc.u.tex.last_layer = pCreateDepthStencilView->Tex2D.ArraySize - 1 +
308                                 desc.u.tex.first_layer;
309      break;
310   case D3D10DDIRESOURCE_TEXTURECUBE:
311      ASSERT(pCreateDepthStencilView->TexCube.ArraySize != (UINT)-1);
312      desc.u.tex.level = pCreateDepthStencilView->TexCube.MipSlice;
313      desc.u.tex.first_layer = pCreateDepthStencilView->TexCube.FirstArraySlice;
314      desc.u.tex.last_layer = pCreateDepthStencilView->TexCube.ArraySize - 1 +
315                                 desc.u.tex.first_layer;
316      break;
317   default:
318      ASSERT(0);
319      return;
320   }
321
322   pDSView->surface = pipe->create_surface(pipe, resource, &desc);
323   assert(pDSView->surface);
324}
325
326
327/*
328 * ----------------------------------------------------------------------
329 *
330 * DestroyDepthStencilView --
331 *
332 *    The DestroyDepthStencilView function destroys the specified
333 *    depth stencil view object. The depth stencil view object can
334 *    be destoyed only if it is not currently bound to a display device.
335 *
336 * ----------------------------------------------------------------------
337 */
338
339void APIENTRY
340DestroyDepthStencilView(D3D10DDI_HDEVICE hDevice,                       // IN
341                        D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView)   // IN
342{
343   LOG_ENTRYPOINT();
344
345   DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);
346
347   pipe_surface_reference(&pDSView->surface, NULL);
348}
349
350
351/*
352 * ----------------------------------------------------------------------
353 *
354 * ClearDepthStencilView --
355 *
356 *    The ClearDepthStencilView function clears the specified
357 *    currently bound depth-stencil view.
358 *
359 * ----------------------------------------------------------------------
360 */
361
362void APIENTRY
363ClearDepthStencilView(D3D10DDI_HDEVICE hDevice,                      // IN
364                      D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView,  // IN
365                      UINT Flags,                                    // IN
366                      FLOAT Depth,                                   // IN
367                      UINT8 Stencil)                                 // IN
368{
369   LOG_ENTRYPOINT();
370
371   struct pipe_context *pipe = CastPipeContext(hDevice);
372   struct pipe_surface *surface = CastPipeDepthStencilView(hDepthStencilView);
373
374   unsigned flags = 0;
375   if (Flags & D3D10_DDI_CLEAR_DEPTH) {
376      flags |= PIPE_CLEAR_DEPTH;
377   }
378   if (Flags & D3D10_DDI_CLEAR_STENCIL) {
379      flags |= PIPE_CLEAR_STENCIL;
380   }
381
382   pipe->clear_depth_stencil(pipe,
383                             surface,
384                             flags,
385                             Depth,
386                             Stencil,
387                             0, 0,
388                             surface->width,
389                             surface->height,
390                             TRUE);
391}
392
393
394/*
395 * ----------------------------------------------------------------------
396 *
397 * CalcPrivateBlendStateSize --
398 *
399 *    The CalcPrivateBlendStateSize function determines the size of
400 *    the user-mode display driver's private region of memory (that
401 *    is, the size of internal driver structures, not the size of
402 *    the resource video memory) for a blend state.
403 *
404 * ----------------------------------------------------------------------
405 */
406
407SIZE_T APIENTRY
408CalcPrivateBlendStateSize(D3D10DDI_HDEVICE hDevice,                     // IN
409                          __in const D3D10_DDI_BLEND_DESC *pBlendDesc)  // IN
410{
411   return sizeof(BlendState);
412}
413
414
415/*
416 * ----------------------------------------------------------------------
417 *
418 * CalcPrivateBlendStateSize1 --
419 *
420 *    The CalcPrivateBlendStateSize function determines the size of
421 *    the user-mode display driver's private region of memory (that
422 *    is, the size of internal driver structures, not the size of
423 *    the resource video memory) for a blend state.
424 *
425 * ----------------------------------------------------------------------
426 */
427
428SIZE_T APIENTRY
429CalcPrivateBlendStateSize1(D3D10DDI_HDEVICE hDevice,                     // IN
430                           __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc)  // IN
431{
432   return sizeof(BlendState);
433}
434
435
436/*
437 * ----------------------------------------------------------------------
438 *
439 * translateBlend --
440 *
441 *   Translate blend function from svga3d to gallium representation.
442 *
443 * ----------------------------------------------------------------------
444 */
445static uint
446translateBlendOp(D3D10_DDI_BLEND_OP op)
447{
448   switch (op) {
449   case D3D10_DDI_BLEND_OP_ADD:
450      return PIPE_BLEND_ADD;
451   case D3D10_DDI_BLEND_OP_SUBTRACT:
452      return PIPE_BLEND_SUBTRACT;
453   case D3D10_DDI_BLEND_OP_REV_SUBTRACT:
454      return PIPE_BLEND_REVERSE_SUBTRACT;
455   case D3D10_DDI_BLEND_OP_MIN:
456      return PIPE_BLEND_MIN;
457   case D3D10_DDI_BLEND_OP_MAX:
458      return PIPE_BLEND_MAX;
459   default:
460      assert(0);
461      return PIPE_BLEND_ADD;
462   }
463}
464
465
466/*
467 * ----------------------------------------------------------------------
468 *
469 * translateBlend --
470 *
471 *   Translate blend factor from svga3d to gallium representation.
472 *
473 * ----------------------------------------------------------------------
474 */
475static uint
476translateBlend(Device *pDevice,
477               D3D10_DDI_BLEND blend)
478{
479   if (!pDevice->max_dual_source_render_targets) {
480      switch (blend) {
481      case D3D10_DDI_BLEND_SRC1_COLOR:
482      case D3D10_DDI_BLEND_SRC1_ALPHA:
483         LOG_UNSUPPORTED(TRUE);
484         return D3D10_DDI_BLEND_ZERO;
485      case D3D10_DDI_BLEND_INV_SRC1_COLOR:
486      case D3D10_DDI_BLEND_INV_SRC1_ALPHA:
487         LOG_UNSUPPORTED(TRUE);
488         return D3D10_DDI_BLEND_ONE;
489      default:
490         break;
491      }
492   }
493
494   switch (blend) {
495   case D3D10_DDI_BLEND_ZERO:
496      return PIPE_BLENDFACTOR_ZERO;
497   case D3D10_DDI_BLEND_ONE:
498      return PIPE_BLENDFACTOR_ONE;
499   case D3D10_DDI_BLEND_SRC_COLOR:
500      return PIPE_BLENDFACTOR_SRC_COLOR;
501   case D3D10_DDI_BLEND_INV_SRC_COLOR:
502      return PIPE_BLENDFACTOR_INV_SRC_COLOR;
503   case D3D10_DDI_BLEND_SRC_ALPHA:
504      return PIPE_BLENDFACTOR_SRC_ALPHA;
505   case D3D10_DDI_BLEND_INV_SRC_ALPHA:
506      return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
507   case D3D10_DDI_BLEND_DEST_ALPHA:
508      return PIPE_BLENDFACTOR_DST_ALPHA;
509   case D3D10_DDI_BLEND_INV_DEST_ALPHA:
510      return PIPE_BLENDFACTOR_INV_DST_ALPHA;
511   case D3D10_DDI_BLEND_DEST_COLOR:
512      return PIPE_BLENDFACTOR_DST_COLOR;
513   case D3D10_DDI_BLEND_INV_DEST_COLOR:
514      return PIPE_BLENDFACTOR_INV_DST_COLOR;
515   case D3D10_DDI_BLEND_SRC_ALPHASAT:
516      return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
517   case D3D10_DDI_BLEND_BLEND_FACTOR:
518      return PIPE_BLENDFACTOR_CONST_COLOR;
519   case D3D10_DDI_BLEND_INVBLEND_FACTOR:
520      return PIPE_BLENDFACTOR_INV_CONST_COLOR;
521   case D3D10_DDI_BLEND_SRC1_COLOR:
522      return PIPE_BLENDFACTOR_SRC1_COLOR;
523   case D3D10_DDI_BLEND_INV_SRC1_COLOR:
524      return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
525   case D3D10_DDI_BLEND_SRC1_ALPHA:
526      return PIPE_BLENDFACTOR_SRC1_ALPHA;
527   case D3D10_DDI_BLEND_INV_SRC1_ALPHA:
528      return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
529   default:
530      assert(0);
531      return PIPE_BLENDFACTOR_ONE;
532   }
533}
534
535
536/*
537 * ----------------------------------------------------------------------
538 *
539 * CreateBlendState --
540 *
541 *    The CreateBlendState function creates a blend state.
542 *
543 * ----------------------------------------------------------------------
544 */
545
546void APIENTRY
547CreateBlendState(D3D10DDI_HDEVICE hDevice,                     // IN
548                 __in const D3D10_DDI_BLEND_DESC *pBlendDesc,  // IN
549                 D3D10DDI_HBLENDSTATE hBlendState,             // IN
550                 D3D10DDI_HRTBLENDSTATE hRTBlendState)         // IN
551{
552   unsigned i;
553
554   LOG_ENTRYPOINT();
555
556   Device *pDevice = CastDevice(hDevice);
557   struct pipe_context *pipe = pDevice->pipe;
558   BlendState *pBlendState = CastBlendState(hBlendState);
559
560   struct pipe_blend_state state;
561   memset(&state, 0, sizeof state);
562
563   for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
564      state.rt[i].blend_enable = pBlendDesc->BlendEnable[i];
565      state.rt[i].colormask = pBlendDesc->RenderTargetWriteMask[i];
566
567      if (pBlendDesc->BlendEnable[0] != pBlendDesc->BlendEnable[i] ||
568          pBlendDesc->RenderTargetWriteMask[0] != pBlendDesc->RenderTargetWriteMask[i]) {
569         state.independent_blend_enable = 1;
570      }
571   }
572
573   state.rt[0].rgb_func = translateBlendOp(pBlendDesc->BlendOp);
574   if (pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MIN ||
575       pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MAX) {
576      state.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
577      state.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
578   } else {
579      state.rt[0].rgb_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlend);
580      state.rt[0].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlend);
581   }
582
583   state.rt[0].alpha_func = translateBlendOp(pBlendDesc->BlendOpAlpha);
584   if (pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||
585       pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {
586      state.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
587      state.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
588   } else {
589      state.rt[0].alpha_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlendAlpha);
590      state.rt[0].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlendAlpha);
591   }
592
593   /*
594    * Propagate to all the other rendertargets
595    */
596   for (i = 1; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
597      state.rt[i].rgb_func = state.rt[0].rgb_func;
598      state.rt[i].rgb_src_factor = state.rt[0].rgb_src_factor;
599      state.rt[i].rgb_dst_factor = state.rt[0].rgb_dst_factor;
600      state.rt[i].alpha_func = state.rt[0].alpha_func;
601      state.rt[i].alpha_src_factor = state.rt[0].alpha_src_factor;
602      state.rt[i].alpha_dst_factor = state.rt[0].alpha_dst_factor;
603   }
604
605   state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;
606
607   pBlendState->handle = pipe->create_blend_state(pipe, &state);
608}
609
610
611/*
612 * ----------------------------------------------------------------------
613 *
614 * CreateBlendState1 --
615 *
616 *    The CreateBlendState function creates a blend state.
617 *
618 * ----------------------------------------------------------------------
619 */
620
621void APIENTRY
622CreateBlendState1(D3D10DDI_HDEVICE hDevice,                     // IN
623                  __in const D3D10_1_DDI_BLEND_DESC *pBlendDesc,  // IN
624                  D3D10DDI_HBLENDSTATE hBlendState,             // IN
625                  D3D10DDI_HRTBLENDSTATE hRTBlendState)         // IN
626{
627   unsigned i;
628
629   LOG_ENTRYPOINT();
630
631   Device *pDevice = CastDevice(hDevice);
632   struct pipe_context *pipe = pDevice->pipe;
633   BlendState *pBlendState = CastBlendState(hBlendState);
634
635   struct pipe_blend_state state;
636   memset(&state, 0, sizeof state);
637
638   state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;
639   state.independent_blend_enable = pBlendDesc->IndependentBlendEnable;
640
641   for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
642      state.rt[i].blend_enable = pBlendDesc->RenderTarget[i].BlendEnable;
643      state.rt[i].colormask = pBlendDesc->RenderTarget[i].RenderTargetWriteMask;
644
645      state.rt[i].rgb_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOp);
646      if (pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MIN ||
647          pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MAX) {
648         state.rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
649         state.rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
650      } else {
651         state.rt[i].rgb_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlend);
652         state.rt[i].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlend);
653      }
654
655      state.rt[i].alpha_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOpAlpha);
656      if (pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||
657          pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {
658         state.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
659         state.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
660      } else {
661         state.rt[i].alpha_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlendAlpha);
662         state.rt[i].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlendAlpha);
663      }
664   }
665
666   pBlendState->handle = pipe->create_blend_state(pipe, &state);
667}
668
669
670/*
671 * ----------------------------------------------------------------------
672 *
673 * DestroyBlendState --
674 *
675 *    The DestroyBlendState function destroys the specified blend
676 *    state object. The blend state object can be destoyed only if
677 *    it is not currently bound to a display device.
678 *
679 * ----------------------------------------------------------------------
680 */
681
682void APIENTRY
683DestroyBlendState(D3D10DDI_HDEVICE hDevice,           // IN
684                  D3D10DDI_HBLENDSTATE hBlendState)   // IN
685{
686   LOG_ENTRYPOINT();
687
688   struct pipe_context *pipe = CastPipeContext(hDevice);
689   BlendState *pBlendState = CastBlendState(hBlendState);
690
691   pipe->delete_blend_state(pipe, pBlendState->handle);
692}
693
694
695/*
696 * ----------------------------------------------------------------------
697 *
698 * SetBlendState --
699 *
700 *    The SetBlendState function sets a blend state.
701 *
702 * ----------------------------------------------------------------------
703 */
704
705void APIENTRY
706SetBlendState(D3D10DDI_HDEVICE hDevice,      // IN
707              D3D10DDI_HBLENDSTATE hState,   // IN
708              const FLOAT pBlendFactor[4],   // IN
709              UINT SampleMask)               // IN
710{
711   LOG_ENTRYPOINT();
712
713   struct pipe_context *pipe = CastPipeContext(hDevice);
714   void *state = CastPipeBlendState(hState);
715
716   pipe->bind_blend_state(pipe, state);
717
718   struct pipe_blend_color color;
719   color.color[0] = pBlendFactor[0];
720   color.color[1] = pBlendFactor[1];
721   color.color[2] = pBlendFactor[2];
722   color.color[3] = pBlendFactor[3];
723
724   pipe->set_blend_color(pipe, &color);
725
726   pipe->set_sample_mask(pipe, SampleMask);
727}
728
729
730/*
731 * ----------------------------------------------------------------------
732 *
733 * SetRenderTargets --
734 *
735 *    Set the rendertargets.
736 *
737 * ----------------------------------------------------------------------
738 */
739
740void APIENTRY
741SetRenderTargets(D3D10DDI_HDEVICE hDevice,                              // IN
742                 __in_ecount (NumViews)
743                  const D3D10DDI_HRENDERTARGETVIEW *phRenderTargetView, // IN
744                 UINT RTargets,                                         // IN
745                 UINT ClearTargets,                                     // IN
746                 D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView)          // IN
747{
748   LOG_ENTRYPOINT();
749
750   Device *pDevice = CastDevice(hDevice);
751
752   struct pipe_context *pipe = pDevice->pipe;
753
754   pDevice->fb.nr_cbufs = 0;
755   for (unsigned i = 0; i < RTargets; ++i) {
756      pipe_surface_reference(&pDevice->fb.cbufs[i],
757                             CastPipeRenderTargetView(phRenderTargetView[i]));
758      if (pDevice->fb.cbufs[i]) {
759         pDevice->fb.nr_cbufs = i + 1;
760      }
761   }
762
763   for (unsigned i = RTargets; i < PIPE_MAX_COLOR_BUFS; ++i) {
764      pipe_surface_reference(&pDevice->fb.cbufs[i], NULL);
765   }
766
767   pipe_surface_reference(&pDevice->fb.zsbuf,
768                          CastPipeDepthStencilView(hDepthStencilView));
769
770   /*
771    * Calculate the width/height fields for this framebuffer.  D3D10
772    * actually specifies that they be identical for all bound views.
773    */
774   unsigned width, height;
775   util_framebuffer_min_size(&pDevice->fb, &width, &height);
776   pDevice->fb.width = width;
777   pDevice->fb.height = height;
778
779   pipe->set_framebuffer_state(pipe, &pDevice->fb);
780}
781
782
783/*
784 * ----------------------------------------------------------------------
785 *
786 * CalcPrivateDepthStencilStateSize --
787 *
788 *    The CalcPrivateDepthStencilStateSize function determines the size
789 *    of the user-mode display driver's private region of memory (that
790 *    is, the size of internal driver structures, not the size of the
791 *    resource video memory) for a depth stencil state.
792 *
793 * ----------------------------------------------------------------------
794 */
795
796SIZE_T APIENTRY
797CalcPrivateDepthStencilStateSize(
798   D3D10DDI_HDEVICE hDevice,                                   // IN
799   __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc) // IN
800{
801   return sizeof(DepthStencilState);
802}
803
804
805/*
806 * ----------------------------------------------------------------------
807 *
808 * translateComparison --
809 *
810 *   Translate comparison function from DX10 to gallium representation.
811 *
812 * ----------------------------------------------------------------------
813 */
814static uint
815translateComparison(D3D10_DDI_COMPARISON_FUNC Func)
816{
817   switch (Func) {
818   case D3D10_DDI_COMPARISON_NEVER:
819      return PIPE_FUNC_NEVER;
820   case D3D10_DDI_COMPARISON_LESS:
821      return PIPE_FUNC_LESS;
822   case D3D10_DDI_COMPARISON_EQUAL:
823      return PIPE_FUNC_EQUAL;
824   case D3D10_DDI_COMPARISON_LESS_EQUAL:
825      return PIPE_FUNC_LEQUAL;
826   case D3D10_DDI_COMPARISON_GREATER:
827      return PIPE_FUNC_GREATER;
828   case D3D10_DDI_COMPARISON_NOT_EQUAL:
829      return PIPE_FUNC_NOTEQUAL;
830   case D3D10_DDI_COMPARISON_GREATER_EQUAL:
831      return PIPE_FUNC_GEQUAL;
832   case D3D10_DDI_COMPARISON_ALWAYS:
833      return PIPE_FUNC_ALWAYS;
834   default:
835      assert(0);
836      return PIPE_FUNC_ALWAYS;
837   }
838}
839
840
841/*
842 * ----------------------------------------------------------------------
843 *
844 * translateStencilOp --
845 *
846 *   Translate stencil op from DX10 to gallium representation.
847 *
848 * ----------------------------------------------------------------------
849 */
850static uint
851translateStencilOp(D3D10_DDI_STENCIL_OP StencilOp)
852{
853   switch (StencilOp) {
854   case D3D10_DDI_STENCIL_OP_KEEP:
855      return PIPE_STENCIL_OP_KEEP;
856   case D3D10_DDI_STENCIL_OP_ZERO:
857      return PIPE_STENCIL_OP_ZERO;
858   case D3D10_DDI_STENCIL_OP_REPLACE:
859      return PIPE_STENCIL_OP_REPLACE;
860   case D3D10_DDI_STENCIL_OP_INCR_SAT:
861      return PIPE_STENCIL_OP_INCR;
862   case D3D10_DDI_STENCIL_OP_DECR_SAT:
863      return PIPE_STENCIL_OP_DECR;
864   case D3D10_DDI_STENCIL_OP_INVERT:
865      return PIPE_STENCIL_OP_INVERT;
866   case D3D10_DDI_STENCIL_OP_INCR:
867      return PIPE_STENCIL_OP_INCR_WRAP;
868   case D3D10_DDI_STENCIL_OP_DECR:
869      return PIPE_STENCIL_OP_DECR_WRAP;
870   default:
871      assert(0);
872      return PIPE_STENCIL_OP_KEEP;
873   }
874}
875
876
877/*
878 * ----------------------------------------------------------------------
879 *
880 * CreateDepthStencilState --
881 *
882 *    The CreateDepthStencilState function creates a depth stencil state.
883 *
884 * ----------------------------------------------------------------------
885 */
886
887void APIENTRY
888CreateDepthStencilState(
889   D3D10DDI_HDEVICE hDevice,                                   // IN
890   __in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc, // IN
891   D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState,             // IN
892   D3D10DDI_HRTDEPTHSTENCILSTATE hRTDepthStencilState)         // IN
893{
894   LOG_ENTRYPOINT();
895
896   struct pipe_context *pipe = CastPipeContext(hDevice);
897   DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);
898
899   struct pipe_depth_stencil_alpha_state state;
900   memset(&state, 0, sizeof state);
901
902   /* Depth. */
903   state.depth_enabled = (pDepthStencilDesc->DepthEnable ? 1 : 0);
904   state.depth_writemask = (pDepthStencilDesc->DepthWriteMask ? 1 : 0);
905   state.depth_func = translateComparison(pDepthStencilDesc->DepthFunc);
906
907   /* Stencil. */
908   if (pDepthStencilDesc->StencilEnable) {
909      struct pipe_stencil_state *face0 = &state.stencil[0];
910      struct pipe_stencil_state *face1 = &state.stencil[1];
911
912      face0->enabled   = 1;
913      face0->func      = translateComparison(pDepthStencilDesc->FrontFace.StencilFunc);
914      face0->fail_op   = translateStencilOp(pDepthStencilDesc->FrontFace.StencilFailOp);
915      face0->zpass_op  = translateStencilOp(pDepthStencilDesc->FrontFace.StencilPassOp);
916      face0->zfail_op  = translateStencilOp(pDepthStencilDesc->FrontFace.StencilDepthFailOp);
917      face0->valuemask = pDepthStencilDesc->StencilReadMask;
918      face0->writemask = pDepthStencilDesc->StencilWriteMask;
919
920      face1->enabled   = 1;
921      face1->func      = translateComparison(pDepthStencilDesc->BackFace.StencilFunc);
922      face1->fail_op   = translateStencilOp(pDepthStencilDesc->BackFace.StencilFailOp);
923      face1->zpass_op  = translateStencilOp(pDepthStencilDesc->BackFace.StencilPassOp);
924      face1->zfail_op  = translateStencilOp(pDepthStencilDesc->BackFace.StencilDepthFailOp);
925      face1->valuemask = pDepthStencilDesc->StencilReadMask;
926      face1->writemask = pDepthStencilDesc->StencilWriteMask;
927#ifdef DEBUG
928      if (!pDepthStencilDesc->FrontEnable) {
929         ASSERT(face0->func == PIPE_FUNC_ALWAYS);
930         ASSERT(face0->fail_op == PIPE_STENCIL_OP_KEEP);
931         ASSERT(face0->zpass_op == PIPE_STENCIL_OP_KEEP);
932         ASSERT(face0->zfail_op == PIPE_STENCIL_OP_KEEP);
933      }
934
935      if (!pDepthStencilDesc->BackEnable) {
936         ASSERT(face1->func == PIPE_FUNC_ALWAYS);
937         ASSERT(face1->fail_op == PIPE_STENCIL_OP_KEEP);
938         ASSERT(face1->zpass_op == PIPE_STENCIL_OP_KEEP);
939         ASSERT(face1->zfail_op == PIPE_STENCIL_OP_KEEP);
940      }
941#endif
942   }
943
944   pDepthStencilState->handle =
945      pipe->create_depth_stencil_alpha_state(pipe, &state);
946}
947
948
949/*
950 * ----------------------------------------------------------------------
951 *
952 * DestroyDepthStencilState --
953 *
954 *    The CreateDepthStencilState function creates a depth stencil state.
955 *
956 * ----------------------------------------------------------------------
957 */
958
959void APIENTRY
960DestroyDepthStencilState(D3D10DDI_HDEVICE hDevice,                         // IN
961                         D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState)   // IN
962{
963   LOG_ENTRYPOINT();
964
965   struct pipe_context *pipe = CastPipeContext(hDevice);
966   DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);
967
968   pipe->delete_depth_stencil_alpha_state(pipe, pDepthStencilState->handle);
969}
970
971
972/*
973 * ----------------------------------------------------------------------
974 *
975 * SetDepthStencilState --
976 *
977 *    The SetDepthStencilState function sets a depth-stencil state.
978 *
979 * ----------------------------------------------------------------------
980 */
981
982void APIENTRY
983SetDepthStencilState(D3D10DDI_HDEVICE hDevice,           // IN
984                     D3D10DDI_HDEPTHSTENCILSTATE hState, // IN
985                     UINT StencilRef)                    // IN
986{
987   LOG_ENTRYPOINT();
988
989   struct pipe_context *pipe = CastPipeContext(hDevice);
990   void *state = CastPipeDepthStencilState(hState);
991   struct pipe_stencil_ref psr;
992
993   psr.ref_value[0] = StencilRef;
994   psr.ref_value[1] = StencilRef;
995
996   pipe->bind_depth_stencil_alpha_state(pipe, state);
997   pipe->set_stencil_ref(pipe, psr);
998}
999