st/nine: Move core of device clear to nine_state
[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 "pipe/p_context.h"
36 #include "pipe/p_state.h"
37 #include "cso_cache/cso_context.h"
38 #include "util/u_upload_mgr.h"
39 #include "util/u_math.h"
40 #include "util/u_box.h"
41 #include "util/u_simple_shaders.h"
42
43 #define DBG_CHANNEL DBG_DEVICE
44
45 /* Check if some states need to be set dirty */
46
47 static inline DWORD
48 check_multisample(struct NineDevice9 *device)
49 {
50 DWORD *rs = device->state.rs;
51 DWORD new_value = (rs[D3DRS_ZENABLE] || rs[D3DRS_STENCILENABLE]) &&
52 device->state.rt[0]->desc.MultiSampleType >= 1 &&
53 rs[D3DRS_MULTISAMPLEANTIALIAS];
54 if (rs[NINED3DRS_MULTISAMPLE] != new_value) {
55 rs[NINED3DRS_MULTISAMPLE] = new_value;
56 return NINE_STATE_RASTERIZER;
57 }
58 return 0;
59 }
60
61 /* State preparation only */
62
63 static inline void
64 prepare_blend(struct NineDevice9 *device)
65 {
66 nine_convert_blend_state(&device->context.pipe.blend, device->state.rs);
67 device->context.commit |= NINE_STATE_COMMIT_BLEND;
68 }
69
70 static inline void
71 prepare_dsa(struct NineDevice9 *device)
72 {
73 nine_convert_dsa_state(&device->context.pipe.dsa, device->state.rs);
74 device->context.commit |= NINE_STATE_COMMIT_DSA;
75 }
76
77 static inline void
78 prepare_rasterizer(struct NineDevice9 *device)
79 {
80 nine_convert_rasterizer_state(device, &device->context.pipe.rast, device->state.rs);
81 device->context.commit |= NINE_STATE_COMMIT_RASTERIZER;
82 }
83
84 static void
85 prepare_vs_constants_userbuf_swvp(struct NineDevice9 *device)
86 {
87 struct nine_state *state = &device->state;
88 struct nine_context *context = &device->context;
89
90 if (state->changed.vs_const_f || state->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 = state->vs_const_f_swvp;
96
97 if (state->vs->lconstf.ranges) {
98 const struct nine_lconstf *lconstf = &device->state.vs->lconstf;
99 const struct nine_range *r = lconstf->ranges;
100 unsigned n = 0;
101 float *dst = device->state.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.cb0_swvp.buffer_offset = cb.buffer_offset;
118 context->pipe.cb0_swvp.buffer_size = cb.buffer_size;
119 context->pipe.cb0_swvp.user_buffer = cb.user_buffer;
120
121 cb.user_buffer = (char *)cb.user_buffer + 4096 * sizeof(float[4]);
122 context->pipe.cb1_swvp.buffer_offset = cb.buffer_offset;
123 context->pipe.cb1_swvp.buffer_size = cb.buffer_size;
124 context->pipe.cb1_swvp.user_buffer = cb.user_buffer;
125 }
126
127 if (state->changed.vs_const_i || state->changed.group & NINE_STATE_SWVP) {
128 struct pipe_constant_buffer cb;
129
130 cb.buffer_offset = 0;
131 cb.buffer_size = 2048 * sizeof(float[4]);
132 cb.user_buffer = state->vs_const_i;
133
134 context->pipe.cb2_swvp.buffer_offset = cb.buffer_offset;
135 context->pipe.cb2_swvp.buffer_size = cb.buffer_size;
136 context->pipe.cb2_swvp.user_buffer = cb.user_buffer;
137 }
138
139 if (state->changed.vs_const_b || state->changed.group & NINE_STATE_SWVP) {
140 struct pipe_constant_buffer cb;
141
142 cb.buffer_offset = 0;
143 cb.buffer_size = 512 * sizeof(float[4]);
144 cb.user_buffer = state->vs_const_b;
145
146 context->pipe.cb3_swvp.buffer_offset = cb.buffer_offset;
147 context->pipe.cb3_swvp.buffer_size = cb.buffer_size;
148 context->pipe.cb3_swvp.user_buffer = cb.user_buffer;
149 }
150
151 if (!device->driver_caps.user_cbufs) {
152 struct pipe_constant_buffer *cb = &(context->pipe.cb0_swvp);
153 u_upload_data(device->constbuf_uploader,
154 0,
155 cb->buffer_size,
156 device->constbuf_alignment,
157 cb->user_buffer,
158 &(cb->buffer_offset),
159 &(cb->buffer));
160 u_upload_unmap(device->constbuf_uploader);
161 cb->user_buffer = NULL;
162
163 cb = &(context->pipe.cb1_swvp);
164 u_upload_data(device->constbuf_uploader,
165 0,
166 cb->buffer_size,
167 device->constbuf_alignment,
168 cb->user_buffer,
169 &(cb->buffer_offset),
170 &(cb->buffer));
171 u_upload_unmap(device->constbuf_uploader);
172 cb->user_buffer = NULL;
173
174 cb = &(context->pipe.cb2_swvp);
175 u_upload_data(device->constbuf_uploader,
176 0,
177 cb->buffer_size,
178 device->constbuf_alignment,
179 cb->user_buffer,
180 &(cb->buffer_offset),
181 &(cb->buffer));
182 u_upload_unmap(device->constbuf_uploader);
183 cb->user_buffer = NULL;
184
185 cb = &(context->pipe.cb3_swvp);
186 u_upload_data(device->constbuf_uploader,
187 0,
188 cb->buffer_size,
189 device->constbuf_alignment,
190 cb->user_buffer,
191 &(cb->buffer_offset),
192 &(cb->buffer));
193 u_upload_unmap(device->constbuf_uploader);
194 cb->user_buffer = NULL;
195 }
196
197 if (device->state.changed.vs_const_f) {
198 struct nine_range *r = device->state.changed.vs_const_f;
199 struct nine_range *p = r;
200 while (p->next)
201 p = p->next;
202 nine_range_pool_put_chain(&device->range_pool, r, p);
203 device->state.changed.vs_const_f = NULL;
204 }
205
206 if (device->state.changed.vs_const_i) {
207 struct nine_range *r = device->state.changed.vs_const_i;
208 struct nine_range *p = r;
209 while (p->next)
210 p = p->next;
211 nine_range_pool_put_chain(&device->range_pool, r, p);
212 device->state.changed.vs_const_i = NULL;
213 }
214
215 if (device->state.changed.vs_const_b) {
216 struct nine_range *r = device->state.changed.vs_const_b;
217 struct nine_range *p = r;
218 while (p->next)
219 p = p->next;
220 nine_range_pool_put_chain(&device->range_pool, r, p);
221 device->state.changed.vs_const_b = NULL;
222 }
223
224 state->changed.group &= ~NINE_STATE_VS_CONST;
225 context->commit |= NINE_STATE_COMMIT_CONST_VS;
226 }
227
228 static void
229 prepare_vs_constants_userbuf(struct NineDevice9 *device)
230 {
231 struct nine_state *state = &device->state;
232 struct nine_context *context = &device->context;
233 struct pipe_constant_buffer cb;
234 cb.buffer = NULL;
235 cb.buffer_offset = 0;
236 cb.buffer_size = device->state.vs->const_used_size;
237 cb.user_buffer = device->state.vs_const_f;
238
239 if (device->swvp) {
240 prepare_vs_constants_userbuf_swvp(device);
241 return;
242 }
243
244 if (state->changed.vs_const_i || state->changed.group & NINE_STATE_SWVP) {
245 int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f];
246 memcpy(idst, state->vs_const_i, NINE_MAX_CONST_I * sizeof(int[4]));
247 }
248
249 if (state->changed.vs_const_b || state->changed.group & NINE_STATE_SWVP) {
250 int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f];
251 uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I];
252 memcpy(bdst, state->vs_const_b, NINE_MAX_CONST_B * sizeof(BOOL));
253 }
254
255 if (device->state.changed.vs_const_i) {
256 struct nine_range *r = device->state.changed.vs_const_i;
257 struct nine_range *p = r;
258 while (p->next)
259 p = p->next;
260 nine_range_pool_put_chain(&device->range_pool, r, p);
261 device->state.changed.vs_const_i = NULL;
262 }
263
264 if (device->state.changed.vs_const_b) {
265 struct nine_range *r = device->state.changed.vs_const_b;
266 struct nine_range *p = r;
267 while (p->next)
268 p = p->next;
269 nine_range_pool_put_chain(&device->range_pool, r, p);
270 device->state.changed.vs_const_b = NULL;
271 }
272
273 if (!cb.buffer_size)
274 return;
275
276 if (device->state.vs->lconstf.ranges) {
277 /* TODO: Can we make it so that we don't have to copy everything ? */
278 const struct nine_lconstf *lconstf = &device->state.vs->lconstf;
279 const struct nine_range *r = lconstf->ranges;
280 unsigned n = 0;
281 float *dst = device->state.vs_lconstf_temp;
282 float *src = (float *)cb.user_buffer;
283 memcpy(dst, src, cb.buffer_size);
284 while (r) {
285 unsigned p = r->bgn;
286 unsigned c = r->end - r->bgn;
287 memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float));
288 n += c;
289 r = r->next;
290 }
291 cb.user_buffer = dst;
292 }
293
294 if (!device->driver_caps.user_cbufs) {
295 context->pipe.cb_vs.buffer_size = cb.buffer_size;
296 u_upload_data(device->constbuf_uploader,
297 0,
298 cb.buffer_size,
299 device->constbuf_alignment,
300 cb.user_buffer,
301 &context->pipe.cb_vs.buffer_offset,
302 &context->pipe.cb_vs.buffer);
303 u_upload_unmap(device->constbuf_uploader);
304 context->pipe.cb_vs.user_buffer = NULL;
305 } else
306 context->pipe.cb_vs = cb;
307
308 if (device->state.changed.vs_const_f) {
309 struct nine_range *r = device->state.changed.vs_const_f;
310 struct nine_range *p = r;
311 while (p->next)
312 p = p->next;
313 nine_range_pool_put_chain(&device->range_pool, r, p);
314 device->state.changed.vs_const_f = NULL;
315 }
316
317 state->changed.group &= ~NINE_STATE_VS_CONST;
318 context->commit |= NINE_STATE_COMMIT_CONST_VS;
319 }
320
321 static void
322 prepare_ps_constants_userbuf(struct NineDevice9 *device)
323 {
324 struct nine_state *state = &device->state;
325 struct nine_context *context = &device->context;
326 struct pipe_constant_buffer cb;
327 cb.buffer = NULL;
328 cb.buffer_offset = 0;
329 cb.buffer_size = device->state.ps->const_used_size;
330 cb.user_buffer = device->state.ps_const_f;
331
332 if (state->changed.ps_const_i) {
333 int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
334 memcpy(idst, state->ps_const_i, sizeof(state->ps_const_i));
335 state->changed.ps_const_i = 0;
336 }
337 if (state->changed.ps_const_b) {
338 int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
339 uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I];
340 memcpy(bdst, state->ps_const_b, sizeof(state->ps_const_b));
341 state->changed.ps_const_b = 0;
342 }
343
344 /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */
345 if (device->state.ps->bumpenvmat_needed) {
346 memcpy(device->state.ps_lconstf_temp, cb.user_buffer, cb.buffer_size);
347 memcpy(&device->state.ps_lconstf_temp[4 * 8], &device->context.bumpmap_vars, sizeof(device->context.bumpmap_vars));
348
349 cb.user_buffer = device->state.ps_lconstf_temp;
350 }
351
352 if (state->ps->byte_code.version < 0x30 &&
353 state->rs[D3DRS_FOGENABLE]) {
354 float *dst = &state->ps_lconstf_temp[4 * 32];
355 if (cb.user_buffer != state->ps_lconstf_temp) {
356 memcpy(state->ps_lconstf_temp, cb.user_buffer, cb.buffer_size);
357 cb.user_buffer = state->ps_lconstf_temp;
358 }
359
360 d3dcolor_to_rgba(dst, state->rs[D3DRS_FOGCOLOR]);
361 if (state->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) {
362 dst[4] = asfloat(state->rs[D3DRS_FOGEND]);
363 dst[5] = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
364 } else if (state->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
365 dst[4] = asfloat(state->rs[D3DRS_FOGDENSITY]);
366 }
367 cb.buffer_size = 4 * 4 * 34;
368 }
369
370 if (!cb.buffer_size)
371 return;
372
373 if (!device->driver_caps.user_cbufs) {
374 context->pipe.cb_ps.buffer_size = cb.buffer_size;
375 u_upload_data(device->constbuf_uploader,
376 0,
377 cb.buffer_size,
378 device->constbuf_alignment,
379 cb.user_buffer,
380 &context->pipe.cb_ps.buffer_offset,
381 &context->pipe.cb_ps.buffer);
382 u_upload_unmap(device->constbuf_uploader);
383 context->pipe.cb_ps.user_buffer = NULL;
384 } else
385 context->pipe.cb_ps = cb;
386
387 if (device->state.changed.ps_const_f) {
388 struct nine_range *r = device->state.changed.ps_const_f;
389 struct nine_range *p = r;
390 while (p->next)
391 p = p->next;
392 nine_range_pool_put_chain(&device->range_pool, r, p);
393 device->state.changed.ps_const_f = NULL;
394 }
395 state->changed.group &= ~NINE_STATE_PS_CONST;
396 context->commit |= NINE_STATE_COMMIT_CONST_PS;
397 }
398
399 static inline uint32_t
400 prepare_vs(struct NineDevice9 *device, uint8_t shader_changed)
401 {
402 struct nine_state *state = &device->state;
403 struct nine_context *context = &device->context;
404 struct NineVertexShader9 *vs = state->vs;
405 uint32_t changed_group = 0;
406 int has_key_changed = 0;
407
408 if (likely(state->programmable_vs))
409 has_key_changed = NineVertexShader9_UpdateKey(vs, device);
410
411 if (!shader_changed && !has_key_changed)
412 return 0;
413
414 /* likely because we dislike FF */
415 if (likely(state->programmable_vs)) {
416 context->cso.vs = NineVertexShader9_GetVariant(vs);
417 } else {
418 vs = device->ff.vs;
419 context->cso.vs = vs->ff_cso;
420 }
421
422 if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
423 state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
424 changed_group |= NINE_STATE_RASTERIZER;
425 }
426
427 if ((context->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask)
428 /* Bound dummy sampler. */
429 changed_group |= NINE_STATE_SAMPLER;
430
431 context->commit |= NINE_STATE_COMMIT_VS;
432 return changed_group;
433 }
434
435 static inline uint32_t
436 prepare_ps(struct NineDevice9 *device, uint8_t shader_changed)
437 {
438 struct nine_state *state = &device->state;
439 struct nine_context *context = &device->context;
440 struct NinePixelShader9 *ps = state->ps;
441 uint32_t changed_group = 0;
442 int has_key_changed = 0;
443
444 if (likely(ps))
445 has_key_changed = NinePixelShader9_UpdateKey(ps, state);
446
447 if (!shader_changed && !has_key_changed)
448 return 0;
449
450 if (likely(ps)) {
451 context->cso.ps = NinePixelShader9_GetVariant(ps);
452 } else {
453 ps = device->ff.ps;
454 context->cso.ps = ps->ff_cso;
455 }
456
457 if ((context->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask)
458 /* Bound dummy sampler. */
459 changed_group |= NINE_STATE_SAMPLER;
460
461 context->commit |= NINE_STATE_COMMIT_PS;
462 return changed_group;
463 }
464
465 /* State preparation incremental */
466
467 /* State preparation + State commit */
468
469 static void
470 update_framebuffer(struct NineDevice9 *device, bool is_clear)
471 {
472 struct pipe_context *pipe = device->pipe;
473 struct nine_state *state = &device->state;
474 struct nine_context *context = &device->context;
475 struct pipe_framebuffer_state *fb = &context->pipe.fb;
476 unsigned i;
477 struct NineSurface9 *rt0 = state->rt[0];
478 unsigned w = rt0->desc.Width;
479 unsigned h = rt0->desc.Height;
480 unsigned nr_samples = rt0->base.info.nr_samples;
481 unsigned ps_mask = state->ps ? state->ps->rt_mask : 1;
482 unsigned mask = is_clear ? 0xf : ps_mask;
483 const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
484
485 DBG("\n");
486
487 context->rt_mask = 0x0;
488 fb->nr_cbufs = 0;
489
490 /* all render targets must have the same size and the depth buffer must be
491 * bigger. Multisample has to match, according to spec. But some apps do
492 * things wrong there, and no error is returned. The behaviour they get
493 * apparently is that depth buffer is disabled if it doesn't match.
494 * Surely the same for render targets. */
495
496 /* Special case: D3DFMT_NULL is used to bound no real render target,
497 * but render to depth buffer. We have to not take into account the render
498 * target info. TODO: know what should happen when there are several render targers
499 * and the first one is D3DFMT_NULL */
500 if (rt0->desc.Format == D3DFMT_NULL && state->ds) {
501 w = state->ds->desc.Width;
502 h = state->ds->desc.Height;
503 nr_samples = state->ds->base.info.nr_samples;
504 }
505
506 for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
507 struct NineSurface9 *rt = state->rt[i];
508
509 if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) &&
510 rt->desc.Width == w && rt->desc.Height == h &&
511 rt->base.info.nr_samples == nr_samples) {
512 fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB);
513 context->rt_mask |= 1 << i;
514 fb->nr_cbufs = i + 1;
515
516 if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) {
517 assert(rt->texture == D3DRTYPE_TEXTURE ||
518 rt->texture == D3DRTYPE_CUBETEXTURE);
519 NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE;
520 }
521 } else {
522 /* Color outputs must match RT slot,
523 * drivers will have to handle NULL entries for GL, too.
524 */
525 fb->cbufs[i] = NULL;
526 }
527 }
528
529 if (state->ds && state->ds->desc.Width >= w &&
530 state->ds->desc.Height >= h &&
531 state->ds->base.info.nr_samples == nr_samples) {
532 fb->zsbuf = NineSurface9_GetSurface(state->ds, 0);
533 } else {
534 fb->zsbuf = NULL;
535 }
536
537 fb->width = w;
538 fb->height = h;
539
540 pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */
541
542 if (is_clear && context->rt_mask == ps_mask)
543 state->changed.group &= ~NINE_STATE_FB;
544 }
545
546 static void
547 update_viewport(struct NineDevice9 *device)
548 {
549 const D3DVIEWPORT9 *vport = &device->state.viewport;
550 struct pipe_viewport_state pvport;
551
552 /* D3D coordinates are:
553 * -1 .. +1 for X,Y and
554 * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz)
555 */
556 pvport.scale[0] = (float)vport->Width * 0.5f;
557 pvport.scale[1] = (float)vport->Height * -0.5f;
558 pvport.scale[2] = vport->MaxZ - vport->MinZ;
559 pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X;
560 pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y;
561 pvport.translate[2] = vport->MinZ;
562
563 /* We found R600 and SI cards have some imprecision
564 * on the barycentric coordinates used for interpolation.
565 * Some shaders rely on having something precise.
566 * We found that the proprietary driver has the imprecision issue,
567 * except when the render target width and height are powers of two.
568 * It is using some sort of workaround for these cases
569 * which covers likely all the cases the applications rely
570 * on something precise.
571 * We haven't found the workaround, but it seems like it's better
572 * for applications if the imprecision is biased towards infinity
573 * instead of -infinity (which is what measured). So shift slightly
574 * the viewport: not enough to change rasterization result (in particular
575 * for multisampling), but enough to make the imprecision biased
576 * towards infinity. We do this shift only if render target width and
577 * height are powers of two.
578 * Solves 'red shadows' bug on UE3 games.
579 */
580 if (device->driver_bugs.buggy_barycentrics &&
581 ((vport->Width & (vport->Width-1)) == 0) &&
582 ((vport->Height & (vport->Height-1)) == 0)) {
583 pvport.translate[0] -= 1.0f / 128.0f;
584 pvport.translate[1] -= 1.0f / 128.0f;
585 }
586
587 cso_set_viewport(device->cso, &pvport);
588 }
589
590 /* Loop through VS inputs and pick the vertex elements with the declared
591 * usage from the vertex declaration, then insert the instance divisor from
592 * the stream source frequency setting.
593 */
594 static void
595 update_vertex_elements(struct NineDevice9 *device)
596 {
597 struct nine_state *state = &device->state;
598 struct nine_context *context = &device->context;
599 const struct NineVertexDeclaration9 *vdecl = device->state.vdecl;
600 const struct NineVertexShader9 *vs;
601 unsigned n, b, i;
602 int index;
603 char vdecl_index_map[16]; /* vs->num_inputs <= 16 */
604 char used_streams[device->caps.MaxStreams];
605 int dummy_vbo_stream = -1;
606 BOOL need_dummy_vbo = FALSE;
607 struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
608
609 state->stream_usage_mask = 0;
610 memset(vdecl_index_map, -1, 16);
611 memset(used_streams, 0, device->caps.MaxStreams);
612 vs = state->programmable_vs ? device->state.vs : device->ff.vs;
613
614 if (vdecl) {
615 for (n = 0; n < vs->num_inputs; ++n) {
616 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
617 n, vs->input_map[n].ndecl, vdecl);
618
619 for (i = 0; i < vdecl->nelems; i++) {
620 if (vdecl->usage_map[i] == vs->input_map[n].ndecl) {
621 vdecl_index_map[n] = i;
622 used_streams[vdecl->elems[i].vertex_buffer_index] = 1;
623 break;
624 }
625 }
626 if (vdecl_index_map[n] < 0)
627 need_dummy_vbo = TRUE;
628 }
629 } else {
630 /* No vertex declaration. Likely will never happen in practice,
631 * but we need not crash on this */
632 need_dummy_vbo = TRUE;
633 }
634
635 if (need_dummy_vbo) {
636 for (i = 0; i < device->caps.MaxStreams; i++ ) {
637 if (!used_streams[i]) {
638 dummy_vbo_stream = i;
639 break;
640 }
641 }
642 }
643 /* there are less vertex shader inputs than stream slots,
644 * so if we need a slot for the dummy vbo, we should have found one */
645 assert (!need_dummy_vbo || dummy_vbo_stream != -1);
646
647 for (n = 0; n < vs->num_inputs; ++n) {
648 index = vdecl_index_map[n];
649 if (index >= 0) {
650 ve[n] = vdecl->elems[index];
651 b = ve[n].vertex_buffer_index;
652 state->stream_usage_mask |= 1 << b;
653 /* XXX wine just uses 1 here: */
654 if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA)
655 ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF;
656 } else {
657 /* if the vertex declaration is incomplete compared to what the
658 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
659 * This is not precised by the spec, but is the behaviour
660 * tested on win */
661 ve[n].vertex_buffer_index = dummy_vbo_stream;
662 ve[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
663 ve[n].src_offset = 0;
664 ve[n].instance_divisor = 0;
665 }
666 }
667
668 if (context->dummy_vbo_bound_at != dummy_vbo_stream) {
669 if (context->dummy_vbo_bound_at >= 0)
670 state->changed.vtxbuf |= 1 << context->dummy_vbo_bound_at;
671 if (dummy_vbo_stream >= 0) {
672 state->changed.vtxbuf |= 1 << dummy_vbo_stream;
673 context->vbo_bound_done = FALSE;
674 }
675 context->dummy_vbo_bound_at = dummy_vbo_stream;
676 }
677
678 cso_set_vertex_elements(device->cso, vs->num_inputs, ve);
679
680 state->changed.stream_freq = 0;
681 }
682
683 static void
684 update_vertex_buffers(struct NineDevice9 *device)
685 {
686 struct pipe_context *pipe = device->pipe;
687 struct nine_context *context = &device->context;
688 struct nine_state *state = &device->state;
689 struct pipe_vertex_buffer dummy_vtxbuf;
690 uint32_t mask = state->changed.vtxbuf;
691 unsigned i;
692
693 DBG("mask=%x\n", mask);
694
695 if (context->dummy_vbo_bound_at >= 0) {
696 if (!context->vbo_bound_done) {
697 dummy_vtxbuf.buffer = device->dummy_vbo;
698 dummy_vtxbuf.stride = 0;
699 dummy_vtxbuf.user_buffer = NULL;
700 dummy_vtxbuf.buffer_offset = 0;
701 pipe->set_vertex_buffers(pipe, context->dummy_vbo_bound_at,
702 1, &dummy_vtxbuf);
703 context->vbo_bound_done = TRUE;
704 }
705 mask &= ~(1 << context->dummy_vbo_bound_at);
706 }
707
708 for (i = 0; mask; mask >>= 1, ++i) {
709 if (mask & 1) {
710 if (state->vtxbuf[i].buffer)
711 pipe->set_vertex_buffers(pipe, i, 1, &state->vtxbuf[i]);
712 else
713 pipe->set_vertex_buffers(pipe, i, 1, NULL);
714 }
715 }
716
717 state->changed.vtxbuf = 0;
718 }
719
720 static inline boolean
721 update_sampler_derived(struct nine_state *state, unsigned s)
722 {
723 boolean changed = FALSE;
724
725 if (state->samp[s][NINED3DSAMP_SHADOW] != state->texture[s]->shadow) {
726 changed = TRUE;
727 state->samp[s][NINED3DSAMP_SHADOW] = state->texture[s]->shadow;
728 }
729
730 if (state->samp[s][NINED3DSAMP_CUBETEX] !=
731 (NineResource9(state->texture[s])->type == D3DRTYPE_CUBETEXTURE)) {
732 changed = TRUE;
733 state->samp[s][NINED3DSAMP_CUBETEX] =
734 NineResource9(state->texture[s])->type == D3DRTYPE_CUBETEXTURE;
735 }
736
737 if (state->samp[s][D3DSAMP_MIPFILTER] != D3DTEXF_NONE) {
738 int lod = state->samp[s][D3DSAMP_MAXMIPLEVEL] - state->texture[s]->managed.lod;
739 if (lod < 0)
740 lod = 0;
741 if (state->samp[s][NINED3DSAMP_MINLOD] != lod) {
742 changed = TRUE;
743 state->samp[s][NINED3DSAMP_MINLOD] = lod;
744 }
745 } else {
746 state->changed.sampler[s] &= ~0x300; /* lod changes irrelevant */
747 }
748
749 return changed;
750 }
751
752 /* TODO: add sRGB override to pipe_sampler_state ? */
753 static void
754 update_textures_and_samplers(struct NineDevice9 *device)
755 {
756 struct nine_state *state = &device->state;
757 struct nine_context *context = &device->context;
758 struct pipe_sampler_view *view[NINE_MAX_SAMPLERS];
759 unsigned num_textures;
760 unsigned i;
761 boolean commit_samplers;
762 uint16_t sampler_mask = state->ps ? state->ps->sampler_mask :
763 device->ff.ps->sampler_mask;
764
765 /* TODO: Can we reduce iterations here ? */
766
767 commit_samplers = FALSE;
768 context->bound_samplers_mask_ps = 0;
769 for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) {
770 const unsigned s = NINE_SAMPLER_PS(i);
771 int sRGB;
772
773 if (!state->texture[s] && !(sampler_mask & (1 << i))) {
774 view[i] = NULL;
775 continue;
776 }
777
778 if (state->texture[s]) {
779 sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0;
780
781 view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB);
782 num_textures = i + 1;
783
784 if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) {
785 state->changed.sampler[s] = 0;
786 commit_samplers = TRUE;
787 nine_convert_sampler_state(device->cso, s, state->samp[s]);
788 }
789 } else {
790 /* Bind dummy sampler. We do not bind dummy sampler when
791 * it is not needed because it could add overhead. The
792 * dummy sampler should have r=g=b=0 and a=1. We do not
793 * unbind dummy sampler directly when they are not needed
794 * anymore, but they're going to be removed as long as texture
795 * or sampler states are changed. */
796 view[i] = device->dummy_sampler_view;
797 num_textures = i + 1;
798
799 cso_single_sampler(device->cso, PIPE_SHADER_FRAGMENT,
800 s - NINE_SAMPLER_PS(0), &device->dummy_sampler_state);
801
802 commit_samplers = TRUE;
803 state->changed.sampler[s] = ~0;
804 }
805
806 context->bound_samplers_mask_ps |= (1 << s);
807 }
808
809 cso_set_sampler_views(device->cso, PIPE_SHADER_FRAGMENT, num_textures, view);
810
811 if (commit_samplers)
812 cso_single_sampler_done(device->cso, PIPE_SHADER_FRAGMENT);
813
814 commit_samplers = FALSE;
815 sampler_mask = state->programmable_vs ? state->vs->sampler_mask : 0;
816 context->bound_samplers_mask_vs = 0;
817 for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_VS; ++i) {
818 const unsigned s = NINE_SAMPLER_VS(i);
819 int sRGB;
820
821 if (!state->texture[s] && !(sampler_mask & (1 << i))) {
822 view[i] = NULL;
823 continue;
824 }
825
826 if (state->texture[s]) {
827 sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0;
828
829 view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB);
830 num_textures = i + 1;
831
832 if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) {
833 state->changed.sampler[s] = 0;
834 commit_samplers = TRUE;
835 nine_convert_sampler_state(device->cso, s, state->samp[s]);
836 }
837 } else {
838 /* Bind dummy sampler. We do not bind dummy sampler when
839 * it is not needed because it could add overhead. The
840 * dummy sampler should have r=g=b=0 and a=1. We do not
841 * unbind dummy sampler directly when they are not needed
842 * anymore, but they're going to be removed as long as texture
843 * or sampler states are changed. */
844 view[i] = device->dummy_sampler_view;
845 num_textures = i + 1;
846
847 cso_single_sampler(device->cso, PIPE_SHADER_VERTEX,
848 s - NINE_SAMPLER_VS(0), &device->dummy_sampler_state);
849
850 commit_samplers = TRUE;
851 state->changed.sampler[s] = ~0;
852 }
853
854 context->bound_samplers_mask_vs |= (1 << s);
855 }
856
857 cso_set_sampler_views(device->cso, PIPE_SHADER_VERTEX, num_textures, view);
858
859 if (commit_samplers)
860 cso_single_sampler_done(device->cso, PIPE_SHADER_VERTEX);
861
862 state->changed.texture = 0;
863 }
864
865 /* State commit only */
866
867 static inline void
868 commit_blend(struct NineDevice9 *device)
869 {
870 cso_set_blend(device->cso, &device->context.pipe.blend);
871 }
872
873 static inline void
874 commit_dsa(struct NineDevice9 *device)
875 {
876 cso_set_depth_stencil_alpha(device->cso, &device->context.pipe.dsa);
877 }
878
879 static inline void
880 commit_scissor(struct NineDevice9 *device)
881 {
882 struct pipe_context *pipe = device->pipe;
883
884 pipe->set_scissor_states(pipe, 0, 1, &device->state.scissor);
885 }
886
887 static inline void
888 commit_rasterizer(struct NineDevice9 *device)
889 {
890 cso_set_rasterizer(device->cso, &device->context.pipe.rast);
891 }
892
893 static inline void
894 commit_index_buffer(struct NineDevice9 *device)
895 {
896 struct pipe_context *pipe = device->pipe;
897 if (device->state.idxbuf)
898 pipe->set_index_buffer(pipe, &device->state.idxbuf->buffer);
899 else
900 pipe->set_index_buffer(pipe, NULL);
901 }
902
903 static inline void
904 commit_vs_constants(struct NineDevice9 *device)
905 {
906 struct pipe_context *pipe = device->pipe;
907
908 if (unlikely(!device->state.programmable_vs))
909 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->context.pipe.cb_vs_ff);
910 else {
911 if (device->swvp) {
912 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->context.pipe.cb0_swvp);
913 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 1, &device->context.pipe.cb1_swvp);
914 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 2, &device->context.pipe.cb2_swvp);
915 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 3, &device->context.pipe.cb3_swvp);
916 } else {
917 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->context.pipe.cb_vs);
918 }
919 }
920 }
921
922 static inline void
923 commit_ps_constants(struct NineDevice9 *device)
924 {
925 struct pipe_context *pipe = device->pipe;
926
927 if (unlikely(!device->state.ps))
928 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &device->context.pipe.cb_ps_ff);
929 else
930 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &device->context.pipe.cb_ps);
931 }
932
933 static inline void
934 commit_vs(struct NineDevice9 *device)
935 {
936 struct nine_context *context = &device->context;
937
938 device->pipe->bind_vs_state(device->pipe, context->cso.vs);
939 }
940
941
942 static inline void
943 commit_ps(struct NineDevice9 *device)
944 {
945 struct nine_context *context = &device->context;
946
947 device->pipe->bind_fs_state(device->pipe, context->cso.ps);
948 }
949 /* State Update */
950
951 #define NINE_STATE_SHADER_CHANGE_VS \
952 (NINE_STATE_VS | \
953 NINE_STATE_TEXTURE | \
954 NINE_STATE_FOG_SHADER | \
955 NINE_STATE_POINTSIZE_SHADER | \
956 NINE_STATE_SWVP)
957
958 #define NINE_STATE_SHADER_CHANGE_PS \
959 (NINE_STATE_PS | \
960 NINE_STATE_TEXTURE | \
961 NINE_STATE_FOG_SHADER | \
962 NINE_STATE_PS1X_SHADER)
963
964 #define NINE_STATE_FREQUENT \
965 (NINE_STATE_RASTERIZER | \
966 NINE_STATE_TEXTURE | \
967 NINE_STATE_SAMPLER | \
968 NINE_STATE_VS_CONST | \
969 NINE_STATE_PS_CONST | \
970 NINE_STATE_MULTISAMPLE)
971
972 #define NINE_STATE_COMMON \
973 (NINE_STATE_FB | \
974 NINE_STATE_BLEND | \
975 NINE_STATE_DSA | \
976 NINE_STATE_VIEWPORT | \
977 NINE_STATE_VDECL | \
978 NINE_STATE_IDXBUF | \
979 NINE_STATE_STREAMFREQ)
980
981 #define NINE_STATE_RARE \
982 (NINE_STATE_SCISSOR | \
983 NINE_STATE_BLEND_COLOR | \
984 NINE_STATE_STENCIL_REF | \
985 NINE_STATE_SAMPLE_MASK)
986
987
988 /* TODO: only go through dirty textures */
989 static void
990 validate_textures(struct NineDevice9 *device)
991 {
992 struct NineBaseTexture9 *tex, *ptr;
993 LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) {
994 list_delinit(&tex->list);
995 NineBaseTexture9_Validate(tex);
996 }
997 }
998
999 static void
1000 update_managed_buffers(struct NineDevice9 *device)
1001 {
1002 struct NineBuffer9 *buf, *ptr;
1003 LIST_FOR_EACH_ENTRY_SAFE(buf, ptr, &device->update_buffers, managed.list) {
1004 list_delinit(&buf->managed.list);
1005 NineBuffer9_Upload(buf);
1006 }
1007 }
1008
1009 boolean
1010 nine_update_state(struct NineDevice9 *device)
1011 {
1012 struct pipe_context *pipe = device->pipe;
1013 struct nine_state *state = &device->state;
1014 struct nine_context *context = &device->context;
1015 uint32_t group;
1016
1017 DBG("changed state groups: %x\n", state->changed.group);
1018
1019 /* NOTE: We may want to use the cso cache for everything, or let
1020 * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't
1021 * have to care about state being clobbered here and could merge this back
1022 * into update_textures. Except, we also need to re-validate textures that
1023 * may be dirty anyway, even if no texture bindings changed.
1024 */
1025 validate_textures(device); /* may clobber state */
1026 update_managed_buffers(device);
1027
1028 /* ff_update may change VS/PS dirty bits */
1029 if (unlikely(!state->programmable_vs || !state->ps))
1030 nine_ff_update(device);
1031 group = state->changed.group;
1032
1033 if (group & (NINE_STATE_SHADER_CHANGE_VS | NINE_STATE_SHADER_CHANGE_PS)) {
1034 if (group & NINE_STATE_SHADER_CHANGE_VS)
1035 group |= prepare_vs(device, (group & NINE_STATE_VS) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/
1036 if (group & NINE_STATE_SHADER_CHANGE_PS)
1037 group |= prepare_ps(device, (group & NINE_STATE_PS) != 0);
1038 }
1039
1040 if (group & (NINE_STATE_COMMON | NINE_STATE_VS)) {
1041 if (group & NINE_STATE_FB)
1042 update_framebuffer(device, FALSE);
1043 if (group & NINE_STATE_BLEND)
1044 prepare_blend(device);
1045 if (group & NINE_STATE_DSA)
1046 prepare_dsa(device);
1047 if (group & NINE_STATE_VIEWPORT)
1048 update_viewport(device);
1049 if (group & (NINE_STATE_VDECL | NINE_STATE_VS | NINE_STATE_STREAMFREQ))
1050 update_vertex_elements(device);
1051 if (group & NINE_STATE_IDXBUF)
1052 commit_index_buffer(device);
1053 }
1054
1055 if (likely(group & (NINE_STATE_FREQUENT | NINE_STATE_VS | NINE_STATE_PS | NINE_STATE_SWVP))) {
1056 if (group & NINE_STATE_MULTISAMPLE)
1057 group |= check_multisample(device);
1058 if (group & NINE_STATE_RASTERIZER)
1059 prepare_rasterizer(device);
1060 if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER))
1061 update_textures_and_samplers(device);
1062 if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS | NINE_STATE_SWVP)) && state->programmable_vs)
1063 prepare_vs_constants_userbuf(device);
1064 if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && state->ps)
1065 prepare_ps_constants_userbuf(device);
1066 }
1067
1068 if (state->changed.vtxbuf)
1069 update_vertex_buffers(device);
1070
1071 if (context->commit & NINE_STATE_COMMIT_BLEND)
1072 commit_blend(device);
1073 if (context->commit & NINE_STATE_COMMIT_DSA)
1074 commit_dsa(device);
1075 if (context->commit & NINE_STATE_COMMIT_RASTERIZER)
1076 commit_rasterizer(device);
1077 if (context->commit & NINE_STATE_COMMIT_CONST_VS)
1078 commit_vs_constants(device);
1079 if (context->commit & NINE_STATE_COMMIT_CONST_PS)
1080 commit_ps_constants(device);
1081 if (context->commit & NINE_STATE_COMMIT_VS)
1082 commit_vs(device);
1083 if (context->commit & NINE_STATE_COMMIT_PS)
1084 commit_ps(device);
1085
1086 context->commit = 0;
1087
1088 if (unlikely(state->changed.ucp)) {
1089 pipe->set_clip_state(pipe, &state->clip);
1090 state->changed.ucp = 0;
1091 }
1092
1093 if (unlikely(group & NINE_STATE_RARE)) {
1094 if (group & NINE_STATE_SCISSOR)
1095 commit_scissor(device);
1096 if (group & NINE_STATE_BLEND_COLOR) {
1097 struct pipe_blend_color color;
1098 d3dcolor_to_rgba(&color.color[0], state->rs[D3DRS_BLENDFACTOR]);
1099 pipe->set_blend_color(pipe, &color);
1100 }
1101 if (group & NINE_STATE_SAMPLE_MASK) {
1102 if (state->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) {
1103 pipe->set_sample_mask(pipe, ~0);
1104 } else {
1105 pipe->set_sample_mask(pipe, state->rs[D3DRS_MULTISAMPLEMASK]);
1106 }
1107 }
1108 if (group & NINE_STATE_STENCIL_REF) {
1109 struct pipe_stencil_ref ref;
1110 ref.ref_value[0] = state->rs[D3DRS_STENCILREF];
1111 ref.ref_value[1] = ref.ref_value[0];
1112 pipe->set_stencil_ref(pipe, &ref);
1113 }
1114 }
1115
1116 device->state.changed.group &=
1117 (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST);
1118
1119 DBG("finished\n");
1120
1121 return TRUE;
1122 }
1123
1124 static void
1125 nine_update_state_framebuffer_clear(struct NineDevice9 *device)
1126 {
1127 struct nine_state *state = &device->state;
1128
1129 validate_textures(device);
1130
1131 if (state->changed.group & NINE_STATE_FB)
1132 update_framebuffer(device, TRUE);
1133 }
1134
1135 /* Checks were already done before the call */
1136 void
1137 nine_context_clear_fb(struct NineDevice9 *device,
1138 DWORD Count,
1139 const D3DRECT *pRects,
1140 DWORD Flags,
1141 D3DCOLOR Color,
1142 float Z,
1143 DWORD Stencil)
1144 {
1145 const int sRGB = device->state.rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
1146 struct pipe_surface *cbuf, *zsbuf;
1147 struct pipe_context *pipe = device->pipe;
1148 struct NineSurface9 *zsbuf_surf = device->state.ds;
1149 struct NineSurface9 *rt;
1150 unsigned bufs = 0;
1151 unsigned r, i;
1152 union pipe_color_union rgba;
1153 unsigned rt_mask = 0;
1154 D3DRECT rect;
1155
1156 nine_update_state_framebuffer_clear(device);
1157
1158 if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR;
1159 /* Ignore Z buffer if not bound */
1160 if (device->context.pipe.fb.zsbuf != NULL) {
1161 if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH;
1162 if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL;
1163 }
1164 if (!bufs)
1165 return;
1166 d3dcolor_to_pipe_color_union(&rgba, Color);
1167
1168 rect.x1 = device->state.viewport.X;
1169 rect.y1 = device->state.viewport.Y;
1170 rect.x2 = device->state.viewport.Width + rect.x1;
1171 rect.y2 = device->state.viewport.Height + rect.y1;
1172
1173 /* Both rectangles apply, which is weird, but that's D3D9. */
1174 if (device->state.rs[D3DRS_SCISSORTESTENABLE]) {
1175 rect.x1 = MAX2(rect.x1, device->state.scissor.minx);
1176 rect.y1 = MAX2(rect.y1, device->state.scissor.miny);
1177 rect.x2 = MIN2(rect.x2, device->state.scissor.maxx);
1178 rect.y2 = MIN2(rect.y2, device->state.scissor.maxy);
1179 }
1180
1181 if (Count) {
1182 /* Maybe apps like to specify a large rect ? */
1183 if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 &&
1184 pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) {
1185 DBG("First rect covers viewport.\n");
1186 Count = 0;
1187 pRects = NULL;
1188 }
1189 }
1190
1191 if (rect.x1 >= device->context.pipe.fb.width || rect.y1 >= device->context.pipe.fb.height)
1192 return;
1193
1194 for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
1195 if (device->state.rt[i] && device->state.rt[i]->desc.Format != D3DFMT_NULL)
1196 rt_mask |= 1 << i;
1197 }
1198
1199 /* fast path, clears everything at once */
1200 if (!Count &&
1201 (!(bufs & PIPE_CLEAR_COLOR) || (rt_mask == device->context.rt_mask)) &&
1202 rect.x1 == 0 && rect.y1 == 0 &&
1203 /* Case we clear only render target. Check clear region vs rt. */
1204 ((!(bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
1205 rect.x2 >= device->context.pipe.fb.width &&
1206 rect.y2 >= device->context.pipe.fb.height) ||
1207 /* Case we clear depth buffer (and eventually rt too).
1208 * depth buffer size is always >= rt size. Compare to clear region */
1209 ((bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
1210 rect.x2 >= zsbuf_surf->desc.Width &&
1211 rect.y2 >= zsbuf_surf->desc.Height))) {
1212 DBG("Clear fast path\n");
1213 pipe->clear(pipe, bufs, &rgba, Z, Stencil);
1214 return;
1215 }
1216
1217 if (!Count) {
1218 Count = 1;
1219 pRects = &rect;
1220 }
1221
1222 for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
1223 rt = device->state.rt[i];
1224 if (!rt || rt->desc.Format == D3DFMT_NULL ||
1225 !(bufs & PIPE_CLEAR_COLOR))
1226 continue; /* save space, compiler should hoist this */
1227 cbuf = NineSurface9_GetSurface(rt, sRGB);
1228 for (r = 0; r < Count; ++r) {
1229 /* Don't trust users to pass these in the right order. */
1230 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
1231 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
1232 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
1233 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
1234 #ifndef NINE_LAX
1235 /* Drop negative rectangles (like wine expects). */
1236 if (pRects[r].x1 > pRects[r].x2) continue;
1237 if (pRects[r].y1 > pRects[r].y2) continue;
1238 #endif
1239
1240 x1 = MAX2(x1, rect.x1);
1241 y1 = MAX2(y1, rect.y1);
1242 x2 = MIN3(x2, rect.x2, rt->desc.Width);
1243 y2 = MIN3(y2, rect.y2, rt->desc.Height);
1244
1245 DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2);
1246 pipe->clear_render_target(pipe, cbuf, &rgba,
1247 x1, y1, x2 - x1, y2 - y1, false);
1248 }
1249 }
1250 if (!(bufs & PIPE_CLEAR_DEPTHSTENCIL))
1251 return;
1252
1253 bufs &= PIPE_CLEAR_DEPTHSTENCIL;
1254
1255 for (r = 0; r < Count; ++r) {
1256 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2);
1257 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2);
1258 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2);
1259 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2);
1260 #ifndef NINE_LAX
1261 /* Drop negative rectangles. */
1262 if (pRects[r].x1 > pRects[r].x2) continue;
1263 if (pRects[r].y1 > pRects[r].y2) continue;
1264 #endif
1265
1266 x1 = MIN2(x1, rect.x1);
1267 y1 = MIN2(y1, rect.y1);
1268 x2 = MIN3(x2, rect.x2, zsbuf_surf->desc.Width);
1269 y2 = MIN3(y2, rect.y2, zsbuf_surf->desc.Height);
1270
1271 zsbuf = NineSurface9_GetSurface(zsbuf_surf, 0);
1272 assert(zsbuf);
1273 pipe->clear_depth_stencil(pipe, zsbuf, bufs, Z, Stencil,
1274 x1, y1, x2 - x1, y2 - y1, false);
1275 }
1276 return;
1277 }
1278
1279 /* State defaults */
1280
1281 static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] =
1282 {
1283 /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */
1284 [D3DRS_ZENABLE] = D3DZB_FALSE,
1285 [D3DRS_FILLMODE] = D3DFILL_SOLID,
1286 [D3DRS_SHADEMODE] = D3DSHADE_GOURAUD,
1287 /* [D3DRS_LINEPATTERN] = 0x00000000, */
1288 [D3DRS_ZWRITEENABLE] = TRUE,
1289 [D3DRS_ALPHATESTENABLE] = FALSE,
1290 [D3DRS_LASTPIXEL] = TRUE,
1291 [D3DRS_SRCBLEND] = D3DBLEND_ONE,
1292 [D3DRS_DESTBLEND] = D3DBLEND_ZERO,
1293 [D3DRS_CULLMODE] = D3DCULL_CCW,
1294 [D3DRS_ZFUNC] = D3DCMP_LESSEQUAL,
1295 [D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS,
1296 [D3DRS_ALPHAREF] = 0,
1297 [D3DRS_DITHERENABLE] = FALSE,
1298 [D3DRS_ALPHABLENDENABLE] = FALSE,
1299 [D3DRS_FOGENABLE] = FALSE,
1300 [D3DRS_SPECULARENABLE] = FALSE,
1301 /* [D3DRS_ZVISIBLE] = 0, */
1302 [D3DRS_FOGCOLOR] = 0,
1303 [D3DRS_FOGTABLEMODE] = D3DFOG_NONE,
1304 [D3DRS_FOGSTART] = 0x00000000,
1305 [D3DRS_FOGEND] = 0x3F800000,
1306 [D3DRS_FOGDENSITY] = 0x3F800000,
1307 /* [D3DRS_EDGEANTIALIAS] = FALSE, */
1308 [D3DRS_RANGEFOGENABLE] = FALSE,
1309 [D3DRS_STENCILENABLE] = FALSE,
1310 [D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP,
1311 [D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP,
1312 [D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP,
1313 [D3DRS_STENCILREF] = 0,
1314 [D3DRS_STENCILMASK] = 0xFFFFFFFF,
1315 [D3DRS_STENCILFUNC] = D3DCMP_ALWAYS,
1316 [D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF,
1317 [D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF,
1318 [D3DRS_WRAP0] = 0,
1319 [D3DRS_WRAP1] = 0,
1320 [D3DRS_WRAP2] = 0,
1321 [D3DRS_WRAP3] = 0,
1322 [D3DRS_WRAP4] = 0,
1323 [D3DRS_WRAP5] = 0,
1324 [D3DRS_WRAP6] = 0,
1325 [D3DRS_WRAP7] = 0,
1326 [D3DRS_CLIPPING] = TRUE,
1327 [D3DRS_LIGHTING] = TRUE,
1328 [D3DRS_AMBIENT] = 0,
1329 [D3DRS_FOGVERTEXMODE] = D3DFOG_NONE,
1330 [D3DRS_COLORVERTEX] = TRUE,
1331 [D3DRS_LOCALVIEWER] = TRUE,
1332 [D3DRS_NORMALIZENORMALS] = FALSE,
1333 [D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1,
1334 [D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2,
1335 [D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL,
1336 [D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL,
1337 [D3DRS_VERTEXBLEND] = D3DVBF_DISABLE,
1338 [D3DRS_CLIPPLANEENABLE] = 0,
1339 /* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */
1340 [D3DRS_POINTSIZE] = 0x3F800000,
1341 [D3DRS_POINTSIZE_MIN] = 0x3F800000,
1342 [D3DRS_POINTSPRITEENABLE] = FALSE,
1343 [D3DRS_POINTSCALEENABLE] = FALSE,
1344 [D3DRS_POINTSCALE_A] = 0x3F800000,
1345 [D3DRS_POINTSCALE_B] = 0x00000000,
1346 [D3DRS_POINTSCALE_C] = 0x00000000,
1347 [D3DRS_MULTISAMPLEANTIALIAS] = TRUE,
1348 [D3DRS_MULTISAMPLEMASK] = 0xFFFFFFFF,
1349 [D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE,
1350 /* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */
1351 [D3DRS_DEBUGMONITORTOKEN] = 0xDEADCAFE,
1352 [D3DRS_POINTSIZE_MAX] = 0x3F800000, /* depends on cap */
1353 [D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE,
1354 [D3DRS_COLORWRITEENABLE] = 0x0000000f,
1355 [D3DRS_TWEENFACTOR] = 0x00000000,
1356 [D3DRS_BLENDOP] = D3DBLENDOP_ADD,
1357 [D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC,
1358 [D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR,
1359 [D3DRS_SCISSORTESTENABLE] = FALSE,
1360 [D3DRS_SLOPESCALEDEPTHBIAS] = 0,
1361 [D3DRS_MINTESSELLATIONLEVEL] = 0x3F800000,
1362 [D3DRS_MAXTESSELLATIONLEVEL] = 0x3F800000,
1363 [D3DRS_ANTIALIASEDLINEENABLE] = FALSE,
1364 [D3DRS_ADAPTIVETESS_X] = 0x00000000,
1365 [D3DRS_ADAPTIVETESS_Y] = 0x00000000,
1366 [D3DRS_ADAPTIVETESS_Z] = 0x3F800000,
1367 [D3DRS_ADAPTIVETESS_W] = 0x00000000,
1368 [D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE,
1369 [D3DRS_TWOSIDEDSTENCILMODE] = FALSE,
1370 [D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP,
1371 [D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP,
1372 [D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP,
1373 [D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS,
1374 [D3DRS_COLORWRITEENABLE1] = 0x0000000F,
1375 [D3DRS_COLORWRITEENABLE2] = 0x0000000F,
1376 [D3DRS_COLORWRITEENABLE3] = 0x0000000F,
1377 [D3DRS_BLENDFACTOR] = 0xFFFFFFFF,
1378 [D3DRS_SRGBWRITEENABLE] = 0,
1379 [D3DRS_DEPTHBIAS] = 0,
1380 [D3DRS_WRAP8] = 0,
1381 [D3DRS_WRAP9] = 0,
1382 [D3DRS_WRAP10] = 0,
1383 [D3DRS_WRAP11] = 0,
1384 [D3DRS_WRAP12] = 0,
1385 [D3DRS_WRAP13] = 0,
1386 [D3DRS_WRAP14] = 0,
1387 [D3DRS_WRAP15] = 0,
1388 [D3DRS_SEPARATEALPHABLENDENABLE] = FALSE,
1389 [D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE,
1390 [D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO,
1391 [D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD,
1392 [NINED3DRS_VSPOINTSIZE] = FALSE,
1393 [NINED3DRS_RTMASK] = 0xf,
1394 [NINED3DRS_ALPHACOVERAGE] = FALSE,
1395 [NINED3DRS_MULTISAMPLE] = FALSE
1396 };
1397 static const DWORD nine_tex_stage_state_defaults[NINED3DTSS_LAST + 1] =
1398 {
1399 [D3DTSS_COLOROP] = D3DTOP_DISABLE,
1400 [D3DTSS_ALPHAOP] = D3DTOP_DISABLE,
1401 [D3DTSS_COLORARG1] = D3DTA_TEXTURE,
1402 [D3DTSS_COLORARG2] = D3DTA_CURRENT,
1403 [D3DTSS_COLORARG0] = D3DTA_CURRENT,
1404 [D3DTSS_ALPHAARG1] = D3DTA_TEXTURE,
1405 [D3DTSS_ALPHAARG2] = D3DTA_CURRENT,
1406 [D3DTSS_ALPHAARG0] = D3DTA_CURRENT,
1407 [D3DTSS_RESULTARG] = D3DTA_CURRENT,
1408 [D3DTSS_BUMPENVMAT00] = 0,
1409 [D3DTSS_BUMPENVMAT01] = 0,
1410 [D3DTSS_BUMPENVMAT10] = 0,
1411 [D3DTSS_BUMPENVMAT11] = 0,
1412 [D3DTSS_BUMPENVLSCALE] = 0,
1413 [D3DTSS_BUMPENVLOFFSET] = 0,
1414 [D3DTSS_TEXCOORDINDEX] = 0,
1415 [D3DTSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE,
1416 };
1417 static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] =
1418 {
1419 [D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP,
1420 [D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP,
1421 [D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP,
1422 [D3DSAMP_BORDERCOLOR] = 0,
1423 [D3DSAMP_MAGFILTER] = D3DTEXF_POINT,
1424 [D3DSAMP_MINFILTER] = D3DTEXF_POINT,
1425 [D3DSAMP_MIPFILTER] = D3DTEXF_NONE,
1426 [D3DSAMP_MIPMAPLODBIAS] = 0,
1427 [D3DSAMP_MAXMIPLEVEL] = 0,
1428 [D3DSAMP_MAXANISOTROPY] = 1,
1429 [D3DSAMP_SRGBTEXTURE] = 0,
1430 [D3DSAMP_ELEMENTINDEX] = 0,
1431 [D3DSAMP_DMAPOFFSET] = 0,
1432 [NINED3DSAMP_MINLOD] = 0,
1433 [NINED3DSAMP_SHADOW] = 0,
1434 [NINED3DSAMP_CUBETEX] = 0
1435 };
1436
1437 void nine_state_restore_non_cso(struct NineDevice9 *device)
1438 {
1439 struct nine_state *state = &device->state;
1440 struct nine_context *context = &device->context;
1441
1442 state->changed.group = NINE_STATE_ALL;
1443 state->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1;
1444 state->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
1445 state->changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
1446 context->commit |= NINE_STATE_COMMIT_CONST_VS | NINE_STATE_COMMIT_CONST_PS;
1447 }
1448
1449 void
1450 nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
1451 boolean is_reset)
1452 {
1453 struct nine_state *state = &device->state;
1454 struct nine_context *context = &device->context;
1455 unsigned s;
1456
1457 /* Initialize defaults.
1458 */
1459 memcpy(state->rs, nine_render_state_defaults, sizeof(state->rs));
1460
1461 for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) {
1462 memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults,
1463 sizeof(state->ff.tex_stage[s]));
1464 state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] = s;
1465 }
1466 state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE;
1467 state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
1468 memset(&context->bumpmap_vars, 0, sizeof(context->bumpmap_vars));
1469
1470 for (s = 0; s < ARRAY_SIZE(state->samp); ++s) {
1471 memcpy(&state->samp[s], nine_samp_state_defaults,
1472 sizeof(state->samp[s]));
1473 memcpy(&state->samp_advertised[s], nine_samp_state_defaults,
1474 sizeof(state->samp_advertised[s]));
1475 }
1476
1477 if (state->vs_const_f)
1478 memset(state->vs_const_f, 0, device->vs_const_size);
1479 if (state->ps_const_f)
1480 memset(state->ps_const_f, 0, device->ps_const_size);
1481
1482 /* Cap dependent initial state:
1483 */
1484 state->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize);
1485
1486 memcpy(state->rs_advertised, state->rs, sizeof(state->rs));
1487
1488 /* Set changed flags to initialize driver.
1489 */
1490 state->changed.group = NINE_STATE_ALL;
1491 state->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1;
1492 state->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
1493 state->changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
1494
1495 state->ff.changed.transform[0] = ~0;
1496 state->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32);
1497
1498 if (!is_reset) {
1499 state->viewport.MinZ = 0.0f;
1500 state->viewport.MaxZ = 1.0f;
1501 }
1502
1503 for (s = 0; s < ARRAY_SIZE(state->changed.sampler); ++s)
1504 state->changed.sampler[s] = ~0;
1505
1506 if (!is_reset) {
1507 context->dummy_vbo_bound_at = -1;
1508 context->vbo_bound_done = FALSE;
1509 }
1510 }
1511
1512 void
1513 nine_state_clear(struct nine_state *state, const boolean device)
1514 {
1515 unsigned i;
1516
1517 for (i = 0; i < ARRAY_SIZE(state->rt); ++i)
1518 nine_bind(&state->rt[i], NULL);
1519 nine_bind(&state->ds, NULL);
1520 nine_bind(&state->vs, NULL);
1521 nine_bind(&state->ps, NULL);
1522 nine_bind(&state->vdecl, NULL);
1523 for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) {
1524 nine_bind(&state->stream[i], NULL);
1525 pipe_resource_reference(&state->vtxbuf[i].buffer, NULL);
1526 }
1527 nine_bind(&state->idxbuf, NULL);
1528 for (i = 0; i < NINE_MAX_SAMPLERS; ++i) {
1529 if (device &&
1530 state->texture[i] &&
1531 --state->texture[i]->bind_count == 0)
1532 list_delinit(&state->texture[i]->list);
1533 nine_bind(&state->texture[i], NULL);
1534 }
1535 }
1536
1537 void
1538 nine_state_init_sw(struct NineDevice9 *device)
1539 {
1540 struct pipe_context *pipe_sw = device->pipe_sw;
1541 struct pipe_rasterizer_state rast;
1542 struct pipe_blend_state blend;
1543 struct pipe_depth_stencil_alpha_state dsa;
1544 struct pipe_framebuffer_state fb;
1545
1546 /* Only used with Streamout */
1547 memset(&rast, 0, sizeof(rast));
1548 rast.rasterizer_discard = true;
1549 rast.point_quad_rasterization = 1; /* to make llvmpipe happy */
1550 cso_set_rasterizer(device->cso_sw, &rast);
1551
1552 /* dummy settings */
1553 memset(&blend, 0, sizeof(blend));
1554 memset(&dsa, 0, sizeof(dsa));
1555 memset(&fb, 0, sizeof(fb));
1556 cso_set_blend(device->cso_sw, &blend);
1557 cso_set_depth_stencil_alpha(device->cso_sw, &dsa);
1558 cso_set_framebuffer(device->cso_sw, &fb);
1559 cso_set_viewport_dims(device->cso_sw, 1.0, 1.0, false);
1560 cso_set_fragment_shader_handle(device->cso_sw, util_make_empty_fragment_shader(pipe_sw));
1561 }
1562
1563 /* There is duplication with update_vertex_elements.
1564 * TODO: Share the code */
1565
1566 static void
1567 update_vertex_elements_sw(struct NineDevice9 *device)
1568 {
1569 struct nine_state *state = &device->state;
1570 const struct NineVertexDeclaration9 *vdecl = device->state.vdecl;
1571 const struct NineVertexShader9 *vs;
1572 unsigned n, b, i;
1573 int index;
1574 char vdecl_index_map[16]; /* vs->num_inputs <= 16 */
1575 char used_streams[device->caps.MaxStreams];
1576 int dummy_vbo_stream = -1;
1577 BOOL need_dummy_vbo = FALSE;
1578 struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
1579
1580 memset(vdecl_index_map, -1, 16);
1581 memset(used_streams, 0, device->caps.MaxStreams);
1582 vs = state->programmable_vs ? device->state.vs : device->ff.vs;
1583
1584 if (vdecl) {
1585 for (n = 0; n < vs->num_inputs; ++n) {
1586 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
1587 n, vs->input_map[n].ndecl, vdecl);
1588
1589 for (i = 0; i < vdecl->nelems; i++) {
1590 if (vdecl->usage_map[i] == vs->input_map[n].ndecl) {
1591 vdecl_index_map[n] = i;
1592 used_streams[vdecl->elems[i].vertex_buffer_index] = 1;
1593 break;
1594 }
1595 }
1596 if (vdecl_index_map[n] < 0)
1597 need_dummy_vbo = TRUE;
1598 }
1599 } else {
1600 /* No vertex declaration. Likely will never happen in practice,
1601 * but we need not crash on this */
1602 need_dummy_vbo = TRUE;
1603 }
1604
1605 if (need_dummy_vbo) {
1606 for (i = 0; i < device->caps.MaxStreams; i++ ) {
1607 if (!used_streams[i]) {
1608 dummy_vbo_stream = i;
1609 break;
1610 }
1611 }
1612 }
1613 /* TODO handle dummy_vbo */
1614 assert (!need_dummy_vbo);
1615
1616 for (n = 0; n < vs->num_inputs; ++n) {
1617 index = vdecl_index_map[n];
1618 if (index >= 0) {
1619 ve[n] = vdecl->elems[index];
1620 b = ve[n].vertex_buffer_index;
1621 /* XXX wine just uses 1 here: */
1622 if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA)
1623 ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF;
1624 } else {
1625 /* if the vertex declaration is incomplete compared to what the
1626 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
1627 * This is not precised by the spec, but is the behaviour
1628 * tested on win */
1629 ve[n].vertex_buffer_index = dummy_vbo_stream;
1630 ve[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1631 ve[n].src_offset = 0;
1632 ve[n].instance_divisor = 0;
1633 }
1634 }
1635
1636 cso_set_vertex_elements(device->cso_sw, vs->num_inputs, ve);
1637 }
1638
1639 static void
1640 update_vertex_buffers_sw(struct NineDevice9 *device, int start_vertice, int num_vertices)
1641 {
1642 struct pipe_context *pipe = device->pipe;
1643 struct pipe_context *pipe_sw = device->pipe_sw;
1644 struct nine_state *state = &device->state;
1645 struct nine_state_sw_internal *sw_internal = &device->state_sw_internal;
1646 struct pipe_vertex_buffer vtxbuf;
1647 uint32_t mask = 0xf;
1648 unsigned i;
1649
1650 DBG("mask=%x\n", mask);
1651
1652 /* TODO: handle dummy_vbo_bound_at */
1653
1654 for (i = 0; mask; mask >>= 1, ++i) {
1655 if (mask & 1) {
1656 if (state->vtxbuf[i].buffer) {
1657 struct pipe_resource *buf;
1658 struct pipe_box box;
1659
1660 vtxbuf = state->vtxbuf[i];
1661
1662 DBG("Locking %p (offset %d, length %d)\n", vtxbuf.buffer,
1663 vtxbuf.buffer_offset, num_vertices * vtxbuf.stride);
1664
1665 u_box_1d(vtxbuf.buffer_offset + start_vertice * vtxbuf.stride,
1666 num_vertices * vtxbuf.stride, &box);
1667 buf = vtxbuf.buffer;
1668 vtxbuf.user_buffer = pipe->transfer_map(pipe, buf, 0, PIPE_TRANSFER_READ, &box,
1669 &(sw_internal->transfers_so[i]));
1670 vtxbuf.buffer = NULL;
1671 if (!device->driver_caps.user_sw_vbufs) {
1672 u_upload_data(device->vertex_sw_uploader,
1673 0,
1674 box.width,
1675 16,
1676 vtxbuf.user_buffer,
1677 &(vtxbuf.buffer_offset),
1678 &(vtxbuf.buffer));
1679 u_upload_unmap(device->vertex_sw_uploader);
1680 vtxbuf.user_buffer = NULL;
1681 }
1682 pipe_sw->set_vertex_buffers(pipe_sw, i, 1, &vtxbuf);
1683 if (vtxbuf.buffer)
1684 pipe_resource_reference(&vtxbuf.buffer, NULL);
1685 } else
1686 pipe_sw->set_vertex_buffers(pipe_sw, i, 1, NULL);
1687 }
1688 }
1689 }
1690
1691 static void
1692 update_vs_constants_sw(struct NineDevice9 *device)
1693 {
1694 struct nine_state *state = &device->state;
1695 struct pipe_context *pipe_sw = device->pipe_sw;
1696
1697 DBG("updating\n");
1698
1699 {
1700 struct pipe_constant_buffer cb;
1701 const void *buf;
1702
1703 cb.buffer = NULL;
1704 cb.buffer_offset = 0;
1705 cb.buffer_size = 4096 * sizeof(float[4]);
1706 cb.user_buffer = state->vs_const_f_swvp;
1707
1708 if (state->vs->lconstf.ranges) {
1709 const struct nine_lconstf *lconstf = &device->state.vs->lconstf;
1710 const struct nine_range *r = lconstf->ranges;
1711 unsigned n = 0;
1712 float *dst = device->state.vs_lconstf_temp;
1713 float *src = (float *)cb.user_buffer;
1714 memcpy(dst, src, 8192 * sizeof(float[4]));
1715 while (r) {
1716 unsigned p = r->bgn;
1717 unsigned c = r->end - r->bgn;
1718 memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float));
1719 n += c;
1720 r = r->next;
1721 }
1722 cb.user_buffer = dst;
1723 }
1724
1725 buf = cb.user_buffer;
1726 if (!device->driver_caps.user_sw_cbufs) {
1727 u_upload_data(device->constbuf_sw_uploader,
1728 0,
1729 cb.buffer_size,
1730 16,
1731 cb.user_buffer,
1732 &(cb.buffer_offset),
1733 &(cb.buffer));
1734 u_upload_unmap(device->constbuf_sw_uploader);
1735 cb.user_buffer = NULL;
1736 }
1737
1738 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 0, &cb);
1739 if (cb.buffer)
1740 pipe_resource_reference(&cb.buffer, NULL);
1741
1742 cb.user_buffer = (char *)buf + 4096 * sizeof(float[4]);
1743 if (!device->driver_caps.user_sw_cbufs) {
1744 u_upload_data(device->constbuf_sw_uploader,
1745 0,
1746 cb.buffer_size,
1747 16,
1748 cb.user_buffer,
1749 &(cb.buffer_offset),
1750 &(cb.buffer));
1751 u_upload_unmap(device->constbuf_sw_uploader);
1752 cb.user_buffer = NULL;
1753 }
1754
1755 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 1, &cb);
1756 if (cb.buffer)
1757 pipe_resource_reference(&cb.buffer, NULL);
1758 }
1759
1760 {
1761 struct pipe_constant_buffer cb;
1762
1763 cb.buffer = NULL;
1764 cb.buffer_offset = 0;
1765 cb.buffer_size = 2048 * sizeof(float[4]);
1766 cb.user_buffer = state->vs_const_i;
1767
1768 if (!device->driver_caps.user_sw_cbufs) {
1769 u_upload_data(device->constbuf_sw_uploader,
1770 0,
1771 cb.buffer_size,
1772 16,
1773 cb.user_buffer,
1774 &(cb.buffer_offset),
1775 &(cb.buffer));
1776 u_upload_unmap(device->constbuf_sw_uploader);
1777 cb.user_buffer = NULL;
1778 }
1779
1780 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 2, &cb);
1781 if (cb.buffer)
1782 pipe_resource_reference(&cb.buffer, NULL);
1783 }
1784
1785 {
1786 struct pipe_constant_buffer cb;
1787
1788 cb.buffer = NULL;
1789 cb.buffer_offset = 0;
1790 cb.buffer_size = 512 * sizeof(float[4]);
1791 cb.user_buffer = state->vs_const_b;
1792
1793 if (!device->driver_caps.user_sw_cbufs) {
1794 u_upload_data(device->constbuf_sw_uploader,
1795 0,
1796 cb.buffer_size,
1797 16,
1798 cb.user_buffer,
1799 &(cb.buffer_offset),
1800 &(cb.buffer));
1801 u_upload_unmap(device->constbuf_sw_uploader);
1802 cb.user_buffer = NULL;
1803 }
1804
1805 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 3, &cb);
1806 if (cb.buffer)
1807 pipe_resource_reference(&cb.buffer, NULL);
1808 }
1809
1810 {
1811 struct pipe_constant_buffer cb;
1812 const D3DVIEWPORT9 *vport = &device->state.viewport;
1813 float viewport_data[8] = {(float)vport->Width * 0.5f,
1814 (float)vport->Height * -0.5f, vport->MaxZ - vport->MinZ, 0.f,
1815 (float)vport->Width * 0.5f + (float)vport->X,
1816 (float)vport->Height * 0.5f + (float)vport->Y,
1817 vport->MinZ, 0.f};
1818
1819 cb.buffer = NULL;
1820 cb.buffer_offset = 0;
1821 cb.buffer_size = 2 * sizeof(float[4]);
1822 cb.user_buffer = viewport_data;
1823
1824 {
1825 u_upload_data(device->constbuf_sw_uploader,
1826 0,
1827 cb.buffer_size,
1828 16,
1829 cb.user_buffer,
1830 &(cb.buffer_offset),
1831 &(cb.buffer));
1832 u_upload_unmap(device->constbuf_sw_uploader);
1833 cb.user_buffer = NULL;
1834 }
1835
1836 pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 4, &cb);
1837 if (cb.buffer)
1838 pipe_resource_reference(&cb.buffer, NULL);
1839 }
1840
1841 }
1842
1843 void
1844 nine_state_prepare_draw_sw(struct NineDevice9 *device, struct NineVertexDeclaration9 *vdecl_out,
1845 int start_vertice, int num_vertices, struct pipe_stream_output_info *so)
1846 {
1847 struct nine_state *state = &device->state;
1848
1849 struct NineVertexShader9 *vs = state->programmable_vs ? device->state.vs : device->ff.vs;
1850
1851 assert(state->programmable_vs);
1852
1853 DBG("Preparing draw\n");
1854 cso_set_vertex_shader_handle(device->cso_sw,
1855 NineVertexShader9_GetVariantProcessVertices(vs, vdecl_out, so));
1856 update_vertex_elements_sw(device);
1857 update_vertex_buffers_sw(device, start_vertice, num_vertices);
1858 update_vs_constants_sw(device);
1859 DBG("Preparation succeeded\n");
1860 }
1861
1862 void
1863 nine_state_after_draw_sw(struct NineDevice9 *device)
1864 {
1865 struct nine_state_sw_internal *sw_internal = &device->state_sw_internal;
1866 struct pipe_context *pipe = device->pipe;
1867 struct pipe_context *pipe_sw = device->pipe_sw;
1868 int i;
1869
1870 for (i = 0; i < 4; i++) {
1871 pipe_sw->set_vertex_buffers(pipe_sw, i, 1, NULL);
1872 if (sw_internal->transfers_so[i])
1873 pipe->transfer_unmap(pipe, sw_internal->transfers_so[i]);
1874 sw_internal->transfers_so[i] = NULL;
1875 }
1876 }
1877
1878 void
1879 nine_state_destroy_sw(struct NineDevice9 *device)
1880 {
1881 (void) device;
1882 /* Everything destroyed with cso */
1883 }
1884
1885 /*
1886 static const DWORD nine_render_states_pixel[] =
1887 {
1888 D3DRS_ALPHABLENDENABLE,
1889 D3DRS_ALPHAFUNC,
1890 D3DRS_ALPHAREF,
1891 D3DRS_ALPHATESTENABLE,
1892 D3DRS_ANTIALIASEDLINEENABLE,
1893 D3DRS_BLENDFACTOR,
1894 D3DRS_BLENDOP,
1895 D3DRS_BLENDOPALPHA,
1896 D3DRS_CCW_STENCILFAIL,
1897 D3DRS_CCW_STENCILPASS,
1898 D3DRS_CCW_STENCILZFAIL,
1899 D3DRS_COLORWRITEENABLE,
1900 D3DRS_COLORWRITEENABLE1,
1901 D3DRS_COLORWRITEENABLE2,
1902 D3DRS_COLORWRITEENABLE3,
1903 D3DRS_DEPTHBIAS,
1904 D3DRS_DESTBLEND,
1905 D3DRS_DESTBLENDALPHA,
1906 D3DRS_DITHERENABLE,
1907 D3DRS_FILLMODE,
1908 D3DRS_FOGDENSITY,
1909 D3DRS_FOGEND,
1910 D3DRS_FOGSTART,
1911 D3DRS_LASTPIXEL,
1912 D3DRS_SCISSORTESTENABLE,
1913 D3DRS_SEPARATEALPHABLENDENABLE,
1914 D3DRS_SHADEMODE,
1915 D3DRS_SLOPESCALEDEPTHBIAS,
1916 D3DRS_SRCBLEND,
1917 D3DRS_SRCBLENDALPHA,
1918 D3DRS_SRGBWRITEENABLE,
1919 D3DRS_STENCILENABLE,
1920 D3DRS_STENCILFAIL,
1921 D3DRS_STENCILFUNC,
1922 D3DRS_STENCILMASK,
1923 D3DRS_STENCILPASS,
1924 D3DRS_STENCILREF,
1925 D3DRS_STENCILWRITEMASK,
1926 D3DRS_STENCILZFAIL,
1927 D3DRS_TEXTUREFACTOR,
1928 D3DRS_TWOSIDEDSTENCILMODE,
1929 D3DRS_WRAP0,
1930 D3DRS_WRAP1,
1931 D3DRS_WRAP10,
1932 D3DRS_WRAP11,
1933 D3DRS_WRAP12,
1934 D3DRS_WRAP13,
1935 D3DRS_WRAP14,
1936 D3DRS_WRAP15,
1937 D3DRS_WRAP2,
1938 D3DRS_WRAP3,
1939 D3DRS_WRAP4,
1940 D3DRS_WRAP5,
1941 D3DRS_WRAP6,
1942 D3DRS_WRAP7,
1943 D3DRS_WRAP8,
1944 D3DRS_WRAP9,
1945 D3DRS_ZENABLE,
1946 D3DRS_ZFUNC,
1947 D3DRS_ZWRITEENABLE
1948 };
1949 */
1950 const uint32_t nine_render_states_pixel[(NINED3DRS_LAST + 31) / 32] =
1951 {
1952 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000,
1953 0x000000ff, 0xde01c900, 0x0003ffcf
1954 };
1955
1956 /*
1957 static const DWORD nine_render_states_vertex[] =
1958 {
1959 D3DRS_ADAPTIVETESS_W,
1960 D3DRS_ADAPTIVETESS_X,
1961 D3DRS_ADAPTIVETESS_Y,
1962 D3DRS_ADAPTIVETESS_Z,
1963 D3DRS_AMBIENT,
1964 D3DRS_AMBIENTMATERIALSOURCE,
1965 D3DRS_CLIPPING,
1966 D3DRS_CLIPPLANEENABLE,
1967 D3DRS_COLORVERTEX,
1968 D3DRS_CULLMODE,
1969 D3DRS_DIFFUSEMATERIALSOURCE,
1970 D3DRS_EMISSIVEMATERIALSOURCE,
1971 D3DRS_ENABLEADAPTIVETESSELLATION,
1972 D3DRS_FOGCOLOR,
1973 D3DRS_FOGDENSITY,
1974 D3DRS_FOGENABLE,
1975 D3DRS_FOGEND,
1976 D3DRS_FOGSTART,
1977 D3DRS_FOGTABLEMODE,
1978 D3DRS_FOGVERTEXMODE,
1979 D3DRS_INDEXEDVERTEXBLENDENABLE,
1980 D3DRS_LIGHTING,
1981 D3DRS_LOCALVIEWER,
1982 D3DRS_MAXTESSELLATIONLEVEL,
1983 D3DRS_MINTESSELLATIONLEVEL,
1984 D3DRS_MULTISAMPLEANTIALIAS,
1985 D3DRS_MULTISAMPLEMASK,
1986 D3DRS_NORMALDEGREE,
1987 D3DRS_NORMALIZENORMALS,
1988 D3DRS_PATCHEDGESTYLE,
1989 D3DRS_POINTSCALE_A,
1990 D3DRS_POINTSCALE_B,
1991 D3DRS_POINTSCALE_C,
1992 D3DRS_POINTSCALEENABLE,
1993 D3DRS_POINTSIZE,
1994 D3DRS_POINTSIZE_MAX,
1995 D3DRS_POINTSIZE_MIN,
1996 D3DRS_POINTSPRITEENABLE,
1997 D3DRS_POSITIONDEGREE,
1998 D3DRS_RANGEFOGENABLE,
1999 D3DRS_SHADEMODE,
2000 D3DRS_SPECULARENABLE,
2001 D3DRS_SPECULARMATERIALSOURCE,
2002 D3DRS_TWEENFACTOR,
2003 D3DRS_VERTEXBLEND
2004 };
2005 */
2006 const uint32_t nine_render_states_vertex[(NINED3DRS_LAST + 31) / 32] =
2007 {
2008 0x30400200, 0x0001007c, 0x00000000, 0x00000000,
2009 0xfd9efb00, 0x01fc34cf, 0x00000000
2010 };
2011
2012 /* TODO: put in the right values */
2013 const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
2014 {
2015 [D3DRS_ZENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE,
2016 [D3DRS_FILLMODE] = NINE_STATE_RASTERIZER,
2017 [D3DRS_SHADEMODE] = NINE_STATE_RASTERIZER,
2018 [D3DRS_ZWRITEENABLE] = NINE_STATE_DSA,
2019 [D3DRS_ALPHATESTENABLE] = NINE_STATE_DSA,
2020 [D3DRS_LASTPIXEL] = NINE_STATE_RASTERIZER,
2021 [D3DRS_SRCBLEND] = NINE_STATE_BLEND,
2022 [D3DRS_DESTBLEND] = NINE_STATE_BLEND,
2023 [D3DRS_CULLMODE] = NINE_STATE_RASTERIZER,
2024 [D3DRS_ZFUNC] = NINE_STATE_DSA,
2025 [D3DRS_ALPHAREF] = NINE_STATE_DSA,
2026 [D3DRS_ALPHAFUNC] = NINE_STATE_DSA,
2027 [D3DRS_DITHERENABLE] = NINE_STATE_BLEND,
2028 [D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND,
2029 [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER | NINE_STATE_FOG_SHADER | NINE_STATE_PS_CONST,
2030 [D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING,
2031 [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
2032 [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER | NINE_STATE_FOG_SHADER | NINE_STATE_PS_CONST,
2033 [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
2034 [D3DRS_FOGEND] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
2035 [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
2036 [D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_OTHER,
2037 [D3DRS_STENCILENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE,
2038 [D3DRS_STENCILFAIL] = NINE_STATE_DSA,
2039 [D3DRS_STENCILZFAIL] = NINE_STATE_DSA,
2040 [D3DRS_STENCILPASS] = NINE_STATE_DSA,
2041 [D3DRS_STENCILFUNC] = NINE_STATE_DSA,
2042 [D3DRS_STENCILREF] = NINE_STATE_STENCIL_REF,
2043 [D3DRS_STENCILMASK] = NINE_STATE_DSA,
2044 [D3DRS_STENCILWRITEMASK] = NINE_STATE_DSA,
2045 [D3DRS_TEXTUREFACTOR] = NINE_STATE_FF_PSSTAGES,
2046 [D3DRS_WRAP0] = NINE_STATE_UNHANDLED, /* cylindrical wrap is crazy */
2047 [D3DRS_WRAP1] = NINE_STATE_UNHANDLED,
2048 [D3DRS_WRAP2] = NINE_STATE_UNHANDLED,
2049 [D3DRS_WRAP3] = NINE_STATE_UNHANDLED,
2050 [D3DRS_WRAP4] = NINE_STATE_UNHANDLED,
2051 [D3DRS_WRAP5] = NINE_STATE_UNHANDLED,
2052 [D3DRS_WRAP6] = NINE_STATE_UNHANDLED,
2053 [D3DRS_WRAP7] = NINE_STATE_UNHANDLED,
2054 [D3DRS_CLIPPING] = 0, /* software vertex processing only */
2055 [D3DRS_LIGHTING] = NINE_STATE_FF_LIGHTING,
2056 [D3DRS_AMBIENT] = NINE_STATE_FF_LIGHTING | NINE_STATE_FF_MATERIAL,
2057 [D3DRS_FOGVERTEXMODE] = NINE_STATE_FF_OTHER,
2058 [D3DRS_COLORVERTEX] = NINE_STATE_FF_LIGHTING,
2059 [D3DRS_LOCALVIEWER] = NINE_STATE_FF_LIGHTING,
2060 [D3DRS_NORMALIZENORMALS] = NINE_STATE_FF_OTHER,
2061 [D3DRS_DIFFUSEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
2062 [D3DRS_SPECULARMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
2063 [D3DRS_AMBIENTMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
2064 [D3DRS_EMISSIVEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING,
2065 [D3DRS_VERTEXBLEND] = NINE_STATE_FF_OTHER,
2066 [D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER,
2067 [D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER,
2068 [D3DRS_POINTSIZE_MIN] = NINE_STATE_RASTERIZER | NINE_STATE_POINTSIZE_SHADER,
2069 [D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER,
2070 [D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_OTHER,
2071 [D3DRS_POINTSCALE_A] = NINE_STATE_FF_OTHER,
2072 [D3DRS_POINTSCALE_B] = NINE_STATE_FF_OTHER,
2073 [D3DRS_POINTSCALE_C] = NINE_STATE_FF_OTHER,
2074 [D3DRS_MULTISAMPLEANTIALIAS] = NINE_STATE_MULTISAMPLE,
2075 [D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK,
2076 [D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED,
2077 [D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED,
2078 [D3DRS_POINTSIZE_MAX] = NINE_STATE_RASTERIZER | NINE_STATE_POINTSIZE_SHADER,
2079 [D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_OTHER,
2080 [D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND,
2081 [D3DRS_TWEENFACTOR] = NINE_STATE_FF_OTHER,
2082 [D3DRS_BLENDOP] = NINE_STATE_BLEND,
2083 [D3DRS_POSITIONDEGREE] = NINE_STATE_UNHANDLED,
2084 [D3DRS_NORMALDEGREE] = NINE_STATE_UNHANDLED,
2085 [D3DRS_SCISSORTESTENABLE] = NINE_STATE_RASTERIZER,
2086 [D3DRS_SLOPESCALEDEPTHBIAS] = NINE_STATE_RASTERIZER,
2087 [D3DRS_ANTIALIASEDLINEENABLE] = NINE_STATE_RASTERIZER,
2088 [D3DRS_MINTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED,
2089 [D3DRS_MAXTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED,
2090 [D3DRS_ADAPTIVETESS_X] = NINE_STATE_UNHANDLED,
2091 [D3DRS_ADAPTIVETESS_Y] = NINE_STATE_UNHANDLED,
2092 [D3DRS_ADAPTIVETESS_Z] = NINE_STATE_UNHANDLED,
2093 [D3DRS_ADAPTIVETESS_W] = NINE_STATE_UNHANDLED,
2094 [D3DRS_ENABLEADAPTIVETESSELLATION] = NINE_STATE_UNHANDLED,
2095 [D3DRS_TWOSIDEDSTENCILMODE] = NINE_STATE_DSA,
2096 [D3DRS_CCW_STENCILFAIL] = NINE_STATE_DSA,
2097 [D3DRS_CCW_STENCILZFAIL] = NINE_STATE_DSA,
2098 [D3DRS_CCW_STENCILPASS] = NINE_STATE_DSA,
2099 [D3DRS_CCW_STENCILFUNC] = NINE_STATE_DSA,
2100 [D3DRS_COLORWRITEENABLE1] = NINE_STATE_BLEND,
2101 [D3DRS_COLORWRITEENABLE2] = NINE_STATE_BLEND,
2102 [D3DRS_COLORWRITEENABLE3] = NINE_STATE_BLEND,
2103 [D3DRS_BLENDFACTOR] = NINE_STATE_BLEND_COLOR,
2104 [D3DRS_SRGBWRITEENABLE] = NINE_STATE_FB,
2105 [D3DRS_DEPTHBIAS] = NINE_STATE_RASTERIZER,
2106 [D3DRS_WRAP8] = NINE_STATE_UNHANDLED, /* cylwrap has to be done via GP */
2107 [D3DRS_WRAP9] = NINE_STATE_UNHANDLED,
2108 [D3DRS_WRAP10] = NINE_STATE_UNHANDLED,
2109 [D3DRS_WRAP11] = NINE_STATE_UNHANDLED,
2110 [D3DRS_WRAP12] = NINE_STATE_UNHANDLED,
2111 [D3DRS_WRAP13] = NINE_STATE_UNHANDLED,
2112 [D3DRS_WRAP14] = NINE_STATE_UNHANDLED,
2113 [D3DRS_WRAP15] = NINE_STATE_UNHANDLED,
2114 [D3DRS_SEPARATEALPHABLENDENABLE] = NINE_STATE_BLEND,
2115 [D3DRS_SRCBLENDALPHA] = NINE_STATE_BLEND,
2116 [D3DRS_DESTBLENDALPHA] = NINE_STATE_BLEND,
2117 [D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND
2118 };
2119
2120 /* Misc */
2121
2122 D3DMATRIX *
2123 nine_state_access_transform(struct nine_state *state, D3DTRANSFORMSTATETYPE t,
2124 boolean alloc)
2125 {
2126 static D3DMATRIX Identity = { .m[0] = { 1, 0, 0, 0 },
2127 .m[1] = { 0, 1, 0, 0 },
2128 .m[2] = { 0, 0, 1, 0 },
2129 .m[3] = { 0, 0, 0, 1 } };
2130 unsigned index;
2131
2132 switch (t) {
2133 case D3DTS_VIEW: index = 0; break;
2134 case D3DTS_PROJECTION: index = 1; break;
2135 case D3DTS_TEXTURE0: index = 2; break;
2136 case D3DTS_TEXTURE1: index = 3; break;
2137 case D3DTS_TEXTURE2: index = 4; break;
2138 case D3DTS_TEXTURE3: index = 5; break;
2139 case D3DTS_TEXTURE4: index = 6; break;
2140 case D3DTS_TEXTURE5: index = 7; break;
2141 case D3DTS_TEXTURE6: index = 8; break;
2142 case D3DTS_TEXTURE7: index = 9; break;
2143 default:
2144 if (!(t >= D3DTS_WORLDMATRIX(0) && t <= D3DTS_WORLDMATRIX(255)))
2145 return NULL;
2146 index = 10 + (t - D3DTS_WORLDMATRIX(0));
2147 break;
2148 }
2149
2150 if (index >= state->ff.num_transforms) {
2151 unsigned N = index + 1;
2152 unsigned n = state->ff.num_transforms;
2153
2154 if (!alloc)
2155 return &Identity;
2156 state->ff.transform = REALLOC(state->ff.transform,
2157 n * sizeof(D3DMATRIX),
2158 N * sizeof(D3DMATRIX));
2159 for (; n < N; ++n)
2160 state->ff.transform[n] = Identity;
2161 state->ff.num_transforms = N;
2162 }
2163 return &state->ff.transform[index];
2164 }
2165
2166 #define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n
2167 const char *nine_d3drs_to_string(DWORD State)
2168 {
2169 switch (State) {
2170 D3DRS_TO_STRING_CASE(ZENABLE);
2171 D3DRS_TO_STRING_CASE(FILLMODE);
2172 D3DRS_TO_STRING_CASE(SHADEMODE);
2173 D3DRS_TO_STRING_CASE(ZWRITEENABLE);
2174 D3DRS_TO_STRING_CASE(ALPHATESTENABLE);
2175 D3DRS_TO_STRING_CASE(LASTPIXEL);
2176 D3DRS_TO_STRING_CASE(SRCBLEND);
2177 D3DRS_TO_STRING_CASE(DESTBLEND);
2178 D3DRS_TO_STRING_CASE(CULLMODE);
2179 D3DRS_TO_STRING_CASE(ZFUNC);
2180 D3DRS_TO_STRING_CASE(ALPHAREF);
2181 D3DRS_TO_STRING_CASE(ALPHAFUNC);
2182 D3DRS_TO_STRING_CASE(DITHERENABLE);
2183 D3DRS_TO_STRING_CASE(ALPHABLENDENABLE);
2184 D3DRS_TO_STRING_CASE(FOGENABLE);
2185 D3DRS_TO_STRING_CASE(SPECULARENABLE);
2186 D3DRS_TO_STRING_CASE(FOGCOLOR);
2187 D3DRS_TO_STRING_CASE(FOGTABLEMODE);
2188 D3DRS_TO_STRING_CASE(FOGSTART);
2189 D3DRS_TO_STRING_CASE(FOGEND);
2190 D3DRS_TO_STRING_CASE(FOGDENSITY);
2191 D3DRS_TO_STRING_CASE(RANGEFOGENABLE);
2192 D3DRS_TO_STRING_CASE(STENCILENABLE);
2193 D3DRS_TO_STRING_CASE(STENCILFAIL);
2194 D3DRS_TO_STRING_CASE(STENCILZFAIL);
2195 D3DRS_TO_STRING_CASE(STENCILPASS);
2196 D3DRS_TO_STRING_CASE(STENCILFUNC);
2197 D3DRS_TO_STRING_CASE(STENCILREF);
2198 D3DRS_TO_STRING_CASE(STENCILMASK);
2199 D3DRS_TO_STRING_CASE(STENCILWRITEMASK);
2200 D3DRS_TO_STRING_CASE(TEXTUREFACTOR);
2201 D3DRS_TO_STRING_CASE(WRAP0);
2202 D3DRS_TO_STRING_CASE(WRAP1);
2203 D3DRS_TO_STRING_CASE(WRAP2);
2204 D3DRS_TO_STRING_CASE(WRAP3);
2205 D3DRS_TO_STRING_CASE(WRAP4);
2206 D3DRS_TO_STRING_CASE(WRAP5);
2207 D3DRS_TO_STRING_CASE(WRAP6);
2208 D3DRS_TO_STRING_CASE(WRAP7);
2209 D3DRS_TO_STRING_CASE(CLIPPING);
2210 D3DRS_TO_STRING_CASE(LIGHTING);
2211 D3DRS_TO_STRING_CASE(AMBIENT);
2212 D3DRS_TO_STRING_CASE(FOGVERTEXMODE);
2213 D3DRS_TO_STRING_CASE(COLORVERTEX);
2214 D3DRS_TO_STRING_CASE(LOCALVIEWER);
2215 D3DRS_TO_STRING_CASE(NORMALIZENORMALS);
2216 D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE);
2217 D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE);
2218 D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE);
2219 D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE);
2220 D3DRS_TO_STRING_CASE(VERTEXBLEND);
2221 D3DRS_TO_STRING_CASE(CLIPPLANEENABLE);
2222 D3DRS_TO_STRING_CASE(POINTSIZE);
2223 D3DRS_TO_STRING_CASE(POINTSIZE_MIN);
2224 D3DRS_TO_STRING_CASE(POINTSPRITEENABLE);
2225 D3DRS_TO_STRING_CASE(POINTSCALEENABLE);
2226 D3DRS_TO_STRING_CASE(POINTSCALE_A);
2227 D3DRS_TO_STRING_CASE(POINTSCALE_B);
2228 D3DRS_TO_STRING_CASE(POINTSCALE_C);
2229 D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS);
2230 D3DRS_TO_STRING_CASE(MULTISAMPLEMASK);
2231 D3DRS_TO_STRING_CASE(PATCHEDGESTYLE);
2232 D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN);
2233 D3DRS_TO_STRING_CASE(POINTSIZE_MAX);
2234 D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE);
2235 D3DRS_TO_STRING_CASE(COLORWRITEENABLE);
2236 D3DRS_TO_STRING_CASE(TWEENFACTOR);
2237 D3DRS_TO_STRING_CASE(BLENDOP);
2238 D3DRS_TO_STRING_CASE(POSITIONDEGREE);
2239 D3DRS_TO_STRING_CASE(NORMALDEGREE);
2240 D3DRS_TO_STRING_CASE(SCISSORTESTENABLE);
2241 D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS);
2242 D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE);
2243 D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL);
2244 D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL);
2245 D3DRS_TO_STRING_CASE(ADAPTIVETESS_X);
2246 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y);
2247 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z);
2248 D3DRS_TO_STRING_CASE(ADAPTIVETESS_W);
2249 D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION);
2250 D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE);
2251 D3DRS_TO_STRING_CASE(CCW_STENCILFAIL);
2252 D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL);
2253 D3DRS_TO_STRING_CASE(CCW_STENCILPASS);
2254 D3DRS_TO_STRING_CASE(CCW_STENCILFUNC);
2255 D3DRS_TO_STRING_CASE(COLORWRITEENABLE1);
2256 D3DRS_TO_STRING_CASE(COLORWRITEENABLE2);
2257 D3DRS_TO_STRING_CASE(COLORWRITEENABLE3);
2258 D3DRS_TO_STRING_CASE(BLENDFACTOR);
2259 D3DRS_TO_STRING_CASE(SRGBWRITEENABLE);
2260 D3DRS_TO_STRING_CASE(DEPTHBIAS);
2261 D3DRS_TO_STRING_CASE(WRAP8);
2262 D3DRS_TO_STRING_CASE(WRAP9);
2263 D3DRS_TO_STRING_CASE(WRAP10);
2264 D3DRS_TO_STRING_CASE(WRAP11);
2265 D3DRS_TO_STRING_CASE(WRAP12);
2266 D3DRS_TO_STRING_CASE(WRAP13);
2267 D3DRS_TO_STRING_CASE(WRAP14);
2268 D3DRS_TO_STRING_CASE(WRAP15);
2269 D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE);
2270 D3DRS_TO_STRING_CASE(SRCBLENDALPHA);
2271 D3DRS_TO_STRING_CASE(DESTBLENDALPHA);
2272 D3DRS_TO_STRING_CASE(BLENDOPALPHA);
2273 default:
2274 return "(invalid)";
2275 }
2276 }