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