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