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