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