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