1b9622b00f8a554c224d2ef414495749e905f43b
[mesa.git] / src / gallium / state_trackers / nine / nine_state.c
1 /*
2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3 * Copyright 2013 Christoph Bumiller
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24 #include "device9.h"
25 #include "basetexture9.h"
26 #include "indexbuffer9.h"
27 #include "surface9.h"
28 #include "vertexdeclaration9.h"
29 #include "vertexshader9.h"
30 #include "pixelshader9.h"
31 #include "nine_pipe.h"
32 #include "nine_ff.h"
33 #include "pipe/p_context.h"
34 #include "pipe/p_state.h"
35 #include "cso_cache/cso_context.h"
36 #include "util/u_upload_mgr.h"
37 #include "util/u_math.h"
38
39 #define DBG_CHANNEL DBG_DEVICE
40
41 /* State preparation only */
42
43 static inline void
44 prepare_blend(struct NineDevice9 *device)
45 {
46 nine_convert_blend_state(&device->state.pipe.blend, device->state.rs);
47 device->state.commit |= NINE_STATE_COMMIT_BLEND;
48 }
49
50 static inline void
51 prepare_dsa(struct NineDevice9 *device)
52 {
53 nine_convert_dsa_state(&device->state.pipe.dsa, device->state.rs);
54 device->state.commit |= NINE_STATE_COMMIT_DSA;
55 }
56
57 static inline void
58 prepare_rasterizer(struct NineDevice9 *device)
59 {
60 nine_convert_rasterizer_state(&device->state.pipe.rast, device->state.rs);
61 device->state.commit |= NINE_STATE_COMMIT_RASTERIZER;
62 }
63
64 #define DO_UPLOAD_CONST_F(buf,p,c,d) \
65 do { \
66 DBG("upload ConstantF [%u .. %u]\n", x, (x) + (c) - 1); \
67 box.x = (p) * 4 * sizeof(float); \
68 box.width = (c) * 4 * sizeof(float); \
69 pipe->transfer_inline_write(pipe, buf, 0, usage, &box, &((d)[p * 4]), \
70 0, 0); \
71 } while(0)
72
73 /* OK, this is a bit ugly ... */
74 static void
75 upload_constants(struct NineDevice9 *device, unsigned shader_type)
76 {
77 struct pipe_context *pipe = device->pipe;
78 struct pipe_resource *buf;
79 struct pipe_box box;
80 const void *data;
81 const float *const_f;
82 const int *const_i;
83 const BOOL *const_b;
84 uint32_t data_b[NINE_MAX_CONST_B];
85 uint16_t dirty_i;
86 uint16_t dirty_b;
87 const unsigned usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE;
88 unsigned x = 0; /* silence warning */
89 unsigned i, c;
90 struct nine_range *r, *p, *lconstf_ranges;
91 float *lconstf_data;
92
93 box.y = 0;
94 box.z = 0;
95 box.height = 1;
96 box.depth = 1;
97
98 if (shader_type == PIPE_SHADER_VERTEX) {
99 DBG("VS\n");
100 buf = device->constbuf_vs;
101
102 const_f = device->state.vs_const_f;
103 for (p = r = device->state.changed.vs_const_f; r; p = r, r = r->next)
104 DO_UPLOAD_CONST_F(buf, r->bgn, r->end - r->bgn, const_f);
105 if (p) {
106 nine_range_pool_put_chain(&device->range_pool,
107 device->state.changed.vs_const_f, p);
108 device->state.changed.vs_const_f = NULL;
109 }
110
111 dirty_i = device->state.changed.vs_const_i;
112 device->state.changed.vs_const_i = 0;
113 const_i = &device->state.vs_const_i[0][0];
114
115 dirty_b = device->state.changed.vs_const_b;
116 device->state.changed.vs_const_b = 0;
117 const_b = device->state.vs_const_b;
118
119 lconstf_ranges = device->state.vs->lconstf.ranges;
120 lconstf_data = device->state.vs->lconstf.data;
121
122 device->state.ff.clobber.vs_const = TRUE;
123 device->state.changed.group &= ~NINE_STATE_VS_CONST;
124 } else {
125 DBG("PS\n");
126 buf = device->constbuf_ps;
127
128 const_f = device->state.ps_const_f;
129 for (p = r = device->state.changed.ps_const_f; r; p = r, r = r->next)
130 DO_UPLOAD_CONST_F(buf, r->bgn, r->end - r->bgn, const_f);
131 if (p) {
132 nine_range_pool_put_chain(&device->range_pool,
133 device->state.changed.ps_const_f, p);
134 device->state.changed.ps_const_f = NULL;
135 }
136
137 dirty_i = device->state.changed.ps_const_i;
138 device->state.changed.ps_const_i = 0;
139 const_i = &device->state.ps_const_i[0][0];
140
141 dirty_b = device->state.changed.ps_const_b;
142 device->state.changed.ps_const_b = 0;
143 const_b = device->state.ps_const_b;
144
145 lconstf_ranges = NULL;
146 lconstf_data = NULL;
147
148 device->state.ff.clobber.ps_const = TRUE;
149 device->state.changed.group &= ~NINE_STATE_PS_CONST;
150 }
151
152 /* write range from min to max changed, it's not much data */
153 /* bool1 */
154 if (dirty_b) {
155 c = util_last_bit(dirty_b);
156 i = ffs(dirty_b) - 1;
157 x = buf->width0 - (NINE_MAX_CONST_B - i) * 4;
158 c -= i;
159 memcpy(data_b, &(const_b[i]), c * sizeof(uint32_t));
160 box.x = x;
161 box.width = c * 4;
162 DBG("upload ConstantB [%u .. %u]\n", x, x + c - 1);
163 pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data_b, 0, 0);
164 }
165
166 /* int4 */
167 for (c = 0, i = 0; dirty_i; i++, dirty_i >>= 1) {
168 if (dirty_i & 1) {
169 if (!c)
170 x = i;
171 ++c;
172 } else
173 if (c) {
174 DBG("upload ConstantI [%u .. %u]\n", x, x + c - 1);
175 data = &const_i[x * 4];
176 box.x = buf->width0 - (NINE_MAX_CONST_I * 4 + NINE_MAX_CONST_B) * 4;
177 box.x += x * 4 * sizeof(int);
178 box.width = c * 4 * sizeof(int);
179 c = 0;
180 pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0);
181 }
182 }
183 if (c) {
184 DBG("upload ConstantI [%u .. %u]\n", x, x + c - 1);
185 data = &const_i[x * 4];
186 box.x = buf->width0 - (NINE_MAX_CONST_I * 4 + NINE_MAX_CONST_B) * 4;
187 box.x += x * 4 * sizeof(int);
188 box.width = c * 4 * sizeof(int);
189 pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0);
190 }
191
192 /* TODO: only upload these when shader itself changes */
193 if (lconstf_ranges) {
194 unsigned n = 0;
195 struct nine_range *r = lconstf_ranges;
196 while (r) {
197 box.x = r->bgn * 4 * sizeof(float);
198 n += r->end - r->bgn;
199 box.width = (r->end - r->bgn) * 4 * sizeof(float);
200 data = &lconstf_data[4 * n];
201 pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0);
202 r = r->next;
203 }
204 }
205 }
206
207 static void
208 prepare_vs_constants_userbuf(struct NineDevice9 *device)
209 {
210 struct nine_state *state = &device->state;
211 struct pipe_constant_buffer cb;
212 cb.buffer = NULL;
213 cb.buffer_offset = 0;
214 cb.buffer_size = device->state.vs->const_used_size;
215 cb.user_buffer = device->state.vs_const_f;
216
217 if (!cb.buffer_size)
218 return;
219
220 if (state->changed.vs_const_i) {
221 int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f];
222 memcpy(idst, state->vs_const_i, sizeof(state->vs_const_i));
223 state->changed.vs_const_i = 0;
224 }
225 if (state->changed.vs_const_b) {
226 int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f];
227 uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I];
228 memcpy(bdst, state->vs_const_b, sizeof(state->vs_const_b));
229 state->changed.vs_const_b = 0;
230 }
231
232 if (device->state.vs->lconstf.ranges) {
233 /* TODO: Can we make it so that we don't have to copy everything ? */
234 const struct nine_lconstf *lconstf = &device->state.vs->lconstf;
235 const struct nine_range *r = lconstf->ranges;
236 unsigned n = 0;
237 float *dst = device->state.vs_lconstf_temp;
238 float *src = (float *)cb.user_buffer;
239 memcpy(dst, src, cb.buffer_size);
240 while (r) {
241 unsigned p = r->bgn;
242 unsigned c = r->end - r->bgn;
243 memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float));
244 n += c;
245 r = r->next;
246 }
247 cb.user_buffer = dst;
248 }
249
250 if (!device->driver_caps.user_cbufs) {
251 u_upload_data(device->constbuf_uploader,
252 0,
253 cb.buffer_size,
254 cb.user_buffer,
255 &cb.buffer_offset,
256 &cb.buffer);
257 u_upload_unmap(device->constbuf_uploader);
258 cb.user_buffer = NULL;
259 }
260
261 state->pipe.cb_vs = cb;
262
263 if (device->state.changed.vs_const_f) {
264 struct nine_range *r = device->state.changed.vs_const_f;
265 struct nine_range *p = r;
266 while (p->next)
267 p = p->next;
268 nine_range_pool_put_chain(&device->range_pool, r, p);
269 device->state.changed.vs_const_f = NULL;
270 }
271 state->changed.group &= ~NINE_STATE_VS_CONST;
272 state->commit |= NINE_STATE_COMMIT_CONST_VS;
273 }
274
275 static void
276 prepare_ps_constants_userbuf(struct NineDevice9 *device)
277 {
278 struct nine_state *state = &device->state;
279 struct pipe_constant_buffer cb;
280 cb.buffer = NULL;
281 cb.buffer_offset = 0;
282 cb.buffer_size = device->state.ps->const_used_size;
283 cb.user_buffer = device->state.ps_const_f;
284
285 if (!cb.buffer_size)
286 return;
287
288 if (state->changed.ps_const_i) {
289 int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
290 memcpy(idst, state->ps_const_i, sizeof(state->ps_const_i));
291 state->changed.ps_const_i = 0;
292 }
293 if (state->changed.ps_const_b) {
294 int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
295 uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I];
296 memcpy(bdst, state->ps_const_b, sizeof(state->ps_const_b));
297 state->changed.ps_const_b = 0;
298 }
299
300 /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */
301 if (device->state.ps->bumpenvmat_needed) {
302 memcpy(device->state.ps_lconstf_temp, cb.user_buffer, cb.buffer_size);
303 memcpy(&device->state.ps_lconstf_temp[4 * 8], &device->state.bumpmap_vars, sizeof(device->state.bumpmap_vars));
304
305 cb.user_buffer = device->state.ps_lconstf_temp;
306 }
307
308 if (!device->driver_caps.user_cbufs) {
309 u_upload_data(device->constbuf_uploader,
310 0,
311 cb.buffer_size,
312 cb.user_buffer,
313 &cb.buffer_offset,
314 &cb.buffer);
315 u_upload_unmap(device->constbuf_uploader);
316 cb.user_buffer = NULL;
317 }
318
319 state->pipe.cb_ps = cb;
320
321 if (device->state.changed.ps_const_f) {
322 struct nine_range *r = device->state.changed.ps_const_f;
323 struct nine_range *p = r;
324 while (p->next)
325 p = p->next;
326 nine_range_pool_put_chain(&device->range_pool, r, p);
327 device->state.changed.ps_const_f = NULL;
328 }
329 state->changed.group &= ~NINE_STATE_PS_CONST;
330 state->commit |= NINE_STATE_COMMIT_CONST_PS;
331 }
332
333 /* State preparation incremental */
334
335 /* State preparation + State commit */
336
337 static uint32_t
338 update_framebuffer(struct NineDevice9 *device)
339 {
340 struct pipe_context *pipe = device->pipe;
341 struct nine_state *state = &device->state;
342 struct pipe_framebuffer_state *fb = &device->state.fb;
343 unsigned i;
344 struct NineSurface9 *rt0 = state->rt[0];
345 unsigned w = rt0->desc.Width;
346 unsigned h = rt0->desc.Height;
347 D3DMULTISAMPLE_TYPE nr_samples = rt0->desc.MultiSampleType;
348 unsigned mask = state->ps ? state->ps->rt_mask : 1;
349 const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
350
351 DBG("\n");
352
353 state->rt_mask = 0x0;
354 fb->nr_cbufs = 0;
355
356 /* all render targets must have the same size and the depth buffer must be
357 * bigger. Multisample has to match, according to spec. But some apps do
358 * things wrong there, and no error is returned. The behaviour they get
359 * apparently is that depth buffer is disabled if it doesn't match.
360 * Surely the same for render targets. */
361
362 /* Special case: D3DFMT_NULL is used to bound no real render target,
363 * but render to depth buffer. We have to not take into account the render
364 * target info. TODO: know what should happen when there are several render targers
365 * and the first one is D3DFMT_NULL */
366 if (rt0->desc.Format == D3DFMT_NULL && state->ds) {
367 w = state->ds->desc.Width;
368 h = state->ds->desc.Height;
369 nr_samples = state->ds->desc.MultiSampleType;
370 }
371
372 for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
373 struct NineSurface9 *rt = state->rt[i];
374
375 if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) &&
376 rt->desc.Width == w && rt->desc.Height == h &&
377 rt->desc.MultiSampleType == nr_samples) {
378 fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB);
379 state->rt_mask |= 1 << i;
380 fb->nr_cbufs = i + 1;
381
382 if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) {
383 assert(rt->texture == D3DRTYPE_TEXTURE ||
384 rt->texture == D3DRTYPE_CUBETEXTURE);
385 NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE;
386 }
387 } else {
388 /* Color outputs must match RT slot,
389 * drivers will have to handle NULL entries for GL, too.
390 */
391 fb->cbufs[i] = NULL;
392 }
393 }
394
395 if (state->ds && state->ds->desc.Width >= w &&
396 state->ds->desc.Height >= h &&
397 state->ds->desc.MultiSampleType == nr_samples) {
398 fb->zsbuf = NineSurface9_GetSurface(state->ds, 0);
399 } else {
400 fb->zsbuf = NULL;
401 }
402
403 fb->width = w;
404 fb->height = h;
405
406 pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */
407
408 if (fb->zsbuf) {
409 DWORD scale;
410 switch (fb->zsbuf->format) {
411 case PIPE_FORMAT_Z32_FLOAT:
412 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
413 scale = fui(1.0f);
414 break;
415 case PIPE_FORMAT_Z16_UNORM:
416 scale = fui((float)(1 << 16));
417 break;
418 default:
419 scale = fui((float)(1 << 24));
420 break;
421 }
422 if (state->rs[NINED3DRS_ZBIASSCALE] != scale) {
423 state->rs[NINED3DRS_ZBIASSCALE] = scale;
424 state->changed.group |= NINE_STATE_RASTERIZER;
425 }
426 }
427
428 return state->changed.group;
429 }
430
431 static void
432 update_viewport(struct NineDevice9 *device)
433 {
434 struct pipe_context *pipe = device->pipe;
435 const D3DVIEWPORT9 *vport = &device->state.viewport;
436 struct pipe_viewport_state pvport;
437
438 /* D3D coordinates are:
439 * -1 .. +1 for X,Y and
440 * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz)
441 */
442 pvport.scale[0] = (float)vport->Width * 0.5f;
443 pvport.scale[1] = (float)vport->Height * -0.5f;
444 pvport.scale[2] = vport->MaxZ - vport->MinZ;
445 pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X;
446 pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y;
447 pvport.translate[2] = vport->MinZ;
448
449 /* We found R600 and SI cards have some imprecision
450 * on the barycentric coordinates used for interpolation.
451 * Some shaders rely on having something precise.
452 * We found that the proprietary driver has the imprecision issue,
453 * except when the render target width and height are powers of two.
454 * It is using some sort of workaround for these cases
455 * which covers likely all the cases the applications rely
456 * on something precise.
457 * We haven't found the workaround, but it seems like it's better
458 * for applications if the imprecision is biased towards infinity
459 * instead of -infinity (which is what measured). So shift slightly
460 * the viewport: not enough to change rasterization result (in particular
461 * for multisampling), but enough to make the imprecision biased
462 * towards infinity. We do this shift only if render target width and
463 * height are powers of two.
464 * Solves 'red shadows' bug on UE3 games.
465 */
466 if (device->driver_bugs.buggy_barycentrics &&
467 ((vport->Width & (vport->Width-1)) == 0) &&
468 ((vport->Height & (vport->Height-1)) == 0)) {
469 pvport.translate[0] -= 1.0f / 128.0f;
470 pvport.translate[1] -= 1.0f / 128.0f;
471 }
472
473 pipe->set_viewport_states(pipe, 0, 1, &pvport);
474 }
475
476 /* Loop through VS inputs and pick the vertex elements with the declared
477 * usage from the vertex declaration, then insert the instance divisor from
478 * the stream source frequency setting.
479 */
480 static void
481 update_vertex_elements(struct NineDevice9 *device)
482 {
483 struct nine_state *state = &device->state;
484 const struct NineVertexDeclaration9 *vdecl = device->state.vdecl;
485 const struct NineVertexShader9 *vs;
486 unsigned n, b, i;
487 int index;
488 char vdecl_index_map[16]; /* vs->num_inputs <= 16 */
489 char used_streams[device->caps.MaxStreams];
490 int dummy_vbo_stream = -1;
491 BOOL need_dummy_vbo = FALSE;
492 struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
493
494 state->stream_usage_mask = 0;
495 memset(vdecl_index_map, -1, 16);
496 memset(used_streams, 0, device->caps.MaxStreams);
497 vs = device->state.vs ? device->state.vs : device->ff.vs;
498
499 if (vdecl) {
500 for (n = 0; n < vs->num_inputs; ++n) {
501 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
502 n, vs->input_map[n].ndecl, vdecl);
503
504 for (i = 0; i < vdecl->nelems; i++) {
505 if (vdecl->usage_map[i] == vs->input_map[n].ndecl) {
506 vdecl_index_map[n] = i;
507 used_streams[vdecl->elems[i].vertex_buffer_index] = 1;
508 break;
509 }
510 }
511 if (vdecl_index_map[n] < 0)
512 need_dummy_vbo = TRUE;
513 }
514 } else {
515 /* No vertex declaration. Likely will never happen in practice,
516 * but we need not crash on this */
517 need_dummy_vbo = TRUE;
518 }
519
520 if (need_dummy_vbo) {
521 for (i = 0; i < device->caps.MaxStreams; i++ ) {
522 if (!used_streams[i]) {
523 dummy_vbo_stream = i;
524 break;
525 }
526 }
527 }
528 /* there are less vertex shader inputs than stream slots,
529 * so if we need a slot for the dummy vbo, we should have found one */
530 assert (!need_dummy_vbo || dummy_vbo_stream != -1);
531
532 for (n = 0; n < vs->num_inputs; ++n) {
533 index = vdecl_index_map[n];
534 if (index >= 0) {
535 ve[n] = vdecl->elems[index];
536 b = ve[n].vertex_buffer_index;
537 state->stream_usage_mask |= 1 << b;
538 /* XXX wine just uses 1 here: */
539 if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA)
540 ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF;
541 } else {
542 /* if the vertex declaration is incomplete compared to what the
543 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
544 * This is not precised by the spec, but is the behaviour
545 * tested on win */
546 ve[n].vertex_buffer_index = dummy_vbo_stream;
547 ve[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
548 ve[n].src_offset = 0;
549 ve[n].instance_divisor = 0;
550 }
551 }
552
553 if (state->dummy_vbo_bound_at != dummy_vbo_stream) {
554 if (state->dummy_vbo_bound_at >= 0)
555 state->changed.vtxbuf |= 1 << state->dummy_vbo_bound_at;
556 if (dummy_vbo_stream >= 0) {
557 state->changed.vtxbuf |= 1 << dummy_vbo_stream;
558 state->vbo_bound_done = FALSE;
559 }
560 state->dummy_vbo_bound_at = dummy_vbo_stream;
561 }
562
563 cso_set_vertex_elements(device->cso, vs->num_inputs, ve);
564
565 state->changed.stream_freq = 0;
566 }
567
568 static inline uint32_t
569 update_shader_variant_keys(struct NineDevice9 *device)
570 {
571 struct nine_state *state = &device->state;
572 uint32_t mask = 0;
573 uint32_t vs_key = state->samplers_shadow;
574 uint32_t ps_key = state->samplers_shadow;
575
576 vs_key = (vs_key & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0);
577 ps_key = (ps_key & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0);
578
579 if (state->vs) vs_key &= state->vs->sampler_mask;
580 if (state->ps) {
581 if (unlikely(state->ps->byte_code.version < 0x20)) {
582 /* no depth textures, but variable targets */
583 uint32_t m = state->ps->sampler_mask;
584 ps_key = 0;
585 while (m) {
586 int s = ffs(m) - 1;
587 m &= ~(1 << s);
588 ps_key |= (state->texture[s] ? state->texture[s]->pstype : 1) << (s * 2);
589 }
590 } else {
591 ps_key &= state->ps->sampler_mask;
592 }
593 }
594
595 if (state->vs && state->vs_key != vs_key) {
596 state->vs_key = vs_key;
597 mask |= NINE_STATE_VS;
598 }
599 if (state->ps && state->ps_key != ps_key) {
600 state->ps_key = ps_key;
601 mask |= NINE_STATE_PS;
602 }
603 return mask;
604 }
605
606 static inline uint32_t
607 update_vs(struct NineDevice9 *device)
608 {
609 struct nine_state *state = &device->state;
610 struct NineVertexShader9 *vs = state->vs;
611 uint32_t changed_group = 0;
612
613 /* likely because we dislike FF */
614 if (likely(vs)) {
615 state->cso.vs = NineVertexShader9_GetVariant(vs, state->vs_key);
616 } else {
617 vs = device->ff.vs;
618 state->cso.vs = vs->variant.cso;
619 }
620 device->pipe->bind_vs_state(device->pipe, state->cso.vs);
621
622 if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
623 state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
624 changed_group |= NINE_STATE_RASTERIZER;
625 }
626
627 if ((state->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask)
628 /* Bound dummy sampler. */
629 changed_group |= NINE_STATE_SAMPLER;
630 return changed_group;
631 }
632
633 static inline uint32_t
634 update_ps(struct NineDevice9 *device)
635 {
636 struct nine_state *state = &device->state;
637 struct NinePixelShader9 *ps = state->ps;
638 uint32_t changed_group = 0;
639
640 if (likely(ps)) {
641 state->cso.ps = NinePixelShader9_GetVariant(ps, state->ps_key);
642 } else {
643 ps = device->ff.ps;
644 state->cso.ps = ps->variant.cso;
645 }
646 device->pipe->bind_fs_state(device->pipe, state->cso.ps);
647
648 if ((state->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask)
649 /* Bound dummy sampler. */
650 changed_group |= NINE_STATE_SAMPLER;
651 return changed_group;
652 }
653
654 static void
655 update_vertex_buffers(struct NineDevice9 *device)
656 {
657 struct pipe_context *pipe = device->pipe;
658 struct nine_state *state = &device->state;
659 struct pipe_vertex_buffer dummy_vtxbuf;
660 uint32_t mask = state->changed.vtxbuf;
661 unsigned i;
662 unsigned start;
663
664 DBG("mask=%x\n", mask);
665
666 if (state->dummy_vbo_bound_at >= 0) {
667 if (!state->vbo_bound_done) {
668 dummy_vtxbuf.buffer = device->dummy_vbo;
669 dummy_vtxbuf.stride = 0;
670 dummy_vtxbuf.user_buffer = NULL;
671 dummy_vtxbuf.buffer_offset = 0;
672 pipe->set_vertex_buffers(pipe, state->dummy_vbo_bound_at,
673 1, &dummy_vtxbuf);
674 state->vbo_bound_done = TRUE;
675 }
676 mask &= ~(1 << state->dummy_vbo_bound_at);
677 }
678
679 for (i = 0; mask; mask >>= 1, ++i) {
680 if (mask & 1) {
681 if (state->vtxbuf[i].buffer)
682 pipe->set_vertex_buffers(pipe, i, 1, &state->vtxbuf[i]);
683 else
684 pipe->set_vertex_buffers(pipe, i, 1, NULL);
685 }
686 }
687
688 state->changed.vtxbuf = 0;
689 }
690
691 static inline boolean
692 update_sampler_derived(struct nine_state *state, unsigned s)
693 {
694 boolean changed = FALSE;
695
696 if (state->samp[s][NINED3DSAMP_SHADOW] != state->texture[s]->shadow) {
697 changed = TRUE;
698 state->samp[s][NINED3DSAMP_SHADOW] = state->texture[s]->shadow;
699 }
700
701 if (state->samp[s][D3DSAMP_MIPFILTER] != D3DTEXF_NONE) {
702 int lod = state->samp[s][D3DSAMP_MAXMIPLEVEL] - state->texture[s]->managed.lod;
703 if (lod < 0)
704 lod = 0;
705 if (state->samp[s][NINED3DSAMP_MINLOD] != lod) {
706 changed = TRUE;
707 state->samp[s][NINED3DSAMP_MINLOD] = lod;
708 }
709 } else {
710 state->changed.sampler[s] &= ~0x300; /* lod changes irrelevant */
711 }
712
713 return changed;
714 }
715
716 /* TODO: add sRGB override to pipe_sampler_state ? */
717 static void
718 update_textures_and_samplers(struct NineDevice9 *device)
719 {
720 struct pipe_context *pipe = device->pipe;
721 struct nine_state *state = &device->state;
722 struct pipe_sampler_view *view[NINE_MAX_SAMPLERS];
723 struct pipe_sampler_state samp;
724 unsigned num_textures;
725 unsigned i;
726 boolean commit_views;
727 boolean commit_samplers;
728 uint16_t sampler_mask = state->ps ? state->ps->sampler_mask :
729 device->ff.ps->sampler_mask;
730
731 /* TODO: Can we reduce iterations here ? */
732
733 commit_views = FALSE;
734 commit_samplers = FALSE;
735 state->bound_samplers_mask_ps = 0;
736 for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) {
737 const unsigned s = NINE_SAMPLER_PS(i);
738 int sRGB;
739
740 if (!state->texture[s] && !(sampler_mask & (1 << i))) {
741 view[i] = NULL;
742 continue;
743 }
744
745 if (state->texture[s]) {
746 sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0;
747
748 view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB);
749 num_textures = i + 1;
750
751 if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) {
752 state->changed.sampler[s] = 0;
753 commit_samplers = TRUE;
754 nine_convert_sampler_state(device->cso, s, state->samp[s]);
755 }
756 } else {
757 /* Bind dummy sampler. We do not bind dummy sampler when
758 * it is not needed because it could add overhead. The
759 * dummy sampler should have r=g=b=0 and a=1. We do not
760 * unbind dummy sampler directly when they are not needed
761 * anymore, but they're going to be removed as long as texture
762 * or sampler states are changed. */
763 view[i] = device->dummy_sampler;
764 num_textures = i + 1;
765
766 memset(&samp, 0, sizeof(samp));
767 samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
768 samp.max_lod = 15.0f;
769 samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
770 samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
771 samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
772 samp.min_img_filter = PIPE_TEX_FILTER_NEAREST;
773 samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
774 samp.compare_mode = PIPE_TEX_COMPARE_NONE;
775 samp.compare_func = PIPE_FUNC_LEQUAL;
776 samp.normalized_coords = 1;
777 samp.seamless_cube_map = 1;
778
779 cso_single_sampler(device->cso, PIPE_SHADER_FRAGMENT,
780 s - NINE_SAMPLER_PS(0), &samp);
781
782 commit_views = TRUE;
783 commit_samplers = TRUE;
784 state->changed.sampler[s] = ~0;
785 }
786
787 state->bound_samplers_mask_ps |= (1 << s);
788 }
789
790 commit_views |= (state->changed.texture & NINE_PS_SAMPLERS_MASK) != 0;
791 commit_views |= state->changed.srgb;
792 if (commit_views)
793 pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
794 num_textures, view);
795
796 if (commit_samplers)
797 cso_single_sampler_done(device->cso, PIPE_SHADER_FRAGMENT);
798
799 commit_views = FALSE;
800 commit_samplers = FALSE;
801 sampler_mask = state->vs ? state->vs->sampler_mask : 0;
802 state->bound_samplers_mask_vs = 0;
803 for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_VS; ++i) {
804 const unsigned s = NINE_SAMPLER_VS(i);
805 int sRGB;
806
807 if (!state->texture[s] && !(sampler_mask & (1 << i))) {
808 view[i] = NULL;
809 continue;
810 }
811
812 if (state->texture[s]) {
813 sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0;
814
815 view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB);
816 num_textures = i + 1;
817
818 if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) {
819 state->changed.sampler[s] = 0;
820 commit_samplers = TRUE;
821 nine_convert_sampler_state(device->cso, s, state->samp[s]);
822 }
823 } else {
824 /* Bind dummy sampler. We do not bind dummy sampler when
825 * it is not needed because it could add overhead. The
826 * dummy sampler should have r=g=b=0 and a=1. We do not
827 * unbind dummy sampler directly when they are not needed
828 * anymore, but they're going to be removed as long as texture
829 * or sampler states are changed. */
830 view[i] = device->dummy_sampler;
831 num_textures = i + 1;
832
833 memset(&samp, 0, sizeof(samp));
834 samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
835 samp.max_lod = 15.0f;
836 samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
837 samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
838 samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
839 samp.min_img_filter = PIPE_TEX_FILTER_NEAREST;
840 samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
841 samp.compare_mode = PIPE_TEX_COMPARE_NONE;
842 samp.compare_func = PIPE_FUNC_LEQUAL;
843 samp.normalized_coords = 1;
844 samp.seamless_cube_map = 1;
845
846 cso_single_sampler(device->cso, PIPE_SHADER_VERTEX,
847 s - NINE_SAMPLER_VS(0), &samp);
848
849 commit_views = TRUE;
850 commit_samplers = TRUE;
851 state->changed.sampler[s] = ~0;
852 }
853
854 state->bound_samplers_mask_vs |= (1 << s);
855 }
856 commit_views |= (state->changed.texture & NINE_VS_SAMPLERS_MASK) != 0;
857 commit_views |= state->changed.srgb;
858 if (commit_views)
859 pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0,
860 num_textures, view);
861
862 if (commit_samplers)
863 cso_single_sampler_done(device->cso, PIPE_SHADER_VERTEX);
864
865 state->changed.srgb = FALSE;
866 state->changed.texture = 0;
867 }
868
869 /* State commit only */
870
871 static inline void
872 commit_blend(struct NineDevice9 *device)
873 {
874 cso_set_blend(device->cso, &device->state.pipe.blend);
875 }
876
877 static inline void
878 commit_dsa(struct NineDevice9 *device)
879 {
880 cso_set_depth_stencil_alpha(device->cso, &device->state.pipe.dsa);
881 }
882
883 static inline void
884 commit_scissor(struct NineDevice9 *device)
885 {
886 struct pipe_context *pipe = device->pipe;
887
888 pipe->set_scissor_states(pipe, 0, 1, &device->state.scissor);
889 }
890
891 static inline void
892 commit_rasterizer(struct NineDevice9 *device)
893 {
894 cso_set_rasterizer(device->cso, &device->state.pipe.rast);
895 }
896
897 static inline void
898 commit_index_buffer(struct NineDevice9 *device)
899 {
900 struct pipe_context *pipe = device->pipe;
901 if (device->state.idxbuf)
902 pipe->set_index_buffer(pipe, &device->state.idxbuf->buffer);
903 else
904 pipe->set_index_buffer(pipe, NULL);
905 }
906
907 static inline void
908 commit_vs_constants(struct NineDevice9 *device)
909 {
910 struct pipe_context *pipe = device->pipe;
911
912 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->state.pipe.cb_vs);
913 }
914
915 static inline void
916 commit_ps_constants(struct NineDevice9 *device)
917 {
918 struct pipe_context *pipe = device->pipe;
919
920 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &device->state.pipe.cb_ps);
921 }
922
923 /* State Update */
924
925 #define NINE_STATE_FREQ_GROUP_0 \
926 (NINE_STATE_FB | \
927 NINE_STATE_VIEWPORT | \
928 NINE_STATE_SCISSOR | \
929 NINE_STATE_BLEND | \
930 NINE_STATE_DSA | \
931 NINE_STATE_RASTERIZER | \
932 NINE_STATE_VS | \
933 NINE_STATE_PS | \
934 NINE_STATE_BLEND_COLOR | \
935 NINE_STATE_STENCIL_REF | \
936 NINE_STATE_SAMPLE_MASK)
937
938 #define NINE_STATE_FREQ_GROUP_1 ~NINE_STATE_FREQ_GROUP_0
939
940 #define NINE_STATE_SHADER_VARIANT_GROUP \
941 (NINE_STATE_TEXTURE | \
942 NINE_STATE_VS | \
943 NINE_STATE_PS)
944
945 /* TODO: only go through dirty textures */
946 static void
947 validate_textures(struct NineDevice9 *device)
948 {
949 struct NineBaseTexture9 *tex, *ptr;
950 LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) {
951 list_delinit(&tex->list);
952 NineBaseTexture9_Validate(tex);
953 }
954 }
955
956 void
957 nine_update_state_framebuffer(struct NineDevice9 *device)
958 {
959 struct nine_state *state = &device->state;
960
961 validate_textures(device);
962
963 if (state->changed.group & NINE_STATE_FB)
964 update_framebuffer(device);
965
966 state->changed.group &= ~NINE_STATE_FB;
967 }
968
969 boolean
970 nine_update_state(struct NineDevice9 *device)
971 {
972 struct pipe_context *pipe = device->pipe;
973 struct nine_state *state = &device->state;
974 uint32_t group;
975
976 DBG("changed state groups: %x | %x\n",
977 state->changed.group & NINE_STATE_FREQ_GROUP_0,
978 state->changed.group & NINE_STATE_FREQ_GROUP_1);
979
980 /* NOTE: We may want to use the cso cache for everything, or let
981 * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't
982 * have to care about state being clobbered here and could merge this back
983 * into update_textures. Except, we also need to re-validate textures that
984 * may be dirty anyway, even if no texture bindings changed.
985 */
986 validate_textures(device); /* may clobber state */
987
988 /* ff_update may change VS/PS dirty bits */
989 if (unlikely(!state->vs || !state->ps))
990 nine_ff_update(device);
991 group = state->changed.group;
992
993 if (group & NINE_STATE_SHADER_VARIANT_GROUP)
994 group |= update_shader_variant_keys(device);
995
996 if (group & NINE_STATE_FREQ_GROUP_0) {
997 if (group & NINE_STATE_FB)
998 group = update_framebuffer(device);
999 if (group & NINE_STATE_VIEWPORT)
1000 update_viewport(device);
1001 if (group & NINE_STATE_SCISSOR)
1002 commit_scissor(device);
1003
1004 if (group & NINE_STATE_DSA)
1005 prepare_dsa(device);
1006 if (group & NINE_STATE_BLEND)
1007 prepare_blend(device);
1008
1009 if (group & NINE_STATE_VS)
1010 group |= update_vs(device);
1011
1012 if (group & NINE_STATE_RASTERIZER)
1013 prepare_rasterizer(device);
1014
1015 if (group & NINE_STATE_PS)
1016 group |= update_ps(device);
1017
1018 if (group & NINE_STATE_BLEND_COLOR) {
1019 struct pipe_blend_color color;
1020 d3dcolor_to_rgba(&color.color[0], state->rs[D3DRS_BLENDFACTOR]);
1021 pipe->set_blend_color(pipe, &color);
1022 }
1023 if (group & NINE_STATE_SAMPLE_MASK) {
1024 pipe->set_sample_mask(pipe, state->rs[D3DRS_MULTISAMPLEMASK]);
1025 }
1026 if (group & NINE_STATE_STENCIL_REF) {
1027 struct pipe_stencil_ref ref;
1028 ref.ref_value[0] = state->rs[D3DRS_STENCILREF];
1029 ref.ref_value[1] = ref.ref_value[0];
1030 pipe->set_stencil_ref(pipe, &ref);
1031 }
1032 }
1033
1034 if (state->changed.ucp) {
1035 pipe->set_clip_state(pipe, &state->clip);
1036 state->changed.ucp = 0;
1037 }
1038
1039 if (group & (NINE_STATE_FREQ_GROUP_1 | NINE_STATE_VS)) {
1040 if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER))
1041 update_textures_and_samplers(device);
1042
1043 if (group & NINE_STATE_IDXBUF)
1044 commit_index_buffer(device);
1045
1046 if ((group & (NINE_STATE_VDECL | NINE_STATE_VS)) ||
1047 state->changed.stream_freq & ~1)
1048 update_vertex_elements(device);
1049
1050 if (device->prefer_user_constbuf) {
1051 if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS)) && state->vs)
1052 prepare_vs_constants_userbuf(device);
1053 if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && state->ps)
1054 prepare_ps_constants_userbuf(device);
1055 } else {
1056 if ((group & NINE_STATE_VS_CONST) && state->vs)
1057 upload_constants(device, PIPE_SHADER_VERTEX);
1058 if ((group & NINE_STATE_PS_CONST) && state->ps)
1059 upload_constants(device, PIPE_SHADER_FRAGMENT);
1060 }
1061 }
1062 if (state->changed.vtxbuf)
1063 update_vertex_buffers(device);
1064
1065 if (state->commit & NINE_STATE_COMMIT_BLEND)
1066 commit_blend(device);
1067 if (state->commit & NINE_STATE_COMMIT_DSA)
1068 commit_dsa(device);
1069 if (state->commit & NINE_STATE_COMMIT_RASTERIZER)
1070 commit_rasterizer(device);
1071 if (state->commit & NINE_STATE_COMMIT_CONST_VS)
1072 commit_vs_constants(device);
1073 if (state->commit & NINE_STATE_COMMIT_CONST_PS)
1074 commit_ps_constants(device);
1075
1076 state->commit = 0;
1077
1078 device->state.changed.group &=
1079 (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST);
1080
1081 DBG("finished\n");
1082
1083 return TRUE;
1084 }
1085
1086 /* State defaults */
1087
1088 static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] =
1089 {
1090 /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */
1091 [D3DRS_ZENABLE] = D3DZB_FALSE,
1092 [D3DRS_FILLMODE] = D3DFILL_SOLID,
1093 [D3DRS_SHADEMODE] = D3DSHADE_GOURAUD,
1094 /* [D3DRS_LINEPATTERN] = 0x00000000, */
1095 [D3DRS_ZWRITEENABLE] = TRUE,
1096 [D3DRS_ALPHATESTENABLE] = FALSE,
1097 [D3DRS_LASTPIXEL] = TRUE,
1098 [D3DRS_SRCBLEND] = D3DBLEND_ONE,
1099 [D3DRS_DESTBLEND] = D3DBLEND_ZERO,
1100 [D3DRS_CULLMODE] = D3DCULL_CCW,
1101 [D3DRS_ZFUNC] = D3DCMP_LESSEQUAL,
1102 [D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS,
1103 [D3DRS_ALPHAREF] = 0,
1104 [D3DRS_DITHERENABLE] = FALSE,
1105 [D3DRS_ALPHABLENDENABLE] = FALSE,
1106 [D3DRS_FOGENABLE] = FALSE,
1107 [D3DRS_SPECULARENABLE] = FALSE,
1108 /* [D3DRS_ZVISIBLE] = 0, */
1109 [D3DRS_FOGCOLOR] = 0,
1110 [D3DRS_FOGTABLEMODE] = D3DFOG_NONE,
1111 [D3DRS_FOGSTART] = 0x00000000,
1112 [D3DRS_FOGEND] = 0x3F800000,
1113 [D3DRS_FOGDENSITY] = 0x3F800000,
1114 /* [D3DRS_EDGEANTIALIAS] = FALSE, */
1115 [D3DRS_RANGEFOGENABLE] = FALSE,
1116 [D3DRS_STENCILENABLE] = FALSE,
1117 [D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP,
1118 [D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP,
1119 [D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP,
1120 [D3DRS_STENCILREF] = 0,
1121 [D3DRS_STENCILMASK] = 0xFFFFFFFF,
1122 [D3DRS_STENCILFUNC] = D3DCMP_ALWAYS,
1123 [D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF,
1124 [D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF,
1125 [D3DRS_WRAP0] = 0,
1126 [D3DRS_WRAP1] = 0,
1127 [D3DRS_WRAP2] = 0,
1128 [D3DRS_WRAP3] = 0,
1129 [D3DRS_WRAP4] = 0,
1130 [D3DRS_WRAP5] = 0,
1131 [D3DRS_WRAP6] = 0,
1132 [D3DRS_WRAP7] = 0,
1133 [D3DRS_CLIPPING] = TRUE,
1134 [D3DRS_LIGHTING] = TRUE,
1135 [D3DRS_AMBIENT] = 0,
1136 [D3DRS_FOGVERTEXMODE] = D3DFOG_NONE,
1137 [D3DRS_COLORVERTEX] = TRUE,
1138 [D3DRS_LOCALVIEWER] = TRUE,
1139 [D3DRS_NORMALIZENORMALS] = FALSE,
1140 [D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1,
1141 [D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2,
1142 [D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL,
1143 [D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL,
1144 [D3DRS_VERTEXBLEND] = D3DVBF_DISABLE,
1145 [D3DRS_CLIPPLANEENABLE] = 0,
1146 /* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */
1147 [D3DRS_POINTSIZE] = 0x3F800000,
1148 [D3DRS_POINTSIZE_MIN] = 0x3F800000,
1149 [D3DRS_POINTSPRITEENABLE] = FALSE,
1150 [D3DRS_POINTSCALEENABLE] = FALSE,
1151 [D3DRS_POINTSCALE_A] = 0x3F800000,
1152 [D3DRS_POINTSCALE_B] = 0x00000000,
1153 [D3DRS_POINTSCALE_C] = 0x00000000,
1154 [D3DRS_MULTISAMPLEANTIALIAS] = TRUE,
1155 [D3DRS_MULTISAMPLEMASK] = 0xFFFFFFFF,
1156 [D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE,
1157 /* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */
1158 [D3DRS_DEBUGMONITORTOKEN] = 0xDEADCAFE,
1159 [D3DRS_POINTSIZE_MAX] = 0x3F800000, /* depends on cap */
1160 [D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE,
1161 [D3DRS_COLORWRITEENABLE] = 0x0000000f,
1162 [D3DRS_TWEENFACTOR] = 0x00000000,
1163 [D3DRS_BLENDOP] = D3DBLENDOP_ADD,
1164 [D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC,
1165 [D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR,
1166 [D3DRS_SCISSORTESTENABLE] = FALSE,
1167 [D3DRS_SLOPESCALEDEPTHBIAS] = 0,
1168 [D3DRS_MINTESSELLATIONLEVEL] = 0x3F800000,
1169 [D3DRS_MAXTESSELLATIONLEVEL] = 0x3F800000,
1170 [D3DRS_ANTIALIASEDLINEENABLE] = FALSE,
1171 [D3DRS_ADAPTIVETESS_X] = 0x00000000,
1172 [D3DRS_ADAPTIVETESS_Y] = 0x00000000,
1173 [D3DRS_ADAPTIVETESS_Z] = 0x3F800000,
1174 [D3DRS_ADAPTIVETESS_W] = 0x00000000,
1175 [D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE,
1176 [D3DRS_TWOSIDEDSTENCILMODE] = FALSE,
1177 [D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP,
1178 [D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP,
1179 [D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP,
1180 [D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS,
1181 [D3DRS_COLORWRITEENABLE1] = 0x0000000F,
1182 [D3DRS_COLORWRITEENABLE2] = 0x0000000F,
1183 [D3DRS_COLORWRITEENABLE3] = 0x0000000F,
1184 [D3DRS_BLENDFACTOR] = 0xFFFFFFFF,
1185 [D3DRS_SRGBWRITEENABLE] = 0,
1186 [D3DRS_DEPTHBIAS] = 0,
1187 [D3DRS_WRAP8] = 0,
1188 [D3DRS_WRAP9] = 0,
1189 [D3DRS_WRAP10] = 0,
1190 [D3DRS_WRAP11] = 0,
1191 [D3DRS_WRAP12] = 0,
1192 [D3DRS_WRAP13] = 0,
1193 [D3DRS_WRAP14] = 0,
1194 [D3DRS_WRAP15] = 0,
1195 [D3DRS_SEPARATEALPHABLENDENABLE] = FALSE,
1196 [D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE,
1197 [D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO,
1198 [D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD,
1199 [NINED3DRS_VSPOINTSIZE] = FALSE,
1200 [NINED3DRS_RTMASK] = 0xf,
1201 [NINED3DRS_ALPHACOVERAGE] = FALSE
1202 };
1203 static const DWORD nine_tex_stage_state_defaults[NINED3DTSS_LAST + 1] =
1204 {
1205 [D3DTSS_COLOROP] = D3DTOP_DISABLE,
1206 [D3DTSS_ALPHAOP] = D3DTOP_DISABLE,
1207 [D3DTSS_COLORARG1] = D3DTA_TEXTURE,
1208 [D3DTSS_COLORARG2] = D3DTA_CURRENT,
1209 [D3DTSS_COLORARG0] = D3DTA_CURRENT,
1210 [D3DTSS_ALPHAARG1] = D3DTA_TEXTURE,
1211 [D3DTSS_ALPHAARG2] = D3DTA_CURRENT,
1212 [D3DTSS_ALPHAARG0] = D3DTA_CURRENT,
1213 [D3DTSS_RESULTARG] = D3DTA_CURRENT,
1214 [D3DTSS_BUMPENVMAT00] = 0,
1215 [D3DTSS_BUMPENVMAT01] = 0,
1216 [D3DTSS_BUMPENVMAT10] = 0,
1217 [D3DTSS_BUMPENVMAT11] = 0,
1218 [D3DTSS_BUMPENVLSCALE] = 0,
1219 [D3DTSS_BUMPENVLOFFSET] = 0,
1220 [D3DTSS_TEXCOORDINDEX] = 0,
1221 [D3DTSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE,
1222 };
1223 static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] =
1224 {
1225 [D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP,
1226 [D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP,
1227 [D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP,
1228 [D3DSAMP_BORDERCOLOR] = 0,
1229 [D3DSAMP_MAGFILTER] = D3DTEXF_POINT,
1230 [D3DSAMP_MINFILTER] = D3DTEXF_POINT,
1231 [D3DSAMP_MIPFILTER] = D3DTEXF_NONE,
1232 [D3DSAMP_MIPMAPLODBIAS] = 0,
1233 [D3DSAMP_MAXMIPLEVEL] = 0,
1234 [D3DSAMP_MAXANISOTROPY] = 1,
1235 [D3DSAMP_SRGBTEXTURE] = 0,
1236 [D3DSAMP_ELEMENTINDEX] = 0,
1237 [D3DSAMP_DMAPOFFSET] = 0,
1238 [NINED3DSAMP_MINLOD] = 0,
1239 [NINED3DSAMP_SHADOW] = 0
1240 };
1241
1242 void nine_state_restore_non_cso(struct NineDevice9 *device)
1243 {
1244 struct nine_state *state = &device->state;
1245
1246 state->changed.group = NINE_STATE_ALL;
1247 state->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1;
1248 state->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
1249 state->changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
1250 state->commit |= NINE_STATE_COMMIT_CONST_VS | NINE_STATE_COMMIT_CONST_PS;
1251 }
1252
1253 void
1254 nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
1255 boolean is_reset)
1256 {
1257 struct nine_state *state = &device->state;
1258 unsigned s;
1259
1260 /* Initialize defaults.
1261 */
1262 memcpy(state->rs, nine_render_state_defaults, sizeof(state->rs));
1263
1264 for (s = 0; s < Elements(state->ff.tex_stage); ++s) {
1265 memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults,
1266 sizeof(state->ff.tex_stage[s]));
1267 state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] = s;
1268 }
1269 state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE;
1270 state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
1271 memset(&state->bumpmap_vars, 0, sizeof(state->bumpmap_vars));
1272
1273 for (s = 0; s < Elements(state->samp); ++s) {
1274 memcpy(&state->samp[s], nine_samp_state_defaults,
1275 sizeof(state->samp[s]));
1276 }
1277
1278 if (state->vs_const_f)
1279 memset(state->vs_const_f, 0, device->vs_const_size);
1280 if (state->ps_const_f)
1281 memset(state->ps_const_f, 0, device->ps_const_size);
1282
1283 /* Cap dependent initial state:
1284 */
1285 state->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize);
1286
1287 /* Set changed flags to initialize driver.
1288 */
1289 state->changed.group = NINE_STATE_ALL;
1290 state->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1;
1291 state->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
1292 state->changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
1293
1294 state->ff.changed.transform[0] = ~0;
1295 state->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32);
1296
1297 if (!is_reset) {
1298 state->viewport.MinZ = 0.0f;
1299 state->viewport.MaxZ = 1.0f;
1300 }
1301
1302 for (s = 0; s < Elements(state->changed.sampler); ++s)
1303 state->changed.sampler[s] = ~0;
1304
1305 if (!is_reset) {
1306 state->dummy_vbo_bound_at = -1;
1307 state->vbo_bound_done = FALSE;
1308 }
1309
1310 if (!device->prefer_user_constbuf) {
1311 /* fill cb_vs and cb_ps for the non user constbuf path */
1312 struct pipe_constant_buffer cb;
1313
1314 cb.buffer_offset = 0;
1315 cb.buffer_size = device->vs_const_size;
1316 cb.buffer = device->constbuf_vs;
1317 cb.user_buffer = NULL;
1318 state->pipe.cb_vs = cb;
1319
1320 cb.buffer_size = device->ps_const_size;
1321 cb.buffer = device->constbuf_ps;
1322 state->pipe.cb_ps = cb;
1323
1324 state->commit |= NINE_STATE_COMMIT_CONST_VS | NINE_STATE_COMMIT_CONST_PS;
1325 }
1326 }
1327
1328 void
1329 nine_state_clear(struct nine_state *state, const boolean device)
1330 {
1331 unsigned i;
1332
1333 for (i = 0; i < Elements(state->rt); ++i)
1334 nine_bind(&state->rt[i], NULL);
1335 nine_bind(&state->ds, NULL);
1336 nine_bind(&state->vs, NULL);
1337 nine_bind(&state->ps, NULL);
1338 nine_bind(&state->vdecl, NULL);
1339 for (i = 0; i < PIPE_MAX_ATTRIBS; ++i)
1340 nine_bind(&state->stream[i], NULL);
1341 nine_bind(&state->idxbuf, NULL);
1342 for (i = 0; i < NINE_MAX_SAMPLERS; ++i) {
1343 if (device &&
1344 state->texture[i] &&
1345 --state->texture[i]->bind_count == 0)
1346 list_delinit(&state->texture[i]->list);
1347 nine_bind(&state->texture[i], NULL);
1348 }
1349 }
1350
1351 /*
1352 static const DWORD nine_render_states_pixel[] =
1353 {
1354 D3DRS_ALPHABLENDENABLE,
1355 D3DRS_ALPHAFUNC,
1356 D3DRS_ALPHAREF,
1357 D3DRS_ALPHATESTENABLE,
1358 D3DRS_ANTIALIASEDLINEENABLE,
1359 D3DRS_BLENDFACTOR,
1360 D3DRS_BLENDOP,
1361 D3DRS_BLENDOPALPHA,
1362 D3DRS_CCW_STENCILFAIL,
1363 D3DRS_CCW_STENCILPASS,
1364 D3DRS_CCW_STENCILZFAIL,
1365 D3DRS_COLORWRITEENABLE,
1366 D3DRS_COLORWRITEENABLE1,
1367 D3DRS_COLORWRITEENABLE2,
1368 D3DRS_COLORWRITEENABLE3,
1369 D3DRS_DEPTHBIAS,
1370 D3DRS_DESTBLEND,
1371 D3DRS_DESTBLENDALPHA,
1372 D3DRS_DITHERENABLE,
1373 D3DRS_FILLMODE,
1374 D3DRS_FOGDENSITY,
1375 D3DRS_FOGEND,
1376 D3DRS_FOGSTART,
1377 D3DRS_LASTPIXEL,
1378 D3DRS_SCISSORTESTENABLE,
1379 D3DRS_SEPARATEALPHABLENDENABLE,
1380 D3DRS_SHADEMODE,
1381 D3DRS_SLOPESCALEDEPTHBIAS,
1382 D3DRS_SRCBLEND,
1383 D3DRS_SRCBLENDALPHA,
1384 D3DRS_SRGBWRITEENABLE,
1385 D3DRS_STENCILENABLE,
1386 D3DRS_STENCILFAIL,
1387 D3DRS_STENCILFUNC,
1388 D3DRS_STENCILMASK,
1389 D3DRS_STENCILPASS,
1390 D3DRS_STENCILREF,
1391 D3DRS_STENCILWRITEMASK,
1392 D3DRS_STENCILZFAIL,
1393 D3DRS_TEXTUREFACTOR,
1394 D3DRS_TWOSIDEDSTENCILMODE,
1395 D3DRS_WRAP0,
1396 D3DRS_WRAP1,
1397 D3DRS_WRAP10,
1398 D3DRS_WRAP11,
1399 D3DRS_WRAP12,
1400 D3DRS_WRAP13,
1401 D3DRS_WRAP14,
1402 D3DRS_WRAP15,
1403 D3DRS_WRAP2,
1404 D3DRS_WRAP3,
1405 D3DRS_WRAP4,
1406 D3DRS_WRAP5,
1407 D3DRS_WRAP6,
1408 D3DRS_WRAP7,
1409 D3DRS_WRAP8,
1410 D3DRS_WRAP9,
1411 D3DRS_ZENABLE,
1412 D3DRS_ZFUNC,
1413 D3DRS_ZWRITEENABLE
1414 };
1415 */
1416 const uint32_t nine_render_states_pixel[(NINED3DRS_LAST + 31) / 32] =
1417 {
1418 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000,
1419 0x000000ff, 0xde01c900, 0x0003ffcf
1420 };
1421
1422 /*
1423 static const DWORD nine_render_states_vertex[] =
1424 {
1425 D3DRS_ADAPTIVETESS_W,
1426 D3DRS_ADAPTIVETESS_X,
1427 D3DRS_ADAPTIVETESS_Y,
1428 D3DRS_ADAPTIVETESS_Z,
1429 D3DRS_AMBIENT,
1430 D3DRS_AMBIENTMATERIALSOURCE,
1431 D3DRS_CLIPPING,
1432 D3DRS_CLIPPLANEENABLE,
1433 D3DRS_COLORVERTEX,
1434 D3DRS_CULLMODE,
1435 D3DRS_DIFFUSEMATERIALSOURCE,
1436 D3DRS_EMISSIVEMATERIALSOURCE,
1437 D3DRS_ENABLEADAPTIVETESSELLATION,
1438 D3DRS_FOGCOLOR,
1439 D3DRS_FOGDENSITY,
1440 D3DRS_FOGENABLE,
1441 D3DRS_FOGEND,
1442 D3DRS_FOGSTART,
1443 D3DRS_FOGTABLEMODE,
1444 D3DRS_FOGVERTEXMODE,
1445 D3DRS_INDEXEDVERTEXBLENDENABLE,
1446 D3DRS_LIGHTING,
1447 D3DRS_LOCALVIEWER,
1448 D3DRS_MAXTESSELLATIONLEVEL,
1449 D3DRS_MINTESSELLATIONLEVEL,
1450 D3DRS_MULTISAMPLEANTIALIAS,
1451 D3DRS_MULTISAMPLEMASK,
1452 D3DRS_NORMALDEGREE,
1453 D3DRS_NORMALIZENORMALS,
1454 D3DRS_PATCHEDGESTYLE,
1455 D3DRS_POINTSCALE_A,
1456 D3DRS_POINTSCALE_B,
1457 D3DRS_POINTSCALE_C,
1458 D3DRS_POINTSCALEENABLE,
1459 D3DRS_POINTSIZE,
1460 D3DRS_POINTSIZE_MAX,
1461 D3DRS_POINTSIZE_MIN,
1462 D3DRS_POINTSPRITEENABLE,
1463 D3DRS_POSITIONDEGREE,
1464 D3DRS_RANGEFOGENABLE,
1465 D3DRS_SHADEMODE,
1466 D3DRS_SPECULARENABLE,
1467 D3DRS_SPECULARMATERIALSOURCE,
1468 D3DRS_TWEENFACTOR,
1469 D3DRS_VERTEXBLEND
1470 };
1471 */
1472 const uint32_t nine_render_states_vertex[(NINED3DRS_LAST + 31) / 32] =
1473 {
1474 0x30400200, 0x0001007c, 0x00000000, 0x00000000,
1475 0xfd9efb00, 0x01fc34cf, 0x00000000
1476 };
1477
1478 /* TODO: put in the right values */
1479 const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
1480 {
1481 [D3DRS_ZENABLE] = NINE_STATE_DSA,
1482 [D3DRS_FILLMODE] = NINE_STATE_RASTERIZER,
1483 [D3DRS_SHADEMODE] = NINE_STATE_RASTERIZER,
1484 [D3DRS_ZWRITEENABLE] = NINE_STATE_DSA,
1485 [D3DRS_ALPHATESTENABLE] = NINE_STATE_DSA,
1486 [D3DRS_LASTPIXEL] = NINE_STATE_RASTERIZER,
1487 [D3DRS_SRCBLEND] = NINE_STATE_BLEND,
1488 [D3DRS_DESTBLEND] = NINE_STATE_BLEND,
1489 [D3DRS_CULLMODE] = NINE_STATE_RASTERIZER,
1490 [D3DRS_ZFUNC] = NINE_STATE_DSA,
1491 [D3DRS_ALPHAREF] = NINE_STATE_DSA,
1492 [D3DRS_ALPHAFUNC] = NINE_STATE_DSA,
1493 [D3DRS_DITHERENABLE] = NINE_STATE_BLEND,
1494 [D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND,
1495 [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER,
1496 [D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING,
1497 [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER,
1498 [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER,
1499 [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER,
1500 [D3DRS_FOGEND] = NINE_STATE_FF_OTHER,
1501 [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER,
1502 [D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_OTHER,
1503 [D3DRS_STENCILENABLE] = NINE_STATE_DSA,
1504 [D3DRS_STENCILFAIL] = NINE_STATE_DSA,
1505 [D3DRS_STENCILZFAIL] = NINE_STATE_DSA,
1506 [D3DRS_STENCILPASS] = NINE_STATE_DSA,
1507 [D3DRS_STENCILFUNC] = NINE_STATE_DSA,
1508 [D3DRS_STENCILREF] = NINE_STATE_STENCIL_REF,
1509 [D3DRS_STENCILMASK] = NINE_STATE_DSA,
1510 [D3DRS_STENCILWRITEMASK] = NINE_STATE_DSA,
1511 [D3DRS_TEXTUREFACTOR] = NINE_STATE_FF_PSSTAGES,
1512 [D3DRS_WRAP0] = NINE_STATE_UNHANDLED, /* cylindrical wrap is crazy */
1513 [D3DRS_WRAP1] = NINE_STATE_UNHANDLED,
1514 [D3DRS_WRAP2] = NINE_STATE_UNHANDLED,
1515 [D3DRS_WRAP3] = NINE_STATE_UNHANDLED,
1516 [D3DRS_WRAP4] = NINE_STATE_UNHANDLED,
1517 [D3DRS_WRAP5] = NINE_STATE_UNHANDLED,
1518 [D3DRS_WRAP6] = NINE_STATE_UNHANDLED,
1519 [D3DRS_WRAP7] = NINE_STATE_UNHANDLED,
1520 [D3DRS_CLIPPING] = 0, /* software vertex processing only */
1521 [D3DRS_LIGHTING] = NINE_STATE_FF_LIGHTING,
1522 [D3DRS_AMBIENT] = NINE_STATE_FF_LIGHTING | NINE_STATE_FF_MATERIAL,
1523 [D3DRS_FOGVERTEXMODE] = NINE_STATE_FF_OTHER,
1524 [D3DRS_COLORVERTEX] = NINE_STATE_FF_LIGHTING,
1525 [D3DRS_LOCALVIEWER] = NINE_STATE_FF_LIGHTING,
1526 [D3DRS_NORMALIZENORMALS] = NINE_STATE_FF_OTHER,
1527 [D3DRS_DIFFUSEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
1528 [D3DRS_SPECULARMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
1529 [D3DRS_AMBIENTMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
1530 [D3DRS_EMISSIVEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
1531 [D3DRS_VERTEXBLEND] = NINE_STATE_FF_OTHER,
1532 [D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER,
1533 [D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER,
1534 [D3DRS_POINTSIZE_MIN] = NINE_STATE_RASTERIZER,
1535 [D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER,
1536 [D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_OTHER,
1537 [D3DRS_POINTSCALE_A] = NINE_STATE_FF_OTHER,
1538 [D3DRS_POINTSCALE_B] = NINE_STATE_FF_OTHER,
1539 [D3DRS_POINTSCALE_C] = NINE_STATE_FF_OTHER,
1540 [D3DRS_MULTISAMPLEANTIALIAS] = NINE_STATE_RASTERIZER,
1541 [D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK,
1542 [D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED,
1543 [D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED,
1544 [D3DRS_POINTSIZE_MAX] = NINE_STATE_RASTERIZER,
1545 [D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_OTHER,
1546 [D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND,
1547 [D3DRS_TWEENFACTOR] = NINE_STATE_FF_OTHER,
1548 [D3DRS_BLENDOP] = NINE_STATE_BLEND,
1549 [D3DRS_POSITIONDEGREE] = NINE_STATE_UNHANDLED,
1550 [D3DRS_NORMALDEGREE] = NINE_STATE_UNHANDLED,
1551 [D3DRS_SCISSORTESTENABLE] = NINE_STATE_RASTERIZER,
1552 [D3DRS_SLOPESCALEDEPTHBIAS] = NINE_STATE_RASTERIZER,
1553 [D3DRS_ANTIALIASEDLINEENABLE] = NINE_STATE_RASTERIZER,
1554 [D3DRS_MINTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED,
1555 [D3DRS_MAXTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED,
1556 [D3DRS_ADAPTIVETESS_X] = NINE_STATE_UNHANDLED,
1557 [D3DRS_ADAPTIVETESS_Y] = NINE_STATE_UNHANDLED,
1558 [D3DRS_ADAPTIVETESS_Z] = NINE_STATE_UNHANDLED,
1559 [D3DRS_ADAPTIVETESS_W] = NINE_STATE_UNHANDLED,
1560 [D3DRS_ENABLEADAPTIVETESSELLATION] = NINE_STATE_UNHANDLED,
1561 [D3DRS_TWOSIDEDSTENCILMODE] = NINE_STATE_DSA,
1562 [D3DRS_CCW_STENCILFAIL] = NINE_STATE_DSA,
1563 [D3DRS_CCW_STENCILZFAIL] = NINE_STATE_DSA,
1564 [D3DRS_CCW_STENCILPASS] = NINE_STATE_DSA,
1565 [D3DRS_CCW_STENCILFUNC] = NINE_STATE_DSA,
1566 [D3DRS_COLORWRITEENABLE1] = NINE_STATE_BLEND,
1567 [D3DRS_COLORWRITEENABLE2] = NINE_STATE_BLEND,
1568 [D3DRS_COLORWRITEENABLE3] = NINE_STATE_BLEND,
1569 [D3DRS_BLENDFACTOR] = NINE_STATE_BLEND_COLOR,
1570 [D3DRS_SRGBWRITEENABLE] = NINE_STATE_FB,
1571 [D3DRS_DEPTHBIAS] = NINE_STATE_RASTERIZER,
1572 [D3DRS_WRAP8] = NINE_STATE_UNHANDLED, /* cylwrap has to be done via GP */
1573 [D3DRS_WRAP9] = NINE_STATE_UNHANDLED,
1574 [D3DRS_WRAP10] = NINE_STATE_UNHANDLED,
1575 [D3DRS_WRAP11] = NINE_STATE_UNHANDLED,
1576 [D3DRS_WRAP12] = NINE_STATE_UNHANDLED,
1577 [D3DRS_WRAP13] = NINE_STATE_UNHANDLED,
1578 [D3DRS_WRAP14] = NINE_STATE_UNHANDLED,
1579 [D3DRS_WRAP15] = NINE_STATE_UNHANDLED,
1580 [D3DRS_SEPARATEALPHABLENDENABLE] = NINE_STATE_BLEND,
1581 [D3DRS_SRCBLENDALPHA] = NINE_STATE_BLEND,
1582 [D3DRS_DESTBLENDALPHA] = NINE_STATE_BLEND,
1583 [D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND
1584 };
1585
1586 /* Misc */
1587
1588 D3DMATRIX *
1589 nine_state_access_transform(struct nine_state *state, D3DTRANSFORMSTATETYPE t,
1590 boolean alloc)
1591 {
1592 static D3DMATRIX Identity = { .m[0] = { 1, 0, 0, 0 },
1593 .m[1] = { 0, 1, 0, 0 },
1594 .m[2] = { 0, 0, 1, 0 },
1595 .m[3] = { 0, 0, 0, 1 } };
1596 unsigned index;
1597
1598 switch (t) {
1599 case D3DTS_VIEW: index = 0; break;
1600 case D3DTS_PROJECTION: index = 1; break;
1601 case D3DTS_TEXTURE0: index = 2; break;
1602 case D3DTS_TEXTURE1: index = 3; break;
1603 case D3DTS_TEXTURE2: index = 4; break;
1604 case D3DTS_TEXTURE3: index = 5; break;
1605 case D3DTS_TEXTURE4: index = 6; break;
1606 case D3DTS_TEXTURE5: index = 7; break;
1607 case D3DTS_TEXTURE6: index = 8; break;
1608 case D3DTS_TEXTURE7: index = 9; break;
1609 default:
1610 if (!(t >= D3DTS_WORLDMATRIX(0) && t <= D3DTS_WORLDMATRIX(255)))
1611 return NULL;
1612 index = 10 + (t - D3DTS_WORLDMATRIX(0));
1613 break;
1614 }
1615
1616 if (index >= state->ff.num_transforms) {
1617 unsigned N = index + 1;
1618 unsigned n = state->ff.num_transforms;
1619
1620 if (!alloc)
1621 return &Identity;
1622 state->ff.transform = REALLOC(state->ff.transform,
1623 n * sizeof(D3DMATRIX),
1624 N * sizeof(D3DMATRIX));
1625 for (; n < N; ++n)
1626 state->ff.transform[n] = Identity;
1627 state->ff.num_transforms = N;
1628 }
1629 return &state->ff.transform[index];
1630 }
1631
1632 #define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n
1633 const char *nine_d3drs_to_string(DWORD State)
1634 {
1635 switch (State) {
1636 D3DRS_TO_STRING_CASE(ZENABLE);
1637 D3DRS_TO_STRING_CASE(FILLMODE);
1638 D3DRS_TO_STRING_CASE(SHADEMODE);
1639 D3DRS_TO_STRING_CASE(ZWRITEENABLE);
1640 D3DRS_TO_STRING_CASE(ALPHATESTENABLE);
1641 D3DRS_TO_STRING_CASE(LASTPIXEL);
1642 D3DRS_TO_STRING_CASE(SRCBLEND);
1643 D3DRS_TO_STRING_CASE(DESTBLEND);
1644 D3DRS_TO_STRING_CASE(CULLMODE);
1645 D3DRS_TO_STRING_CASE(ZFUNC);
1646 D3DRS_TO_STRING_CASE(ALPHAREF);
1647 D3DRS_TO_STRING_CASE(ALPHAFUNC);
1648 D3DRS_TO_STRING_CASE(DITHERENABLE);
1649 D3DRS_TO_STRING_CASE(ALPHABLENDENABLE);
1650 D3DRS_TO_STRING_CASE(FOGENABLE);
1651 D3DRS_TO_STRING_CASE(SPECULARENABLE);
1652 D3DRS_TO_STRING_CASE(FOGCOLOR);
1653 D3DRS_TO_STRING_CASE(FOGTABLEMODE);
1654 D3DRS_TO_STRING_CASE(FOGSTART);
1655 D3DRS_TO_STRING_CASE(FOGEND);
1656 D3DRS_TO_STRING_CASE(FOGDENSITY);
1657 D3DRS_TO_STRING_CASE(RANGEFOGENABLE);
1658 D3DRS_TO_STRING_CASE(STENCILENABLE);
1659 D3DRS_TO_STRING_CASE(STENCILFAIL);
1660 D3DRS_TO_STRING_CASE(STENCILZFAIL);
1661 D3DRS_TO_STRING_CASE(STENCILPASS);
1662 D3DRS_TO_STRING_CASE(STENCILFUNC);
1663 D3DRS_TO_STRING_CASE(STENCILREF);
1664 D3DRS_TO_STRING_CASE(STENCILMASK);
1665 D3DRS_TO_STRING_CASE(STENCILWRITEMASK);
1666 D3DRS_TO_STRING_CASE(TEXTUREFACTOR);
1667 D3DRS_TO_STRING_CASE(WRAP0);
1668 D3DRS_TO_STRING_CASE(WRAP1);
1669 D3DRS_TO_STRING_CASE(WRAP2);
1670 D3DRS_TO_STRING_CASE(WRAP3);
1671 D3DRS_TO_STRING_CASE(WRAP4);
1672 D3DRS_TO_STRING_CASE(WRAP5);
1673 D3DRS_TO_STRING_CASE(WRAP6);
1674 D3DRS_TO_STRING_CASE(WRAP7);
1675 D3DRS_TO_STRING_CASE(CLIPPING);
1676 D3DRS_TO_STRING_CASE(LIGHTING);
1677 D3DRS_TO_STRING_CASE(AMBIENT);
1678 D3DRS_TO_STRING_CASE(FOGVERTEXMODE);
1679 D3DRS_TO_STRING_CASE(COLORVERTEX);
1680 D3DRS_TO_STRING_CASE(LOCALVIEWER);
1681 D3DRS_TO_STRING_CASE(NORMALIZENORMALS);
1682 D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE);
1683 D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE);
1684 D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE);
1685 D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE);
1686 D3DRS_TO_STRING_CASE(VERTEXBLEND);
1687 D3DRS_TO_STRING_CASE(CLIPPLANEENABLE);
1688 D3DRS_TO_STRING_CASE(POINTSIZE);
1689 D3DRS_TO_STRING_CASE(POINTSIZE_MIN);
1690 D3DRS_TO_STRING_CASE(POINTSPRITEENABLE);
1691 D3DRS_TO_STRING_CASE(POINTSCALEENABLE);
1692 D3DRS_TO_STRING_CASE(POINTSCALE_A);
1693 D3DRS_TO_STRING_CASE(POINTSCALE_B);
1694 D3DRS_TO_STRING_CASE(POINTSCALE_C);
1695 D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS);
1696 D3DRS_TO_STRING_CASE(MULTISAMPLEMASK);
1697 D3DRS_TO_STRING_CASE(PATCHEDGESTYLE);
1698 D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN);
1699 D3DRS_TO_STRING_CASE(POINTSIZE_MAX);
1700 D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE);
1701 D3DRS_TO_STRING_CASE(COLORWRITEENABLE);
1702 D3DRS_TO_STRING_CASE(TWEENFACTOR);
1703 D3DRS_TO_STRING_CASE(BLENDOP);
1704 D3DRS_TO_STRING_CASE(POSITIONDEGREE);
1705 D3DRS_TO_STRING_CASE(NORMALDEGREE);
1706 D3DRS_TO_STRING_CASE(SCISSORTESTENABLE);
1707 D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS);
1708 D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE);
1709 D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL);
1710 D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL);
1711 D3DRS_TO_STRING_CASE(ADAPTIVETESS_X);
1712 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y);
1713 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z);
1714 D3DRS_TO_STRING_CASE(ADAPTIVETESS_W);
1715 D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION);
1716 D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE);
1717 D3DRS_TO_STRING_CASE(CCW_STENCILFAIL);
1718 D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL);
1719 D3DRS_TO_STRING_CASE(CCW_STENCILPASS);
1720 D3DRS_TO_STRING_CASE(CCW_STENCILFUNC);
1721 D3DRS_TO_STRING_CASE(COLORWRITEENABLE1);
1722 D3DRS_TO_STRING_CASE(COLORWRITEENABLE2);
1723 D3DRS_TO_STRING_CASE(COLORWRITEENABLE3);
1724 D3DRS_TO_STRING_CASE(BLENDFACTOR);
1725 D3DRS_TO_STRING_CASE(SRGBWRITEENABLE);
1726 D3DRS_TO_STRING_CASE(DEPTHBIAS);
1727 D3DRS_TO_STRING_CASE(WRAP8);
1728 D3DRS_TO_STRING_CASE(WRAP9);
1729 D3DRS_TO_STRING_CASE(WRAP10);
1730 D3DRS_TO_STRING_CASE(WRAP11);
1731 D3DRS_TO_STRING_CASE(WRAP12);
1732 D3DRS_TO_STRING_CASE(WRAP13);
1733 D3DRS_TO_STRING_CASE(WRAP14);
1734 D3DRS_TO_STRING_CASE(WRAP15);
1735 D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE);
1736 D3DRS_TO_STRING_CASE(SRCBLENDALPHA);
1737 D3DRS_TO_STRING_CASE(DESTBLENDALPHA);
1738 D3DRS_TO_STRING_CASE(BLENDOPALPHA);
1739 default:
1740 return "(invalid)";
1741 }
1742 }