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