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