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