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