1/* 2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 3 * Copyright 2013 Christoph Bumiller 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23 24#define NINE_STATE 25 26#include "device9.h" 27#include "swapchain9.h" 28#include "basetexture9.h" 29#include "buffer9.h" 30#include "indexbuffer9.h" 31#include "surface9.h" 32#include "vertexbuffer9.h" 33#include "vertexdeclaration9.h" 34#include "vertexshader9.h" 35#include "pixelshader9.h" 36#include "nine_pipe.h" 37#include "nine_ff.h" 38#include "nine_limits.h" 39#include "pipe/p_context.h" 40#include "pipe/p_state.h" 41#include "cso_cache/cso_context.h" 42#include "util/u_atomic.h" 43#include "util/u_upload_mgr.h" 44#include "util/u_math.h" 45#include "util/u_box.h" 46#include "util/u_simple_shaders.h" 47#include "util/u_gen_mipmap.h" 48 49/* CSMT headers */ 50#include "nine_queue.h" 51#include "nine_csmt_helper.h" 52#include "os/os_thread.h" 53 54#define DBG_CHANNEL DBG_DEVICE 55 56/* Nine CSMT */ 57 58struct csmt_instruction { 59 int (* func)(struct NineDevice9 *This, struct csmt_instruction *instr); 60}; 61 62struct csmt_context { 63 thrd_t worker; 64 struct nine_queue_pool* pool; 65 BOOL terminate; 66 cnd_t event_processed; 67 mtx_t mutex_processed; 68 struct NineDevice9 *device; 69 BOOL processed; 70 BOOL toPause; 71 BOOL hasPaused; 72 mtx_t thread_running; 73 mtx_t thread_resume; 74}; 75 76/* Wait for instruction to be processed. 77 * Caller has to ensure that only one thread waits at time. 78 */ 79static void 80nine_csmt_wait_processed(struct csmt_context *ctx) 81{ 82 mtx_lock(&ctx->mutex_processed); 83 while (!p_atomic_read(&ctx->processed)) { 84 cnd_wait(&ctx->event_processed, &ctx->mutex_processed); 85 } 86 mtx_unlock(&ctx->mutex_processed); 87} 88 89/* CSMT worker thread */ 90static 91int 92nine_csmt_worker(void *arg) 93{ 94 struct csmt_context *ctx = arg; 95 struct csmt_instruction *instr; 96 DBG("CSMT worker spawned\n"); 97 98 u_thread_setname("CSMT-Worker"); 99 100 while (1) { 101 nine_queue_wait_flush(ctx->pool); 102 mtx_lock(&ctx->thread_running); 103 104 /* Get instruction. NULL on empty cmdbuf. */ 105 while (!p_atomic_read(&ctx->terminate) && 106 (instr = (struct csmt_instruction *)nine_queue_get(ctx->pool))) { 107 108 /* decode */ 109 if (instr->func(ctx->device, instr)) { 110 mtx_lock(&ctx->mutex_processed); 111 p_atomic_set(&ctx->processed, TRUE); 112 cnd_signal(&ctx->event_processed); 113 mtx_unlock(&ctx->mutex_processed); 114 } 115 if (p_atomic_read(&ctx->toPause)) { 116 mtx_unlock(&ctx->thread_running); 117 /* will wait here the thread can be resumed */ 118 mtx_lock(&ctx->thread_resume); 119 mtx_lock(&ctx->thread_running); 120 mtx_unlock(&ctx->thread_resume); 121 } 122 } 123 124 mtx_unlock(&ctx->thread_running); 125 if (p_atomic_read(&ctx->terminate)) { 126 mtx_lock(&ctx->mutex_processed); 127 p_atomic_set(&ctx->processed, TRUE); 128 cnd_signal(&ctx->event_processed); 129 mtx_unlock(&ctx->mutex_processed); 130 break; 131 } 132 } 133 134 DBG("CSMT worker destroyed\n"); 135 return 0; 136} 137 138/* Create a CSMT context. 139 * Spawns a worker thread. 140 */ 141struct csmt_context * 142nine_csmt_create( struct NineDevice9 *This ) 143{ 144 struct csmt_context *ctx; 145 146 ctx = CALLOC_STRUCT(csmt_context); 147 if (!ctx) 148 return NULL; 149 150 ctx->pool = nine_queue_create(); 151 if (!ctx->pool) { 152 FREE(ctx); 153 return NULL; 154 } 155 cnd_init(&ctx->event_processed); 156 (void) mtx_init(&ctx->mutex_processed, mtx_plain); 157 (void) mtx_init(&ctx->thread_running, mtx_plain); 158 (void) mtx_init(&ctx->thread_resume, mtx_plain); 159 160#if defined(DEBUG) || !defined(NDEBUG) 161 u_thread_setname("Main thread"); 162#endif 163 164 ctx->device = This; 165 166 if (thrd_success != u_thread_create(&ctx->worker, nine_csmt_worker, ctx)) { 167 nine_queue_delete(ctx->pool); 168 FREE(ctx); 169 return NULL; 170 } 171 172 DBG("Returning context %p\n", ctx); 173 174 return ctx; 175} 176 177static int 178nop_func( struct NineDevice9 *This, struct csmt_instruction *instr ) 179{ 180 (void) This; 181 (void) instr; 182 183 return 1; 184} 185 186/* Push nop instruction and flush the queue. 187 * Waits for the worker to complete. */ 188void 189nine_csmt_process( struct NineDevice9 *device ) 190{ 191 struct csmt_instruction* instr; 192 struct csmt_context *ctx = device->csmt_ctx; 193 194 if (!device->csmt_active) 195 return; 196 197 if (nine_queue_isempty(ctx->pool)) 198 return; 199 200 DBG("device=%p\n", device); 201 202 /* NOP */ 203 instr = nine_queue_alloc(ctx->pool, sizeof(struct csmt_instruction)); 204 assert(instr); 205 instr->func = nop_func; 206 207 p_atomic_set(&ctx->processed, FALSE); 208 nine_queue_flush(ctx->pool); 209 210 nine_csmt_wait_processed(ctx); 211} 212 213void 214nine_csmt_flush( struct NineDevice9* device ) 215{ 216 if (!device->csmt_active) 217 return; 218 219 nine_queue_flush(device->csmt_ctx->pool); 220} 221 222 223/* Destroys a CSMT context. 224 * Waits for the worker thread to terminate. 225 */ 226void 227nine_csmt_destroy( struct NineDevice9 *device, struct csmt_context *ctx ) 228{ 229 struct csmt_instruction* instr; 230 thrd_t render_thread = ctx->worker; 231 232 DBG("device=%p ctx=%p\n", device, ctx); 233 234 /* Push nop and flush the queue. */ 235 instr = nine_queue_alloc(ctx->pool, sizeof(struct csmt_instruction)); 236 assert(instr); 237 instr->func = nop_func; 238 239 p_atomic_set(&ctx->processed, FALSE); 240 /* Signal worker to terminate. */ 241 p_atomic_set(&ctx->terminate, TRUE); 242 nine_queue_flush(ctx->pool); 243 244 nine_csmt_wait_processed(ctx); 245 nine_queue_delete(ctx->pool); 246 247 mtx_destroy(&ctx->thread_resume); 248 mtx_destroy(&ctx->thread_running); 249 250 mtx_destroy(&ctx->mutex_processed); 251 cnd_destroy(&ctx->event_processed); 252 253 FREE(ctx); 254 255 thrd_join(render_thread, NULL); 256} 257 258static void 259nine_csmt_pause( struct NineDevice9 *device ) 260{ 261 struct csmt_context *ctx = device->csmt_ctx; 262 263 if (!device->csmt_active) 264 return; 265 266 /* No need to pause the thread */ 267 if (nine_queue_no_flushed_work(ctx->pool)) 268 return; 269 270 mtx_lock(&ctx->thread_resume); 271 p_atomic_set(&ctx->toPause, TRUE); 272 273 /* Wait the thread is paused */ 274 mtx_lock(&ctx->thread_running); 275 ctx->hasPaused = TRUE; 276 p_atomic_set(&ctx->toPause, FALSE); 277} 278 279static void 280nine_csmt_resume( struct NineDevice9 *device ) 281{ 282 struct csmt_context *ctx = device->csmt_ctx; 283 284 if (!device->csmt_active) 285 return; 286 287 if (!ctx->hasPaused) 288 return; 289 290 ctx->hasPaused = FALSE; 291 mtx_unlock(&ctx->thread_running); 292 mtx_unlock(&ctx->thread_resume); 293} 294 295struct pipe_context * 296nine_context_get_pipe( struct NineDevice9 *device ) 297{ 298 nine_csmt_process(device); 299 return device->context.pipe; 300} 301 302struct pipe_context * 303nine_context_get_pipe_multithread( struct NineDevice9 *device ) 304{ 305 struct csmt_context *ctx = device->csmt_ctx; 306 307 if (!device->csmt_active) 308 return device->context.pipe; 309 310 if (!u_thread_is_self(ctx->worker)) 311 nine_csmt_process(device); 312 313 return device->context.pipe; 314} 315 316struct pipe_context * 317nine_context_get_pipe_acquire( struct NineDevice9 *device ) 318{ 319 nine_csmt_pause(device); 320 return device->context.pipe; 321} 322 323void 324nine_context_get_pipe_release( struct NineDevice9 *device ) 325{ 326 nine_csmt_resume(device); 327} 328 329bool 330nine_context_is_worker( struct NineDevice9 *device ) 331{ 332 struct csmt_context *ctx = device->csmt_ctx; 333 334 if (!device->csmt_active) 335 return false; 336 337 return u_thread_is_self(ctx->worker); 338} 339 340/* Nine state functions */ 341 342/* Check if some states need to be set dirty */ 343 344static inline DWORD 345check_multisample(struct NineDevice9 *device) 346{ 347 struct nine_context *context = &device->context; 348 DWORD *rs = context->rs; 349 struct NineSurface9 *rt0 = context->rt[0]; 350 bool multisampled_target; 351 DWORD new_value; 352 353 multisampled_target = rt0 && rt0->desc.MultiSampleType >= 1; 354 if (rt0 && rt0->desc.Format == D3DFMT_NULL && context->ds) 355 multisampled_target = context->ds->desc.MultiSampleType >= 1; 356 new_value = (multisampled_target && rs[D3DRS_MULTISAMPLEANTIALIAS]) ? 1 : 0; 357 if (rs[NINED3DRS_MULTISAMPLE] != new_value) { 358 rs[NINED3DRS_MULTISAMPLE] = new_value; 359 return NINE_STATE_RASTERIZER; 360 } 361 return 0; 362} 363 364/* State preparation only */ 365 366static inline void 367prepare_blend(struct NineDevice9 *device) 368{ 369 nine_convert_blend_state(&device->context.pipe_data.blend, device->context.rs); 370 device->context.commit |= NINE_STATE_COMMIT_BLEND; 371} 372 373static inline void 374prepare_dsa(struct NineDevice9 *device) 375{ 376 nine_convert_dsa_state(&device->context.pipe_data.dsa, device->context.rs); 377 device->context.commit |= NINE_STATE_COMMIT_DSA; 378} 379 380static inline void 381prepare_rasterizer(struct NineDevice9 *device) 382{ 383 nine_convert_rasterizer_state(device, &device->context.pipe_data.rast, device->context.rs); 384 device->context.commit |= NINE_STATE_COMMIT_RASTERIZER; 385} 386 387static void 388prepare_vs_constants_userbuf_swvp(struct NineDevice9 *device) 389{ 390 struct nine_context *context = &device->context; 391 392 if (context->changed.vs_const_f || context->changed.group & NINE_STATE_SWVP) { 393 struct pipe_constant_buffer cb; 394 395 cb.buffer_offset = 0; 396 cb.buffer_size = 4096 * sizeof(float[4]); 397 cb.user_buffer = context->vs_const_f_swvp; 398 399 if (context->vs->lconstf.ranges) { 400 const struct nine_lconstf *lconstf = &(context->vs->lconstf); 401 const struct nine_range *r = lconstf->ranges; 402 unsigned n = 0; 403 float *dst = context->vs_lconstf_temp; 404 float *src = (float *)cb.user_buffer; 405 memcpy(dst, src, cb.buffer_size); 406 while (r) { 407 unsigned p = r->bgn; 408 unsigned c = r->end - r->bgn; 409 memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); 410 n += c; 411 r = r->next; 412 } 413 cb.user_buffer = dst; 414 } 415 416 context->pipe_data.cb0_swvp.buffer_offset = cb.buffer_offset; 417 context->pipe_data.cb0_swvp.buffer_size = cb.buffer_size; 418 context->pipe_data.cb0_swvp.user_buffer = cb.user_buffer; 419 420 cb.user_buffer = (int8_t *)cb.user_buffer + 4096 * sizeof(float[4]); 421 context->pipe_data.cb1_swvp.buffer_offset = cb.buffer_offset; 422 context->pipe_data.cb1_swvp.buffer_size = cb.buffer_size; 423 context->pipe_data.cb1_swvp.user_buffer = cb.user_buffer; 424 425 context->changed.vs_const_f = 0; 426 } 427 428 if (context->changed.vs_const_i || context->changed.group & NINE_STATE_SWVP) { 429 struct pipe_constant_buffer cb; 430 431 cb.buffer_offset = 0; 432 cb.buffer_size = 2048 * sizeof(float[4]); 433 cb.user_buffer = context->vs_const_i; 434 435 context->pipe_data.cb2_swvp.buffer_offset = cb.buffer_offset; 436 context->pipe_data.cb2_swvp.buffer_size = cb.buffer_size; 437 context->pipe_data.cb2_swvp.user_buffer = cb.user_buffer; 438 context->changed.vs_const_i = 0; 439 } 440 441 if (context->changed.vs_const_b || context->changed.group & NINE_STATE_SWVP) { 442 struct pipe_constant_buffer cb; 443 444 cb.buffer_offset = 0; 445 cb.buffer_size = 512 * sizeof(float[4]); 446 cb.user_buffer = context->vs_const_b; 447 448 context->pipe_data.cb3_swvp.buffer_offset = cb.buffer_offset; 449 context->pipe_data.cb3_swvp.buffer_size = cb.buffer_size; 450 context->pipe_data.cb3_swvp.user_buffer = cb.user_buffer; 451 context->changed.vs_const_b = 0; 452 } 453 454 context->changed.group &= ~NINE_STATE_VS_CONST; 455 context->commit |= NINE_STATE_COMMIT_CONST_VS; 456} 457 458static void 459prepare_vs_constants_userbuf(struct NineDevice9 *device) 460{ 461 struct nine_context *context = &device->context; 462 uint8_t *upload_ptr = NULL; 463 struct pipe_constant_buffer cb; 464 cb.buffer = NULL; 465 cb.buffer_offset = 0; 466 cb.buffer_size = context->cso_shader.vs_const_used_size; 467 cb.user_buffer = context->vs_const_f; 468 469 if (context->swvp) { 470 prepare_vs_constants_userbuf_swvp(device); 471 return; 472 } 473 474 if (context->changed.vs_const_i || context->changed.group & NINE_STATE_SWVP) { 475 int *idst = (int *)&context->vs_const_f[4 * device->max_vs_const_f]; 476 memcpy(idst, context->vs_const_i, NINE_MAX_CONST_I * sizeof(int[4])); 477 context->changed.vs_const_i = 0; 478 } 479 480 if (context->changed.vs_const_b || context->changed.group & NINE_STATE_SWVP) { 481 int *idst = (int *)&context->vs_const_f[4 * device->max_vs_const_f]; 482 uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; 483 memcpy(bdst, context->vs_const_b, NINE_MAX_CONST_B * sizeof(BOOL)); 484 context->changed.vs_const_b = 0; 485 } 486 487 if (!cb.buffer_size) 488 return; 489 490 if (context->vs->lconstf.ranges) { 491 /* TODO: Can we make it so that we don't have to copy everything ? */ 492 const struct nine_lconstf *lconstf = &(context->vs->lconstf); 493 const struct nine_range *r = lconstf->ranges; 494 unsigned n = 0; 495 float *dst = context->vs_lconstf_temp; 496 float *src = (float *)cb.user_buffer; 497 memcpy(dst, src, cb.buffer_size); 498 while (r) { 499 unsigned p = r->bgn; 500 unsigned c = r->end - r->bgn; 501 memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); 502 n += c; 503 r = r->next; 504 } 505 cb.user_buffer = dst; 506 } 507 508 /* Note: We probably don't want to do separate memcpy to 509 * upload_ptr directly, if we have to copy some constants 510 * at random locations (context->vs->lconstf.ranges), 511 * to have efficient WC. Thus for this case we really want 512 * that intermediate buffer. */ 513 514 u_upload_alloc(context->pipe->const_uploader, 515 0, 516 cb.buffer_size, 517 256, /* Be conservative about alignment */ 518 &(cb.buffer_offset), 519 &(cb.buffer), 520 (void**)&upload_ptr); 521 522 assert(cb.buffer && upload_ptr); 523 524 if (!context->cso_shader.vs_const_ranges) { 525 memcpy(upload_ptr, cb.user_buffer, cb.buffer_size); 526 } else { 527 unsigned i = 0; 528 unsigned offset = 0; 529 while (context->cso_shader.vs_const_ranges[i*2+1] != 0) { 530 memcpy(upload_ptr+offset, 531 &((float*)cb.user_buffer)[4*context->cso_shader.vs_const_ranges[i*2]], 532 context->cso_shader.vs_const_ranges[i*2+1] * sizeof(float[4])); 533 offset += context->cso_shader.vs_const_ranges[i*2+1] * sizeof(float[4]); 534 i++; 535 } 536 } 537 538 u_upload_unmap(context->pipe->const_uploader); 539 cb.user_buffer = NULL; 540 541 /* Free previous resource */ 542 pipe_resource_reference(&context->pipe_data.cb_vs.buffer, NULL); 543 544 context->pipe_data.cb_vs = cb; 545 context->changed.vs_const_f = 0; 546 547 context->changed.group &= ~NINE_STATE_VS_CONST; 548 context->commit |= NINE_STATE_COMMIT_CONST_VS; 549} 550 551static void 552prepare_ps_constants_userbuf(struct NineDevice9 *device) 553{ 554 struct nine_context *context = &device->context; 555 uint8_t *upload_ptr = NULL; 556 struct pipe_constant_buffer cb; 557 cb.buffer = NULL; 558 cb.buffer_offset = 0; 559 cb.buffer_size = context->cso_shader.ps_const_used_size; 560 cb.user_buffer = context->ps_const_f; 561 562 if (context->changed.ps_const_i) { 563 int *idst = (int *)&context->ps_const_f[4 * device->max_ps_const_f]; 564 memcpy(idst, context->ps_const_i, sizeof(context->ps_const_i)); 565 context->changed.ps_const_i = 0; 566 } 567 if (context->changed.ps_const_b) { 568 int *idst = (int *)&context->ps_const_f[4 * device->max_ps_const_f]; 569 uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; 570 memcpy(bdst, context->ps_const_b, sizeof(context->ps_const_b)); 571 context->changed.ps_const_b = 0; 572 } 573 574 /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */ 575 if (context->ps->bumpenvmat_needed) { 576 memcpy(context->ps_lconstf_temp, cb.user_buffer, 8 * sizeof(float[4])); 577 memcpy(&context->ps_lconstf_temp[4 * 8], &device->context.bumpmap_vars, sizeof(device->context.bumpmap_vars)); 578 579 cb.user_buffer = context->ps_lconstf_temp; 580 } 581 582 if (context->ps->byte_code.version < 0x30 && 583 context->rs[D3DRS_FOGENABLE]) { 584 float *dst = &context->ps_lconstf_temp[4 * 32]; 585 if (cb.user_buffer != context->ps_lconstf_temp) { 586 memcpy(context->ps_lconstf_temp, cb.user_buffer, 32 * sizeof(float[4])); 587 cb.user_buffer = context->ps_lconstf_temp; 588 } 589 590 d3dcolor_to_rgba(dst, context->rs[D3DRS_FOGCOLOR]); 591 if (context->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) { 592 dst[4] = asfloat(context->rs[D3DRS_FOGEND]); 593 dst[5] = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART])); 594 } else if (context->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) { 595 dst[4] = asfloat(context->rs[D3DRS_FOGDENSITY]); 596 } 597 } 598 599 if (!cb.buffer_size) 600 return; 601 602 u_upload_alloc(context->pipe->const_uploader, 603 0, 604 cb.buffer_size, 605 256, /* Be conservative about alignment */ 606 &(cb.buffer_offset), 607 &(cb.buffer), 608 (void**)&upload_ptr); 609 610 assert(cb.buffer && upload_ptr); 611 612 if (!context->cso_shader.ps_const_ranges) { 613 memcpy(upload_ptr, cb.user_buffer, cb.buffer_size); 614 } else { 615 unsigned i = 0; 616 unsigned offset = 0; 617 while (context->cso_shader.ps_const_ranges[i*2+1] != 0) { 618 memcpy(upload_ptr+offset, 619 &((float*)cb.user_buffer)[4*context->cso_shader.ps_const_ranges[i*2]], 620 context->cso_shader.ps_const_ranges[i*2+1] * sizeof(float[4])); 621 offset += context->cso_shader.ps_const_ranges[i*2+1] * sizeof(float[4]); 622 i++; 623 } 624 } 625 626 u_upload_unmap(context->pipe->const_uploader); 627 cb.user_buffer = NULL; 628 629 /* Free previous resource */ 630 pipe_resource_reference(&context->pipe_data.cb_ps.buffer, NULL); 631 632 context->pipe_data.cb_ps = cb; 633 context->changed.ps_const_f = 0; 634 635 context->changed.group &= ~NINE_STATE_PS_CONST; 636 context->commit |= NINE_STATE_COMMIT_CONST_PS; 637} 638 639static inline uint32_t 640prepare_vs(struct NineDevice9 *device, uint8_t shader_changed) 641{ 642 struct nine_context *context = &device->context; 643 struct NineVertexShader9 *vs = context->vs; 644 uint32_t changed_group = 0; 645 int has_key_changed = 0; 646 647 if (likely(context->programmable_vs)) 648 has_key_changed = NineVertexShader9_UpdateKey(vs, device); 649 650 if (!shader_changed && !has_key_changed) 651 return 0; 652 653 /* likely because we dislike FF */ 654 if (likely(context->programmable_vs)) { 655 context->cso_shader.vs = NineVertexShader9_GetVariant(vs, 656 &context->cso_shader.vs_const_ranges, 657 &context->cso_shader.vs_const_used_size); 658 } else { 659 vs = device->ff.vs; 660 context->cso_shader.vs = vs->ff_cso; 661 } 662 663 if (context->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) { 664 context->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size; 665 changed_group |= NINE_STATE_RASTERIZER; 666 } 667 668 if ((context->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask) 669 /* Bound dummy sampler. */ 670 changed_group |= NINE_STATE_SAMPLER; 671 672 context->commit |= NINE_STATE_COMMIT_VS; 673 return changed_group; 674} 675 676static inline uint32_t 677prepare_ps(struct NineDevice9 *device, uint8_t shader_changed) 678{ 679 struct nine_context *context = &device->context; 680 struct NinePixelShader9 *ps = context->ps; 681 uint32_t changed_group = 0; 682 int has_key_changed = 0; 683 684 if (likely(ps)) 685 has_key_changed = NinePixelShader9_UpdateKey(ps, context); 686 687 if (!shader_changed && !has_key_changed) 688 return 0; 689 690 if (likely(ps)) { 691 context->cso_shader.ps = NinePixelShader9_GetVariant(ps, 692 &context->cso_shader.ps_const_ranges, 693 &context->cso_shader.ps_const_used_size); 694 } else { 695 ps = device->ff.ps; 696 context->cso_shader.ps = ps->ff_cso; 697 } 698 699 if ((context->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask) 700 /* Bound dummy sampler. */ 701 changed_group |= NINE_STATE_SAMPLER; 702 703 context->commit |= NINE_STATE_COMMIT_PS; 704 return changed_group; 705} 706 707/* State preparation incremental */ 708 709/* State preparation + State commit */ 710 711static void 712update_framebuffer(struct NineDevice9 *device, bool is_clear) 713{ 714 struct nine_context *context = &device->context; 715 struct pipe_context *pipe = context->pipe; 716 struct pipe_framebuffer_state *fb = &context->pipe_data.fb; 717 unsigned i; 718 struct NineSurface9 *rt0 = context->rt[0]; 719 unsigned w = rt0->desc.Width; 720 unsigned h = rt0->desc.Height; 721 unsigned nr_samples = rt0->base.info.nr_samples; 722 unsigned ps_mask = context->ps ? context->ps->rt_mask : 1; 723 unsigned mask = is_clear ? 0xf : ps_mask; 724 const int sRGB = context->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; 725 726 DBG("\n"); 727 728 context->rt_mask = 0x0; 729 fb->nr_cbufs = 0; 730 731 /* all render targets must have the same size and the depth buffer must be 732 * bigger. Multisample has to match, according to spec. But some apps do 733 * things wrong there, and no error is returned. The behaviour they get 734 * apparently is that depth buffer is disabled if it doesn't match. 735 * Surely the same for render targets. */ 736 737 /* Special case: D3DFMT_NULL is used to bound no real render target, 738 * but render to depth buffer. We have to not take into account the render 739 * target info. TODO: know what should happen when there are several render targers 740 * and the first one is D3DFMT_NULL */ 741 if (rt0->desc.Format == D3DFMT_NULL && context->ds) { 742 w = context->ds->desc.Width; 743 h = context->ds->desc.Height; 744 nr_samples = context->ds->base.info.nr_samples; 745 } 746 747 for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { 748 struct NineSurface9 *rt = context->rt[i]; 749 750 if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) && 751 rt->desc.Width == w && rt->desc.Height == h && 752 rt->base.info.nr_samples == nr_samples) { 753 fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB); 754 context->rt_mask |= 1 << i; 755 fb->nr_cbufs = i + 1; 756 } else { 757 /* Color outputs must match RT slot, 758 * drivers will have to handle NULL entries for GL, too. 759 */ 760 fb->cbufs[i] = NULL; 761 } 762 } 763 764 if (context->ds && context->ds->desc.Width >= w && 765 context->ds->desc.Height >= h && 766 context->ds->base.info.nr_samples == nr_samples) { 767 fb->zsbuf = NineSurface9_GetSurface(context->ds, 0); 768 } else { 769 fb->zsbuf = NULL; 770 } 771 772 fb->width = w; 773 fb->height = h; 774 775 pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */ 776 777 if (is_clear && context->rt_mask == ps_mask) 778 context->changed.group &= ~NINE_STATE_FB; 779} 780 781static void 782update_viewport(struct NineDevice9 *device) 783{ 784 struct nine_context *context = &device->context; 785 const D3DVIEWPORT9 *vport = &context->viewport; 786 struct pipe_viewport_state pvport; 787 788 /* D3D coordinates are: 789 * -1 .. +1 for X,Y and 790 * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz) 791 */ 792 pvport.scale[0] = (float)vport->Width * 0.5f; 793 pvport.scale[1] = (float)vport->Height * -0.5f; 794 pvport.scale[2] = vport->MaxZ - vport->MinZ; 795 pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X; 796 pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y; 797 pvport.translate[2] = vport->MinZ; 798 pvport.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X; 799 pvport.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y; 800 pvport.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z; 801 pvport.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W; 802 803 /* We found R600 and SI cards have some imprecision 804 * on the barycentric coordinates used for interpolation. 805 * Some shaders rely on having something precise. 806 * We found that the proprietary driver has the imprecision issue, 807 * except when the render target width and height are powers of two. 808 * It is using some sort of workaround for these cases 809 * which covers likely all the cases the applications rely 810 * on something precise. 811 * We haven't found the workaround, but it seems like it's better 812 * for applications if the imprecision is biased towards infinity 813 * instead of -infinity (which is what measured). So shift slightly 814 * the viewport: not enough to change rasterization result (in particular 815 * for multisampling), but enough to make the imprecision biased 816 * towards infinity. We do this shift only if render target width and 817 * height are powers of two. 818 * Solves 'red shadows' bug on UE3 games. 819 */ 820 if (device->driver_bugs.buggy_barycentrics && 821 ((vport->Width & (vport->Width-1)) == 0) && 822 ((vport->Height & (vport->Height-1)) == 0)) { 823 pvport.translate[0] -= 1.0f / 128.0f; 824 pvport.translate[1] -= 1.0f / 128.0f; 825 } 826 827 cso_set_viewport(context->cso, &pvport); 828} 829 830/* Loop through VS inputs and pick the vertex elements with the declared 831 * usage from the vertex declaration, then insert the instance divisor from 832 * the stream source frequency setting. 833 */ 834static void 835update_vertex_elements(struct NineDevice9 *device) 836{ 837 struct nine_context *context = &device->context; 838 const struct NineVertexDeclaration9 *vdecl = device->context.vdecl; 839 const struct NineVertexShader9 *vs; 840 unsigned n, b, i; 841 int index; 842 int8_t vdecl_index_map[16]; /* vs->num_inputs <= 16 */ 843 uint16_t used_streams = 0; 844 int dummy_vbo_stream = -1; 845 BOOL need_dummy_vbo = FALSE; 846 struct cso_velems_state ve; 847 848 context->stream_usage_mask = 0; 849 memset(vdecl_index_map, -1, 16); 850 vs = context->programmable_vs ? context->vs : device->ff.vs; 851 852 if (vdecl) { 853 for (n = 0; n < vs->num_inputs; ++n) { 854 DBG("looking up input %u (usage %u) from vdecl(%p)\n", 855 n, vs->input_map[n].ndecl, vdecl); 856 857 for (i = 0; i < vdecl->nelems; i++) { 858 if (vdecl->usage_map[i] == vs->input_map[n].ndecl) { 859 vdecl_index_map[n] = i; 860 used_streams |= BITFIELD_BIT(vdecl->elems[i].vertex_buffer_index); 861 break; 862 } 863 } 864 if (vdecl_index_map[n] < 0) 865 need_dummy_vbo = TRUE; 866 } 867 } else { 868 /* No vertex declaration. Likely will never happen in practice, 869 * but we need not crash on this */ 870 need_dummy_vbo = TRUE; 871 } 872 873 if (need_dummy_vbo) { 874 u_foreach_bit(bit, BITFIELD_MASK(device->caps.MaxStreams) & ~used_streams) { 875 dummy_vbo_stream = bit; 876 break; 877 } 878 } 879 /* there are less vertex shader inputs than stream slots, 880 * so if we need a slot for the dummy vbo, we should have found one */ 881 assert (!need_dummy_vbo || dummy_vbo_stream != -1); 882 883 for (n = 0; n < vs->num_inputs; ++n) { 884 index = vdecl_index_map[n]; 885 if (index >= 0) { 886 ve.velems[n] = vdecl->elems[index]; 887 b = ve.velems[n].vertex_buffer_index; 888 context->stream_usage_mask |= 1 << b; 889 /* XXX wine just uses 1 here: */ 890 if (context->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA) 891 ve.velems[n].instance_divisor = context->stream_freq[b] & 0x7FFFFF; 892 } else { 893 /* if the vertex declaration is incomplete compared to what the 894 * vertex shader needs, we bind a dummy vbo with 0 0 0 0. 895 * This is not precised by the spec, but is the behaviour 896 * tested on win */ 897 ve.velems[n].vertex_buffer_index = dummy_vbo_stream; 898 ve.velems[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 899 ve.velems[n].src_offset = 0; 900 ve.velems[n].instance_divisor = 0; 901 ve.velems[n].dual_slot = false; 902 } 903 } 904 905 if (context->dummy_vbo_bound_at != dummy_vbo_stream) { 906 if (context->dummy_vbo_bound_at >= 0) 907 context->changed.vtxbuf |= 1 << context->dummy_vbo_bound_at; 908 if (dummy_vbo_stream >= 0) { 909 context->changed.vtxbuf |= 1 << dummy_vbo_stream; 910 context->vbo_bound_done = FALSE; 911 } 912 context->dummy_vbo_bound_at = dummy_vbo_stream; 913 } 914 915 ve.count = vs->num_inputs; 916 cso_set_vertex_elements(context->cso, &ve); 917} 918 919static void 920update_vertex_buffers(struct NineDevice9 *device) 921{ 922 struct nine_context *context = &device->context; 923 struct pipe_context *pipe = context->pipe; 924 struct pipe_vertex_buffer dummy_vtxbuf; 925 uint32_t mask = context->changed.vtxbuf; 926 unsigned i; 927 928 DBG("mask=%x\n", mask); 929 930 if (context->dummy_vbo_bound_at >= 0) { 931 if (!context->vbo_bound_done) { 932 dummy_vtxbuf.buffer.resource = device->dummy_vbo; 933 dummy_vtxbuf.stride = 0; 934 dummy_vtxbuf.is_user_buffer = false; 935 dummy_vtxbuf.buffer_offset = 0; 936 pipe->set_vertex_buffers(pipe, context->dummy_vbo_bound_at, 937 1, 0, false, &dummy_vtxbuf); 938 context->vbo_bound_done = TRUE; 939 } 940 mask &= ~(1 << context->dummy_vbo_bound_at); 941 } 942 943 for (i = 0; mask; mask >>= 1, ++i) { 944 if (mask & 1) { 945 if (context->vtxbuf[i].buffer.resource) 946 pipe->set_vertex_buffers(pipe, i, 1, 0, false, &context->vtxbuf[i]); 947 else 948 pipe->set_vertex_buffers(pipe, i, 0, 1, false, NULL); 949 } 950 } 951 952 context->changed.vtxbuf = 0; 953} 954 955static inline boolean 956update_sampler_derived(struct nine_context *context, unsigned s) 957{ 958 boolean changed = FALSE; 959 960 if (context->samp[s][NINED3DSAMP_SHADOW] != context->texture[s].shadow) { 961 changed = TRUE; 962 context->samp[s][NINED3DSAMP_SHADOW] = context->texture[s].shadow; 963 } 964 965 if (context->samp[s][NINED3DSAMP_CUBETEX] != 966 (context->texture[s].type == D3DRTYPE_CUBETEXTURE)) { 967 changed = TRUE; 968 context->samp[s][NINED3DSAMP_CUBETEX] = 969 context->texture[s].type == D3DRTYPE_CUBETEXTURE; 970 } 971 972 if (context->samp[s][D3DSAMP_MIPFILTER] != D3DTEXF_NONE) { 973 int lod = context->samp[s][D3DSAMP_MAXMIPLEVEL] - context->texture[s].lod; 974 if (lod < 0) 975 lod = 0; 976 if (context->samp[s][NINED3DSAMP_MINLOD] != lod) { 977 changed = TRUE; 978 context->samp[s][NINED3DSAMP_MINLOD] = lod; 979 } 980 } else { 981 context->changed.sampler[s] &= ~0x300; /* lod changes irrelevant */ 982 } 983 984 return changed; 985} 986 987/* TODO: add sRGB override to pipe_sampler_state ? */ 988static void 989update_textures_and_samplers(struct NineDevice9 *device) 990{ 991 struct nine_context *context = &device->context; 992 struct pipe_context *pipe = context->pipe; 993 struct pipe_sampler_view *view[NINE_MAX_SAMPLERS]; 994 unsigned num_textures = 0; 995 boolean commit_samplers; 996 uint16_t sampler_mask = context->ps ? context->ps->sampler_mask : 997 device->ff.ps->sampler_mask; 998 999 commit_samplers = FALSE; 1000 const uint16_t ps_mask = sampler_mask | context->enabled_samplers_mask_ps; 1001 context->bound_samplers_mask_ps = ps_mask; 1002 num_textures = util_last_bit(ps_mask) + 1; 1003 /* iterate over the enabled samplers */ 1004 u_foreach_bit(i, context->enabled_samplers_mask_ps) { 1005 const unsigned s = NINE_SAMPLER_PS(i); 1006 int sRGB = context->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; 1007 1008 view[i] = context->texture[s].view[sRGB]; 1009 1010 if (update_sampler_derived(context, s) || (context->changed.sampler[s] & 0x05fe)) { 1011 context->changed.sampler[s] = 0; 1012 commit_samplers = TRUE; 1013 nine_convert_sampler_state(context->cso, s, context->samp[s]); 1014 } 1015 } 1016 /* iterate over the dummy samplers */ 1017 u_foreach_bit(i, sampler_mask & ~context->enabled_samplers_mask_ps) { 1018 const unsigned s = NINE_SAMPLER_PS(i); 1019 /* Bind dummy sampler. We do not bind dummy sampler when 1020 * it is not needed because it could add overhead. The 1021 * dummy sampler should have r=g=b=0 and a=1. We do not 1022 * unbind dummy sampler directly when they are not needed 1023 * anymore, but they're going to be removed as long as texture 1024 * or sampler states are changed. */ 1025 view[i] = device->dummy_sampler_view; 1026 1027 cso_single_sampler(context->cso, PIPE_SHADER_FRAGMENT, 1028 s - NINE_SAMPLER_PS(0), &device->dummy_sampler_state); 1029 1030 commit_samplers = TRUE; 1031 context->changed.sampler[s] = ~0; 1032 } 1033 /* fill in unused samplers */ 1034 u_foreach_bit(i, BITFIELD_MASK(num_textures) & ~ps_mask) 1035 view[i] = NULL; 1036 1037 pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_textures, 1038 num_textures < context->enabled_sampler_count_ps ? context->enabled_sampler_count_ps - num_textures : 0, 1039 false, view); 1040 context->enabled_sampler_count_ps = num_textures; 1041 1042 if (commit_samplers) 1043 cso_single_sampler_done(context->cso, PIPE_SHADER_FRAGMENT); 1044 1045 commit_samplers = FALSE; 1046 sampler_mask = context->programmable_vs ? context->vs->sampler_mask : 0; 1047 const uint16_t vs_mask = sampler_mask | context->enabled_samplers_mask_vs; 1048 context->bound_samplers_mask_vs = vs_mask; 1049 num_textures = util_last_bit(vs_mask) + 1; 1050 u_foreach_bit(i, context->enabled_samplers_mask_vs) { 1051 const unsigned s = NINE_SAMPLER_VS(i); 1052 int sRGB = context->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; 1053 1054 view[i] = context->texture[s].view[sRGB]; 1055 1056 if (update_sampler_derived(context, s) || (context->changed.sampler[s] & 0x05fe)) { 1057 context->changed.sampler[s] = 0; 1058 commit_samplers = TRUE; 1059 nine_convert_sampler_state(context->cso, s, context->samp[s]); 1060 } 1061 } 1062 u_foreach_bit(i, sampler_mask & ~context->enabled_samplers_mask_vs) { 1063 const unsigned s = NINE_SAMPLER_VS(i); 1064 /* Bind dummy sampler. We do not bind dummy sampler when 1065 * it is not needed because it could add overhead. The 1066 * dummy sampler should have r=g=b=0 and a=1. We do not 1067 * unbind dummy sampler directly when they are not needed 1068 * anymore, but they're going to be removed as long as texture 1069 * or sampler states are changed. */ 1070 view[i] = device->dummy_sampler_view; 1071 1072 cso_single_sampler(context->cso, PIPE_SHADER_VERTEX, 1073 s - NINE_SAMPLER_VS(0), &device->dummy_sampler_state); 1074 1075 commit_samplers = TRUE; 1076 context->changed.sampler[s] = ~0; 1077 } 1078 /* fill in unused samplers */ 1079 u_foreach_bit(i, BITFIELD_MASK(num_textures) & ~vs_mask) 1080 view[i] = NULL; 1081 1082 pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, num_textures, 1083 num_textures < context->enabled_sampler_count_vs ? context->enabled_sampler_count_vs - num_textures : 0, 1084 false, view); 1085 context->enabled_sampler_count_vs = num_textures; 1086 1087 if (commit_samplers) 1088 cso_single_sampler_done(context->cso, PIPE_SHADER_VERTEX); 1089} 1090 1091/* State commit only */ 1092 1093static inline void 1094commit_blend(struct NineDevice9 *device) 1095{ 1096 struct nine_context *context = &device->context; 1097 1098 cso_set_blend(context->cso, &context->pipe_data.blend); 1099} 1100 1101static inline void 1102commit_dsa(struct NineDevice9 *device) 1103{ 1104 struct nine_context *context = &device->context; 1105 1106 cso_set_depth_stencil_alpha(context->cso, &context->pipe_data.dsa); 1107} 1108 1109static inline void 1110commit_scissor(struct NineDevice9 *device) 1111{ 1112 struct nine_context *context = &device->context; 1113 struct pipe_context *pipe = context->pipe; 1114 1115 pipe->set_scissor_states(pipe, 0, 1, &context->scissor); 1116} 1117 1118static inline void 1119commit_rasterizer(struct NineDevice9 *device) 1120{ 1121 struct nine_context *context = &device->context; 1122 1123 cso_set_rasterizer(context->cso, &context->pipe_data.rast); 1124} 1125 1126static inline void 1127commit_vs_constants(struct NineDevice9 *device) 1128{ 1129 struct nine_context *context = &device->context; 1130 struct pipe_context *pipe = context->pipe; 1131 1132 if (unlikely(!context->programmable_vs)) 1133 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, false, &context->pipe_data.cb_vs_ff); 1134 else { 1135 if (context->swvp) { 1136 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, false, &context->pipe_data.cb0_swvp); 1137 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 1, false, &context->pipe_data.cb1_swvp); 1138 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 2, false, &context->pipe_data.cb2_swvp); 1139 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 3, false, &context->pipe_data.cb3_swvp); 1140 } else { 1141 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, false, &context->pipe_data.cb_vs); 1142 } 1143 } 1144} 1145 1146static inline void 1147commit_ps_constants(struct NineDevice9 *device) 1148{ 1149 struct nine_context *context = &device->context; 1150 struct pipe_context *pipe = context->pipe; 1151 1152 if (unlikely(!context->ps)) 1153 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, false, &context->pipe_data.cb_ps_ff); 1154 else 1155 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, false, &context->pipe_data.cb_ps); 1156} 1157 1158static inline void 1159commit_vs(struct NineDevice9 *device) 1160{ 1161 struct nine_context *context = &device->context; 1162 1163 context->pipe->bind_vs_state(context->pipe, context->cso_shader.vs); 1164} 1165 1166 1167static inline void 1168commit_ps(struct NineDevice9 *device) 1169{ 1170 struct nine_context *context = &device->context; 1171 1172 context->pipe->bind_fs_state(context->pipe, context->cso_shader.ps); 1173} 1174/* State Update */ 1175 1176#define NINE_STATE_SHADER_CHANGE_VS \ 1177 (NINE_STATE_VS | \ 1178 NINE_STATE_TEXTURE | \ 1179 NINE_STATE_VS_PARAMS_MISC | \ 1180 NINE_STATE_SWVP) 1181 1182#define NINE_STATE_SHADER_CHANGE_PS \ 1183 (NINE_STATE_PS | \ 1184 NINE_STATE_TEXTURE | \ 1185 NINE_STATE_PS_PARAMS_MISC) 1186 1187#define NINE_STATE_FREQUENT \ 1188 (NINE_STATE_RASTERIZER | \ 1189 NINE_STATE_TEXTURE | \ 1190 NINE_STATE_SAMPLER | \ 1191 NINE_STATE_VS_CONST | \ 1192 NINE_STATE_PS_CONST | \ 1193 NINE_STATE_MULTISAMPLE) 1194 1195#define NINE_STATE_COMMON \ 1196 (NINE_STATE_FB | \ 1197 NINE_STATE_BLEND | \ 1198 NINE_STATE_DSA | \ 1199 NINE_STATE_VIEWPORT | \ 1200 NINE_STATE_VDECL | \ 1201 NINE_STATE_IDXBUF | \ 1202 NINE_STATE_STREAMFREQ) 1203 1204#define NINE_STATE_RARE \ 1205 (NINE_STATE_SCISSOR | \ 1206 NINE_STATE_BLEND_COLOR | \ 1207 NINE_STATE_STENCIL_REF | \ 1208 NINE_STATE_SAMPLE_MASK) 1209 1210static void 1211nine_update_state(struct NineDevice9 *device) 1212{ 1213 struct nine_context *context = &device->context; 1214 struct pipe_context *pipe = context->pipe; 1215 uint32_t group; 1216 1217 DBG("changed state groups: %x\n", context->changed.group); 1218 1219 /* NOTE: We may want to use the cso cache for everything, or let 1220 * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't 1221 * have to care about state being clobbered here and could merge this back 1222 * into update_textures. Except, we also need to re-validate textures that 1223 * may be dirty anyway, even if no texture bindings changed. 1224 */ 1225 1226 /* ff_update may change VS/PS dirty bits */ 1227 if (unlikely(!context->programmable_vs || !context->ps)) 1228 nine_ff_update(device); 1229 group = context->changed.group; 1230 1231 if (group & (NINE_STATE_SHADER_CHANGE_VS | NINE_STATE_SHADER_CHANGE_PS)) { 1232 if (group & NINE_STATE_SHADER_CHANGE_VS) 1233 group |= prepare_vs(device, (group & NINE_STATE_VS) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/ 1234 if (group & NINE_STATE_SHADER_CHANGE_PS) 1235 group |= prepare_ps(device, (group & NINE_STATE_PS) != 0); 1236 } 1237 1238 if (group & (NINE_STATE_COMMON | NINE_STATE_VS)) { 1239 if (group & NINE_STATE_FB) 1240 update_framebuffer(device, FALSE); 1241 if (group & NINE_STATE_BLEND) 1242 prepare_blend(device); 1243 if (group & NINE_STATE_DSA) 1244 prepare_dsa(device); 1245 if (group & NINE_STATE_VIEWPORT) 1246 update_viewport(device); 1247 if (group & (NINE_STATE_VDECL | NINE_STATE_VS | NINE_STATE_STREAMFREQ)) 1248 update_vertex_elements(device); 1249 } 1250 1251 if (likely(group & (NINE_STATE_FREQUENT | NINE_STATE_VS | NINE_STATE_PS | NINE_STATE_SWVP))) { 1252 if (group & NINE_STATE_MULTISAMPLE) 1253 group |= check_multisample(device); 1254 if (group & NINE_STATE_RASTERIZER) 1255 prepare_rasterizer(device); 1256 if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER)) 1257 update_textures_and_samplers(device); 1258 if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS | NINE_STATE_SWVP)) && context->programmable_vs) 1259 prepare_vs_constants_userbuf(device); 1260 if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && context->ps) 1261 prepare_ps_constants_userbuf(device); 1262 } 1263 1264 if (context->changed.vtxbuf) 1265 update_vertex_buffers(device); 1266 1267 if (context->commit & NINE_STATE_COMMIT_BLEND) 1268 commit_blend(device); 1269 if (context->commit & NINE_STATE_COMMIT_DSA) 1270 commit_dsa(device); 1271 if (context->commit & NINE_STATE_COMMIT_RASTERIZER) 1272 commit_rasterizer(device); 1273 if (context->commit & NINE_STATE_COMMIT_CONST_VS) 1274 commit_vs_constants(device); 1275 if (context->commit & NINE_STATE_COMMIT_CONST_PS) 1276 commit_ps_constants(device); 1277 if (context->commit & NINE_STATE_COMMIT_VS) 1278 commit_vs(device); 1279 if (context->commit & NINE_STATE_COMMIT_PS) 1280 commit_ps(device); 1281 1282 context->commit = 0; 1283 1284 if (unlikely(context->changed.ucp)) { 1285 pipe->set_clip_state(pipe, &context->clip); 1286 context->changed.ucp = FALSE; 1287 } 1288 1289 if (unlikely(group & NINE_STATE_RARE)) { 1290 if (group & NINE_STATE_SCISSOR) 1291 commit_scissor(device); 1292 if (group & NINE_STATE_BLEND_COLOR) { 1293 struct pipe_blend_color color; 1294 d3dcolor_to_rgba(&color.color[0], context->rs[D3DRS_BLENDFACTOR]); 1295 pipe->set_blend_color(pipe, &color); 1296 } 1297 if (group & NINE_STATE_SAMPLE_MASK) { 1298 if (context->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) { 1299 pipe->set_sample_mask(pipe, ~0); 1300 } else { 1301 pipe->set_sample_mask(pipe, context->rs[D3DRS_MULTISAMPLEMASK]); 1302 } 1303 } 1304 if (group & NINE_STATE_STENCIL_REF) { 1305 struct pipe_stencil_ref ref; 1306 ref.ref_value[0] = context->rs[D3DRS_STENCILREF]; 1307 ref.ref_value[1] = ref.ref_value[0]; 1308 pipe->set_stencil_ref(pipe, ref); 1309 } 1310 } 1311 1312 context->changed.group &= 1313 (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST); 1314 1315 DBG("finished\n"); 1316} 1317 1318#define RESZ_CODE 0x7fa05000 1319 1320static void 1321NineDevice9_ResolveZ( struct NineDevice9 *device ) 1322{ 1323 struct nine_context *context = &device->context; 1324 const struct util_format_description *desc; 1325 struct NineSurface9 *source = context->ds; 1326 struct pipe_resource *src, *dst; 1327 struct pipe_blit_info blit; 1328 1329 DBG("RESZ resolve\n"); 1330 1331 if (!source || !context->texture[0].enabled || 1332 context->texture[0].type != D3DRTYPE_TEXTURE) 1333 return; 1334 1335 src = source->base.resource; 1336 dst = context->texture[0].resource; 1337 1338 if (!src || !dst) 1339 return; 1340 1341 /* check dst is depth format. we know already for src */ 1342 desc = util_format_description(dst->format); 1343 if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) 1344 return; 1345 1346 memset(&blit, 0, sizeof(blit)); 1347 blit.src.resource = src; 1348 blit.src.level = 0; 1349 blit.src.format = src->format; 1350 blit.src.box.z = 0; 1351 blit.src.box.depth = 1; 1352 blit.src.box.x = 0; 1353 blit.src.box.y = 0; 1354 blit.src.box.width = src->width0; 1355 blit.src.box.height = src->height0; 1356 1357 blit.dst.resource = dst; 1358 blit.dst.level = 0; 1359 blit.dst.format = dst->format; 1360 blit.dst.box.z = 0; 1361 blit.dst.box.depth = 1; 1362 blit.dst.box.x = 0; 1363 blit.dst.box.y = 0; 1364 blit.dst.box.width = dst->width0; 1365 blit.dst.box.height = dst->height0; 1366 1367 blit.mask = PIPE_MASK_ZS; 1368 blit.filter = PIPE_TEX_FILTER_NEAREST; 1369 blit.scissor_enable = FALSE; 1370 1371 context->pipe->blit(context->pipe, &blit); 1372} 1373 1374#define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1') 1375#define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0') 1376#define FETCH4_ENABLE MAKEFOURCC('G', 'E', 'T', '4') 1377#define FETCH4_DISABLE MAKEFOURCC('G', 'E', 'T', '1') 1378 1379/* Nine_context functions. 1380 * Serialized through CSMT macros. 1381 */ 1382 1383static void 1384nine_context_set_texture_apply(struct NineDevice9 *device, 1385 DWORD stage, 1386 DWORD fetch4_shadow_enabled, 1387 DWORD lod, 1388 D3DRESOURCETYPE type, 1389 uint8_t pstype, 1390 struct pipe_resource *res, 1391 struct pipe_sampler_view *view0, 1392 struct pipe_sampler_view *view1); 1393 1394static void 1395nine_context_set_pixel_shader_constant_i_transformed(struct NineDevice9 *device, 1396 UINT StartRegister, 1397 const int *pConstantData, 1398 unsigned pConstantData_size, 1399 UINT Vector4iCount); 1400 1401CSMT_ITEM_NO_WAIT(nine_context_set_render_state, 1402 ARG_VAL(D3DRENDERSTATETYPE, State), 1403 ARG_VAL(DWORD, Value)) 1404{ 1405 struct nine_context *context = &device->context; 1406 1407 /* Amd hacks (equivalent to GL extensions) */ 1408 if (unlikely(State == D3DRS_POINTSIZE)) { 1409 if (Value == RESZ_CODE) { 1410 NineDevice9_ResolveZ(device); 1411 return; 1412 } 1413 1414 /* NINED3DRS_ALPHACOVERAGE: 1415 * bit 0: NVIDIA alpha to coverage 1416 * bit 1: NVIDIA ATOC state active 1417 * bit 2: AMD alpha to coverage 1418 * These need to be separate else the set of states to 1419 * disable NVIDIA alpha to coverage can disable the AMD one */ 1420 if (Value == ALPHA_TO_COVERAGE_ENABLE || 1421 Value == ALPHA_TO_COVERAGE_DISABLE) { 1422 context->rs[NINED3DRS_ALPHACOVERAGE] &= 3; 1423 context->rs[NINED3DRS_ALPHACOVERAGE] |= (Value == ALPHA_TO_COVERAGE_ENABLE) ? 4 : 0; 1424 context->changed.group |= NINE_STATE_BLEND; 1425 return; 1426 } 1427 } 1428 1429 /* NV hack */ 1430 if (unlikely(State == D3DRS_ADAPTIVETESS_Y)) { 1431 if (Value == D3DFMT_ATOC || (Value == D3DFMT_UNKNOWN && context->rs[NINED3DRS_ALPHACOVERAGE] & 3)) { 1432 context->rs[NINED3DRS_ALPHACOVERAGE] &= 4; 1433 context->rs[NINED3DRS_ALPHACOVERAGE] |= 1434 ((Value == D3DFMT_ATOC) ? 3 : 0) & (context->rs[D3DRS_ALPHATESTENABLE] ? 3 : 2); 1435 context->changed.group |= NINE_STATE_BLEND; 1436 return; 1437 } 1438 } 1439 if (unlikely(State == D3DRS_ALPHATESTENABLE && (context->rs[NINED3DRS_ALPHACOVERAGE] & 2))) { 1440 context->rs[NINED3DRS_ALPHACOVERAGE] &= 6; 1441 context->rs[NINED3DRS_ALPHACOVERAGE] |= (Value ? 1 : 0); 1442 } 1443 1444 context->rs[State] = nine_fix_render_state_value(State, Value); 1445 context->changed.group |= nine_render_state_group[State]; 1446} 1447 1448CSMT_ITEM_NO_WAIT(nine_context_set_texture_apply, 1449 ARG_VAL(DWORD, stage), 1450 ARG_VAL(DWORD, fetch4_shadow_enabled), 1451 ARG_VAL(DWORD, lod), 1452 ARG_VAL(D3DRESOURCETYPE, type), 1453 ARG_VAL(uint8_t, pstype), 1454 ARG_BIND_RES(struct pipe_resource, res), 1455 ARG_BIND_VIEW(struct pipe_sampler_view, view0), 1456 ARG_BIND_VIEW(struct pipe_sampler_view, view1)) 1457{ 1458 struct nine_context *context = &device->context; 1459 uint enabled = fetch4_shadow_enabled & 1; 1460 uint shadow = (fetch4_shadow_enabled >> 1) & 1; 1461 uint fetch4_compatible = (fetch4_shadow_enabled >> 2) & 1; 1462 1463 context->texture[stage].enabled = enabled; 1464 if (enabled) { 1465 if (stage < NINE_MAX_SAMPLERS_PS) 1466 context->enabled_samplers_mask_ps |= BITFIELD_BIT(stage - NINE_SAMPLER_PS(0)); 1467 else if (stage >= NINE_SAMPLER_VS(0)) 1468 context->enabled_samplers_mask_vs |= BITFIELD_BIT(stage - NINE_SAMPLER_VS(0)); 1469 } else { 1470 if (stage < NINE_MAX_SAMPLERS_PS) 1471 context->enabled_samplers_mask_ps &= ~BITFIELD_BIT(stage - NINE_SAMPLER_PS(0)); 1472 else if (stage >= NINE_SAMPLER_VS(0)) 1473 context->enabled_samplers_mask_vs &= ~BITFIELD_BIT(stage - NINE_SAMPLER_VS(0)); 1474 } 1475 context->samplers_shadow &= ~(1 << stage); 1476 context->samplers_shadow |= shadow << stage; 1477 context->samplers_fetch4 &= ~(1 << stage); 1478 context->samplers_fetch4 |= fetch4_compatible << stage; 1479 context->texture[stage].shadow = shadow; 1480 context->texture[stage].lod = lod; 1481 context->texture[stage].type = type; 1482 context->texture[stage].pstype = pstype; 1483 pipe_resource_reference(&context->texture[stage].resource, res); 1484 pipe_sampler_view_reference(&context->texture[stage].view[0], view0); 1485 pipe_sampler_view_reference(&context->texture[stage].view[1], view1); 1486 1487 context->changed.group |= NINE_STATE_TEXTURE; 1488} 1489 1490void 1491nine_context_set_texture(struct NineDevice9 *device, 1492 DWORD Stage, 1493 struct NineBaseTexture9 *tex) 1494{ 1495 DWORD fetch4_shadow_enabled = 0; 1496 DWORD lod = 0; 1497 D3DRESOURCETYPE type = D3DRTYPE_TEXTURE; 1498 uint8_t pstype = 0; 1499 struct pipe_resource *res = NULL; 1500 struct pipe_sampler_view *view0 = NULL, *view1 = NULL; 1501 1502 /* For managed pool, the data can be initially incomplete. 1503 * In that case, the texture is rebound later 1504 * (in NineBaseTexture9_Validate/NineBaseTexture9_UploadSelf). */ 1505 if (tex && tex->base.resource) { 1506 fetch4_shadow_enabled = 1; 1507 fetch4_shadow_enabled |= tex->shadow << 1; 1508 fetch4_shadow_enabled |= tex->fetch4_compatible << 2; 1509 lod = tex->managed.lod; 1510 type = tex->base.type; 1511 pstype = tex->pstype; 1512 res = tex->base.resource; 1513 view0 = NineBaseTexture9_GetSamplerView(tex, 0); 1514 view1 = NineBaseTexture9_GetSamplerView(tex, 1); 1515 } 1516 1517 nine_context_set_texture_apply(device, Stage, 1518 fetch4_shadow_enabled, 1519 lod, type, pstype, 1520 res, view0, view1); 1521} 1522 1523CSMT_ITEM_NO_WAIT(nine_context_set_sampler_state, 1524 ARG_VAL(DWORD, Sampler), 1525 ARG_VAL(D3DSAMPLERSTATETYPE, Type), 1526 ARG_VAL(DWORD, Value)) 1527{ 1528 struct nine_context *context = &device->context; 1529 1530 if (unlikely(Type == D3DSAMP_MIPMAPLODBIAS)) { 1531 if (Value == FETCH4_ENABLE || 1532 Value == FETCH4_DISABLE) { 1533 context->rs[NINED3DRS_FETCH4] &= ~(1 << Sampler); 1534 context->rs[NINED3DRS_FETCH4] |= (Value == FETCH4_ENABLE) << Sampler; 1535 context->changed.group |= NINE_STATE_PS_PARAMS_MISC; 1536 if (Value == FETCH4_ENABLE) 1537 WARN_ONCE("FETCH4 support is incomplete. Please report if buggy shadows."); 1538 return; 1539 } 1540 } 1541 1542 if (unlikely(!nine_check_sampler_state_value(Type, Value))) 1543 return; 1544 1545 context->samp[Sampler][Type] = Value; 1546 context->changed.group |= NINE_STATE_SAMPLER; 1547 context->changed.sampler[Sampler] |= 1 << Type; 1548} 1549 1550CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_apply, 1551 ARG_VAL(UINT, StreamNumber), 1552 ARG_BIND_RES(struct pipe_resource, res), 1553 ARG_VAL(UINT, OffsetInBytes), 1554 ARG_VAL(UINT, Stride)) 1555{ 1556 struct nine_context *context = &device->context; 1557 const unsigned i = StreamNumber; 1558 1559 /* For normal draws, these tests are useless, 1560 * but not for *Up draws */ 1561 if (context->vtxbuf[i].buffer.resource == res && 1562 context->vtxbuf[i].buffer_offset == OffsetInBytes && 1563 context->vtxbuf[i].stride == Stride) 1564 return; 1565 1566 context->vtxbuf[i].stride = Stride; 1567 context->vtxbuf[i].buffer_offset = OffsetInBytes; 1568 pipe_resource_reference(&context->vtxbuf[i].buffer.resource, res); 1569 1570 context->changed.vtxbuf |= 1 << StreamNumber; 1571} 1572 1573void 1574nine_context_set_stream_source(struct NineDevice9 *device, 1575 UINT StreamNumber, 1576 struct NineVertexBuffer9 *pVBuf9, 1577 UINT OffsetInBytes, 1578 UINT Stride) 1579{ 1580 struct pipe_resource *res = NULL; 1581 unsigned offset = 0; 1582 1583 if (pVBuf9) 1584 res = NineVertexBuffer9_GetResource(pVBuf9, &offset); 1585 /* in the future when there is internal offset, add it 1586 * to OffsetInBytes */ 1587 1588 nine_context_set_stream_source_apply(device, StreamNumber, 1589 res, offset + OffsetInBytes, 1590 Stride); 1591} 1592 1593CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_freq, 1594 ARG_VAL(UINT, StreamNumber), 1595 ARG_VAL(UINT, Setting)) 1596{ 1597 struct nine_context *context = &device->context; 1598 1599 context->stream_freq[StreamNumber] = Setting; 1600 1601 if (Setting & D3DSTREAMSOURCE_INSTANCEDATA) 1602 context->stream_instancedata_mask |= 1 << StreamNumber; 1603 else 1604 context->stream_instancedata_mask &= ~(1 << StreamNumber); 1605 1606 if (StreamNumber != 0) 1607 context->changed.group |= NINE_STATE_STREAMFREQ; 1608} 1609 1610CSMT_ITEM_NO_WAIT(nine_context_set_indices_apply, 1611 ARG_BIND_RES(struct pipe_resource, res), 1612 ARG_VAL(UINT, IndexSize), 1613 ARG_VAL(UINT, OffsetInBytes)) 1614{ 1615 struct nine_context *context = &device->context; 1616 1617 context->index_size = IndexSize; 1618 context->index_offset = OffsetInBytes; 1619 pipe_resource_reference(&context->idxbuf, res); 1620 1621 context->changed.group |= NINE_STATE_IDXBUF; 1622} 1623 1624void 1625nine_context_set_indices(struct NineDevice9 *device, 1626 struct NineIndexBuffer9 *idxbuf) 1627{ 1628 struct pipe_resource *res = NULL; 1629 UINT IndexSize = 0; 1630 unsigned OffsetInBytes = 0; 1631 1632 if (idxbuf) { 1633 res = NineIndexBuffer9_GetBuffer(idxbuf, &OffsetInBytes); 1634 IndexSize = idxbuf->index_size; 1635 } 1636 1637 nine_context_set_indices_apply(device, res, IndexSize, OffsetInBytes); 1638} 1639 1640CSMT_ITEM_NO_WAIT(nine_context_set_vertex_declaration, 1641 ARG_BIND_REF(struct NineVertexDeclaration9, vdecl)) 1642{ 1643 struct nine_context *context = &device->context; 1644 BOOL was_programmable_vs = context->programmable_vs; 1645 1646 nine_bind(&context->vdecl, vdecl); 1647 1648 context->programmable_vs = context->vs && !(context->vdecl && context->vdecl->position_t); 1649 if (was_programmable_vs != context->programmable_vs) { 1650 context->commit |= NINE_STATE_COMMIT_CONST_VS; 1651 context->changed.group |= NINE_STATE_VS; 1652 } 1653 1654 context->changed.group |= NINE_STATE_VDECL; 1655} 1656 1657CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader, 1658 ARG_BIND_REF(struct NineVertexShader9, pShader)) 1659{ 1660 struct nine_context *context = &device->context; 1661 BOOL was_programmable_vs = context->programmable_vs; 1662 1663 nine_bind(&context->vs, pShader); 1664 1665 context->programmable_vs = context->vs && !(context->vdecl && context->vdecl->position_t); 1666 1667 /* ff -> non-ff: commit back non-ff constants */ 1668 if (!was_programmable_vs && context->programmable_vs) 1669 context->commit |= NINE_STATE_COMMIT_CONST_VS; 1670 1671 context->changed.group |= NINE_STATE_VS; 1672} 1673 1674CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_f, 1675 ARG_VAL(UINT, StartRegister), 1676 ARG_MEM(float, pConstantData), 1677 ARG_MEM_SIZE(unsigned, pConstantData_size), 1678 ARG_VAL(UINT, Vector4fCount)) 1679{ 1680 struct nine_context *context = &device->context; 1681 float *vs_const_f = device->may_swvp ? context->vs_const_f_swvp : context->vs_const_f; 1682 1683 memcpy(&vs_const_f[StartRegister * 4], 1684 pConstantData, 1685 pConstantData_size); 1686 1687 if (device->may_swvp) { 1688 Vector4fCount = MIN2(StartRegister + Vector4fCount, NINE_MAX_CONST_F) - StartRegister; 1689 if (StartRegister < NINE_MAX_CONST_F) 1690 memcpy(&context->vs_const_f[StartRegister * 4], 1691 pConstantData, 1692 Vector4fCount * 4 * sizeof(context->vs_const_f[0])); 1693 } 1694 1695 context->changed.vs_const_f = TRUE; 1696 context->changed.group |= NINE_STATE_VS_CONST; 1697} 1698 1699CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_i, 1700 ARG_VAL(UINT, StartRegister), 1701 ARG_MEM(int, pConstantData), 1702 ARG_MEM_SIZE(unsigned, pConstantData_size), 1703 ARG_VAL(UINT, Vector4iCount)) 1704{ 1705 struct nine_context *context = &device->context; 1706 int i; 1707 1708 if (device->driver_caps.vs_integer) { 1709 memcpy(&context->vs_const_i[4 * StartRegister], 1710 pConstantData, 1711 pConstantData_size); 1712 } else { 1713 for (i = 0; i < Vector4iCount; i++) { 1714 context->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i])); 1715 context->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1])); 1716 context->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2])); 1717 context->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3])); 1718 } 1719 } 1720 1721 context->changed.vs_const_i = TRUE; 1722 context->changed.group |= NINE_STATE_VS_CONST | NINE_STATE_VS_PARAMS_MISC; 1723} 1724 1725CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_b, 1726 ARG_VAL(UINT, StartRegister), 1727 ARG_MEM(BOOL, pConstantData), 1728 ARG_MEM_SIZE(unsigned, pConstantData_size), 1729 ARG_VAL(UINT, BoolCount)) 1730{ 1731 struct nine_context *context = &device->context; 1732 int i; 1733 uint32_t bool_true = device->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); 1734 1735 (void) pConstantData_size; 1736 1737 for (i = 0; i < BoolCount; i++) 1738 context->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 1739 1740 context->changed.vs_const_b = TRUE; 1741 context->changed.group |= NINE_STATE_VS_CONST | NINE_STATE_VS_PARAMS_MISC; 1742} 1743 1744CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader, 1745 ARG_BIND_REF(struct NinePixelShader9, ps)) 1746{ 1747 struct nine_context *context = &device->context; 1748 unsigned old_mask = context->ps ? context->ps->rt_mask : 1; 1749 unsigned mask; 1750 1751 /* ff -> non-ff: commit back non-ff constants */ 1752 if (!context->ps && ps) 1753 context->commit |= NINE_STATE_COMMIT_CONST_PS; 1754 1755 nine_bind(&context->ps, ps); 1756 1757 context->changed.group |= NINE_STATE_PS; 1758 1759 mask = context->ps ? context->ps->rt_mask : 1; 1760 /* We need to update cbufs if the pixel shader would 1761 * write to different render targets */ 1762 if (mask != old_mask) 1763 context->changed.group |= NINE_STATE_FB; 1764} 1765 1766CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_f, 1767 ARG_VAL(UINT, StartRegister), 1768 ARG_MEM(float, pConstantData), 1769 ARG_MEM_SIZE(unsigned, pConstantData_size), 1770 ARG_VAL(UINT, Vector4fCount)) 1771{ 1772 struct nine_context *context = &device->context; 1773 1774 memcpy(&context->ps_const_f[StartRegister * 4], 1775 pConstantData, 1776 pConstantData_size); 1777 1778 context->changed.ps_const_f = TRUE; 1779 context->changed.group |= NINE_STATE_PS_CONST; 1780} 1781 1782/* For stateblocks */ 1783CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i_transformed, 1784 ARG_VAL(UINT, StartRegister), 1785 ARG_MEM(int, pConstantData), 1786 ARG_MEM_SIZE(unsigned, pConstantData_size), 1787 ARG_VAL(UINT, Vector4iCount)) 1788{ 1789 struct nine_context *context = &device->context; 1790 1791 memcpy(&context->ps_const_i[StartRegister][0], 1792 pConstantData, 1793 Vector4iCount * sizeof(context->ps_const_i[0])); 1794 1795 context->changed.ps_const_i = TRUE; 1796 context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; 1797} 1798 1799CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i, 1800 ARG_VAL(UINT, StartRegister), 1801 ARG_MEM(int, pConstantData), 1802 ARG_MEM_SIZE(unsigned, pConstantData_size), 1803 ARG_VAL(UINT, Vector4iCount)) 1804{ 1805 struct nine_context *context = &device->context; 1806 int i; 1807 1808 if (device->driver_caps.ps_integer) { 1809 memcpy(&context->ps_const_i[StartRegister][0], 1810 pConstantData, 1811 pConstantData_size); 1812 } else { 1813 for (i = 0; i < Vector4iCount; i++) { 1814 context->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); 1815 context->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); 1816 context->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); 1817 context->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); 1818 } 1819 } 1820 context->changed.ps_const_i = TRUE; 1821 context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; 1822} 1823 1824CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_b, 1825 ARG_VAL(UINT, StartRegister), 1826 ARG_MEM(BOOL, pConstantData), 1827 ARG_MEM_SIZE(unsigned, pConstantData_size), 1828 ARG_VAL(UINT, BoolCount)) 1829{ 1830 struct nine_context *context = &device->context; 1831 int i; 1832 uint32_t bool_true = device->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); 1833 1834 (void) pConstantData_size; 1835 1836 for (i = 0; i < BoolCount; i++) 1837 context->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 1838 1839 context->changed.ps_const_b = TRUE; 1840 context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; 1841} 1842 1843/* XXX: use resource, as resource might change */ 1844CSMT_ITEM_NO_WAIT(nine_context_set_render_target, 1845 ARG_VAL(DWORD, RenderTargetIndex), 1846 ARG_BIND_REF(struct NineSurface9, rt)) 1847{ 1848 struct nine_context *context = &device->context; 1849 const unsigned i = RenderTargetIndex; 1850 1851 if (i == 0) { 1852 context->changed.group |= NINE_STATE_MULTISAMPLE; 1853 1854 if (context->rt[0] && 1855 (context->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) != 1856 (rt->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE)) 1857 context->changed.group |= NINE_STATE_SAMPLE_MASK; 1858 } 1859 1860 if (context->rt[i] != rt) { 1861 nine_bind(&context->rt[i], rt); 1862 context->changed.group |= NINE_STATE_FB; 1863 } 1864} 1865 1866/* XXX: use resource instead of ds, as resource might change */ 1867CSMT_ITEM_NO_WAIT(nine_context_set_depth_stencil, 1868 ARG_BIND_REF(struct NineSurface9, ds)) 1869{ 1870 struct nine_context *context = &device->context; 1871 1872 nine_bind(&context->ds, ds); 1873 context->changed.group |= NINE_STATE_FB; 1874} 1875 1876CSMT_ITEM_NO_WAIT(nine_context_set_viewport, 1877 ARG_COPY_REF(D3DVIEWPORT9, viewport)) 1878{ 1879 struct nine_context *context = &device->context; 1880 1881 if (!memcmp(viewport, &context->viewport, sizeof(context->viewport))) 1882 return; 1883 1884 context->viewport = *viewport; 1885 context->changed.group |= NINE_STATE_VIEWPORT; 1886} 1887 1888CSMT_ITEM_NO_WAIT(nine_context_set_scissor, 1889 ARG_COPY_REF(struct pipe_scissor_state, scissor)) 1890{ 1891 struct nine_context *context = &device->context; 1892 1893 if (!memcmp(scissor, &context->scissor, sizeof(context->scissor))) 1894 return; 1895 1896 context->scissor = *scissor; 1897 context->changed.group |= NINE_STATE_SCISSOR; 1898} 1899 1900CSMT_ITEM_NO_WAIT(nine_context_set_transform, 1901 ARG_VAL(D3DTRANSFORMSTATETYPE, State), 1902 ARG_COPY_REF(D3DMATRIX, pMatrix)) 1903{ 1904 struct nine_context *context = &device->context; 1905 D3DMATRIX *M = nine_state_access_transform(&context->ff, State, TRUE); 1906 1907 *M = *pMatrix; 1908 context->ff.changed.transform[State / 32] |= 1 << (State % 32); 1909 context->changed.group |= NINE_STATE_FF; 1910} 1911 1912CSMT_ITEM_NO_WAIT(nine_context_set_material, 1913 ARG_COPY_REF(D3DMATERIAL9, pMaterial)) 1914{ 1915 struct nine_context *context = &device->context; 1916 1917 context->ff.material = *pMaterial; 1918 context->changed.group |= NINE_STATE_FF_MATERIAL; 1919} 1920 1921CSMT_ITEM_NO_WAIT(nine_context_set_light, 1922 ARG_VAL(DWORD, Index), 1923 ARG_COPY_REF(D3DLIGHT9, pLight)) 1924{ 1925 struct nine_context *context = &device->context; 1926 1927 (void)nine_state_set_light(&context->ff, Index, pLight); 1928 context->changed.group |= NINE_STATE_FF_LIGHTING; 1929} 1930 1931 1932/* For stateblocks */ 1933static void 1934nine_context_light_enable_stateblock(struct NineDevice9 *device, 1935 const uint16_t active_light[NINE_MAX_LIGHTS_ACTIVE], /* TODO: use pointer that convey size for csmt */ 1936 unsigned int num_lights_active) 1937{ 1938 struct nine_context *context = &device->context; 1939 1940 /* TODO: Use CSMT_* to avoid calling nine_csmt_process */ 1941 nine_csmt_process(device); 1942 memcpy(context->ff.active_light, active_light, NINE_MAX_LIGHTS_ACTIVE * sizeof(context->ff.active_light[0])); 1943 context->ff.num_lights_active = num_lights_active; 1944 context->changed.group |= NINE_STATE_FF_LIGHTING; 1945} 1946 1947CSMT_ITEM_NO_WAIT(nine_context_light_enable, 1948 ARG_VAL(DWORD, Index), 1949 ARG_VAL(BOOL, Enable)) 1950{ 1951 struct nine_context *context = &device->context; 1952 1953 nine_state_light_enable(&context->ff, Index, Enable); 1954 context->changed.group |= NINE_STATE_FF_LIGHTING; 1955} 1956 1957CSMT_ITEM_NO_WAIT(nine_context_set_texture_stage_state, 1958 ARG_VAL(DWORD, Stage), 1959 ARG_VAL(D3DTEXTURESTAGESTATETYPE, Type), 1960 ARG_VAL(DWORD, Value)) 1961{ 1962 struct nine_context *context = &device->context; 1963 int bumpmap_index = -1; 1964 1965 context->ff.tex_stage[Stage][Type] = Value; 1966 switch (Type) { 1967 case D3DTSS_BUMPENVMAT00: 1968 bumpmap_index = 4 * Stage; 1969 break; 1970 case D3DTSS_BUMPENVMAT01: 1971 bumpmap_index = 4 * Stage + 1; 1972 break; 1973 case D3DTSS_BUMPENVMAT10: 1974 bumpmap_index = 4 * Stage + 2; 1975 break; 1976 case D3DTSS_BUMPENVMAT11: 1977 bumpmap_index = 4 * Stage + 3; 1978 break; 1979 case D3DTSS_BUMPENVLSCALE: 1980 bumpmap_index = 4 * 8 + 2 * Stage; 1981 break; 1982 case D3DTSS_BUMPENVLOFFSET: 1983 bumpmap_index = 4 * 8 + 2 * Stage + 1; 1984 break; 1985 case D3DTSS_TEXTURETRANSFORMFLAGS: 1986 context->changed.group |= NINE_STATE_PS_PARAMS_MISC; 1987 break; 1988 default: 1989 break; 1990 } 1991 1992 if (bumpmap_index >= 0) { 1993 context->bumpmap_vars[bumpmap_index] = Value; 1994 context->changed.group |= NINE_STATE_PS_CONST; 1995 } 1996 1997 context->changed.group |= NINE_STATE_FF_PS_CONSTS; 1998 context->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); 1999} 2000 2001CSMT_ITEM_NO_WAIT(nine_context_set_clip_plane, 2002 ARG_VAL(DWORD, Index), 2003 ARG_COPY_REF(struct nine_clipplane, pPlane)) 2004{ 2005 struct nine_context *context = &device->context; 2006 2007 memcpy(&context->clip.ucp[Index][0], pPlane, sizeof(context->clip.ucp[0])); 2008 context->changed.ucp = TRUE; 2009} 2010 2011CSMT_ITEM_NO_WAIT(nine_context_set_swvp, 2012 ARG_VAL(boolean, swvp)) 2013{ 2014 struct nine_context *context = &device->context; 2015 2016 context->swvp = swvp; 2017 context->changed.group |= NINE_STATE_SWVP; 2018} 2019 2020/* Do not write to nine_context directly. Slower, 2021 * but works with csmt. TODO: write a special csmt version that 2022 * would record the list of commands as much as possible, 2023 * and use the version above else. 2024 */ 2025void 2026nine_context_apply_stateblock(struct NineDevice9 *device, 2027 const struct nine_state *src) 2028{ 2029 int i; 2030 2031 /* No need to apply src->changed.group, since all calls do 2032 * set context->changed.group */ 2033 2034 for (i = 0; i < ARRAY_SIZE(src->changed.rs); ++i) { 2035 uint32_t m = src->changed.rs[i]; 2036 while (m) { 2037 const int r = ffs(m) - 1; 2038 m &= ~(1 << r); 2039 nine_context_set_render_state(device, i * 32 + r, src->rs_advertised[i * 32 + r]); 2040 } 2041 } 2042 2043 /* Textures */ 2044 if (src->changed.texture) { 2045 uint32_t m = src->changed.texture; 2046 unsigned s; 2047 2048 for (s = 0; m; ++s, m >>= 1) { 2049 struct NineBaseTexture9 *tex = src->texture[s]; 2050 if (!(m & 1)) 2051 continue; 2052 nine_context_set_texture(device, s, tex); 2053 } 2054 } 2055 2056 /* Sampler state */ 2057 if (src->changed.group & NINE_STATE_SAMPLER) { 2058 unsigned s; 2059 2060 for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { 2061 uint32_t m = src->changed.sampler[s]; 2062 while (m) { 2063 const int i = ffs(m) - 1; 2064 m &= ~(1 << i); 2065 nine_context_set_sampler_state(device, s, i, src->samp_advertised[s][i]); 2066 } 2067 } 2068 } 2069 2070 /* Vertex buffers */ 2071 if (src->changed.vtxbuf | src->changed.stream_freq) { 2072 uint32_t m = src->changed.vtxbuf | src->changed.stream_freq; 2073 for (i = 0; m; ++i, m >>= 1) { 2074 if (src->changed.vtxbuf & (1 << i)) 2075 nine_context_set_stream_source(device, i, src->stream[i], src->vtxbuf[i].buffer_offset, src->vtxbuf[i].stride); 2076 if (src->changed.stream_freq & (1 << i)) 2077 nine_context_set_stream_source_freq(device, i, src->stream_freq[i]); 2078 } 2079 } 2080 2081 /* Index buffer */ 2082 if (src->changed.group & NINE_STATE_IDXBUF) 2083 nine_context_set_indices(device, src->idxbuf); 2084 2085 /* Vertex declaration */ 2086 if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl) 2087 nine_context_set_vertex_declaration(device, src->vdecl); 2088 2089 /* Vertex shader */ 2090 if (src->changed.group & NINE_STATE_VS) 2091 nine_context_set_vertex_shader(device, src->vs); 2092 2093 /* Pixel shader */ 2094 if (src->changed.group & NINE_STATE_PS) 2095 nine_context_set_pixel_shader(device, src->ps); 2096 2097 /* Vertex constants */ 2098 if (src->changed.group & NINE_STATE_VS_CONST) { 2099 struct nine_range *r; 2100 for (r = src->changed.vs_const_f; r; r = r->next) 2101 nine_context_set_vertex_shader_constant_f(device, r->bgn, 2102 &src->vs_const_f[r->bgn * 4], 2103 sizeof(float[4]) * (r->end - r->bgn), 2104 r->end - r->bgn); 2105 for (r = src->changed.vs_const_i; r; r = r->next) 2106 nine_context_set_vertex_shader_constant_i(device, r->bgn, 2107 &src->vs_const_i[r->bgn * 4], 2108 sizeof(int[4]) * (r->end - r->bgn), 2109 r->end - r->bgn); 2110 for (r = src->changed.vs_const_b; r; r = r->next) 2111 nine_context_set_vertex_shader_constant_b(device, r->bgn, 2112 &src->vs_const_b[r->bgn * 4], 2113 sizeof(BOOL) * (r->end - r->bgn), 2114 r->end - r->bgn); 2115 } 2116 2117 /* Pixel constants */ 2118 if (src->changed.group & NINE_STATE_PS_CONST) { 2119 struct nine_range *r; 2120 for (r = src->changed.ps_const_f; r; r = r->next) 2121 nine_context_set_pixel_shader_constant_f(device, r->bgn, 2122 &src->ps_const_f[r->bgn * 4], 2123 sizeof(float[4]) * (r->end - r->bgn), 2124 r->end - r->bgn); 2125 if (src->changed.ps_const_i) { 2126 uint16_t m = src->changed.ps_const_i; 2127 for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) 2128 if (m & 1) 2129 nine_context_set_pixel_shader_constant_i_transformed(device, i, 2130 src->ps_const_i[i], sizeof(int[4]), 1); 2131 } 2132 if (src->changed.ps_const_b) { 2133 uint16_t m = src->changed.ps_const_b; 2134 for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) 2135 if (m & 1) 2136 nine_context_set_pixel_shader_constant_b(device, i, 2137 &src->ps_const_b[i], sizeof(BOOL), 1); 2138 } 2139 } 2140 2141 /* Viewport */ 2142 if (src->changed.group & NINE_STATE_VIEWPORT) 2143 nine_context_set_viewport(device, &src->viewport); 2144 2145 /* Scissor */ 2146 if (src->changed.group & NINE_STATE_SCISSOR) 2147 nine_context_set_scissor(device, &src->scissor); 2148 2149 /* User Clip Planes */ 2150 if (src->changed.ucp) 2151 for (i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) 2152 if (src->changed.ucp & (1 << i)) 2153 nine_context_set_clip_plane(device, i, (struct nine_clipplane*)&src->clip.ucp[i][0]); 2154 2155 if (!(src->changed.group & NINE_STATE_FF)) 2156 return; 2157 2158 /* Fixed function state. */ 2159 2160 if (src->changed.group & NINE_STATE_FF_MATERIAL) 2161 nine_context_set_material(device, &src->ff.material); 2162 2163 if (src->changed.group & NINE_STATE_FF_PS_CONSTS) { 2164 unsigned s; 2165 for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { 2166 for (i = 0; i < NINED3DTSS_COUNT; ++i) 2167 if (src->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32))) 2168 nine_context_set_texture_stage_state(device, s, i, src->ff.tex_stage[s][i]); 2169 } 2170 } 2171 if (src->changed.group & NINE_STATE_FF_LIGHTING) { 2172 for (i = 0; i < src->ff.num_lights; ++i) 2173 if (src->ff.light[i].Type != NINED3DLIGHT_INVALID) 2174 nine_context_set_light(device, i, &src->ff.light[i]); 2175 2176 nine_context_light_enable_stateblock(device, src->ff.active_light, src->ff.num_lights_active); 2177 } 2178 if (src->changed.group & NINE_STATE_FF_VSTRANSF) { 2179 for (i = 0; i < ARRAY_SIZE(src->ff.changed.transform); ++i) { 2180 unsigned s; 2181 if (!src->ff.changed.transform[i]) 2182 continue; 2183 for (s = i * 32; s < (i * 32 + 32); ++s) { 2184 if (!(src->ff.changed.transform[i] & (1 << (s % 32)))) 2185 continue; 2186 /* MaxVertexBlendMatrixIndex is 8, which means 2187 * we don't read past index D3DTS_WORLDMATRIX(8). 2188 * swvp is supposed to allow all 256, but we don't 2189 * implement it for now. */ 2190 if (s > D3DTS_WORLDMATRIX(8)) 2191 break; 2192 nine_context_set_transform(device, s, 2193 nine_state_access_transform( 2194 (struct nine_ff_state *)&src->ff, 2195 s, FALSE)); 2196 } 2197 } 2198 } 2199} 2200 2201static void 2202nine_update_state_framebuffer_clear(struct NineDevice9 *device) 2203{ 2204 struct nine_context *context = &device->context; 2205 2206 if (context->changed.group & NINE_STATE_FB) 2207 update_framebuffer(device, TRUE); 2208} 2209 2210CSMT_ITEM_NO_WAIT(nine_context_clear_fb, 2211 ARG_VAL(DWORD, Count), 2212 ARG_COPY_REF(D3DRECT, pRects), 2213 ARG_VAL(DWORD, Flags), 2214 ARG_VAL(D3DCOLOR, Color), 2215 ARG_VAL(float, Z), 2216 ARG_VAL(DWORD, Stencil)) 2217{ 2218 struct nine_context *context = &device->context; 2219 const int sRGB = context->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; 2220 struct pipe_surface *cbuf, *zsbuf; 2221 struct pipe_context *pipe = context->pipe; 2222 struct NineSurface9 *zsbuf_surf = context->ds; 2223 struct NineSurface9 *rt; 2224 unsigned bufs = 0; 2225 unsigned r, i; 2226 union pipe_color_union rgba; 2227 unsigned rt_mask = 0; 2228 D3DRECT rect; 2229 2230 nine_update_state_framebuffer_clear(device); 2231 2232 if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR; 2233 /* Ignore Z buffer if not bound */ 2234 if (context->pipe_data.fb.zsbuf != NULL) { 2235 if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH; 2236 if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL; 2237 } 2238 if (!bufs) 2239 return; 2240 d3dcolor_to_pipe_color_union(&rgba, Color); 2241 2242 rect.x1 = context->viewport.X; 2243 rect.y1 = context->viewport.Y; 2244 rect.x2 = context->viewport.Width + rect.x1; 2245 rect.y2 = context->viewport.Height + rect.y1; 2246 2247 /* Both rectangles apply, which is weird, but that's D3D9. */ 2248 if (context->rs[D3DRS_SCISSORTESTENABLE]) { 2249 rect.x1 = MAX2(rect.x1, context->scissor.minx); 2250 rect.y1 = MAX2(rect.y1, context->scissor.miny); 2251 rect.x2 = MIN2(rect.x2, context->scissor.maxx); 2252 rect.y2 = MIN2(rect.y2, context->scissor.maxy); 2253 } 2254 2255 if (Count) { 2256 /* Maybe apps like to specify a large rect ? */ 2257 if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 && 2258 pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) { 2259 DBG("First rect covers viewport.\n"); 2260 Count = 0; 2261 pRects = NULL; 2262 } 2263 } 2264 2265 if (rect.x1 >= context->pipe_data.fb.width || rect.y1 >= context->pipe_data.fb.height) 2266 return; 2267 2268 for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { 2269 if (context->rt[i] && context->rt[i]->desc.Format != D3DFMT_NULL) 2270 rt_mask |= 1 << i; 2271 } 2272 2273 /* fast path, clears everything at once */ 2274 if (!Count && 2275 (!(bufs & PIPE_CLEAR_COLOR) || (rt_mask == context->rt_mask)) && 2276 rect.x1 == 0 && rect.y1 == 0 && 2277 /* Case we clear only render target. Check clear region vs rt. */ 2278 ((!(bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && 2279 rect.x2 >= context->pipe_data.fb.width && 2280 rect.y2 >= context->pipe_data.fb.height) || 2281 /* Case we clear depth buffer (and eventually rt too). 2282 * depth buffer size is always >= rt size. Compare to clear region */ 2283 ((bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && 2284 rect.x2 >= zsbuf_surf->desc.Width && 2285 rect.y2 >= zsbuf_surf->desc.Height))) { 2286 DBG("Clear fast path\n"); 2287 pipe->clear(pipe, bufs, NULL, &rgba, Z, Stencil); 2288 return; 2289 } 2290 2291 if (!Count) { 2292 Count = 1; 2293 pRects = ▭ 2294 } 2295 2296 for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { 2297 rt = context->rt[i]; 2298 if (!rt || rt->desc.Format == D3DFMT_NULL || 2299 !(bufs & PIPE_CLEAR_COLOR)) 2300 continue; /* save space, compiler should hoist this */ 2301 cbuf = NineSurface9_GetSurface(rt, sRGB); 2302 for (r = 0; r < Count; ++r) { 2303 /* Don't trust users to pass these in the right order. */ 2304 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); 2305 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); 2306 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); 2307 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); 2308#ifndef NINE_LAX 2309 /* Drop negative rectangles (like wine expects). */ 2310 if (pRects[r].x1 > pRects[r].x2) continue; 2311 if (pRects[r].y1 > pRects[r].y2) continue; 2312#endif 2313 2314 x1 = MAX2(x1, rect.x1); 2315 y1 = MAX2(y1, rect.y1); 2316 x2 = MIN3(x2, rect.x2, rt->desc.Width); 2317 y2 = MIN3(y2, rect.y2, rt->desc.Height); 2318 2319 DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2); 2320 pipe->clear_render_target(pipe, cbuf, &rgba, 2321 x1, y1, x2 - x1, y2 - y1, false); 2322 } 2323 } 2324 if (!(bufs & PIPE_CLEAR_DEPTHSTENCIL)) 2325 return; 2326 2327 bufs &= PIPE_CLEAR_DEPTHSTENCIL; 2328 2329 for (r = 0; r < Count; ++r) { 2330 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); 2331 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); 2332 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); 2333 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); 2334#ifndef NINE_LAX 2335 /* Drop negative rectangles. */ 2336 if (pRects[r].x1 > pRects[r].x2) continue; 2337 if (pRects[r].y1 > pRects[r].y2) continue; 2338#endif 2339 2340 x1 = MIN2(x1, rect.x1); 2341 y1 = MIN2(y1, rect.y1); 2342 x2 = MIN3(x2, rect.x2, zsbuf_surf->desc.Width); 2343 y2 = MIN3(y2, rect.y2, zsbuf_surf->desc.Height); 2344 2345 zsbuf = NineSurface9_GetSurface(zsbuf_surf, 0); 2346 assert(zsbuf); 2347 pipe->clear_depth_stencil(pipe, zsbuf, bufs, Z, Stencil, 2348 x1, y1, x2 - x1, y2 - y1, false); 2349 } 2350 return; 2351} 2352 2353 2354static inline void 2355init_draw_info(struct pipe_draw_info *info, 2356 struct pipe_draw_start_count_bias *draw, 2357 struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count) 2358{ 2359 info->mode = d3dprimitivetype_to_pipe_prim(type); 2360 draw->count = prim_count_to_vertex_count(type, count); 2361 info->start_instance = 0; 2362 info->instance_count = 1; 2363 if (dev->context.stream_instancedata_mask & dev->context.stream_usage_mask) 2364 info->instance_count = MAX2(dev->context.stream_freq[0] & 0x7FFFFF, 1); 2365 info->primitive_restart = FALSE; 2366 info->has_user_indices = FALSE; 2367 info->take_index_buffer_ownership = FALSE; 2368 info->index_bias_varies = FALSE; 2369 info->increment_draw_id = FALSE; 2370 info->was_line_loop = FALSE; 2371 info->restart_index = 0; 2372 info->view_mask = 0; 2373} 2374 2375CSMT_ITEM_NO_WAIT(nine_context_draw_primitive, 2376 ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), 2377 ARG_VAL(UINT, StartVertex), 2378 ARG_VAL(UINT, PrimitiveCount)) 2379{ 2380 struct nine_context *context = &device->context; 2381 struct pipe_draw_info info; 2382 struct pipe_draw_start_count_bias draw; 2383 2384 if (context->vs && context->vs->swvp_only && !context->swvp) 2385 return; 2386 2387 nine_update_state(device); 2388 2389 init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount); 2390 info.index_size = 0; 2391 draw.start = StartVertex; 2392 draw.index_bias = 0; 2393 info.min_index = draw.start; 2394 info.max_index = draw.start + draw.count - 1; 2395 info.index.resource = NULL; 2396 2397 context->pipe->draw_vbo(context->pipe, &info, 0, NULL, &draw, 1); 2398} 2399 2400CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive, 2401 ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), 2402 ARG_VAL(INT, BaseVertexIndex), 2403 ARG_VAL(UINT, MinVertexIndex), 2404 ARG_VAL(UINT, NumVertices), 2405 ARG_VAL(UINT, StartIndex), 2406 ARG_VAL(UINT, PrimitiveCount)) 2407{ 2408 struct nine_context *context = &device->context; 2409 struct pipe_draw_info info; 2410 struct pipe_draw_start_count_bias draw; 2411 2412 if (context->vs && context->vs->swvp_only && !context->swvp) 2413 return; 2414 2415 nine_update_state(device); 2416 2417 init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount); 2418 info.index_size = context->index_size; 2419 draw.start = context->index_offset / context->index_size + StartIndex; 2420 draw.index_bias = BaseVertexIndex; 2421 info.index_bounds_valid = true; 2422 /* These don't include index bias: */ 2423 info.min_index = MinVertexIndex; 2424 info.max_index = MinVertexIndex + NumVertices - 1; 2425 info.index.resource = context->idxbuf; 2426 2427 context->pipe->draw_vbo(context->pipe, &info, 0, NULL, &draw, 1); 2428} 2429 2430CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf, 2431 ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), 2432 ARG_VAL(UINT, MinVertexIndex), 2433 ARG_VAL(UINT, NumVertices), 2434 ARG_VAL(UINT, PrimitiveCount), 2435 ARG_BIND_VBUF(struct pipe_vertex_buffer, vbuf), 2436 ARG_BIND_RES(struct pipe_resource, ibuf), 2437 ARG_VAL(void *, user_ibuf), 2438 ARG_VAL(UINT, index_offset), 2439 ARG_VAL(UINT, index_size)) 2440{ 2441 struct nine_context *context = &device->context; 2442 struct pipe_draw_info info; 2443 struct pipe_draw_start_count_bias draw; 2444 2445 if (context->vs && context->vs->swvp_only && !context->swvp) 2446 return; 2447 2448 nine_update_state(device); 2449 2450 init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount); 2451 info.index_size = index_size; 2452 draw.start = index_offset / info.index_size; 2453 draw.index_bias = 0; 2454 info.index_bounds_valid = true; 2455 info.min_index = MinVertexIndex; 2456 info.max_index = MinVertexIndex + NumVertices - 1; 2457 info.has_user_indices = ibuf == NULL; 2458 if (ibuf) 2459 info.index.resource = ibuf; 2460 else 2461 info.index.user = user_ibuf; 2462 2463 context->pipe->set_vertex_buffers(context->pipe, 0, 1, 0, false, vbuf); 2464 context->changed.vtxbuf |= 1; 2465 2466 context->pipe->draw_vbo(context->pipe, &info, 0, NULL, &draw, 1); 2467} 2468 2469CSMT_ITEM_NO_WAIT(nine_context_resource_copy_region, 2470 ARG_BIND_REF(struct NineUnknown, dst), 2471 ARG_BIND_REF(struct NineUnknown, src), 2472 ARG_BIND_RES(struct pipe_resource, dst_res), 2473 ARG_VAL(unsigned, dst_level), 2474 ARG_COPY_REF(struct pipe_box, dst_box), 2475 ARG_BIND_RES(struct pipe_resource, src_res), 2476 ARG_VAL(unsigned, src_level), 2477 ARG_COPY_REF(struct pipe_box, src_box)) 2478{ 2479 struct nine_context *context = &device->context; 2480 2481 (void) dst; 2482 (void) src; 2483 2484 context->pipe->resource_copy_region(context->pipe, 2485 dst_res, dst_level, 2486 dst_box->x, dst_box->y, dst_box->z, 2487 src_res, src_level, 2488 src_box); 2489} 2490 2491CSMT_ITEM_NO_WAIT(nine_context_blit, 2492 ARG_BIND_REF(struct NineUnknown, dst), 2493 ARG_BIND_REF(struct NineUnknown, src), 2494 ARG_BIND_BLIT(struct pipe_blit_info, blit)) 2495{ 2496 struct nine_context *context = &device->context; 2497 2498 (void) dst; 2499 (void) src; 2500 2501 context->pipe->blit(context->pipe, blit); 2502} 2503 2504CSMT_ITEM_NO_WAIT(nine_context_clear_render_target, 2505 ARG_BIND_REF(struct NineSurface9, surface), 2506 ARG_VAL(D3DCOLOR, color), 2507 ARG_VAL(UINT, x), 2508 ARG_VAL(UINT, y), 2509 ARG_VAL(UINT, width), 2510 ARG_VAL(UINT, height)) 2511{ 2512 struct nine_context *context = &device->context; 2513 struct pipe_surface *surf; 2514 union pipe_color_union rgba; 2515 2516 d3dcolor_to_pipe_color_union(&rgba, color); 2517 surf = NineSurface9_GetSurface(surface, 0); 2518 context->pipe->clear_render_target(context->pipe, surf, &rgba, x, y, width, height, false); 2519} 2520 2521CSMT_ITEM_NO_WAIT(nine_context_gen_mipmap, 2522 ARG_BIND_REF(struct NineUnknown, dst), 2523 ARG_BIND_RES(struct pipe_resource, res), 2524 ARG_VAL(UINT, base_level), 2525 ARG_VAL(UINT, last_level), 2526 ARG_VAL(UINT, first_layer), 2527 ARG_VAL(UINT, last_layer), 2528 ARG_VAL(UINT, filter)) 2529{ 2530 struct nine_context *context = &device->context; 2531 2532 /* We just bind dst for the bind count */ 2533 (void)dst; 2534 2535 util_gen_mipmap(context->pipe, res, res->format, base_level, 2536 last_level, first_layer, last_layer, filter); 2537} 2538 2539CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_range_upload, 2540 ARG_BIND_REF(struct NineUnknown, src_ref), 2541 ARG_BIND_RES(struct pipe_resource, res), 2542 ARG_VAL(unsigned, offset), 2543 ARG_VAL(unsigned, size), 2544 ARG_VAL(unsigned, usage), 2545 ARG_VAL(const void *, data)) 2546{ 2547 struct nine_context *context = &device->context; 2548 2549 /* Binding src_ref avoids release before upload */ 2550 (void)src_ref; 2551 2552 context->pipe->buffer_subdata(context->pipe, res, usage, offset, size, data); 2553} 2554 2555CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_box_upload, 2556 ARG_BIND_REF(struct NineUnknown, src_ref), 2557 ARG_BIND_RES(struct pipe_resource, res), 2558 ARG_VAL(unsigned, level), 2559 ARG_COPY_REF(struct pipe_box, dst_box), 2560 ARG_VAL(enum pipe_format, src_format), 2561 ARG_VAL(const void *, src), 2562 ARG_VAL(unsigned, src_stride), 2563 ARG_VAL(unsigned, src_layer_stride), 2564 ARG_COPY_REF(struct pipe_box, src_box)) 2565{ 2566 struct nine_context *context = &device->context; 2567 struct pipe_context *pipe = context->pipe; 2568 struct pipe_transfer *transfer = NULL; 2569 uint8_t *map; 2570 2571 /* Binding src_ref avoids release before upload */ 2572 (void)src_ref; 2573 2574 if (is_ATI1_ATI2(src_format)) { 2575 const unsigned bw = util_format_get_blockwidth(src_format); 2576 const unsigned bh = util_format_get_blockheight(src_format); 2577 /* For these formats, the allocate surface can be too small to contain 2578 * a block. Yet we can be asked to upload such surfaces. 2579 * It is ok for these surfaces to have buggy content, 2580 * but we should avoid crashing. 2581 * Calling util_format_translate_3d would read out of bounds. */ 2582 if (dst_box->width < bw || dst_box->height < bh) 2583 return; 2584 } 2585 2586 map = pipe->texture_map(pipe, 2587 res, 2588 level, 2589 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE, 2590 dst_box, &transfer); 2591 if (!map) 2592 return; 2593 2594 /* Note: if formats are the sames, it will revert 2595 * to normal memcpy */ 2596 (void) util_format_translate_3d(res->format, 2597 map, transfer->stride, 2598 transfer->layer_stride, 2599 0, 0, 0, 2600 src_format, 2601 src, src_stride, 2602 src_layer_stride, 2603 src_box->x, src_box->y, src_box->z, 2604 dst_box->width, dst_box->height, 2605 dst_box->depth); 2606 2607 pipe_texture_unmap(pipe, transfer); 2608} 2609 2610struct pipe_query * 2611nine_context_create_query(struct NineDevice9 *device, unsigned query_type) 2612{ 2613 struct pipe_context *pipe; 2614 struct pipe_query *res; 2615 2616 pipe = nine_context_get_pipe_acquire(device); 2617 res = pipe->create_query(pipe, query_type, 0); 2618 nine_context_get_pipe_release(device); 2619 return res; 2620} 2621 2622CSMT_ITEM_DO_WAIT(nine_context_destroy_query, 2623 ARG_REF(struct pipe_query, query)) 2624{ 2625 struct nine_context *context = &device->context; 2626 2627 context->pipe->destroy_query(context->pipe, query); 2628} 2629 2630CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_begin_query, 2631 ARG_REF(struct pipe_query, query)) 2632{ 2633 struct nine_context *context = &device->context; 2634 2635 (void) context->pipe->begin_query(context->pipe, query); 2636} 2637 2638CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_end_query, 2639 ARG_REF(struct pipe_query, query)) 2640{ 2641 struct nine_context *context = &device->context; 2642 2643 (void) context->pipe->end_query(context->pipe, query); 2644} 2645 2646boolean 2647nine_context_get_query_result(struct NineDevice9 *device, struct pipe_query *query, 2648 unsigned *counter, boolean flush, boolean wait, 2649 union pipe_query_result *result) 2650{ 2651 struct pipe_context *pipe; 2652 boolean ret; 2653 2654 if (wait) 2655 nine_csmt_process(device); 2656 else if (p_atomic_read(counter) > 0) { 2657 if (flush && device->csmt_active) 2658 nine_queue_flush(device->csmt_ctx->pool); 2659 DBG("Pending begin/end. Returning\n"); 2660 return false; 2661 } 2662 2663 pipe = nine_context_get_pipe_acquire(device); 2664 ret = pipe->get_query_result(pipe, query, wait, result); 2665 nine_context_get_pipe_release(device); 2666 2667 DBG("Query result %s\n", ret ? "found" : "not yet available"); 2668 return ret; 2669} 2670 2671CSMT_ITEM_NO_WAIT(nine_context_pipe_flush) 2672{ 2673 struct nine_context *context = &device->context; 2674 2675 context->pipe->flush(context->pipe, NULL, PIPE_FLUSH_ASYNC); 2676} 2677 2678/* State defaults */ 2679 2680static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] = 2681{ 2682 /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */ 2683 [D3DRS_ZENABLE] = D3DZB_FALSE, 2684 [D3DRS_FILLMODE] = D3DFILL_SOLID, 2685 [D3DRS_SHADEMODE] = D3DSHADE_GOURAUD, 2686/* [D3DRS_LINEPATTERN] = 0x00000000, */ 2687 [D3DRS_ZWRITEENABLE] = TRUE, 2688 [D3DRS_ALPHATESTENABLE] = FALSE, 2689 [D3DRS_LASTPIXEL] = TRUE, 2690 [D3DRS_SRCBLEND] = D3DBLEND_ONE, 2691 [D3DRS_DESTBLEND] = D3DBLEND_ZERO, 2692 [D3DRS_CULLMODE] = D3DCULL_CCW, 2693 [D3DRS_ZFUNC] = D3DCMP_LESSEQUAL, 2694 [D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS, 2695 [D3DRS_ALPHAREF] = 0, 2696 [D3DRS_DITHERENABLE] = FALSE, 2697 [D3DRS_ALPHABLENDENABLE] = FALSE, 2698 [D3DRS_FOGENABLE] = FALSE, 2699 [D3DRS_SPECULARENABLE] = FALSE, 2700/* [D3DRS_ZVISIBLE] = 0, */ 2701 [D3DRS_FOGCOLOR] = 0, 2702 [D3DRS_FOGTABLEMODE] = D3DFOG_NONE, 2703 [D3DRS_FOGSTART] = 0x00000000, 2704 [D3DRS_FOGEND] = 0x3F800000, 2705 [D3DRS_FOGDENSITY] = 0x3F800000, 2706/* [D3DRS_EDGEANTIALIAS] = FALSE, */ 2707 [D3DRS_RANGEFOGENABLE] = FALSE, 2708 [D3DRS_STENCILENABLE] = FALSE, 2709 [D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP, 2710 [D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP, 2711 [D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP, 2712 [D3DRS_STENCILREF] = 0, 2713 [D3DRS_STENCILMASK] = 0xFFFFFFFF, 2714 [D3DRS_STENCILFUNC] = D3DCMP_ALWAYS, 2715 [D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF, 2716 [D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF, 2717 [D3DRS_WRAP0] = 0, 2718 [D3DRS_WRAP1] = 0, 2719 [D3DRS_WRAP2] = 0, 2720 [D3DRS_WRAP3] = 0, 2721 [D3DRS_WRAP4] = 0, 2722 [D3DRS_WRAP5] = 0, 2723 [D3DRS_WRAP6] = 0, 2724 [D3DRS_WRAP7] = 0, 2725 [D3DRS_CLIPPING] = TRUE, 2726 [D3DRS_LIGHTING] = TRUE, 2727 [D3DRS_AMBIENT] = 0, 2728 [D3DRS_FOGVERTEXMODE] = D3DFOG_NONE, 2729 [D3DRS_COLORVERTEX] = TRUE, 2730 [D3DRS_LOCALVIEWER] = TRUE, 2731 [D3DRS_NORMALIZENORMALS] = FALSE, 2732 [D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1, 2733 [D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2, 2734 [D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL, 2735 [D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL, 2736 [D3DRS_VERTEXBLEND] = D3DVBF_DISABLE, 2737 [D3DRS_CLIPPLANEENABLE] = 0, 2738/* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */ 2739 [D3DRS_POINTSIZE] = 0x3F800000, 2740 [D3DRS_POINTSIZE_MIN] = 0x3F800000, 2741 [D3DRS_POINTSPRITEENABLE] = FALSE, 2742 [D3DRS_POINTSCALEENABLE] = FALSE, 2743 [D3DRS_POINTSCALE_A] = 0x3F800000, 2744 [D3DRS_POINTSCALE_B] = 0x00000000, 2745 [D3DRS_POINTSCALE_C] = 0x00000000, 2746 [D3DRS_MULTISAMPLEANTIALIAS] = TRUE, 2747 [D3DRS_MULTISAMPLEMASK] = 0xFFFFFFFF, 2748 [D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE, 2749/* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */ 2750 [D3DRS_DEBUGMONITORTOKEN] = 0xDEADCAFE, 2751 [D3DRS_POINTSIZE_MAX] = 0x3F800000, /* depends on cap */ 2752 [D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE, 2753 [D3DRS_COLORWRITEENABLE] = 0x0000000f, 2754 [D3DRS_TWEENFACTOR] = 0x00000000, 2755 [D3DRS_BLENDOP] = D3DBLENDOP_ADD, 2756 [D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC, 2757 [D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR, 2758 [D3DRS_SCISSORTESTENABLE] = FALSE, 2759 [D3DRS_SLOPESCALEDEPTHBIAS] = 0, 2760 [D3DRS_MINTESSELLATIONLEVEL] = 0x3F800000, 2761 [D3DRS_MAXTESSELLATIONLEVEL] = 0x3F800000, 2762 [D3DRS_ANTIALIASEDLINEENABLE] = FALSE, 2763 [D3DRS_ADAPTIVETESS_X] = 0x00000000, 2764 [D3DRS_ADAPTIVETESS_Y] = 0x00000000, 2765 [D3DRS_ADAPTIVETESS_Z] = 0x3F800000, 2766 [D3DRS_ADAPTIVETESS_W] = 0x00000000, 2767 [D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE, 2768 [D3DRS_TWOSIDEDSTENCILMODE] = FALSE, 2769 [D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP, 2770 [D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP, 2771 [D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP, 2772 [D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS, 2773 [D3DRS_COLORWRITEENABLE1] = 0x0000000F, 2774 [D3DRS_COLORWRITEENABLE2] = 0x0000000F, 2775 [D3DRS_COLORWRITEENABLE3] = 0x0000000F, 2776 [D3DRS_BLENDFACTOR] = 0xFFFFFFFF, 2777 [D3DRS_SRGBWRITEENABLE] = 0, 2778 [D3DRS_DEPTHBIAS] = 0, 2779 [D3DRS_WRAP8] = 0, 2780 [D3DRS_WRAP9] = 0, 2781 [D3DRS_WRAP10] = 0, 2782 [D3DRS_WRAP11] = 0, 2783 [D3DRS_WRAP12] = 0, 2784 [D3DRS_WRAP13] = 0, 2785 [D3DRS_WRAP14] = 0, 2786 [D3DRS_WRAP15] = 0, 2787 [D3DRS_SEPARATEALPHABLENDENABLE] = FALSE, 2788 [D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE, 2789 [D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO, 2790 [D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD, 2791 [NINED3DRS_VSPOINTSIZE] = FALSE, 2792 [NINED3DRS_RTMASK] = 0xf, 2793 [NINED3DRS_ALPHACOVERAGE] = FALSE, 2794 [NINED3DRS_MULTISAMPLE] = FALSE, 2795 [NINED3DRS_FETCH4] = 0 2796}; 2797static const DWORD nine_tex_stage_state_defaults[NINED3DTSS_LAST + 1] = 2798{ 2799 [D3DTSS_COLOROP] = D3DTOP_DISABLE, 2800 [D3DTSS_ALPHAOP] = D3DTOP_DISABLE, 2801 [D3DTSS_COLORARG1] = D3DTA_TEXTURE, 2802 [D3DTSS_COLORARG2] = D3DTA_CURRENT, 2803 [D3DTSS_COLORARG0] = D3DTA_CURRENT, 2804 [D3DTSS_ALPHAARG1] = D3DTA_TEXTURE, 2805 [D3DTSS_ALPHAARG2] = D3DTA_CURRENT, 2806 [D3DTSS_ALPHAARG0] = D3DTA_CURRENT, 2807 [D3DTSS_RESULTARG] = D3DTA_CURRENT, 2808 [D3DTSS_BUMPENVMAT00] = 0, 2809 [D3DTSS_BUMPENVMAT01] = 0, 2810 [D3DTSS_BUMPENVMAT10] = 0, 2811 [D3DTSS_BUMPENVMAT11] = 0, 2812 [D3DTSS_BUMPENVLSCALE] = 0, 2813 [D3DTSS_BUMPENVLOFFSET] = 0, 2814 [D3DTSS_TEXCOORDINDEX] = 0, 2815 [D3DTSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE, 2816}; 2817static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] = 2818{ 2819 [D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP, 2820 [D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP, 2821 [D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP, 2822 [D3DSAMP_BORDERCOLOR] = 0, 2823 [D3DSAMP_MAGFILTER] = D3DTEXF_POINT, 2824 [D3DSAMP_MINFILTER] = D3DTEXF_POINT, 2825 [D3DSAMP_MIPFILTER] = D3DTEXF_NONE, 2826 [D3DSAMP_MIPMAPLODBIAS] = 0, 2827 [D3DSAMP_MAXMIPLEVEL] = 0, 2828 [D3DSAMP_MAXANISOTROPY] = 1, 2829 [D3DSAMP_SRGBTEXTURE] = 0, 2830 [D3DSAMP_ELEMENTINDEX] = 0, 2831 [D3DSAMP_DMAPOFFSET] = 0, 2832 [NINED3DSAMP_MINLOD] = 0, 2833 [NINED3DSAMP_SHADOW] = 0, 2834 [NINED3DSAMP_CUBETEX] = 0 2835}; 2836 2837/* Note: The following 4 functions assume there is no 2838 * pending commands */ 2839 2840void nine_state_restore_non_cso(struct NineDevice9 *device) 2841{ 2842 struct nine_context *context = &device->context; 2843 2844 context->changed.group = NINE_STATE_ALL; /* TODO: we can remove states that have prepared commits */ 2845 context->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1; 2846 context->changed.ucp = TRUE; 2847 context->commit |= 0xffffffff; /* re-commit everything */ 2848 context->enabled_sampler_count_vs = 0; 2849 context->enabled_sampler_count_ps = 0; 2850} 2851 2852void 2853nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps, 2854 boolean is_reset) 2855{ 2856 struct nine_state *state = &device->state; 2857 struct nine_context *context = &device->context; 2858 unsigned s; 2859 2860 /* Initialize defaults. 2861 */ 2862 memcpy(context->rs, nine_render_state_defaults, sizeof(context->rs)); 2863 2864 for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) { 2865 memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults, 2866 sizeof(state->ff.tex_stage[s])); 2867 state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] = s; 2868 } 2869 state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE; 2870 state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1; 2871 2872 for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) 2873 memcpy(&context->ff.tex_stage[s], state->ff.tex_stage[s], 2874 sizeof(state->ff.tex_stage[s])); 2875 2876 memset(&context->bumpmap_vars, 0, sizeof(context->bumpmap_vars)); 2877 2878 for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { 2879 memcpy(&context->samp[s], nine_samp_state_defaults, 2880 sizeof(context->samp[s])); 2881 memcpy(&state->samp_advertised[s], nine_samp_state_defaults, 2882 sizeof(state->samp_advertised[s])); 2883 } 2884 2885 memset(state->vs_const_f, 0, VS_CONST_F_SIZE(device)); 2886 memset(context->vs_const_f, 0, device->vs_const_size); 2887 if (context->vs_const_f_swvp) 2888 memset(context->vs_const_f_swvp, 0, NINE_MAX_CONST_F_SWVP * sizeof(float[4])); 2889 memset(state->vs_const_i, 0, VS_CONST_I_SIZE(device)); 2890 memset(context->vs_const_i, 0, VS_CONST_I_SIZE(device)); 2891 memset(state->vs_const_b, 0, VS_CONST_B_SIZE(device)); 2892 memset(context->vs_const_b, 0, VS_CONST_B_SIZE(device)); 2893 memset(state->ps_const_f, 0, device->ps_const_size); 2894 memset(context->ps_const_f, 0, device->ps_const_size); 2895 memset(state->ps_const_i, 0, sizeof(state->ps_const_i)); 2896 memset(context->ps_const_i, 0, sizeof(context->ps_const_i)); 2897 memset(state->ps_const_b, 0, sizeof(state->ps_const_b)); 2898 memset(context->ps_const_b, 0, sizeof(context->ps_const_b)); 2899 2900 /* Cap dependent initial state: 2901 */ 2902 context->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize); 2903 2904 memcpy(state->rs_advertised, context->rs, sizeof(context->rs)); 2905 2906 /* Set changed flags to initialize driver. 2907 */ 2908 context->changed.group = NINE_STATE_ALL; 2909 context->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1; 2910 context->changed.ucp = TRUE; 2911 2912 context->ff.changed.transform[0] = ~0; 2913 context->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); 2914 2915 if (!is_reset) { 2916 state->viewport.MinZ = context->viewport.MinZ = 0.0f; 2917 state->viewport.MaxZ = context->viewport.MaxZ = 1.0f; 2918 } 2919 2920 for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 2921 context->changed.sampler[s] = ~0; 2922 2923 if (!is_reset) { 2924 context->dummy_vbo_bound_at = -1; 2925 context->vbo_bound_done = FALSE; 2926 } 2927} 2928 2929void 2930nine_device_state_clear(struct NineDevice9 *device) 2931{ 2932 struct nine_state *state = &device->state; 2933 unsigned i; 2934 2935 for (i = 0; i < ARRAY_SIZE(state->rt); ++i) 2936 nine_bind(&state->rt[i], NULL); 2937 nine_bind(&state->ds, NULL); 2938 nine_bind(&state->vs, NULL); 2939 nine_bind(&state->ps, NULL); 2940 nine_bind(&state->vdecl, NULL); 2941 for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) 2942 NineBindBufferToDevice(device, 2943 (struct NineBuffer9 **)&state->stream[i], 2944 NULL); 2945 NineBindBufferToDevice(device, 2946 (struct NineBuffer9 **)&state->idxbuf, 2947 NULL); 2948 2949 for (i = 0; i < NINE_MAX_SAMPLERS; ++i) 2950 NineBindTextureToDevice(device, &state->texture[i], NULL); 2951} 2952 2953void 2954nine_context_clear(struct NineDevice9 *device) 2955{ 2956 struct nine_context *context = &device->context; 2957 struct pipe_context *pipe = context->pipe; 2958 struct cso_context *cso = context->cso; 2959 unsigned i; 2960 2961 /* Early device ctor failure. Nothing to do */ 2962 if (!pipe || !cso) 2963 return; 2964 2965 pipe->bind_vs_state(pipe, NULL); 2966 pipe->bind_fs_state(pipe, NULL); 2967 2968 /* Don't unbind constant buffers, they're device-private and 2969 * do not change on Reset. 2970 */ 2971 2972 cso_set_samplers(cso, PIPE_SHADER_VERTEX, 0, NULL); 2973 cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 0, NULL); 2974 context->enabled_sampler_count_vs = 0; 2975 context->enabled_sampler_count_ps = 0; 2976 2977 pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, 0, 2978 NINE_MAX_SAMPLERS_VS, false, NULL); 2979 pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 0, 2980 NINE_MAX_SAMPLERS_PS, false, NULL); 2981 2982 pipe->set_vertex_buffers(pipe, 0, 0, device->caps.MaxStreams, false, NULL); 2983 2984 for (i = 0; i < ARRAY_SIZE(context->rt); ++i) 2985 nine_bind(&context->rt[i], NULL); 2986 nine_bind(&context->ds, NULL); 2987 nine_bind(&context->vs, NULL); 2988 nine_bind(&context->ps, NULL); 2989 nine_bind(&context->vdecl, NULL); 2990 for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) 2991 pipe_vertex_buffer_unreference(&context->vtxbuf[i]); 2992 pipe_resource_reference(&context->idxbuf, NULL); 2993 pipe_resource_reference(&context->pipe_data.cb_vs.buffer, NULL); 2994 pipe_resource_reference(&context->pipe_data.cb_ps.buffer, NULL); 2995 2996 for (i = 0; i < NINE_MAX_SAMPLERS; ++i) { 2997 context->texture[i].enabled = FALSE; 2998 pipe_resource_reference(&context->texture[i].resource, 2999 NULL); 3000 pipe_sampler_view_reference(&context->texture[i].view[0], 3001 NULL); 3002 pipe_sampler_view_reference(&context->texture[i].view[1], 3003 NULL); 3004 } 3005} 3006 3007void 3008nine_context_update_state(struct NineDevice9 *device) 3009{ 3010 nine_update_state(device); 3011} 3012 3013void 3014nine_state_init_sw(struct NineDevice9 *device) 3015{ 3016 struct pipe_context *pipe_sw = device->pipe_sw; 3017 struct pipe_rasterizer_state rast; 3018 struct pipe_blend_state blend; 3019 struct pipe_depth_stencil_alpha_state dsa; 3020 struct pipe_framebuffer_state fb; 3021 3022 /* Only used with Streamout */ 3023 memset(&rast, 0, sizeof(rast)); 3024 rast.rasterizer_discard = true; 3025 rast.point_quad_rasterization = 1; /* to make llvmpipe happy */ 3026 cso_set_rasterizer(device->cso_sw, &rast); 3027 3028 /* dummy settings */ 3029 memset(&blend, 0, sizeof(blend)); 3030 memset(&dsa, 0, sizeof(dsa)); 3031 memset(&fb, 0, sizeof(fb)); 3032 cso_set_blend(device->cso_sw, &blend); 3033 cso_set_depth_stencil_alpha(device->cso_sw, &dsa); 3034 cso_set_framebuffer(device->cso_sw, &fb); 3035 cso_set_viewport_dims(device->cso_sw, 1.0, 1.0, false); 3036 cso_set_fragment_shader_handle(device->cso_sw, util_make_empty_fragment_shader(pipe_sw)); 3037} 3038 3039/* There is duplication with update_vertex_elements. 3040 * TODO: Share the code */ 3041 3042static void 3043update_vertex_elements_sw(struct NineDevice9 *device) 3044{ 3045 struct nine_state *state = &device->state; 3046 const struct NineVertexDeclaration9 *vdecl = device->state.vdecl; 3047 const struct NineVertexShader9 *vs; 3048 unsigned n, b, i; 3049 int index; 3050 int8_t vdecl_index_map[16]; /* vs->num_inputs <= 16 */ 3051 int8_t used_streams[device->caps.MaxStreams]; 3052 int dummy_vbo_stream = -1; 3053 BOOL need_dummy_vbo = FALSE; 3054 struct cso_velems_state ve; 3055 bool programmable_vs = state->vs && !(state->vdecl && state->vdecl->position_t); 3056 3057 memset(vdecl_index_map, -1, 16); 3058 memset(used_streams, 0, device->caps.MaxStreams); 3059 vs = programmable_vs ? device->state.vs : device->ff.vs; 3060 3061 if (vdecl) { 3062 for (n = 0; n < vs->num_inputs; ++n) { 3063 DBG("looking up input %u (usage %u) from vdecl(%p)\n", 3064 n, vs->input_map[n].ndecl, vdecl); 3065 3066 for (i = 0; i < vdecl->nelems; i++) { 3067 if (vdecl->usage_map[i] == vs->input_map[n].ndecl) { 3068 vdecl_index_map[n] = i; 3069 used_streams[vdecl->elems[i].vertex_buffer_index] = 1; 3070 break; 3071 } 3072 } 3073 if (vdecl_index_map[n] < 0) 3074 need_dummy_vbo = TRUE; 3075 } 3076 } else { 3077 /* No vertex declaration. Likely will never happen in practice, 3078 * but we need not crash on this */ 3079 need_dummy_vbo = TRUE; 3080 } 3081 3082 if (need_dummy_vbo) { 3083 for (i = 0; i < device->caps.MaxStreams; i++ ) { 3084 if (!used_streams[i]) { 3085 dummy_vbo_stream = i; 3086 break; 3087 } 3088 } 3089 } 3090 /* TODO handle dummy_vbo */ 3091 assert (!need_dummy_vbo); 3092 3093 for (n = 0; n < vs->num_inputs; ++n) { 3094 index = vdecl_index_map[n]; 3095 if (index >= 0) { 3096 ve.velems[n] = vdecl->elems[index]; 3097 b = ve.velems[n].vertex_buffer_index; 3098 /* XXX wine just uses 1 here: */ 3099 if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA) 3100 ve.velems[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF; 3101 } else { 3102 /* if the vertex declaration is incomplete compared to what the 3103 * vertex shader needs, we bind a dummy vbo with 0 0 0 0. 3104 * This is not precised by the spec, but is the behaviour 3105 * tested on win */ 3106 ve.velems[n].vertex_buffer_index = dummy_vbo_stream; 3107 ve.velems[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 3108 ve.velems[n].src_offset = 0; 3109 ve.velems[n].instance_divisor = 0; 3110 ve.velems[n].dual_slot = false; 3111 } 3112 } 3113 3114 ve.count = vs->num_inputs; 3115 cso_set_vertex_elements(device->cso_sw, &ve); 3116} 3117 3118static void 3119update_vertex_buffers_sw(struct NineDevice9 *device, int start_vertice, int num_vertices) 3120{ 3121 struct pipe_context *pipe = nine_context_get_pipe_acquire(device); 3122 struct pipe_context *pipe_sw = device->pipe_sw; 3123 struct nine_state *state = &device->state; 3124 struct nine_state_sw_internal *sw_internal = &device->state_sw_internal; 3125 struct pipe_vertex_buffer vtxbuf; 3126 uint32_t mask = 0xf; 3127 unsigned i; 3128 3129 DBG("mask=%x\n", mask); 3130 3131 /* TODO: handle dummy_vbo_bound_at */ 3132 3133 for (i = 0; mask; mask >>= 1, ++i) { 3134 if (mask & 1) { 3135 if (state->stream[i]) { 3136 unsigned offset; 3137 struct pipe_resource *buf; 3138 struct pipe_box box; 3139 void *userbuf; 3140 3141 vtxbuf = state->vtxbuf[i]; 3142 buf = NineVertexBuffer9_GetResource(state->stream[i], &offset); 3143 3144 DBG("Locking %p (offset %d, length %d)\n", buf, 3145 vtxbuf.buffer_offset, num_vertices * vtxbuf.stride); 3146 3147 u_box_1d(vtxbuf.buffer_offset + offset + start_vertice * vtxbuf.stride, 3148 num_vertices * vtxbuf.stride, &box); 3149 3150 userbuf = pipe->buffer_map(pipe, buf, 0, PIPE_MAP_READ, &box, 3151 &(sw_internal->transfers_so[i])); 3152 vtxbuf.is_user_buffer = true; 3153 vtxbuf.buffer.user = userbuf; 3154 3155 if (!device->driver_caps.user_sw_vbufs) { 3156 vtxbuf.buffer.resource = NULL; 3157 vtxbuf.is_user_buffer = false; 3158 u_upload_data(device->pipe_sw->stream_uploader, 3159 0, 3160 box.width, 3161 16, 3162 userbuf, 3163 &(vtxbuf.buffer_offset), 3164 &(vtxbuf.buffer.resource)); 3165 u_upload_unmap(device->pipe_sw->stream_uploader); 3166 } 3167 pipe_sw->set_vertex_buffers(pipe_sw, i, 1, 0, false, &vtxbuf); 3168 pipe_vertex_buffer_unreference(&vtxbuf); 3169 } else 3170 pipe_sw->set_vertex_buffers(pipe_sw, i, 0, 1, false, NULL); 3171 } 3172 } 3173 nine_context_get_pipe_release(device); 3174} 3175 3176static void 3177update_vs_constants_sw(struct NineDevice9 *device) 3178{ 3179 struct nine_state *state = &device->state; 3180 struct pipe_context *pipe_sw = device->pipe_sw; 3181 3182 DBG("updating\n"); 3183 3184 { 3185 struct pipe_constant_buffer cb; 3186 const void *buf; 3187 3188 cb.buffer = NULL; 3189 cb.buffer_offset = 0; 3190 cb.buffer_size = 4096 * sizeof(float[4]); 3191 cb.user_buffer = state->vs_const_f; 3192 3193 if (state->vs->lconstf.ranges) { 3194 const struct nine_lconstf *lconstf = &device->state.vs->lconstf; 3195 const struct nine_range *r = lconstf->ranges; 3196 unsigned n = 0; 3197 float *dst = device->state.vs_lconstf_temp; 3198 float *src = (float *)cb.user_buffer; 3199 memcpy(dst, src, 8192 * sizeof(float[4])); 3200 while (r) { 3201 unsigned p = r->bgn; 3202 unsigned c = r->end - r->bgn; 3203 memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); 3204 n += c; 3205 r = r->next; 3206 } 3207 cb.user_buffer = dst; 3208 } 3209 3210 buf = cb.user_buffer; 3211 3212 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 0, false, &cb); 3213 if (cb.buffer) 3214 pipe_resource_reference(&cb.buffer, NULL); 3215 3216 cb.user_buffer = (int8_t *)buf + 4096 * sizeof(float[4]); 3217 3218 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 1, false, &cb); 3219 if (cb.buffer) 3220 pipe_resource_reference(&cb.buffer, NULL); 3221 } 3222 3223 { 3224 struct pipe_constant_buffer cb; 3225 3226 cb.buffer = NULL; 3227 cb.buffer_offset = 0; 3228 cb.buffer_size = 2048 * sizeof(float[4]); 3229 cb.user_buffer = state->vs_const_i; 3230 3231 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 2, false, &cb); 3232 if (cb.buffer) 3233 pipe_resource_reference(&cb.buffer, NULL); 3234 } 3235 3236 { 3237 struct pipe_constant_buffer cb; 3238 3239 cb.buffer = NULL; 3240 cb.buffer_offset = 0; 3241 cb.buffer_size = 512 * sizeof(float[4]); 3242 cb.user_buffer = state->vs_const_b; 3243 3244 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 3, false, &cb); 3245 if (cb.buffer) 3246 pipe_resource_reference(&cb.buffer, NULL); 3247 } 3248 3249 { 3250 struct pipe_constant_buffer cb; 3251 const D3DVIEWPORT9 *vport = &device->state.viewport; 3252 float viewport_data[8] = {(float)vport->Width * 0.5f, 3253 (float)vport->Height * -0.5f, vport->MaxZ - vport->MinZ, 0.f, 3254 (float)vport->Width * 0.5f + (float)vport->X, 3255 (float)vport->Height * 0.5f + (float)vport->Y, 3256 vport->MinZ, 0.f}; 3257 3258 cb.buffer = NULL; 3259 cb.buffer_offset = 0; 3260 cb.buffer_size = 2 * sizeof(float[4]); 3261 cb.user_buffer = viewport_data; 3262 3263 { 3264 u_upload_data(device->pipe_sw->const_uploader, 3265 0, 3266 cb.buffer_size, 3267 16, 3268 cb.user_buffer, 3269 &(cb.buffer_offset), 3270 &(cb.buffer)); 3271 u_upload_unmap(device->pipe_sw->const_uploader); 3272 cb.user_buffer = NULL; 3273 } 3274 3275 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 4, false, &cb); 3276 if (cb.buffer) 3277 pipe_resource_reference(&cb.buffer, NULL); 3278 } 3279 3280} 3281 3282void 3283nine_state_prepare_draw_sw(struct NineDevice9 *device, struct NineVertexDeclaration9 *vdecl_out, 3284 int start_vertice, int num_vertices, struct pipe_stream_output_info *so) 3285{ 3286 struct nine_state *state = &device->state; 3287 bool programmable_vs = state->vs && !(state->vdecl && state->vdecl->position_t); 3288 struct NineVertexShader9 *vs = programmable_vs ? device->state.vs : device->ff.vs; 3289 3290 assert(programmable_vs); 3291 3292 DBG("Preparing draw\n"); 3293 cso_set_vertex_shader_handle(device->cso_sw, 3294 NineVertexShader9_GetVariantProcessVertices(vs, vdecl_out, so)); 3295 update_vertex_elements_sw(device); 3296 update_vertex_buffers_sw(device, start_vertice, num_vertices); 3297 update_vs_constants_sw(device); 3298 DBG("Preparation succeeded\n"); 3299} 3300 3301void 3302nine_state_after_draw_sw(struct NineDevice9 *device) 3303{ 3304 struct nine_state_sw_internal *sw_internal = &device->state_sw_internal; 3305 struct pipe_context *pipe = nine_context_get_pipe_acquire(device); 3306 struct pipe_context *pipe_sw = device->pipe_sw; 3307 int i; 3308 3309 for (i = 0; i < 4; i++) { 3310 pipe_sw->set_vertex_buffers(pipe_sw, i, 0, 1, false, NULL); 3311 if (sw_internal->transfers_so[i]) 3312 pipe->buffer_unmap(pipe, sw_internal->transfers_so[i]); 3313 sw_internal->transfers_so[i] = NULL; 3314 } 3315 nine_context_get_pipe_release(device); 3316} 3317 3318void 3319nine_state_destroy_sw(struct NineDevice9 *device) 3320{ 3321 (void) device; 3322 /* Everything destroyed with cso */ 3323} 3324 3325/* 3326static const DWORD nine_render_states_pixel[] = 3327{ 3328 D3DRS_ALPHABLENDENABLE, 3329 D3DRS_ALPHAFUNC, 3330 D3DRS_ALPHAREF, 3331 D3DRS_ALPHATESTENABLE, 3332 D3DRS_ANTIALIASEDLINEENABLE, 3333 D3DRS_BLENDFACTOR, 3334 D3DRS_BLENDOP, 3335 D3DRS_BLENDOPALPHA, 3336 D3DRS_CCW_STENCILFAIL, 3337 D3DRS_CCW_STENCILPASS, 3338 D3DRS_CCW_STENCILZFAIL, 3339 D3DRS_COLORWRITEENABLE, 3340 D3DRS_COLORWRITEENABLE1, 3341 D3DRS_COLORWRITEENABLE2, 3342 D3DRS_COLORWRITEENABLE3, 3343 D3DRS_DEPTHBIAS, 3344 D3DRS_DESTBLEND, 3345 D3DRS_DESTBLENDALPHA, 3346 D3DRS_DITHERENABLE, 3347 D3DRS_FILLMODE, 3348 D3DRS_FOGDENSITY, 3349 D3DRS_FOGEND, 3350 D3DRS_FOGSTART, 3351 D3DRS_LASTPIXEL, 3352 D3DRS_SCISSORTESTENABLE, 3353 D3DRS_SEPARATEALPHABLENDENABLE, 3354 D3DRS_SHADEMODE, 3355 D3DRS_SLOPESCALEDEPTHBIAS, 3356 D3DRS_SRCBLEND, 3357 D3DRS_SRCBLENDALPHA, 3358 D3DRS_SRGBWRITEENABLE, 3359 D3DRS_STENCILENABLE, 3360 D3DRS_STENCILFAIL, 3361 D3DRS_STENCILFUNC, 3362 D3DRS_STENCILMASK, 3363 D3DRS_STENCILPASS, 3364 D3DRS_STENCILREF, 3365 D3DRS_STENCILWRITEMASK, 3366 D3DRS_STENCILZFAIL, 3367 D3DRS_TEXTUREFACTOR, 3368 D3DRS_TWOSIDEDSTENCILMODE, 3369 D3DRS_WRAP0, 3370 D3DRS_WRAP1, 3371 D3DRS_WRAP10, 3372 D3DRS_WRAP11, 3373 D3DRS_WRAP12, 3374 D3DRS_WRAP13, 3375 D3DRS_WRAP14, 3376 D3DRS_WRAP15, 3377 D3DRS_WRAP2, 3378 D3DRS_WRAP3, 3379 D3DRS_WRAP4, 3380 D3DRS_WRAP5, 3381 D3DRS_WRAP6, 3382 D3DRS_WRAP7, 3383 D3DRS_WRAP8, 3384 D3DRS_WRAP9, 3385 D3DRS_ZENABLE, 3386 D3DRS_ZFUNC, 3387 D3DRS_ZWRITEENABLE 3388}; 3389*/ 3390const uint32_t nine_render_states_pixel[(NINED3DRS_LAST + 31) / 32] = 3391{ 3392 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000, 3393 0x000000ff, 0xde01c900, 0x0003ffcf 3394}; 3395 3396/* 3397static const DWORD nine_render_states_vertex[] = 3398{ 3399 D3DRS_ADAPTIVETESS_W, 3400 D3DRS_ADAPTIVETESS_X, 3401 D3DRS_ADAPTIVETESS_Y, 3402 D3DRS_ADAPTIVETESS_Z, 3403 D3DRS_AMBIENT, 3404 D3DRS_AMBIENTMATERIALSOURCE, 3405 D3DRS_CLIPPING, 3406 D3DRS_CLIPPLANEENABLE, 3407 D3DRS_COLORVERTEX, 3408 D3DRS_CULLMODE, 3409 D3DRS_DIFFUSEMATERIALSOURCE, 3410 D3DRS_EMISSIVEMATERIALSOURCE, 3411 D3DRS_ENABLEADAPTIVETESSELLATION, 3412 D3DRS_FOGCOLOR, 3413 D3DRS_FOGDENSITY, 3414 D3DRS_FOGENABLE, 3415 D3DRS_FOGEND, 3416 D3DRS_FOGSTART, 3417 D3DRS_FOGTABLEMODE, 3418 D3DRS_FOGVERTEXMODE, 3419 D3DRS_INDEXEDVERTEXBLENDENABLE, 3420 D3DRS_LIGHTING, 3421 D3DRS_LOCALVIEWER, 3422 D3DRS_MAXTESSELLATIONLEVEL, 3423 D3DRS_MINTESSELLATIONLEVEL, 3424 D3DRS_MULTISAMPLEANTIALIAS, 3425 D3DRS_MULTISAMPLEMASK, 3426 D3DRS_NORMALDEGREE, 3427 D3DRS_NORMALIZENORMALS, 3428 D3DRS_PATCHEDGESTYLE, 3429 D3DRS_POINTSCALE_A, 3430 D3DRS_POINTSCALE_B, 3431 D3DRS_POINTSCALE_C, 3432 D3DRS_POINTSCALEENABLE, 3433 D3DRS_POINTSIZE, 3434 D3DRS_POINTSIZE_MAX, 3435 D3DRS_POINTSIZE_MIN, 3436 D3DRS_POINTSPRITEENABLE, 3437 D3DRS_POSITIONDEGREE, 3438 D3DRS_RANGEFOGENABLE, 3439 D3DRS_SHADEMODE, 3440 D3DRS_SPECULARENABLE, 3441 D3DRS_SPECULARMATERIALSOURCE, 3442 D3DRS_TWEENFACTOR, 3443 D3DRS_VERTEXBLEND 3444}; 3445*/ 3446const uint32_t nine_render_states_vertex[(NINED3DRS_LAST + 31) / 32] = 3447{ 3448 0x30400200, 0x0001007c, 0x00000000, 0x00000000, 3449 0xfd9efb00, 0x01fc34cf, 0x00000000 3450}; 3451 3452/* TODO: put in the right values */ 3453const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] = 3454{ 3455 [D3DRS_ZENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE, 3456 [D3DRS_FILLMODE] = NINE_STATE_RASTERIZER, 3457 [D3DRS_SHADEMODE] = NINE_STATE_RASTERIZER, 3458 [D3DRS_ZWRITEENABLE] = NINE_STATE_DSA, 3459 [D3DRS_ALPHATESTENABLE] = NINE_STATE_DSA, 3460 [D3DRS_LASTPIXEL] = NINE_STATE_RASTERIZER, 3461 [D3DRS_SRCBLEND] = NINE_STATE_BLEND, 3462 [D3DRS_DESTBLEND] = NINE_STATE_BLEND, 3463 [D3DRS_CULLMODE] = NINE_STATE_RASTERIZER, 3464 [D3DRS_ZFUNC] = NINE_STATE_DSA, 3465 [D3DRS_ALPHAREF] = NINE_STATE_DSA, 3466 [D3DRS_ALPHAFUNC] = NINE_STATE_DSA, 3467 [D3DRS_DITHERENABLE] = NINE_STATE_BLEND, 3468 [D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND, 3469 [D3DRS_FOGENABLE] = NINE_STATE_FF_SHADER | NINE_STATE_VS_PARAMS_MISC | NINE_STATE_PS_PARAMS_MISC | NINE_STATE_PS_CONST, 3470 [D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING, 3471 [D3DRS_FOGCOLOR] = NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, 3472 [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_SHADER | NINE_STATE_PS_PARAMS_MISC | NINE_STATE_PS_CONST, 3473 [D3DRS_FOGSTART] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, 3474 [D3DRS_FOGEND] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, 3475 [D3DRS_FOGDENSITY] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, 3476 [D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_SHADER, 3477 [D3DRS_STENCILENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE, 3478 [D3DRS_STENCILFAIL] = NINE_STATE_DSA, 3479 [D3DRS_STENCILZFAIL] = NINE_STATE_DSA, 3480 [D3DRS_STENCILPASS] = NINE_STATE_DSA, 3481 [D3DRS_STENCILFUNC] = NINE_STATE_DSA, 3482 [D3DRS_STENCILREF] = NINE_STATE_STENCIL_REF, 3483 [D3DRS_STENCILMASK] = NINE_STATE_DSA, 3484 [D3DRS_STENCILWRITEMASK] = NINE_STATE_DSA, 3485 [D3DRS_TEXTUREFACTOR] = NINE_STATE_FF_PS_CONSTS, 3486 [D3DRS_WRAP0] = NINE_STATE_UNHANDLED, /* cylindrical wrap is crazy */ 3487 [D3DRS_WRAP1] = NINE_STATE_UNHANDLED, 3488 [D3DRS_WRAP2] = NINE_STATE_UNHANDLED, 3489 [D3DRS_WRAP3] = NINE_STATE_UNHANDLED, 3490 [D3DRS_WRAP4] = NINE_STATE_UNHANDLED, 3491 [D3DRS_WRAP5] = NINE_STATE_UNHANDLED, 3492 [D3DRS_WRAP6] = NINE_STATE_UNHANDLED, 3493 [D3DRS_WRAP7] = NINE_STATE_UNHANDLED, 3494 [D3DRS_CLIPPING] = 0, /* software vertex processing only */ 3495 [D3DRS_LIGHTING] = NINE_STATE_FF_LIGHTING, 3496 [D3DRS_AMBIENT] = NINE_STATE_FF_LIGHTING | NINE_STATE_FF_MATERIAL, 3497 [D3DRS_FOGVERTEXMODE] = NINE_STATE_FF_SHADER, 3498 [D3DRS_COLORVERTEX] = NINE_STATE_FF_LIGHTING, 3499 [D3DRS_LOCALVIEWER] = NINE_STATE_FF_LIGHTING, 3500 [D3DRS_NORMALIZENORMALS] = NINE_STATE_FF_SHADER, 3501 [D3DRS_DIFFUSEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, 3502 [D3DRS_SPECULARMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, 3503 [D3DRS_AMBIENTMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, 3504 [D3DRS_EMISSIVEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, 3505 [D3DRS_VERTEXBLEND] = NINE_STATE_FF_SHADER, 3506 [D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER, 3507 [D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER, 3508 [D3DRS_POINTSIZE_MIN] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER | NINE_STATE_VS_PARAMS_MISC, 3509 [D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER, 3510 [D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_SHADER, 3511 [D3DRS_POINTSCALE_A] = NINE_STATE_FF_VS_OTHER, 3512 [D3DRS_POINTSCALE_B] = NINE_STATE_FF_VS_OTHER, 3513 [D3DRS_POINTSCALE_C] = NINE_STATE_FF_VS_OTHER, 3514 [D3DRS_MULTISAMPLEANTIALIAS] = NINE_STATE_MULTISAMPLE, 3515 [D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK, 3516 [D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED, 3517 [D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED, 3518 [D3DRS_POINTSIZE_MAX] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER | NINE_STATE_VS_PARAMS_MISC, 3519 [D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_SHADER, 3520 [D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND, 3521 [D3DRS_TWEENFACTOR] = NINE_STATE_FF_VS_OTHER, 3522 [D3DRS_BLENDOP] = NINE_STATE_BLEND, 3523 [D3DRS_POSITIONDEGREE] = NINE_STATE_UNHANDLED, 3524 [D3DRS_NORMALDEGREE] = NINE_STATE_UNHANDLED, 3525 [D3DRS_SCISSORTESTENABLE] = NINE_STATE_RASTERIZER, 3526 [D3DRS_SLOPESCALEDEPTHBIAS] = NINE_STATE_RASTERIZER, 3527 [D3DRS_ANTIALIASEDLINEENABLE] = NINE_STATE_RASTERIZER, 3528 [D3DRS_MINTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, 3529 [D3DRS_MAXTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, 3530 [D3DRS_ADAPTIVETESS_X] = NINE_STATE_UNHANDLED, 3531 [D3DRS_ADAPTIVETESS_Y] = NINE_STATE_UNHANDLED, 3532 [D3DRS_ADAPTIVETESS_Z] = NINE_STATE_UNHANDLED, 3533 [D3DRS_ADAPTIVETESS_W] = NINE_STATE_UNHANDLED, 3534 [D3DRS_ENABLEADAPTIVETESSELLATION] = NINE_STATE_UNHANDLED, 3535 [D3DRS_TWOSIDEDSTENCILMODE] = NINE_STATE_DSA, 3536 [D3DRS_CCW_STENCILFAIL] = NINE_STATE_DSA, 3537 [D3DRS_CCW_STENCILZFAIL] = NINE_STATE_DSA, 3538 [D3DRS_CCW_STENCILPASS] = NINE_STATE_DSA, 3539 [D3DRS_CCW_STENCILFUNC] = NINE_STATE_DSA, 3540 [D3DRS_COLORWRITEENABLE1] = NINE_STATE_BLEND, 3541 [D3DRS_COLORWRITEENABLE2] = NINE_STATE_BLEND, 3542 [D3DRS_COLORWRITEENABLE3] = NINE_STATE_BLEND, 3543 [D3DRS_BLENDFACTOR] = NINE_STATE_BLEND_COLOR, 3544 [D3DRS_SRGBWRITEENABLE] = NINE_STATE_FB, 3545 [D3DRS_DEPTHBIAS] = NINE_STATE_RASTERIZER, 3546 [D3DRS_WRAP8] = NINE_STATE_UNHANDLED, /* cylwrap has to be done via GP */ 3547 [D3DRS_WRAP9] = NINE_STATE_UNHANDLED, 3548 [D3DRS_WRAP10] = NINE_STATE_UNHANDLED, 3549 [D3DRS_WRAP11] = NINE_STATE_UNHANDLED, 3550 [D3DRS_WRAP12] = NINE_STATE_UNHANDLED, 3551 [D3DRS_WRAP13] = NINE_STATE_UNHANDLED, 3552 [D3DRS_WRAP14] = NINE_STATE_UNHANDLED, 3553 [D3DRS_WRAP15] = NINE_STATE_UNHANDLED, 3554 [D3DRS_SEPARATEALPHABLENDENABLE] = NINE_STATE_BLEND, 3555 [D3DRS_SRCBLENDALPHA] = NINE_STATE_BLEND, 3556 [D3DRS_DESTBLENDALPHA] = NINE_STATE_BLEND, 3557 [D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND 3558}; 3559 3560/* Misc */ 3561 3562static D3DMATRIX nine_state_identity = { .m[0] = { 1, 0, 0, 0 }, 3563 .m[1] = { 0, 1, 0, 0 }, 3564 .m[2] = { 0, 0, 1, 0 }, 3565 .m[3] = { 0, 0, 0, 1 } }; 3566 3567void 3568nine_state_resize_transform(struct nine_ff_state *ff_state, unsigned N) 3569{ 3570 unsigned n = ff_state->num_transforms; 3571 3572 if (N <= n) 3573 return; 3574 3575 ff_state->transform = REALLOC(ff_state->transform, 3576 n * sizeof(D3DMATRIX), 3577 N * sizeof(D3DMATRIX)); 3578 for (; n < N; ++n) 3579 ff_state->transform[n] = nine_state_identity; 3580 ff_state->num_transforms = N; 3581} 3582 3583D3DMATRIX * 3584nine_state_access_transform(struct nine_ff_state *ff_state, D3DTRANSFORMSTATETYPE t, 3585 boolean alloc) 3586{ 3587 unsigned index; 3588 3589 switch (t) { 3590 case D3DTS_VIEW: index = 0; break; 3591 case D3DTS_PROJECTION: index = 1; break; 3592 case D3DTS_TEXTURE0: index = 2; break; 3593 case D3DTS_TEXTURE1: index = 3; break; 3594 case D3DTS_TEXTURE2: index = 4; break; 3595 case D3DTS_TEXTURE3: index = 5; break; 3596 case D3DTS_TEXTURE4: index = 6; break; 3597 case D3DTS_TEXTURE5: index = 7; break; 3598 case D3DTS_TEXTURE6: index = 8; break; 3599 case D3DTS_TEXTURE7: index = 9; break; 3600 default: 3601 if (!(t >= D3DTS_WORLDMATRIX(0) && t <= D3DTS_WORLDMATRIX(255))) 3602 return NULL; 3603 index = 10 + (t - D3DTS_WORLDMATRIX(0)); 3604 break; 3605 } 3606 3607 if (index >= ff_state->num_transforms) { 3608 if (!alloc) 3609 return &nine_state_identity; 3610 nine_state_resize_transform(ff_state, index + 1); 3611 } 3612 return &ff_state->transform[index]; 3613} 3614 3615HRESULT 3616nine_state_set_light(struct nine_ff_state *ff_state, DWORD Index, 3617 const D3DLIGHT9 *pLight) 3618{ 3619 if (Index >= ff_state->num_lights) { 3620 unsigned n = ff_state->num_lights; 3621 unsigned N = Index + 1; 3622 3623 ff_state->light = REALLOC(ff_state->light, n * sizeof(D3DLIGHT9), 3624 N * sizeof(D3DLIGHT9)); 3625 if (!ff_state->light) 3626 return E_OUTOFMEMORY; 3627 ff_state->num_lights = N; 3628 3629 for (; n < Index; ++n) { 3630 memset(&ff_state->light[n], 0, sizeof(D3DLIGHT9)); 3631 ff_state->light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; 3632 } 3633 } 3634 ff_state->light[Index] = *pLight; 3635 3636 if (pLight->Type == D3DLIGHT_SPOT && pLight->Theta >= pLight->Phi) { 3637 DBG("Warning: clamping D3DLIGHT9.Theta\n"); 3638 ff_state->light[Index].Theta = ff_state->light[Index].Phi; 3639 } 3640 return D3D_OK; 3641} 3642 3643HRESULT 3644nine_state_light_enable(struct nine_ff_state *ff_state, 3645 DWORD Index, BOOL Enable) 3646{ 3647 unsigned i; 3648 3649 user_assert(Index < ff_state->num_lights, D3DERR_INVALIDCALL); 3650 3651 for (i = 0; i < ff_state->num_lights_active; ++i) { 3652 if (ff_state->active_light[i] == Index) 3653 break; 3654 } 3655 3656 if (Enable) { 3657 if (i < ff_state->num_lights_active) 3658 return D3D_OK; 3659 /* XXX wine thinks this should still succeed: 3660 */ 3661 user_assert(i < NINE_MAX_LIGHTS_ACTIVE, D3DERR_INVALIDCALL); 3662 3663 ff_state->active_light[i] = Index; 3664 ff_state->num_lights_active++; 3665 } else { 3666 if (i == ff_state->num_lights_active) 3667 return D3D_OK; 3668 --ff_state->num_lights_active; 3669 for (; i < ff_state->num_lights_active; ++i) 3670 ff_state->active_light[i] = ff_state->active_light[i + 1]; 3671 } 3672 3673 return D3D_OK; 3674} 3675 3676#define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n 3677const char *nine_d3drs_to_string(DWORD State) 3678{ 3679 switch (State) { 3680 D3DRS_TO_STRING_CASE(ZENABLE); 3681 D3DRS_TO_STRING_CASE(FILLMODE); 3682 D3DRS_TO_STRING_CASE(SHADEMODE); 3683 D3DRS_TO_STRING_CASE(ZWRITEENABLE); 3684 D3DRS_TO_STRING_CASE(ALPHATESTENABLE); 3685 D3DRS_TO_STRING_CASE(LASTPIXEL); 3686 D3DRS_TO_STRING_CASE(SRCBLEND); 3687 D3DRS_TO_STRING_CASE(DESTBLEND); 3688 D3DRS_TO_STRING_CASE(CULLMODE); 3689 D3DRS_TO_STRING_CASE(ZFUNC); 3690 D3DRS_TO_STRING_CASE(ALPHAREF); 3691 D3DRS_TO_STRING_CASE(ALPHAFUNC); 3692 D3DRS_TO_STRING_CASE(DITHERENABLE); 3693 D3DRS_TO_STRING_CASE(ALPHABLENDENABLE); 3694 D3DRS_TO_STRING_CASE(FOGENABLE); 3695 D3DRS_TO_STRING_CASE(SPECULARENABLE); 3696 D3DRS_TO_STRING_CASE(FOGCOLOR); 3697 D3DRS_TO_STRING_CASE(FOGTABLEMODE); 3698 D3DRS_TO_STRING_CASE(FOGSTART); 3699 D3DRS_TO_STRING_CASE(FOGEND); 3700 D3DRS_TO_STRING_CASE(FOGDENSITY); 3701 D3DRS_TO_STRING_CASE(RANGEFOGENABLE); 3702 D3DRS_TO_STRING_CASE(STENCILENABLE); 3703 D3DRS_TO_STRING_CASE(STENCILFAIL); 3704 D3DRS_TO_STRING_CASE(STENCILZFAIL); 3705 D3DRS_TO_STRING_CASE(STENCILPASS); 3706 D3DRS_TO_STRING_CASE(STENCILFUNC); 3707 D3DRS_TO_STRING_CASE(STENCILREF); 3708 D3DRS_TO_STRING_CASE(STENCILMASK); 3709 D3DRS_TO_STRING_CASE(STENCILWRITEMASK); 3710 D3DRS_TO_STRING_CASE(TEXTUREFACTOR); 3711 D3DRS_TO_STRING_CASE(WRAP0); 3712 D3DRS_TO_STRING_CASE(WRAP1); 3713 D3DRS_TO_STRING_CASE(WRAP2); 3714 D3DRS_TO_STRING_CASE(WRAP3); 3715 D3DRS_TO_STRING_CASE(WRAP4); 3716 D3DRS_TO_STRING_CASE(WRAP5); 3717 D3DRS_TO_STRING_CASE(WRAP6); 3718 D3DRS_TO_STRING_CASE(WRAP7); 3719 D3DRS_TO_STRING_CASE(CLIPPING); 3720 D3DRS_TO_STRING_CASE(LIGHTING); 3721 D3DRS_TO_STRING_CASE(AMBIENT); 3722 D3DRS_TO_STRING_CASE(FOGVERTEXMODE); 3723 D3DRS_TO_STRING_CASE(COLORVERTEX); 3724 D3DRS_TO_STRING_CASE(LOCALVIEWER); 3725 D3DRS_TO_STRING_CASE(NORMALIZENORMALS); 3726 D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE); 3727 D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE); 3728 D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE); 3729 D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE); 3730 D3DRS_TO_STRING_CASE(VERTEXBLEND); 3731 D3DRS_TO_STRING_CASE(CLIPPLANEENABLE); 3732 D3DRS_TO_STRING_CASE(POINTSIZE); 3733 D3DRS_TO_STRING_CASE(POINTSIZE_MIN); 3734 D3DRS_TO_STRING_CASE(POINTSPRITEENABLE); 3735 D3DRS_TO_STRING_CASE(POINTSCALEENABLE); 3736 D3DRS_TO_STRING_CASE(POINTSCALE_A); 3737 D3DRS_TO_STRING_CASE(POINTSCALE_B); 3738 D3DRS_TO_STRING_CASE(POINTSCALE_C); 3739 D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS); 3740 D3DRS_TO_STRING_CASE(MULTISAMPLEMASK); 3741 D3DRS_TO_STRING_CASE(PATCHEDGESTYLE); 3742 D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN); 3743 D3DRS_TO_STRING_CASE(POINTSIZE_MAX); 3744 D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE); 3745 D3DRS_TO_STRING_CASE(COLORWRITEENABLE); 3746 D3DRS_TO_STRING_CASE(TWEENFACTOR); 3747 D3DRS_TO_STRING_CASE(BLENDOP); 3748 D3DRS_TO_STRING_CASE(POSITIONDEGREE); 3749 D3DRS_TO_STRING_CASE(NORMALDEGREE); 3750 D3DRS_TO_STRING_CASE(SCISSORTESTENABLE); 3751 D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS); 3752 D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE); 3753 D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL); 3754 D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL); 3755 D3DRS_TO_STRING_CASE(ADAPTIVETESS_X); 3756 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y); 3757 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z); 3758 D3DRS_TO_STRING_CASE(ADAPTIVETESS_W); 3759 D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION); 3760 D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE); 3761 D3DRS_TO_STRING_CASE(CCW_STENCILFAIL); 3762 D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL); 3763 D3DRS_TO_STRING_CASE(CCW_STENCILPASS); 3764 D3DRS_TO_STRING_CASE(CCW_STENCILFUNC); 3765 D3DRS_TO_STRING_CASE(COLORWRITEENABLE1); 3766 D3DRS_TO_STRING_CASE(COLORWRITEENABLE2); 3767 D3DRS_TO_STRING_CASE(COLORWRITEENABLE3); 3768 D3DRS_TO_STRING_CASE(BLENDFACTOR); 3769 D3DRS_TO_STRING_CASE(SRGBWRITEENABLE); 3770 D3DRS_TO_STRING_CASE(DEPTHBIAS); 3771 D3DRS_TO_STRING_CASE(WRAP8); 3772 D3DRS_TO_STRING_CASE(WRAP9); 3773 D3DRS_TO_STRING_CASE(WRAP10); 3774 D3DRS_TO_STRING_CASE(WRAP11); 3775 D3DRS_TO_STRING_CASE(WRAP12); 3776 D3DRS_TO_STRING_CASE(WRAP13); 3777 D3DRS_TO_STRING_CASE(WRAP14); 3778 D3DRS_TO_STRING_CASE(WRAP15); 3779 D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE); 3780 D3DRS_TO_STRING_CASE(SRCBLENDALPHA); 3781 D3DRS_TO_STRING_CASE(DESTBLENDALPHA); 3782 D3DRS_TO_STRING_CASE(BLENDOPALPHA); 3783 default: 3784 return "(invalid)"; 3785 } 3786} 3787