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 
58 SIZE_T APIENTRY
CalcPrivateRenderTargetViewSize(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATERENDERTARGETVIEW * pCreateRenderTargetView)59 CalcPrivateRenderTargetViewSize(
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 
77 void APIENTRY
CreateRenderTargetView(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATERENDERTARGETVIEW * pCreateRenderTargetView,D3D10DDI_HRENDERTARGETVIEW hRenderTargetView,D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView)78 CreateRenderTargetView(
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 
150 void APIENTRY
DestroyRenderTargetView(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRENDERTARGETVIEW hRenderTargetView)151 DestroyRenderTargetView(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 
173 void APIENTRY
ClearRenderTargetView(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRENDERTARGETVIEW hRenderTargetView,FLOAT pColorRGBA[4])174 ClearRenderTargetView(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 
258 SIZE_T APIENTRY
CalcPrivateDepthStencilViewSize(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW * pCreateDepthStencilView)259 CalcPrivateDepthStencilViewSize(
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 
277 void APIENTRY
CreateDepthStencilView(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW * pCreateDepthStencilView,D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView,D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView)278 CreateDepthStencilView(
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 
339 void APIENTRY
DestroyDepthStencilView(D3D10DDI_HDEVICE hDevice,D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView)340 DestroyDepthStencilView(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 
362 void APIENTRY
ClearDepthStencilView(D3D10DDI_HDEVICE hDevice,D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView,UINT Flags,FLOAT Depth,UINT8 Stencil)363 ClearDepthStencilView(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 
407 SIZE_T APIENTRY
CalcPrivateBlendStateSize(D3D10DDI_HDEVICE hDevice,__in const D3D10_DDI_BLEND_DESC * pBlendDesc)408 CalcPrivateBlendStateSize(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 
428 SIZE_T APIENTRY
CalcPrivateBlendStateSize1(D3D10DDI_HDEVICE hDevice,__in const D3D10_1_DDI_BLEND_DESC * pBlendDesc)429 CalcPrivateBlendStateSize1(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  */
445 static uint
translateBlendOp(D3D10_DDI_BLEND_OP op)446 translateBlendOp(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  */
475 static uint
translateBlend(Device * pDevice,D3D10_DDI_BLEND blend)476 translateBlend(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 
546 void APIENTRY
CreateBlendState(D3D10DDI_HDEVICE hDevice,__in const D3D10_DDI_BLEND_DESC * pBlendDesc,D3D10DDI_HBLENDSTATE hBlendState,D3D10DDI_HRTBLENDSTATE hRTBlendState)547 CreateBlendState(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 
621 void APIENTRY
CreateBlendState1(D3D10DDI_HDEVICE hDevice,__in const D3D10_1_DDI_BLEND_DESC * pBlendDesc,D3D10DDI_HBLENDSTATE hBlendState,D3D10DDI_HRTBLENDSTATE hRTBlendState)622 CreateBlendState1(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 
682 void APIENTRY
DestroyBlendState(D3D10DDI_HDEVICE hDevice,D3D10DDI_HBLENDSTATE hBlendState)683 DestroyBlendState(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 
705 void APIENTRY
SetBlendState(D3D10DDI_HDEVICE hDevice,D3D10DDI_HBLENDSTATE hState,const FLOAT pBlendFactor[4],UINT SampleMask)706 SetBlendState(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 
740 void APIENTRY
SetRenderTargets(D3D10DDI_HDEVICE hDevice,__in_ecount (NumViews)const D3D10DDI_HRENDERTARGETVIEW * phRenderTargetView,UINT RTargets,UINT ClearTargets,D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView)741 SetRenderTargets(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 
796 SIZE_T APIENTRY
CalcPrivateDepthStencilStateSize(D3D10DDI_HDEVICE hDevice,__in const D3D10_DDI_DEPTH_STENCIL_DESC * pDepthStencilDesc)797 CalcPrivateDepthStencilStateSize(
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  */
814 static uint
translateComparison(D3D10_DDI_COMPARISON_FUNC Func)815 translateComparison(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  */
850 static uint
translateStencilOp(D3D10_DDI_STENCIL_OP StencilOp)851 translateStencilOp(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 
887 void APIENTRY
CreateDepthStencilState(D3D10DDI_HDEVICE hDevice,__in const D3D10_DDI_DEPTH_STENCIL_DESC * pDepthStencilDesc,D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState,D3D10DDI_HRTDEPTHSTENCILSTATE hRTDepthStencilState)888 CreateDepthStencilState(
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 
959 void APIENTRY
DestroyDepthStencilState(D3D10DDI_HDEVICE hDevice,D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState)960 DestroyDepthStencilState(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 
982 void APIENTRY
SetDepthStencilState(D3D10DDI_HDEVICE hDevice,D3D10DDI_HDEPTHSTENCILSTATE hState,UINT StencilRef)983 SetDepthStencilState(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