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