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