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