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