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