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