2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3 * Copyright 2013 Christoph Bumiller
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:
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
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. */
27 #include "swapchain9.h"
28 #include "basetexture9.h"
30 #include "indexbuffer9.h"
32 #include "vertexbuffer9.h"
33 #include "vertexdeclaration9.h"
34 #include "vertexshader9.h"
35 #include "pixelshader9.h"
36 #include "nine_pipe.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"
50 #include "nine_queue.h"
51 #include "nine_csmt_helper.h"
52 #include "os/os_thread.h"
54 #define DBG_CHANNEL DBG_DEVICE
58 struct csmt_instruction
{
59 int (* func
)(struct NineDevice9
*This
, struct csmt_instruction
*instr
);
64 struct nine_queue_pool
* pool
;
66 cnd_t event_processed
;
67 mtx_t mutex_processed
;
68 struct NineDevice9
*device
;
76 /* Wait for instruction to be processed.
77 * Caller has to ensure that only one thread waits at time.
80 nine_csmt_wait_processed(struct csmt_context
*ctx
)
82 mtx_lock(&ctx
->mutex_processed
);
83 while (!p_atomic_read(&ctx
->processed
)) {
84 cnd_wait(&ctx
->event_processed
, &ctx
->mutex_processed
);
86 mtx_unlock(&ctx
->mutex_processed
);
89 /* CSMT worker thread */
92 nine_csmt_worker(void *arg
)
94 struct csmt_context
*ctx
= arg
;
95 struct csmt_instruction
*instr
;
96 DBG("CSMT worker spawned\n");
98 u_thread_setname("CSMT-Worker");
101 nine_queue_wait_flush(ctx
->pool
);
102 mtx_lock(&ctx
->thread_running
);
104 /* Get instruction. NULL on empty cmdbuf. */
105 while (!p_atomic_read(&ctx
->terminate
) &&
106 (instr
= (struct csmt_instruction
*)nine_queue_get(ctx
->pool
))) {
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
);
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
);
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
);
134 DBG("CSMT worker destroyed\n");
138 /* Create a CSMT context.
139 * Spawns a worker thread.
141 struct csmt_context
*
142 nine_csmt_create( struct NineDevice9
*This
)
144 struct csmt_context
*ctx
;
146 ctx
= CALLOC_STRUCT(csmt_context
);
150 ctx
->pool
= nine_queue_create();
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
);
160 #if defined(DEBUG) || !defined(NDEBUG)
161 u_thread_setname("Main thread");
166 ctx
->worker
= u_thread_create(nine_csmt_worker
, ctx
);
168 nine_queue_delete(ctx
->pool
);
173 DBG("Returning context %p\n", ctx
);
179 nop_func( struct NineDevice9
*This
, struct csmt_instruction
*instr
)
187 /* Push nop instruction and flush the queue.
188 * Waits for the worker to complete. */
190 nine_csmt_process( struct NineDevice9
*device
)
192 struct csmt_instruction
* instr
;
193 struct csmt_context
*ctx
= device
->csmt_ctx
;
195 if (!device
->csmt_active
)
198 if (nine_queue_isempty(ctx
->pool
))
201 DBG("device=%p\n", device
);
204 instr
= nine_queue_alloc(ctx
->pool
, sizeof(struct csmt_instruction
));
206 instr
->func
= nop_func
;
208 p_atomic_set(&ctx
->processed
, FALSE
);
209 nine_queue_flush(ctx
->pool
);
211 nine_csmt_wait_processed(ctx
);
214 /* Destroys a CSMT context.
215 * Waits for the worker thread to terminate.
218 nine_csmt_destroy( struct NineDevice9
*device
, struct csmt_context
*ctx
)
220 struct csmt_instruction
* instr
;
221 thrd_t render_thread
= ctx
->worker
;
223 DBG("device=%p ctx=%p\n", device
, ctx
);
225 /* Push nop and flush the queue. */
226 instr
= nine_queue_alloc(ctx
->pool
, sizeof(struct csmt_instruction
));
228 instr
->func
= nop_func
;
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
);
235 nine_csmt_wait_processed(ctx
);
236 nine_queue_delete(ctx
->pool
);
238 mtx_destroy(&ctx
->thread_resume
);
239 mtx_destroy(&ctx
->thread_running
);
241 mtx_destroy(&ctx
->mutex_processed
);
242 cnd_destroy(&ctx
->event_processed
);
246 thrd_join(render_thread
, NULL
);
250 nine_csmt_pause( struct NineDevice9
*device
)
252 struct csmt_context
*ctx
= device
->csmt_ctx
;
254 if (!device
->csmt_active
)
257 /* No need to pause the thread */
258 if (nine_queue_no_flushed_work(ctx
->pool
))
261 mtx_lock(&ctx
->thread_resume
);
262 p_atomic_set(&ctx
->toPause
, TRUE
);
264 /* Wait the thread is paused */
265 mtx_lock(&ctx
->thread_running
);
266 ctx
->hasPaused
= TRUE
;
267 p_atomic_set(&ctx
->toPause
, FALSE
);
271 nine_csmt_resume( struct NineDevice9
*device
)
273 struct csmt_context
*ctx
= device
->csmt_ctx
;
275 if (!device
->csmt_active
)
281 ctx
->hasPaused
= FALSE
;
282 mtx_unlock(&ctx
->thread_running
);
283 mtx_unlock(&ctx
->thread_resume
);
286 struct pipe_context
*
287 nine_context_get_pipe( struct NineDevice9
*device
)
289 nine_csmt_process(device
);
290 return device
->context
.pipe
;
293 struct pipe_context
*
294 nine_context_get_pipe_multithread( struct NineDevice9
*device
)
296 struct csmt_context
*ctx
= device
->csmt_ctx
;
298 if (!device
->csmt_active
)
299 return device
->context
.pipe
;
301 if (!u_thread_is_self(ctx
->worker
))
302 nine_csmt_process(device
);
304 return device
->context
.pipe
;
307 struct pipe_context
*
308 nine_context_get_pipe_acquire( struct NineDevice9
*device
)
310 nine_csmt_pause(device
);
311 return device
->context
.pipe
;
315 nine_context_get_pipe_release( struct NineDevice9
*device
)
317 nine_csmt_resume(device
);
320 /* Nine state functions */
322 /* Check if some states need to be set dirty */
325 check_multisample(struct NineDevice9
*device
)
327 DWORD
*rs
= device
->context
.rs
;
328 DWORD new_value
= (rs
[D3DRS_ZENABLE
] || rs
[D3DRS_STENCILENABLE
]) &&
329 device
->context
.rt
[0]->desc
.MultiSampleType
>= 1 &&
330 rs
[D3DRS_MULTISAMPLEANTIALIAS
];
331 if (rs
[NINED3DRS_MULTISAMPLE
] != new_value
) {
332 rs
[NINED3DRS_MULTISAMPLE
] = new_value
;
333 return NINE_STATE_RASTERIZER
;
338 /* State preparation only */
341 prepare_blend(struct NineDevice9
*device
)
343 nine_convert_blend_state(&device
->context
.pipe_data
.blend
, device
->context
.rs
);
344 device
->context
.commit
|= NINE_STATE_COMMIT_BLEND
;
348 prepare_dsa(struct NineDevice9
*device
)
350 nine_convert_dsa_state(&device
->context
.pipe_data
.dsa
, device
->context
.rs
);
351 device
->context
.commit
|= NINE_STATE_COMMIT_DSA
;
355 prepare_rasterizer(struct NineDevice9
*device
)
357 nine_convert_rasterizer_state(device
, &device
->context
.pipe_data
.rast
, device
->context
.rs
);
358 device
->context
.commit
|= NINE_STATE_COMMIT_RASTERIZER
;
362 prepare_vs_constants_userbuf_swvp(struct NineDevice9
*device
)
364 struct nine_context
*context
= &device
->context
;
366 if (context
->changed
.vs_const_f
|| context
->changed
.group
& NINE_STATE_SWVP
) {
367 struct pipe_constant_buffer cb
;
369 cb
.buffer_offset
= 0;
370 cb
.buffer_size
= 4096 * sizeof(float[4]);
371 cb
.user_buffer
= context
->vs_const_f_swvp
;
373 if (context
->vs
->lconstf
.ranges
) {
374 const struct nine_lconstf
*lconstf
= &(context
->vs
->lconstf
);
375 const struct nine_range
*r
= lconstf
->ranges
;
377 float *dst
= context
->vs_lconstf_temp
;
378 float *src
= (float *)cb
.user_buffer
;
379 memcpy(dst
, src
, cb
.buffer_size
);
382 unsigned c
= r
->end
- r
->bgn
;
383 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
387 cb
.user_buffer
= dst
;
390 context
->pipe_data
.cb0_swvp
.buffer_offset
= cb
.buffer_offset
;
391 context
->pipe_data
.cb0_swvp
.buffer_size
= cb
.buffer_size
;
392 context
->pipe_data
.cb0_swvp
.user_buffer
= cb
.user_buffer
;
394 cb
.user_buffer
= (char *)cb
.user_buffer
+ 4096 * sizeof(float[4]);
395 context
->pipe_data
.cb1_swvp
.buffer_offset
= cb
.buffer_offset
;
396 context
->pipe_data
.cb1_swvp
.buffer_size
= cb
.buffer_size
;
397 context
->pipe_data
.cb1_swvp
.user_buffer
= cb
.user_buffer
;
399 context
->changed
.vs_const_f
= 0;
402 if (context
->changed
.vs_const_i
|| context
->changed
.group
& NINE_STATE_SWVP
) {
403 struct pipe_constant_buffer cb
;
405 cb
.buffer_offset
= 0;
406 cb
.buffer_size
= 2048 * sizeof(float[4]);
407 cb
.user_buffer
= context
->vs_const_i
;
409 context
->pipe_data
.cb2_swvp
.buffer_offset
= cb
.buffer_offset
;
410 context
->pipe_data
.cb2_swvp
.buffer_size
= cb
.buffer_size
;
411 context
->pipe_data
.cb2_swvp
.user_buffer
= cb
.user_buffer
;
412 context
->changed
.vs_const_i
= 0;
415 if (context
->changed
.vs_const_b
|| context
->changed
.group
& NINE_STATE_SWVP
) {
416 struct pipe_constant_buffer cb
;
418 cb
.buffer_offset
= 0;
419 cb
.buffer_size
= 512 * sizeof(float[4]);
420 cb
.user_buffer
= context
->vs_const_b
;
422 context
->pipe_data
.cb3_swvp
.buffer_offset
= cb
.buffer_offset
;
423 context
->pipe_data
.cb3_swvp
.buffer_size
= cb
.buffer_size
;
424 context
->pipe_data
.cb3_swvp
.user_buffer
= cb
.user_buffer
;
425 context
->changed
.vs_const_b
= 0;
428 context
->changed
.group
&= ~NINE_STATE_VS_CONST
;
429 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
433 prepare_vs_constants_userbuf(struct NineDevice9
*device
)
435 struct nine_context
*context
= &device
->context
;
436 uint8_t *upload_ptr
= NULL
;
437 struct pipe_constant_buffer cb
;
439 cb
.buffer_offset
= 0;
440 cb
.buffer_size
= context
->cso_shader
.vs_const_used_size
;
441 cb
.user_buffer
= context
->vs_const_f
;
444 prepare_vs_constants_userbuf_swvp(device
);
448 if (context
->changed
.vs_const_i
|| context
->changed
.group
& NINE_STATE_SWVP
) {
449 int *idst
= (int *)&context
->vs_const_f
[4 * device
->max_vs_const_f
];
450 memcpy(idst
, context
->vs_const_i
, NINE_MAX_CONST_I
* sizeof(int[4]));
451 context
->changed
.vs_const_i
= 0;
454 if (context
->changed
.vs_const_b
|| context
->changed
.group
& NINE_STATE_SWVP
) {
455 int *idst
= (int *)&context
->vs_const_f
[4 * device
->max_vs_const_f
];
456 uint32_t *bdst
= (uint32_t *)&idst
[4 * NINE_MAX_CONST_I
];
457 memcpy(bdst
, context
->vs_const_b
, NINE_MAX_CONST_B
* sizeof(BOOL
));
458 context
->changed
.vs_const_b
= 0;
464 if (context
->vs
->lconstf
.ranges
) {
465 /* TODO: Can we make it so that we don't have to copy everything ? */
466 const struct nine_lconstf
*lconstf
= &(context
->vs
->lconstf
);
467 const struct nine_range
*r
= lconstf
->ranges
;
469 float *dst
= context
->vs_lconstf_temp
;
470 float *src
= (float *)cb
.user_buffer
;
471 memcpy(dst
, src
, cb
.buffer_size
);
474 unsigned c
= r
->end
- r
->bgn
;
475 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
479 cb
.user_buffer
= dst
;
482 /* Note: We probably don't want to do separate memcpy to
483 * upload_ptr directly, if we have to copy some constants
484 * at random locations (context->vs->lconstf.ranges),
485 * to have efficient WC. Thus for this case we really want
486 * that intermediate buffer. */
488 u_upload_alloc(context
->pipe
->const_uploader
,
491 256, /* Be conservative about alignment */
494 (void**)&upload_ptr
);
496 assert(cb
.buffer
&& upload_ptr
);
498 if (!context
->cso_shader
.vs_const_ranges
) {
499 memcpy(upload_ptr
, cb
.user_buffer
, cb
.buffer_size
);
503 while (context
->cso_shader
.vs_const_ranges
[i
*2+1] != 0) {
504 memcpy(upload_ptr
+offset
,
505 &((float*)cb
.user_buffer
)[4*context
->cso_shader
.vs_const_ranges
[i
*2]],
506 context
->cso_shader
.vs_const_ranges
[i
*2+1] * sizeof(float[4]));
507 offset
+= context
->cso_shader
.vs_const_ranges
[i
*2+1] * sizeof(float[4]);
512 u_upload_unmap(context
->pipe
->const_uploader
);
513 cb
.user_buffer
= NULL
;
515 /* Free previous resource */
516 pipe_resource_reference(&context
->pipe_data
.cb_vs
.buffer
, NULL
);
518 context
->pipe_data
.cb_vs
= cb
;
519 context
->changed
.vs_const_f
= 0;
521 context
->changed
.group
&= ~NINE_STATE_VS_CONST
;
522 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
526 prepare_ps_constants_userbuf(struct NineDevice9
*device
)
528 struct nine_context
*context
= &device
->context
;
529 uint8_t *upload_ptr
= NULL
;
530 struct pipe_constant_buffer cb
;
532 cb
.buffer_offset
= 0;
533 cb
.buffer_size
= context
->cso_shader
.ps_const_used_size
;
534 cb
.user_buffer
= context
->ps_const_f
;
536 if (context
->changed
.ps_const_i
) {
537 int *idst
= (int *)&context
->ps_const_f
[4 * device
->max_ps_const_f
];
538 memcpy(idst
, context
->ps_const_i
, sizeof(context
->ps_const_i
));
539 context
->changed
.ps_const_i
= 0;
541 if (context
->changed
.ps_const_b
) {
542 int *idst
= (int *)&context
->ps_const_f
[4 * device
->max_ps_const_f
];
543 uint32_t *bdst
= (uint32_t *)&idst
[4 * NINE_MAX_CONST_I
];
544 memcpy(bdst
, context
->ps_const_b
, sizeof(context
->ps_const_b
));
545 context
->changed
.ps_const_b
= 0;
548 /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */
549 if (context
->ps
->bumpenvmat_needed
) {
550 memcpy(context
->ps_lconstf_temp
, cb
.user_buffer
, 8 * sizeof(float[4]));
551 memcpy(&context
->ps_lconstf_temp
[4 * 8], &device
->context
.bumpmap_vars
, sizeof(device
->context
.bumpmap_vars
));
553 cb
.user_buffer
= context
->ps_lconstf_temp
;
556 if (context
->ps
->byte_code
.version
< 0x30 &&
557 context
->rs
[D3DRS_FOGENABLE
]) {
558 float *dst
= &context
->ps_lconstf_temp
[4 * 32];
559 if (cb
.user_buffer
!= context
->ps_lconstf_temp
) {
560 memcpy(context
->ps_lconstf_temp
, cb
.user_buffer
, 32 * sizeof(float[4]));
561 cb
.user_buffer
= context
->ps_lconstf_temp
;
564 d3dcolor_to_rgba(dst
, context
->rs
[D3DRS_FOGCOLOR
]);
565 if (context
->rs
[D3DRS_FOGTABLEMODE
] == D3DFOG_LINEAR
) {
566 dst
[4] = asfloat(context
->rs
[D3DRS_FOGEND
]);
567 dst
[5] = 1.0f
/ (asfloat(context
->rs
[D3DRS_FOGEND
]) - asfloat(context
->rs
[D3DRS_FOGSTART
]));
568 } else if (context
->rs
[D3DRS_FOGTABLEMODE
] != D3DFOG_NONE
) {
569 dst
[4] = asfloat(context
->rs
[D3DRS_FOGDENSITY
]);
576 u_upload_alloc(context
->pipe
->const_uploader
,
579 256, /* Be conservative about alignment */
582 (void**)&upload_ptr
);
584 assert(cb
.buffer
&& upload_ptr
);
586 if (!context
->cso_shader
.ps_const_ranges
) {
587 memcpy(upload_ptr
, cb
.user_buffer
, cb
.buffer_size
);
591 while (context
->cso_shader
.ps_const_ranges
[i
*2+1] != 0) {
592 memcpy(upload_ptr
+offset
,
593 &((float*)cb
.user_buffer
)[4*context
->cso_shader
.ps_const_ranges
[i
*2]],
594 context
->cso_shader
.ps_const_ranges
[i
*2+1] * sizeof(float[4]));
595 offset
+= context
->cso_shader
.ps_const_ranges
[i
*2+1] * sizeof(float[4]);
600 u_upload_unmap(context
->pipe
->const_uploader
);
601 cb
.user_buffer
= NULL
;
603 /* Free previous resource */
604 pipe_resource_reference(&context
->pipe_data
.cb_ps
.buffer
, NULL
);
606 context
->pipe_data
.cb_ps
= cb
;
607 context
->changed
.ps_const_f
= 0;
609 context
->changed
.group
&= ~NINE_STATE_PS_CONST
;
610 context
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
613 static inline uint32_t
614 prepare_vs(struct NineDevice9
*device
, uint8_t shader_changed
)
616 struct nine_context
*context
= &device
->context
;
617 struct NineVertexShader9
*vs
= context
->vs
;
618 uint32_t changed_group
= 0;
619 int has_key_changed
= 0;
621 if (likely(context
->programmable_vs
))
622 has_key_changed
= NineVertexShader9_UpdateKey(vs
, device
);
624 if (!shader_changed
&& !has_key_changed
)
627 /* likely because we dislike FF */
628 if (likely(context
->programmable_vs
)) {
629 context
->cso_shader
.vs
= NineVertexShader9_GetVariant(vs
,
630 &context
->cso_shader
.vs_const_ranges
,
631 &context
->cso_shader
.vs_const_used_size
);
634 context
->cso_shader
.vs
= vs
->ff_cso
;
637 if (context
->rs
[NINED3DRS_VSPOINTSIZE
] != vs
->point_size
) {
638 context
->rs
[NINED3DRS_VSPOINTSIZE
] = vs
->point_size
;
639 changed_group
|= NINE_STATE_RASTERIZER
;
642 if ((context
->bound_samplers_mask_vs
& vs
->sampler_mask
) != vs
->sampler_mask
)
643 /* Bound dummy sampler. */
644 changed_group
|= NINE_STATE_SAMPLER
;
646 context
->commit
|= NINE_STATE_COMMIT_VS
;
647 return changed_group
;
650 static inline uint32_t
651 prepare_ps(struct NineDevice9
*device
, uint8_t shader_changed
)
653 struct nine_context
*context
= &device
->context
;
654 struct NinePixelShader9
*ps
= context
->ps
;
655 uint32_t changed_group
= 0;
656 int has_key_changed
= 0;
659 has_key_changed
= NinePixelShader9_UpdateKey(ps
, context
);
661 if (!shader_changed
&& !has_key_changed
)
665 context
->cso_shader
.ps
= NinePixelShader9_GetVariant(ps
,
666 &context
->cso_shader
.ps_const_ranges
,
667 &context
->cso_shader
.ps_const_used_size
);
670 context
->cso_shader
.ps
= ps
->ff_cso
;
673 if ((context
->bound_samplers_mask_ps
& ps
->sampler_mask
) != ps
->sampler_mask
)
674 /* Bound dummy sampler. */
675 changed_group
|= NINE_STATE_SAMPLER
;
677 context
->commit
|= NINE_STATE_COMMIT_PS
;
678 return changed_group
;
681 /* State preparation incremental */
683 /* State preparation + State commit */
686 update_framebuffer(struct NineDevice9
*device
, bool is_clear
)
688 struct nine_context
*context
= &device
->context
;
689 struct pipe_context
*pipe
= context
->pipe
;
690 struct pipe_framebuffer_state
*fb
= &context
->pipe_data
.fb
;
692 struct NineSurface9
*rt0
= context
->rt
[0];
693 unsigned w
= rt0
->desc
.Width
;
694 unsigned h
= rt0
->desc
.Height
;
695 unsigned nr_samples
= rt0
->base
.info
.nr_samples
;
696 unsigned ps_mask
= context
->ps
? context
->ps
->rt_mask
: 1;
697 unsigned mask
= is_clear
? 0xf : ps_mask
;
698 const int sRGB
= context
->rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
702 context
->rt_mask
= 0x0;
705 /* all render targets must have the same size and the depth buffer must be
706 * bigger. Multisample has to match, according to spec. But some apps do
707 * things wrong there, and no error is returned. The behaviour they get
708 * apparently is that depth buffer is disabled if it doesn't match.
709 * Surely the same for render targets. */
711 /* Special case: D3DFMT_NULL is used to bound no real render target,
712 * but render to depth buffer. We have to not take into account the render
713 * target info. TODO: know what should happen when there are several render targers
714 * and the first one is D3DFMT_NULL */
715 if (rt0
->desc
.Format
== D3DFMT_NULL
&& context
->ds
) {
716 w
= context
->ds
->desc
.Width
;
717 h
= context
->ds
->desc
.Height
;
718 nr_samples
= context
->ds
->base
.info
.nr_samples
;
721 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
722 struct NineSurface9
*rt
= context
->rt
[i
];
724 if (rt
&& rt
->desc
.Format
!= D3DFMT_NULL
&& (mask
& (1 << i
)) &&
725 rt
->desc
.Width
== w
&& rt
->desc
.Height
== h
&&
726 rt
->base
.info
.nr_samples
== nr_samples
) {
727 fb
->cbufs
[i
] = NineSurface9_GetSurface(rt
, sRGB
);
728 context
->rt_mask
|= 1 << i
;
729 fb
->nr_cbufs
= i
+ 1;
731 /* Color outputs must match RT slot,
732 * drivers will have to handle NULL entries for GL, too.
738 if (context
->ds
&& context
->ds
->desc
.Width
>= w
&&
739 context
->ds
->desc
.Height
>= h
&&
740 context
->ds
->base
.info
.nr_samples
== nr_samples
) {
741 fb
->zsbuf
= NineSurface9_GetSurface(context
->ds
, 0);
749 pipe
->set_framebuffer_state(pipe
, fb
); /* XXX: cso ? */
751 if (is_clear
&& context
->rt_mask
== ps_mask
)
752 context
->changed
.group
&= ~NINE_STATE_FB
;
756 update_viewport(struct NineDevice9
*device
)
758 struct nine_context
*context
= &device
->context
;
759 const D3DVIEWPORT9
*vport
= &context
->viewport
;
760 struct pipe_viewport_state pvport
;
762 /* D3D coordinates are:
763 * -1 .. +1 for X,Y and
764 * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz)
766 pvport
.scale
[0] = (float)vport
->Width
* 0.5f
;
767 pvport
.scale
[1] = (float)vport
->Height
* -0.5f
;
768 pvport
.scale
[2] = vport
->MaxZ
- vport
->MinZ
;
769 pvport
.translate
[0] = (float)vport
->Width
* 0.5f
+ (float)vport
->X
;
770 pvport
.translate
[1] = (float)vport
->Height
* 0.5f
+ (float)vport
->Y
;
771 pvport
.translate
[2] = vport
->MinZ
;
773 /* We found R600 and SI cards have some imprecision
774 * on the barycentric coordinates used for interpolation.
775 * Some shaders rely on having something precise.
776 * We found that the proprietary driver has the imprecision issue,
777 * except when the render target width and height are powers of two.
778 * It is using some sort of workaround for these cases
779 * which covers likely all the cases the applications rely
780 * on something precise.
781 * We haven't found the workaround, but it seems like it's better
782 * for applications if the imprecision is biased towards infinity
783 * instead of -infinity (which is what measured). So shift slightly
784 * the viewport: not enough to change rasterization result (in particular
785 * for multisampling), but enough to make the imprecision biased
786 * towards infinity. We do this shift only if render target width and
787 * height are powers of two.
788 * Solves 'red shadows' bug on UE3 games.
790 if (device
->driver_bugs
.buggy_barycentrics
&&
791 ((vport
->Width
& (vport
->Width
-1)) == 0) &&
792 ((vport
->Height
& (vport
->Height
-1)) == 0)) {
793 pvport
.translate
[0] -= 1.0f
/ 128.0f
;
794 pvport
.translate
[1] -= 1.0f
/ 128.0f
;
797 cso_set_viewport(context
->cso
, &pvport
);
800 /* Loop through VS inputs and pick the vertex elements with the declared
801 * usage from the vertex declaration, then insert the instance divisor from
802 * the stream source frequency setting.
805 update_vertex_elements(struct NineDevice9
*device
)
807 struct nine_context
*context
= &device
->context
;
808 const struct NineVertexDeclaration9
*vdecl
= device
->context
.vdecl
;
809 const struct NineVertexShader9
*vs
;
812 char vdecl_index_map
[16]; /* vs->num_inputs <= 16 */
813 char used_streams
[device
->caps
.MaxStreams
];
814 int dummy_vbo_stream
= -1;
815 BOOL need_dummy_vbo
= FALSE
;
816 struct cso_velems_state ve
;
818 context
->stream_usage_mask
= 0;
819 memset(vdecl_index_map
, -1, 16);
820 memset(used_streams
, 0, device
->caps
.MaxStreams
);
821 vs
= context
->programmable_vs
? context
->vs
: device
->ff
.vs
;
824 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
825 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
826 n
, vs
->input_map
[n
].ndecl
, vdecl
);
828 for (i
= 0; i
< vdecl
->nelems
; i
++) {
829 if (vdecl
->usage_map
[i
] == vs
->input_map
[n
].ndecl
) {
830 vdecl_index_map
[n
] = i
;
831 used_streams
[vdecl
->elems
[i
].vertex_buffer_index
] = 1;
835 if (vdecl_index_map
[n
] < 0)
836 need_dummy_vbo
= TRUE
;
839 /* No vertex declaration. Likely will never happen in practice,
840 * but we need not crash on this */
841 need_dummy_vbo
= TRUE
;
844 if (need_dummy_vbo
) {
845 for (i
= 0; i
< device
->caps
.MaxStreams
; i
++ ) {
846 if (!used_streams
[i
]) {
847 dummy_vbo_stream
= i
;
852 /* there are less vertex shader inputs than stream slots,
853 * so if we need a slot for the dummy vbo, we should have found one */
854 assert (!need_dummy_vbo
|| dummy_vbo_stream
!= -1);
856 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
857 index
= vdecl_index_map
[n
];
859 ve
.velems
[n
] = vdecl
->elems
[index
];
860 b
= ve
.velems
[n
].vertex_buffer_index
;
861 context
->stream_usage_mask
|= 1 << b
;
862 /* XXX wine just uses 1 here: */
863 if (context
->stream_freq
[b
] & D3DSTREAMSOURCE_INSTANCEDATA
)
864 ve
.velems
[n
].instance_divisor
= context
->stream_freq
[b
] & 0x7FFFFF;
866 /* if the vertex declaration is incomplete compared to what the
867 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
868 * This is not precised by the spec, but is the behaviour
870 ve
.velems
[n
].vertex_buffer_index
= dummy_vbo_stream
;
871 ve
.velems
[n
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
872 ve
.velems
[n
].src_offset
= 0;
873 ve
.velems
[n
].instance_divisor
= 0;
877 if (context
->dummy_vbo_bound_at
!= dummy_vbo_stream
) {
878 if (context
->dummy_vbo_bound_at
>= 0)
879 context
->changed
.vtxbuf
|= 1 << context
->dummy_vbo_bound_at
;
880 if (dummy_vbo_stream
>= 0) {
881 context
->changed
.vtxbuf
|= 1 << dummy_vbo_stream
;
882 context
->vbo_bound_done
= FALSE
;
884 context
->dummy_vbo_bound_at
= dummy_vbo_stream
;
887 ve
.count
= vs
->num_inputs
;
888 cso_set_vertex_elements(context
->cso
, &ve
);
892 update_vertex_buffers(struct NineDevice9
*device
)
894 struct nine_context
*context
= &device
->context
;
895 struct pipe_context
*pipe
= context
->pipe
;
896 struct pipe_vertex_buffer dummy_vtxbuf
;
897 uint32_t mask
= context
->changed
.vtxbuf
;
900 DBG("mask=%x\n", mask
);
902 if (context
->dummy_vbo_bound_at
>= 0) {
903 if (!context
->vbo_bound_done
) {
904 dummy_vtxbuf
.buffer
.resource
= device
->dummy_vbo
;
905 dummy_vtxbuf
.stride
= 0;
906 dummy_vtxbuf
.is_user_buffer
= false;
907 dummy_vtxbuf
.buffer_offset
= 0;
908 pipe
->set_vertex_buffers(pipe
, context
->dummy_vbo_bound_at
,
910 context
->vbo_bound_done
= TRUE
;
912 mask
&= ~(1 << context
->dummy_vbo_bound_at
);
915 for (i
= 0; mask
; mask
>>= 1, ++i
) {
917 if (context
->vtxbuf
[i
].buffer
.resource
)
918 pipe
->set_vertex_buffers(pipe
, i
, 1, &context
->vtxbuf
[i
]);
920 pipe
->set_vertex_buffers(pipe
, i
, 1, NULL
);
924 context
->changed
.vtxbuf
= 0;
927 static inline boolean
928 update_sampler_derived(struct nine_context
*context
, unsigned s
)
930 boolean changed
= FALSE
;
932 if (context
->samp
[s
][NINED3DSAMP_SHADOW
] != context
->texture
[s
].shadow
) {
934 context
->samp
[s
][NINED3DSAMP_SHADOW
] = context
->texture
[s
].shadow
;
937 if (context
->samp
[s
][NINED3DSAMP_CUBETEX
] !=
938 (context
->texture
[s
].type
== D3DRTYPE_CUBETEXTURE
)) {
940 context
->samp
[s
][NINED3DSAMP_CUBETEX
] =
941 context
->texture
[s
].type
== D3DRTYPE_CUBETEXTURE
;
944 if (context
->samp
[s
][D3DSAMP_MIPFILTER
] != D3DTEXF_NONE
) {
945 int lod
= context
->samp
[s
][D3DSAMP_MAXMIPLEVEL
] - context
->texture
[s
].lod
;
948 if (context
->samp
[s
][NINED3DSAMP_MINLOD
] != lod
) {
950 context
->samp
[s
][NINED3DSAMP_MINLOD
] = lod
;
953 context
->changed
.sampler
[s
] &= ~0x300; /* lod changes irrelevant */
959 /* TODO: add sRGB override to pipe_sampler_state ? */
961 update_textures_and_samplers(struct NineDevice9
*device
)
963 struct nine_context
*context
= &device
->context
;
964 struct pipe_sampler_view
*view
[NINE_MAX_SAMPLERS
];
965 unsigned num_textures
;
967 boolean commit_samplers
;
968 uint16_t sampler_mask
= context
->ps
? context
->ps
->sampler_mask
:
969 device
->ff
.ps
->sampler_mask
;
971 /* TODO: Can we reduce iterations here ? */
973 commit_samplers
= FALSE
;
974 context
->bound_samplers_mask_ps
= 0;
975 for (num_textures
= 0, i
= 0; i
< NINE_MAX_SAMPLERS_PS
; ++i
) {
976 const unsigned s
= NINE_SAMPLER_PS(i
);
979 if (!context
->texture
[s
].enabled
&& !(sampler_mask
& (1 << i
))) {
984 if (context
->texture
[s
].enabled
) {
985 sRGB
= context
->samp
[s
][D3DSAMP_SRGBTEXTURE
] ? 1 : 0;
987 view
[i
] = context
->texture
[s
].view
[sRGB
];
988 num_textures
= i
+ 1;
990 if (update_sampler_derived(context
, s
) || (context
->changed
.sampler
[s
] & 0x05fe)) {
991 context
->changed
.sampler
[s
] = 0;
992 commit_samplers
= TRUE
;
993 nine_convert_sampler_state(context
->cso
, s
, context
->samp
[s
]);
996 /* Bind dummy sampler. We do not bind dummy sampler when
997 * it is not needed because it could add overhead. The
998 * dummy sampler should have r=g=b=0 and a=1. We do not
999 * unbind dummy sampler directly when they are not needed
1000 * anymore, but they're going to be removed as long as texture
1001 * or sampler states are changed. */
1002 view
[i
] = device
->dummy_sampler_view
;
1003 num_textures
= i
+ 1;
1005 cso_single_sampler(context
->cso
, PIPE_SHADER_FRAGMENT
,
1006 s
- NINE_SAMPLER_PS(0), &device
->dummy_sampler_state
);
1008 commit_samplers
= TRUE
;
1009 context
->changed
.sampler
[s
] = ~0;
1012 context
->bound_samplers_mask_ps
|= (1 << s
);
1015 cso_set_sampler_views(context
->cso
, PIPE_SHADER_FRAGMENT
, num_textures
, view
);
1017 if (commit_samplers
)
1018 cso_single_sampler_done(context
->cso
, PIPE_SHADER_FRAGMENT
);
1020 commit_samplers
= FALSE
;
1021 sampler_mask
= context
->programmable_vs
? context
->vs
->sampler_mask
: 0;
1022 context
->bound_samplers_mask_vs
= 0;
1023 for (num_textures
= 0, i
= 0; i
< NINE_MAX_SAMPLERS_VS
; ++i
) {
1024 const unsigned s
= NINE_SAMPLER_VS(i
);
1027 if (!context
->texture
[s
].enabled
&& !(sampler_mask
& (1 << i
))) {
1032 if (context
->texture
[s
].enabled
) {
1033 sRGB
= context
->samp
[s
][D3DSAMP_SRGBTEXTURE
] ? 1 : 0;
1035 view
[i
] = context
->texture
[s
].view
[sRGB
];
1036 num_textures
= i
+ 1;
1038 if (update_sampler_derived(context
, s
) || (context
->changed
.sampler
[s
] & 0x05fe)) {
1039 context
->changed
.sampler
[s
] = 0;
1040 commit_samplers
= TRUE
;
1041 nine_convert_sampler_state(context
->cso
, s
, context
->samp
[s
]);
1044 /* Bind dummy sampler. We do not bind dummy sampler when
1045 * it is not needed because it could add overhead. The
1046 * dummy sampler should have r=g=b=0 and a=1. We do not
1047 * unbind dummy sampler directly when they are not needed
1048 * anymore, but they're going to be removed as long as texture
1049 * or sampler states are changed. */
1050 view
[i
] = device
->dummy_sampler_view
;
1051 num_textures
= i
+ 1;
1053 cso_single_sampler(context
->cso
, PIPE_SHADER_VERTEX
,
1054 s
- NINE_SAMPLER_VS(0), &device
->dummy_sampler_state
);
1056 commit_samplers
= TRUE
;
1057 context
->changed
.sampler
[s
] = ~0;
1060 context
->bound_samplers_mask_vs
|= (1 << i
);
1063 cso_set_sampler_views(context
->cso
, PIPE_SHADER_VERTEX
, num_textures
, view
);
1065 if (commit_samplers
)
1066 cso_single_sampler_done(context
->cso
, PIPE_SHADER_VERTEX
);
1069 /* State commit only */
1072 commit_blend(struct NineDevice9
*device
)
1074 struct nine_context
*context
= &device
->context
;
1076 cso_set_blend(context
->cso
, &context
->pipe_data
.blend
);
1080 commit_dsa(struct NineDevice9
*device
)
1082 struct nine_context
*context
= &device
->context
;
1084 cso_set_depth_stencil_alpha(context
->cso
, &context
->pipe_data
.dsa
);
1088 commit_scissor(struct NineDevice9
*device
)
1090 struct nine_context
*context
= &device
->context
;
1091 struct pipe_context
*pipe
= context
->pipe
;
1093 pipe
->set_scissor_states(pipe
, 0, 1, &context
->scissor
);
1097 commit_rasterizer(struct NineDevice9
*device
)
1099 struct nine_context
*context
= &device
->context
;
1101 cso_set_rasterizer(context
->cso
, &context
->pipe_data
.rast
);
1105 commit_vs_constants(struct NineDevice9
*device
)
1107 struct nine_context
*context
= &device
->context
;
1108 struct pipe_context
*pipe
= context
->pipe
;
1110 if (unlikely(!context
->programmable_vs
))
1111 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &context
->pipe_data
.cb_vs_ff
);
1113 if (context
->swvp
) {
1114 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &context
->pipe_data
.cb0_swvp
);
1115 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 1, &context
->pipe_data
.cb1_swvp
);
1116 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 2, &context
->pipe_data
.cb2_swvp
);
1117 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 3, &context
->pipe_data
.cb3_swvp
);
1119 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &context
->pipe_data
.cb_vs
);
1125 commit_ps_constants(struct NineDevice9
*device
)
1127 struct nine_context
*context
= &device
->context
;
1128 struct pipe_context
*pipe
= context
->pipe
;
1130 if (unlikely(!context
->ps
))
1131 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &context
->pipe_data
.cb_ps_ff
);
1133 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &context
->pipe_data
.cb_ps
);
1137 commit_vs(struct NineDevice9
*device
)
1139 struct nine_context
*context
= &device
->context
;
1141 context
->pipe
->bind_vs_state(context
->pipe
, context
->cso_shader
.vs
);
1146 commit_ps(struct NineDevice9
*device
)
1148 struct nine_context
*context
= &device
->context
;
1150 context
->pipe
->bind_fs_state(context
->pipe
, context
->cso_shader
.ps
);
1154 #define NINE_STATE_SHADER_CHANGE_VS \
1156 NINE_STATE_TEXTURE | \
1157 NINE_STATE_VS_PARAMS_MISC | \
1160 #define NINE_STATE_SHADER_CHANGE_PS \
1162 NINE_STATE_TEXTURE | \
1163 NINE_STATE_PS_PARAMS_MISC)
1165 #define NINE_STATE_FREQUENT \
1166 (NINE_STATE_RASTERIZER | \
1167 NINE_STATE_TEXTURE | \
1168 NINE_STATE_SAMPLER | \
1169 NINE_STATE_VS_CONST | \
1170 NINE_STATE_PS_CONST | \
1171 NINE_STATE_MULTISAMPLE)
1173 #define NINE_STATE_COMMON \
1175 NINE_STATE_BLEND | \
1177 NINE_STATE_VIEWPORT | \
1178 NINE_STATE_VDECL | \
1179 NINE_STATE_IDXBUF | \
1180 NINE_STATE_STREAMFREQ)
1182 #define NINE_STATE_RARE \
1183 (NINE_STATE_SCISSOR | \
1184 NINE_STATE_BLEND_COLOR | \
1185 NINE_STATE_STENCIL_REF | \
1186 NINE_STATE_SAMPLE_MASK)
1189 nine_update_state(struct NineDevice9
*device
)
1191 struct nine_context
*context
= &device
->context
;
1192 struct pipe_context
*pipe
= context
->pipe
;
1195 DBG("changed state groups: %x\n", context
->changed
.group
);
1197 /* NOTE: We may want to use the cso cache for everything, or let
1198 * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't
1199 * have to care about state being clobbered here and could merge this back
1200 * into update_textures. Except, we also need to re-validate textures that
1201 * may be dirty anyway, even if no texture bindings changed.
1204 /* ff_update may change VS/PS dirty bits */
1205 if (unlikely(!context
->programmable_vs
|| !context
->ps
))
1206 nine_ff_update(device
);
1207 group
= context
->changed
.group
;
1209 if (group
& (NINE_STATE_SHADER_CHANGE_VS
| NINE_STATE_SHADER_CHANGE_PS
)) {
1210 if (group
& NINE_STATE_SHADER_CHANGE_VS
)
1211 group
|= prepare_vs(device
, (group
& NINE_STATE_VS
) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/
1212 if (group
& NINE_STATE_SHADER_CHANGE_PS
)
1213 group
|= prepare_ps(device
, (group
& NINE_STATE_PS
) != 0);
1216 if (group
& (NINE_STATE_COMMON
| NINE_STATE_VS
)) {
1217 if (group
& NINE_STATE_FB
)
1218 update_framebuffer(device
, FALSE
);
1219 if (group
& NINE_STATE_BLEND
)
1220 prepare_blend(device
);
1221 if (group
& NINE_STATE_DSA
)
1222 prepare_dsa(device
);
1223 if (group
& NINE_STATE_VIEWPORT
)
1224 update_viewport(device
);
1225 if (group
& (NINE_STATE_VDECL
| NINE_STATE_VS
| NINE_STATE_STREAMFREQ
))
1226 update_vertex_elements(device
);
1229 if (likely(group
& (NINE_STATE_FREQUENT
| NINE_STATE_VS
| NINE_STATE_PS
| NINE_STATE_SWVP
))) {
1230 if (group
& NINE_STATE_MULTISAMPLE
)
1231 group
|= check_multisample(device
);
1232 if (group
& NINE_STATE_RASTERIZER
)
1233 prepare_rasterizer(device
);
1234 if (group
& (NINE_STATE_TEXTURE
| NINE_STATE_SAMPLER
))
1235 update_textures_and_samplers(device
);
1236 if ((group
& (NINE_STATE_VS_CONST
| NINE_STATE_VS
| NINE_STATE_SWVP
)) && context
->programmable_vs
)
1237 prepare_vs_constants_userbuf(device
);
1238 if ((group
& (NINE_STATE_PS_CONST
| NINE_STATE_PS
)) && context
->ps
)
1239 prepare_ps_constants_userbuf(device
);
1242 if (context
->changed
.vtxbuf
)
1243 update_vertex_buffers(device
);
1245 if (context
->commit
& NINE_STATE_COMMIT_BLEND
)
1246 commit_blend(device
);
1247 if (context
->commit
& NINE_STATE_COMMIT_DSA
)
1249 if (context
->commit
& NINE_STATE_COMMIT_RASTERIZER
)
1250 commit_rasterizer(device
);
1251 if (context
->commit
& NINE_STATE_COMMIT_CONST_VS
)
1252 commit_vs_constants(device
);
1253 if (context
->commit
& NINE_STATE_COMMIT_CONST_PS
)
1254 commit_ps_constants(device
);
1255 if (context
->commit
& NINE_STATE_COMMIT_VS
)
1257 if (context
->commit
& NINE_STATE_COMMIT_PS
)
1260 context
->commit
= 0;
1262 if (unlikely(context
->changed
.ucp
)) {
1263 pipe
->set_clip_state(pipe
, &context
->clip
);
1264 context
->changed
.ucp
= FALSE
;
1267 if (unlikely(group
& NINE_STATE_RARE
)) {
1268 if (group
& NINE_STATE_SCISSOR
)
1269 commit_scissor(device
);
1270 if (group
& NINE_STATE_BLEND_COLOR
) {
1271 struct pipe_blend_color color
;
1272 d3dcolor_to_rgba(&color
.color
[0], context
->rs
[D3DRS_BLENDFACTOR
]);
1273 pipe
->set_blend_color(pipe
, &color
);
1275 if (group
& NINE_STATE_SAMPLE_MASK
) {
1276 if (context
->rt
[0]->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
) {
1277 pipe
->set_sample_mask(pipe
, ~0);
1279 pipe
->set_sample_mask(pipe
, context
->rs
[D3DRS_MULTISAMPLEMASK
]);
1282 if (group
& NINE_STATE_STENCIL_REF
) {
1283 struct pipe_stencil_ref ref
;
1284 ref
.ref_value
[0] = context
->rs
[D3DRS_STENCILREF
];
1285 ref
.ref_value
[1] = ref
.ref_value
[0];
1286 pipe
->set_stencil_ref(pipe
, &ref
);
1290 context
->changed
.group
&=
1291 (NINE_STATE_FF
| NINE_STATE_VS_CONST
| NINE_STATE_PS_CONST
);
1296 #define RESZ_CODE 0x7fa05000
1299 NineDevice9_ResolveZ( struct NineDevice9
*device
)
1301 struct nine_context
*context
= &device
->context
;
1302 const struct util_format_description
*desc
;
1303 struct NineSurface9
*source
= context
->ds
;
1304 struct pipe_resource
*src
, *dst
;
1305 struct pipe_blit_info blit
;
1307 DBG("RESZ resolve\n");
1309 if (!source
|| !context
->texture
[0].enabled
||
1310 context
->texture
[0].type
!= D3DRTYPE_TEXTURE
)
1313 src
= source
->base
.resource
;
1314 dst
= context
->texture
[0].resource
;
1319 /* check dst is depth format. we know already for src */
1320 desc
= util_format_description(dst
->format
);
1321 if (desc
->colorspace
!= UTIL_FORMAT_COLORSPACE_ZS
)
1324 memset(&blit
, 0, sizeof(blit
));
1325 blit
.src
.resource
= src
;
1327 blit
.src
.format
= src
->format
;
1329 blit
.src
.box
.depth
= 1;
1332 blit
.src
.box
.width
= src
->width0
;
1333 blit
.src
.box
.height
= src
->height0
;
1335 blit
.dst
.resource
= dst
;
1337 blit
.dst
.format
= dst
->format
;
1339 blit
.dst
.box
.depth
= 1;
1342 blit
.dst
.box
.width
= dst
->width0
;
1343 blit
.dst
.box
.height
= dst
->height0
;
1345 blit
.mask
= PIPE_MASK_ZS
;
1346 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
1347 blit
.scissor_enable
= FALSE
;
1349 context
->pipe
->blit(context
->pipe
, &blit
);
1352 #define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1')
1353 #define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0')
1355 /* Nine_context functions.
1356 * Serialized through CSMT macros.
1360 nine_context_set_texture_apply(struct NineDevice9
*device
,
1365 D3DRESOURCETYPE type
,
1367 struct pipe_resource
*res
,
1368 struct pipe_sampler_view
*view0
,
1369 struct pipe_sampler_view
*view1
);
1371 nine_context_set_stream_source_apply(struct NineDevice9
*device
,
1373 struct pipe_resource
*res
,
1378 nine_context_set_indices_apply(struct NineDevice9
*device
,
1379 struct pipe_resource
*res
,
1381 UINT OffsetInBytes
);
1384 nine_context_set_pixel_shader_constant_i_transformed(struct NineDevice9
*device
,
1386 const int *pConstantData
,
1387 unsigned pConstantData_size
,
1388 UINT Vector4iCount
);
1390 CSMT_ITEM_NO_WAIT(nine_context_set_render_state
,
1391 ARG_VAL(D3DRENDERSTATETYPE
, State
),
1392 ARG_VAL(DWORD
, Value
))
1394 struct nine_context
*context
= &device
->context
;
1396 /* Amd hacks (equivalent to GL extensions) */
1397 if (unlikely(State
== D3DRS_POINTSIZE
)) {
1398 if (Value
== RESZ_CODE
) {
1399 NineDevice9_ResolveZ(device
);
1403 if (Value
== ALPHA_TO_COVERAGE_ENABLE
||
1404 Value
== ALPHA_TO_COVERAGE_DISABLE
) {
1405 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== ALPHA_TO_COVERAGE_ENABLE
);
1406 context
->changed
.group
|= NINE_STATE_BLEND
;
1412 if (unlikely(State
== D3DRS_ADAPTIVETESS_Y
)) {
1413 if (Value
== D3DFMT_ATOC
|| (Value
== D3DFMT_UNKNOWN
&& context
->rs
[NINED3DRS_ALPHACOVERAGE
])) {
1414 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== D3DFMT_ATOC
) ? 3 : 0;
1415 context
->rs
[NINED3DRS_ALPHACOVERAGE
] &= context
->rs
[D3DRS_ALPHATESTENABLE
] ? 3 : 2;
1416 context
->changed
.group
|= NINE_STATE_BLEND
;
1420 if (unlikely(State
== D3DRS_ALPHATESTENABLE
&& (context
->rs
[NINED3DRS_ALPHACOVERAGE
] & 2))) {
1421 DWORD alphacoverage_prev
= context
->rs
[NINED3DRS_ALPHACOVERAGE
];
1422 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
? 3 : 2);
1423 if (context
->rs
[NINED3DRS_ALPHACOVERAGE
] != alphacoverage_prev
)
1424 context
->changed
.group
|= NINE_STATE_BLEND
;
1427 context
->rs
[State
] = nine_fix_render_state_value(State
, Value
);
1428 context
->changed
.group
|= nine_render_state_group
[State
];
1431 CSMT_ITEM_NO_WAIT(nine_context_set_texture_apply
,
1432 ARG_VAL(DWORD
, stage
),
1433 ARG_VAL(BOOL
, enabled
),
1434 ARG_VAL(BOOL
, shadow
),
1435 ARG_VAL(DWORD
, lod
),
1436 ARG_VAL(D3DRESOURCETYPE
, type
),
1437 ARG_VAL(uint8_t, pstype
),
1438 ARG_BIND_RES(struct pipe_resource
, res
),
1439 ARG_BIND_VIEW(struct pipe_sampler_view
, view0
),
1440 ARG_BIND_VIEW(struct pipe_sampler_view
, view1
))
1442 struct nine_context
*context
= &device
->context
;
1444 context
->texture
[stage
].enabled
= enabled
;
1445 context
->samplers_shadow
&= ~(1 << stage
);
1446 context
->samplers_shadow
|= shadow
<< stage
;
1447 context
->texture
[stage
].shadow
= shadow
;
1448 context
->texture
[stage
].lod
= lod
;
1449 context
->texture
[stage
].type
= type
;
1450 context
->texture
[stage
].pstype
= pstype
;
1451 pipe_resource_reference(&context
->texture
[stage
].resource
, res
);
1452 pipe_sampler_view_reference(&context
->texture
[stage
].view
[0], view0
);
1453 pipe_sampler_view_reference(&context
->texture
[stage
].view
[1], view1
);
1455 context
->changed
.group
|= NINE_STATE_TEXTURE
;
1459 nine_context_set_texture(struct NineDevice9
*device
,
1461 struct NineBaseTexture9
*tex
)
1463 BOOL enabled
= FALSE
;
1464 BOOL shadow
= FALSE
;
1466 D3DRESOURCETYPE type
= D3DRTYPE_TEXTURE
;
1468 struct pipe_resource
*res
= NULL
;
1469 struct pipe_sampler_view
*view0
= NULL
, *view1
= NULL
;
1471 /* For managed pool, the data can be initially incomplete.
1472 * In that case, the texture is rebound later
1473 * (in NineBaseTexture9_Validate/NineBaseTexture9_UploadSelf). */
1474 if (tex
&& tex
->base
.resource
) {
1476 shadow
= tex
->shadow
;
1477 lod
= tex
->managed
.lod
;
1478 type
= tex
->base
.type
;
1479 pstype
= tex
->pstype
;
1480 res
= tex
->base
.resource
;
1481 view0
= NineBaseTexture9_GetSamplerView(tex
, 0);
1482 view1
= NineBaseTexture9_GetSamplerView(tex
, 1);
1485 nine_context_set_texture_apply(device
, Stage
, enabled
,
1486 shadow
, lod
, type
, pstype
,
1490 CSMT_ITEM_NO_WAIT(nine_context_set_sampler_state
,
1491 ARG_VAL(DWORD
, Sampler
),
1492 ARG_VAL(D3DSAMPLERSTATETYPE
, Type
),
1493 ARG_VAL(DWORD
, Value
))
1495 struct nine_context
*context
= &device
->context
;
1497 if (unlikely(!nine_check_sampler_state_value(Type
, Value
)))
1500 context
->samp
[Sampler
][Type
] = Value
;
1501 context
->changed
.group
|= NINE_STATE_SAMPLER
;
1502 context
->changed
.sampler
[Sampler
] |= 1 << Type
;
1505 CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_apply
,
1506 ARG_VAL(UINT
, StreamNumber
),
1507 ARG_BIND_RES(struct pipe_resource
, res
),
1508 ARG_VAL(UINT
, OffsetInBytes
),
1509 ARG_VAL(UINT
, Stride
))
1511 struct nine_context
*context
= &device
->context
;
1512 const unsigned i
= StreamNumber
;
1514 context
->vtxbuf
[i
].stride
= Stride
;
1515 context
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
1516 pipe_resource_reference(&context
->vtxbuf
[i
].buffer
.resource
, res
);
1518 context
->changed
.vtxbuf
|= 1 << StreamNumber
;
1522 nine_context_set_stream_source(struct NineDevice9
*device
,
1524 struct NineVertexBuffer9
*pVBuf9
,
1528 struct pipe_resource
*res
= NULL
;
1529 unsigned offset
= 0;
1532 res
= NineVertexBuffer9_GetResource(pVBuf9
, &offset
);
1533 /* in the future when there is internal offset, add it
1534 * to OffsetInBytes */
1536 nine_context_set_stream_source_apply(device
, StreamNumber
,
1537 res
, offset
+ OffsetInBytes
,
1541 CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_freq
,
1542 ARG_VAL(UINT
, StreamNumber
),
1543 ARG_VAL(UINT
, Setting
))
1545 struct nine_context
*context
= &device
->context
;
1547 context
->stream_freq
[StreamNumber
] = Setting
;
1549 if (Setting
& D3DSTREAMSOURCE_INSTANCEDATA
)
1550 context
->stream_instancedata_mask
|= 1 << StreamNumber
;
1552 context
->stream_instancedata_mask
&= ~(1 << StreamNumber
);
1554 if (StreamNumber
!= 0)
1555 context
->changed
.group
|= NINE_STATE_STREAMFREQ
;
1558 CSMT_ITEM_NO_WAIT(nine_context_set_indices_apply
,
1559 ARG_BIND_RES(struct pipe_resource
, res
),
1560 ARG_VAL(UINT
, IndexSize
),
1561 ARG_VAL(UINT
, OffsetInBytes
))
1563 struct nine_context
*context
= &device
->context
;
1565 context
->index_size
= IndexSize
;
1566 context
->index_offset
= OffsetInBytes
;
1567 pipe_resource_reference(&context
->idxbuf
, res
);
1569 context
->changed
.group
|= NINE_STATE_IDXBUF
;
1573 nine_context_set_indices(struct NineDevice9
*device
,
1574 struct NineIndexBuffer9
*idxbuf
)
1576 struct pipe_resource
*res
= NULL
;
1578 unsigned OffsetInBytes
= 0;
1581 res
= NineIndexBuffer9_GetBuffer(idxbuf
, &OffsetInBytes
);
1582 IndexSize
= idxbuf
->index_size
;
1585 nine_context_set_indices_apply(device
, res
, IndexSize
, OffsetInBytes
);
1588 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_declaration
,
1589 ARG_BIND_REF(struct NineVertexDeclaration9
, vdecl
))
1591 struct nine_context
*context
= &device
->context
;
1592 BOOL was_programmable_vs
= context
->programmable_vs
;
1594 nine_bind(&context
->vdecl
, vdecl
);
1596 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
1597 if (was_programmable_vs
!= context
->programmable_vs
) {
1598 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
1599 context
->changed
.group
|= NINE_STATE_VS
;
1602 context
->changed
.group
|= NINE_STATE_VDECL
;
1605 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader
,
1606 ARG_BIND_REF(struct NineVertexShader9
, pShader
))
1608 struct nine_context
*context
= &device
->context
;
1609 BOOL was_programmable_vs
= context
->programmable_vs
;
1611 nine_bind(&context
->vs
, pShader
);
1613 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
1615 /* ff -> non-ff: commit back non-ff constants */
1616 if (!was_programmable_vs
&& context
->programmable_vs
)
1617 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
1619 context
->changed
.group
|= NINE_STATE_VS
;
1622 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_f
,
1623 ARG_VAL(UINT
, StartRegister
),
1624 ARG_MEM(float, pConstantData
),
1625 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1626 ARG_VAL(UINT
, Vector4fCount
))
1628 struct nine_context
*context
= &device
->context
;
1629 float *vs_const_f
= device
->may_swvp
? context
->vs_const_f_swvp
: context
->vs_const_f
;
1631 memcpy(&vs_const_f
[StartRegister
* 4],
1633 pConstantData_size
);
1635 if (device
->may_swvp
) {
1636 Vector4fCount
= MIN2(StartRegister
+ Vector4fCount
, NINE_MAX_CONST_F
) - StartRegister
;
1637 if (StartRegister
< NINE_MAX_CONST_F
)
1638 memcpy(&context
->vs_const_f
[StartRegister
* 4],
1640 Vector4fCount
* 4 * sizeof(context
->vs_const_f
[0]));
1643 context
->changed
.vs_const_f
= TRUE
;
1644 context
->changed
.group
|= NINE_STATE_VS_CONST
;
1647 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_i
,
1648 ARG_VAL(UINT
, StartRegister
),
1649 ARG_MEM(int, pConstantData
),
1650 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1651 ARG_VAL(UINT
, Vector4iCount
))
1653 struct nine_context
*context
= &device
->context
;
1656 if (device
->driver_caps
.vs_integer
) {
1657 memcpy(&context
->vs_const_i
[4 * StartRegister
],
1659 pConstantData_size
);
1661 for (i
= 0; i
< Vector4iCount
; i
++) {
1662 context
->vs_const_i
[4 * (StartRegister
+ i
)] = fui((float)(pConstantData
[4 * i
]));
1663 context
->vs_const_i
[4 * (StartRegister
+ i
) + 1] = fui((float)(pConstantData
[4 * i
+ 1]));
1664 context
->vs_const_i
[4 * (StartRegister
+ i
) + 2] = fui((float)(pConstantData
[4 * i
+ 2]));
1665 context
->vs_const_i
[4 * (StartRegister
+ i
) + 3] = fui((float)(pConstantData
[4 * i
+ 3]));
1669 context
->changed
.vs_const_i
= TRUE
;
1670 context
->changed
.group
|= NINE_STATE_VS_CONST
| NINE_STATE_VS_PARAMS_MISC
;
1673 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_b
,
1674 ARG_VAL(UINT
, StartRegister
),
1675 ARG_MEM(BOOL
, pConstantData
),
1676 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1677 ARG_VAL(UINT
, BoolCount
))
1679 struct nine_context
*context
= &device
->context
;
1681 uint32_t bool_true
= device
->driver_caps
.vs_integer
? 0xFFFFFFFF : fui(1.0f
);
1683 (void) pConstantData_size
;
1685 for (i
= 0; i
< BoolCount
; i
++)
1686 context
->vs_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
1688 context
->changed
.vs_const_b
= TRUE
;
1689 context
->changed
.group
|= NINE_STATE_VS_CONST
| NINE_STATE_VS_PARAMS_MISC
;
1692 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader
,
1693 ARG_BIND_REF(struct NinePixelShader9
, ps
))
1695 struct nine_context
*context
= &device
->context
;
1696 unsigned old_mask
= context
->ps
? context
->ps
->rt_mask
: 1;
1699 /* ff -> non-ff: commit back non-ff constants */
1700 if (!context
->ps
&& ps
)
1701 context
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
1703 nine_bind(&context
->ps
, ps
);
1705 context
->changed
.group
|= NINE_STATE_PS
;
1707 mask
= context
->ps
? context
->ps
->rt_mask
: 1;
1708 /* We need to update cbufs if the pixel shader would
1709 * write to different render targets */
1710 if (mask
!= old_mask
)
1711 context
->changed
.group
|= NINE_STATE_FB
;
1714 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_f
,
1715 ARG_VAL(UINT
, StartRegister
),
1716 ARG_MEM(float, pConstantData
),
1717 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1718 ARG_VAL(UINT
, Vector4fCount
))
1720 struct nine_context
*context
= &device
->context
;
1722 memcpy(&context
->ps_const_f
[StartRegister
* 4],
1724 pConstantData_size
);
1726 context
->changed
.ps_const_f
= TRUE
;
1727 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1730 /* For stateblocks */
1731 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i_transformed
,
1732 ARG_VAL(UINT
, StartRegister
),
1733 ARG_MEM(int, pConstantData
),
1734 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1735 ARG_VAL(UINT
, Vector4iCount
))
1737 struct nine_context
*context
= &device
->context
;
1739 memcpy(&context
->ps_const_i
[StartRegister
][0],
1741 Vector4iCount
* sizeof(context
->ps_const_i
[0]));
1743 context
->changed
.ps_const_i
= TRUE
;
1744 context
->changed
.group
|= NINE_STATE_PS_CONST
| NINE_STATE_PS_PARAMS_MISC
;
1747 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i
,
1748 ARG_VAL(UINT
, StartRegister
),
1749 ARG_MEM(int, pConstantData
),
1750 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1751 ARG_VAL(UINT
, Vector4iCount
))
1753 struct nine_context
*context
= &device
->context
;
1756 if (device
->driver_caps
.ps_integer
) {
1757 memcpy(&context
->ps_const_i
[StartRegister
][0],
1759 pConstantData_size
);
1761 for (i
= 0; i
< Vector4iCount
; i
++) {
1762 context
->ps_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
1763 context
->ps_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
1764 context
->ps_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
1765 context
->ps_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
1768 context
->changed
.ps_const_i
= TRUE
;
1769 context
->changed
.group
|= NINE_STATE_PS_CONST
| NINE_STATE_PS_PARAMS_MISC
;
1772 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_b
,
1773 ARG_VAL(UINT
, StartRegister
),
1774 ARG_MEM(BOOL
, pConstantData
),
1775 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1776 ARG_VAL(UINT
, BoolCount
))
1778 struct nine_context
*context
= &device
->context
;
1780 uint32_t bool_true
= device
->driver_caps
.ps_integer
? 0xFFFFFFFF : fui(1.0f
);
1782 (void) pConstantData_size
;
1784 for (i
= 0; i
< BoolCount
; i
++)
1785 context
->ps_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
1787 context
->changed
.ps_const_b
= TRUE
;
1788 context
->changed
.group
|= NINE_STATE_PS_CONST
| NINE_STATE_PS_PARAMS_MISC
;
1791 /* XXX: use resource, as resource might change */
1792 CSMT_ITEM_NO_WAIT(nine_context_set_render_target
,
1793 ARG_VAL(DWORD
, RenderTargetIndex
),
1794 ARG_BIND_REF(struct NineSurface9
, rt
))
1796 struct nine_context
*context
= &device
->context
;
1797 const unsigned i
= RenderTargetIndex
;
1800 context
->viewport
.X
= 0;
1801 context
->viewport
.Y
= 0;
1802 context
->viewport
.Width
= rt
->desc
.Width
;
1803 context
->viewport
.Height
= rt
->desc
.Height
;
1804 context
->viewport
.MinZ
= 0.0f
;
1805 context
->viewport
.MaxZ
= 1.0f
;
1807 context
->scissor
.minx
= 0;
1808 context
->scissor
.miny
= 0;
1809 context
->scissor
.maxx
= rt
->desc
.Width
;
1810 context
->scissor
.maxy
= rt
->desc
.Height
;
1812 context
->changed
.group
|= NINE_STATE_VIEWPORT
| NINE_STATE_SCISSOR
| NINE_STATE_MULTISAMPLE
;
1814 if (context
->rt
[0] &&
1815 (context
->rt
[0]->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
) !=
1816 (rt
->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
))
1817 context
->changed
.group
|= NINE_STATE_SAMPLE_MASK
;
1820 if (context
->rt
[i
] != rt
) {
1821 nine_bind(&context
->rt
[i
], rt
);
1822 context
->changed
.group
|= NINE_STATE_FB
;
1826 /* XXX: use resource instead of ds, as resource might change */
1827 CSMT_ITEM_NO_WAIT(nine_context_set_depth_stencil
,
1828 ARG_BIND_REF(struct NineSurface9
, ds
))
1830 struct nine_context
*context
= &device
->context
;
1832 nine_bind(&context
->ds
, ds
);
1833 context
->changed
.group
|= NINE_STATE_FB
;
1836 CSMT_ITEM_NO_WAIT(nine_context_set_viewport
,
1837 ARG_COPY_REF(D3DVIEWPORT9
, viewport
))
1839 struct nine_context
*context
= &device
->context
;
1841 context
->viewport
= *viewport
;
1842 context
->changed
.group
|= NINE_STATE_VIEWPORT
;
1845 CSMT_ITEM_NO_WAIT(nine_context_set_scissor
,
1846 ARG_COPY_REF(struct pipe_scissor_state
, scissor
))
1848 struct nine_context
*context
= &device
->context
;
1850 context
->scissor
= *scissor
;
1851 context
->changed
.group
|= NINE_STATE_SCISSOR
;
1854 CSMT_ITEM_NO_WAIT(nine_context_set_transform
,
1855 ARG_VAL(D3DTRANSFORMSTATETYPE
, State
),
1856 ARG_COPY_REF(D3DMATRIX
, pMatrix
))
1858 struct nine_context
*context
= &device
->context
;
1859 D3DMATRIX
*M
= nine_state_access_transform(&context
->ff
, State
, TRUE
);
1862 context
->ff
.changed
.transform
[State
/ 32] |= 1 << (State
% 32);
1863 context
->changed
.group
|= NINE_STATE_FF
;
1866 CSMT_ITEM_NO_WAIT(nine_context_set_material
,
1867 ARG_COPY_REF(D3DMATERIAL9
, pMaterial
))
1869 struct nine_context
*context
= &device
->context
;
1871 context
->ff
.material
= *pMaterial
;
1872 context
->changed
.group
|= NINE_STATE_FF_MATERIAL
;
1875 CSMT_ITEM_NO_WAIT(nine_context_set_light
,
1876 ARG_VAL(DWORD
, Index
),
1877 ARG_COPY_REF(D3DLIGHT9
, pLight
))
1879 struct nine_context
*context
= &device
->context
;
1881 (void)nine_state_set_light(&context
->ff
, Index
, pLight
);
1882 context
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
1886 /* For stateblocks */
1888 nine_context_light_enable_stateblock(struct NineDevice9
*device
,
1889 const uint16_t active_light
[NINE_MAX_LIGHTS_ACTIVE
], /* TODO: use pointer that convey size for csmt */
1890 unsigned int num_lights_active
)
1892 struct nine_context
*context
= &device
->context
;
1894 /* TODO: Use CSMT_* to avoid calling nine_csmt_process */
1895 nine_csmt_process(device
);
1896 memcpy(context
->ff
.active_light
, active_light
, NINE_MAX_LIGHTS_ACTIVE
* sizeof(context
->ff
.active_light
[0]));
1897 context
->ff
.num_lights_active
= num_lights_active
;
1898 context
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
1901 CSMT_ITEM_NO_WAIT(nine_context_light_enable
,
1902 ARG_VAL(DWORD
, Index
),
1903 ARG_VAL(BOOL
, Enable
))
1905 struct nine_context
*context
= &device
->context
;
1907 nine_state_light_enable(&context
->ff
, Index
, Enable
);
1908 context
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
1911 CSMT_ITEM_NO_WAIT(nine_context_set_texture_stage_state
,
1912 ARG_VAL(DWORD
, Stage
),
1913 ARG_VAL(D3DTEXTURESTAGESTATETYPE
, Type
),
1914 ARG_VAL(DWORD
, Value
))
1916 struct nine_context
*context
= &device
->context
;
1917 int bumpmap_index
= -1;
1919 context
->ff
.tex_stage
[Stage
][Type
] = Value
;
1921 case D3DTSS_BUMPENVMAT00
:
1922 bumpmap_index
= 4 * Stage
;
1924 case D3DTSS_BUMPENVMAT01
:
1925 bumpmap_index
= 4 * Stage
+ 1;
1927 case D3DTSS_BUMPENVMAT10
:
1928 bumpmap_index
= 4 * Stage
+ 2;
1930 case D3DTSS_BUMPENVMAT11
:
1931 bumpmap_index
= 4 * Stage
+ 3;
1933 case D3DTSS_BUMPENVLSCALE
:
1934 bumpmap_index
= 4 * 8 + 2 * Stage
;
1936 case D3DTSS_BUMPENVLOFFSET
:
1937 bumpmap_index
= 4 * 8 + 2 * Stage
+ 1;
1939 case D3DTSS_TEXTURETRANSFORMFLAGS
:
1940 context
->changed
.group
|= NINE_STATE_PS_PARAMS_MISC
;
1946 if (bumpmap_index
>= 0) {
1947 context
->bumpmap_vars
[bumpmap_index
] = Value
;
1948 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1951 context
->changed
.group
|= NINE_STATE_FF_PS_CONSTS
;
1952 context
->ff
.changed
.tex_stage
[Stage
][Type
/ 32] |= 1 << (Type
% 32);
1955 CSMT_ITEM_NO_WAIT(nine_context_set_clip_plane
,
1956 ARG_VAL(DWORD
, Index
),
1957 ARG_COPY_REF(struct nine_clipplane
, pPlane
))
1959 struct nine_context
*context
= &device
->context
;
1961 memcpy(&context
->clip
.ucp
[Index
][0], pPlane
, sizeof(context
->clip
.ucp
[0]));
1962 context
->changed
.ucp
= TRUE
;
1965 CSMT_ITEM_NO_WAIT(nine_context_set_swvp
,
1966 ARG_VAL(boolean
, swvp
))
1968 struct nine_context
*context
= &device
->context
;
1970 context
->swvp
= swvp
;
1971 context
->changed
.group
|= NINE_STATE_SWVP
;
1974 /* Do not write to nine_context directly. Slower,
1975 * but works with csmt. TODO: write a special csmt version that
1976 * would record the list of commands as much as possible,
1977 * and use the version above else.
1980 nine_context_apply_stateblock(struct NineDevice9
*device
,
1981 const struct nine_state
*src
)
1985 /* No need to apply src->changed.group, since all calls do
1986 * set context->changed.group */
1988 for (i
= 0; i
< ARRAY_SIZE(src
->changed
.rs
); ++i
) {
1989 uint32_t m
= src
->changed
.rs
[i
];
1991 const int r
= ffs(m
) - 1;
1993 nine_context_set_render_state(device
, i
* 32 + r
, src
->rs_advertised
[i
* 32 + r
]);
1998 if (src
->changed
.texture
) {
1999 uint32_t m
= src
->changed
.texture
;
2002 for (s
= 0; m
; ++s
, m
>>= 1) {
2003 struct NineBaseTexture9
*tex
= src
->texture
[s
];
2006 nine_context_set_texture(device
, s
, tex
);
2011 if (src
->changed
.group
& NINE_STATE_SAMPLER
) {
2014 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
2015 uint32_t m
= src
->changed
.sampler
[s
];
2017 const int i
= ffs(m
) - 1;
2019 nine_context_set_sampler_state(device
, s
, i
, src
->samp_advertised
[s
][i
]);
2024 /* Vertex buffers */
2025 if (src
->changed
.vtxbuf
| src
->changed
.stream_freq
) {
2026 uint32_t m
= src
->changed
.vtxbuf
| src
->changed
.stream_freq
;
2027 for (i
= 0; m
; ++i
, m
>>= 1) {
2028 if (src
->changed
.vtxbuf
& (1 << i
))
2029 nine_context_set_stream_source(device
, i
, src
->stream
[i
], src
->vtxbuf
[i
].buffer_offset
, src
->vtxbuf
[i
].stride
);
2030 if (src
->changed
.stream_freq
& (1 << i
))
2031 nine_context_set_stream_source_freq(device
, i
, src
->stream_freq
[i
]);
2036 if (src
->changed
.group
& NINE_STATE_IDXBUF
)
2037 nine_context_set_indices(device
, src
->idxbuf
);
2039 /* Vertex declaration */
2040 if ((src
->changed
.group
& NINE_STATE_VDECL
) && src
->vdecl
)
2041 nine_context_set_vertex_declaration(device
, src
->vdecl
);
2044 if (src
->changed
.group
& NINE_STATE_VS
)
2045 nine_context_set_vertex_shader(device
, src
->vs
);
2048 if (src
->changed
.group
& NINE_STATE_PS
)
2049 nine_context_set_pixel_shader(device
, src
->ps
);
2051 /* Vertex constants */
2052 if (src
->changed
.group
& NINE_STATE_VS_CONST
) {
2053 struct nine_range
*r
;
2054 for (r
= src
->changed
.vs_const_f
; r
; r
= r
->next
)
2055 nine_context_set_vertex_shader_constant_f(device
, r
->bgn
,
2056 &src
->vs_const_f
[r
->bgn
* 4],
2057 sizeof(float[4]) * (r
->end
- r
->bgn
),
2059 for (r
= src
->changed
.vs_const_i
; r
; r
= r
->next
)
2060 nine_context_set_vertex_shader_constant_i(device
, r
->bgn
,
2061 &src
->vs_const_i
[r
->bgn
* 4],
2062 sizeof(int[4]) * (r
->end
- r
->bgn
),
2064 for (r
= src
->changed
.vs_const_b
; r
; r
= r
->next
)
2065 nine_context_set_vertex_shader_constant_b(device
, r
->bgn
,
2066 &src
->vs_const_b
[r
->bgn
* 4],
2067 sizeof(BOOL
) * (r
->end
- r
->bgn
),
2071 /* Pixel constants */
2072 if (src
->changed
.group
& NINE_STATE_PS_CONST
) {
2073 struct nine_range
*r
;
2074 for (r
= src
->changed
.ps_const_f
; r
; r
= r
->next
)
2075 nine_context_set_pixel_shader_constant_f(device
, r
->bgn
,
2076 &src
->ps_const_f
[r
->bgn
* 4],
2077 sizeof(float[4]) * (r
->end
- r
->bgn
),
2079 if (src
->changed
.ps_const_i
) {
2080 uint16_t m
= src
->changed
.ps_const_i
;
2081 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
2083 nine_context_set_pixel_shader_constant_i_transformed(device
, i
,
2084 src
->ps_const_i
[i
], sizeof(int[4]), 1);
2086 if (src
->changed
.ps_const_b
) {
2087 uint16_t m
= src
->changed
.ps_const_b
;
2088 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
2090 nine_context_set_pixel_shader_constant_b(device
, i
,
2091 &src
->ps_const_b
[i
], sizeof(BOOL
), 1);
2096 if (src
->changed
.group
& NINE_STATE_VIEWPORT
)
2097 nine_context_set_viewport(device
, &src
->viewport
);
2100 if (src
->changed
.group
& NINE_STATE_SCISSOR
)
2101 nine_context_set_scissor(device
, &src
->scissor
);
2103 /* User Clip Planes */
2104 if (src
->changed
.ucp
)
2105 for (i
= 0; i
< PIPE_MAX_CLIP_PLANES
; ++i
)
2106 if (src
->changed
.ucp
& (1 << i
))
2107 nine_context_set_clip_plane(device
, i
, (struct nine_clipplane
*)&src
->clip
.ucp
[i
][0]);
2109 if (!(src
->changed
.group
& NINE_STATE_FF
))
2112 /* Fixed function state. */
2114 if (src
->changed
.group
& NINE_STATE_FF_MATERIAL
)
2115 nine_context_set_material(device
, &src
->ff
.material
);
2117 if (src
->changed
.group
& NINE_STATE_FF_PS_CONSTS
) {
2119 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
2120 for (i
= 0; i
< NINED3DTSS_COUNT
; ++i
)
2121 if (src
->ff
.changed
.tex_stage
[s
][i
/ 32] & (1 << (i
% 32)))
2122 nine_context_set_texture_stage_state(device
, s
, i
, src
->ff
.tex_stage
[s
][i
]);
2125 if (src
->changed
.group
& NINE_STATE_FF_LIGHTING
) {
2126 for (i
= 0; i
< src
->ff
.num_lights
; ++i
)
2127 if (src
->ff
.light
[i
].Type
!= NINED3DLIGHT_INVALID
)
2128 nine_context_set_light(device
, i
, &src
->ff
.light
[i
]);
2130 nine_context_light_enable_stateblock(device
, src
->ff
.active_light
, src
->ff
.num_lights_active
);
2132 if (src
->changed
.group
& NINE_STATE_FF_VSTRANSF
) {
2133 for (i
= 0; i
< ARRAY_SIZE(src
->ff
.changed
.transform
); ++i
) {
2135 if (!src
->ff
.changed
.transform
[i
])
2137 for (s
= i
* 32; s
< (i
* 32 + 32); ++s
) {
2138 if (!(src
->ff
.changed
.transform
[i
] & (1 << (s
% 32))))
2140 /* MaxVertexBlendMatrixIndex is 8, which means
2141 * we don't read past index D3DTS_WORLDMATRIX(8).
2142 * swvp is supposed to allow all 256, but we don't
2143 * implement it for now. */
2144 if (s
> D3DTS_WORLDMATRIX(8))
2146 nine_context_set_transform(device
, s
,
2147 nine_state_access_transform(
2148 (struct nine_ff_state
*)&src
->ff
,
2156 nine_update_state_framebuffer_clear(struct NineDevice9
*device
)
2158 struct nine_context
*context
= &device
->context
;
2160 if (context
->changed
.group
& NINE_STATE_FB
)
2161 update_framebuffer(device
, TRUE
);
2164 CSMT_ITEM_NO_WAIT(nine_context_clear_fb
,
2165 ARG_VAL(DWORD
, Count
),
2166 ARG_COPY_REF(D3DRECT
, pRects
),
2167 ARG_VAL(DWORD
, Flags
),
2168 ARG_VAL(D3DCOLOR
, Color
),
2170 ARG_VAL(DWORD
, Stencil
))
2172 struct nine_context
*context
= &device
->context
;
2173 const int sRGB
= context
->rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
2174 struct pipe_surface
*cbuf
, *zsbuf
;
2175 struct pipe_context
*pipe
= context
->pipe
;
2176 struct NineSurface9
*zsbuf_surf
= context
->ds
;
2177 struct NineSurface9
*rt
;
2180 union pipe_color_union rgba
;
2181 unsigned rt_mask
= 0;
2184 nine_update_state_framebuffer_clear(device
);
2186 if (Flags
& D3DCLEAR_TARGET
) bufs
|= PIPE_CLEAR_COLOR
;
2187 /* Ignore Z buffer if not bound */
2188 if (context
->pipe_data
.fb
.zsbuf
!= NULL
) {
2189 if (Flags
& D3DCLEAR_ZBUFFER
) bufs
|= PIPE_CLEAR_DEPTH
;
2190 if (Flags
& D3DCLEAR_STENCIL
) bufs
|= PIPE_CLEAR_STENCIL
;
2194 d3dcolor_to_pipe_color_union(&rgba
, Color
);
2196 rect
.x1
= context
->viewport
.X
;
2197 rect
.y1
= context
->viewport
.Y
;
2198 rect
.x2
= context
->viewport
.Width
+ rect
.x1
;
2199 rect
.y2
= context
->viewport
.Height
+ rect
.y1
;
2201 /* Both rectangles apply, which is weird, but that's D3D9. */
2202 if (context
->rs
[D3DRS_SCISSORTESTENABLE
]) {
2203 rect
.x1
= MAX2(rect
.x1
, context
->scissor
.minx
);
2204 rect
.y1
= MAX2(rect
.y1
, context
->scissor
.miny
);
2205 rect
.x2
= MIN2(rect
.x2
, context
->scissor
.maxx
);
2206 rect
.y2
= MIN2(rect
.y2
, context
->scissor
.maxy
);
2210 /* Maybe apps like to specify a large rect ? */
2211 if (pRects
[0].x1
<= rect
.x1
&& pRects
[0].x2
>= rect
.x2
&&
2212 pRects
[0].y1
<= rect
.y1
&& pRects
[0].y2
>= rect
.y2
) {
2213 DBG("First rect covers viewport.\n");
2219 if (rect
.x1
>= context
->pipe_data
.fb
.width
|| rect
.y1
>= context
->pipe_data
.fb
.height
)
2222 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
2223 if (context
->rt
[i
] && context
->rt
[i
]->desc
.Format
!= D3DFMT_NULL
)
2227 /* fast path, clears everything at once */
2229 (!(bufs
& PIPE_CLEAR_COLOR
) || (rt_mask
== context
->rt_mask
)) &&
2230 rect
.x1
== 0 && rect
.y1
== 0 &&
2231 /* Case we clear only render target. Check clear region vs rt. */
2232 ((!(bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
2233 rect
.x2
>= context
->pipe_data
.fb
.width
&&
2234 rect
.y2
>= context
->pipe_data
.fb
.height
) ||
2235 /* Case we clear depth buffer (and eventually rt too).
2236 * depth buffer size is always >= rt size. Compare to clear region */
2237 ((bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
2238 rect
.x2
>= zsbuf_surf
->desc
.Width
&&
2239 rect
.y2
>= zsbuf_surf
->desc
.Height
))) {
2240 DBG("Clear fast path\n");
2241 pipe
->clear(pipe
, bufs
, NULL
, &rgba
, Z
, Stencil
);
2250 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
2251 rt
= context
->rt
[i
];
2252 if (!rt
|| rt
->desc
.Format
== D3DFMT_NULL
||
2253 !(bufs
& PIPE_CLEAR_COLOR
))
2254 continue; /* save space, compiler should hoist this */
2255 cbuf
= NineSurface9_GetSurface(rt
, sRGB
);
2256 for (r
= 0; r
< Count
; ++r
) {
2257 /* Don't trust users to pass these in the right order. */
2258 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
2259 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
2260 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
2261 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
2263 /* Drop negative rectangles (like wine expects). */
2264 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
2265 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2268 x1
= MAX2(x1
, rect
.x1
);
2269 y1
= MAX2(y1
, rect
.y1
);
2270 x2
= MIN3(x2
, rect
.x2
, rt
->desc
.Width
);
2271 y2
= MIN3(y2
, rect
.y2
, rt
->desc
.Height
);
2273 DBG("Clearing (%u..%u)x(%u..%u)\n", x1
, x2
, y1
, y2
);
2274 pipe
->clear_render_target(pipe
, cbuf
, &rgba
,
2275 x1
, y1
, x2
- x1
, y2
- y1
, false);
2278 if (!(bufs
& PIPE_CLEAR_DEPTHSTENCIL
))
2281 bufs
&= PIPE_CLEAR_DEPTHSTENCIL
;
2283 for (r
= 0; r
< Count
; ++r
) {
2284 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
2285 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
2286 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
2287 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
2289 /* Drop negative rectangles. */
2290 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
2291 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2294 x1
= MIN2(x1
, rect
.x1
);
2295 y1
= MIN2(y1
, rect
.y1
);
2296 x2
= MIN3(x2
, rect
.x2
, zsbuf_surf
->desc
.Width
);
2297 y2
= MIN3(y2
, rect
.y2
, zsbuf_surf
->desc
.Height
);
2299 zsbuf
= NineSurface9_GetSurface(zsbuf_surf
, 0);
2301 pipe
->clear_depth_stencil(pipe
, zsbuf
, bufs
, Z
, Stencil
,
2302 x1
, y1
, x2
- x1
, y2
- y1
, false);
2309 init_draw_info(struct pipe_draw_info
*info
,
2310 struct NineDevice9
*dev
, D3DPRIMITIVETYPE type
, UINT count
)
2312 info
->mode
= d3dprimitivetype_to_pipe_prim(type
);
2313 info
->count
= prim_count_to_vertex_count(type
, count
);
2314 info
->start_instance
= 0;
2315 info
->instance_count
= 1;
2316 if (dev
->context
.stream_instancedata_mask
& dev
->context
.stream_usage_mask
)
2317 info
->instance_count
= MAX2(dev
->context
.stream_freq
[0] & 0x7FFFFF, 1);
2318 info
->primitive_restart
= FALSE
;
2319 info
->has_user_indices
= FALSE
;
2320 info
->restart_index
= 0;
2321 info
->count_from_stream_output
= NULL
;
2322 info
->indirect
= NULL
;
2325 CSMT_ITEM_NO_WAIT(nine_context_draw_primitive
,
2326 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2327 ARG_VAL(UINT
, StartVertex
),
2328 ARG_VAL(UINT
, PrimitiveCount
))
2330 struct nine_context
*context
= &device
->context
;
2331 struct pipe_draw_info info
;
2333 nine_update_state(device
);
2335 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2336 info
.index_size
= 0;
2337 info
.start
= StartVertex
;
2338 info
.index_bias
= 0;
2339 info
.min_index
= info
.start
;
2340 info
.max_index
= info
.count
- 1;
2341 info
.index
.resource
= NULL
;
2343 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2346 CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive
,
2347 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2348 ARG_VAL(INT
, BaseVertexIndex
),
2349 ARG_VAL(UINT
, MinVertexIndex
),
2350 ARG_VAL(UINT
, NumVertices
),
2351 ARG_VAL(UINT
, StartIndex
),
2352 ARG_VAL(UINT
, PrimitiveCount
))
2354 struct nine_context
*context
= &device
->context
;
2355 struct pipe_draw_info info
;
2357 nine_update_state(device
);
2359 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2360 info
.index_size
= context
->index_size
;
2361 info
.start
= context
->index_offset
/ context
->index_size
+ StartIndex
;
2362 info
.index_bias
= BaseVertexIndex
;
2363 /* These don't include index bias: */
2364 info
.min_index
= MinVertexIndex
;
2365 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2366 info
.index
.resource
= context
->idxbuf
;
2368 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2371 CSMT_ITEM_NO_WAIT(nine_context_draw_primitive_from_vtxbuf
,
2372 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2373 ARG_VAL(UINT
, PrimitiveCount
),
2374 ARG_BIND_VBUF(struct pipe_vertex_buffer
, vtxbuf
))
2376 struct nine_context
*context
= &device
->context
;
2377 struct pipe_draw_info info
;
2379 nine_update_state(device
);
2381 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2382 info
.index_size
= 0;
2384 info
.index_bias
= 0;
2386 info
.max_index
= info
.count
- 1;
2387 info
.index
.resource
= NULL
;
2389 context
->pipe
->set_vertex_buffers(context
->pipe
, 0, 1, vtxbuf
);
2391 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2394 CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf
,
2395 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2396 ARG_VAL(UINT
, MinVertexIndex
),
2397 ARG_VAL(UINT
, NumVertices
),
2398 ARG_VAL(UINT
, PrimitiveCount
),
2399 ARG_BIND_VBUF(struct pipe_vertex_buffer
, vbuf
),
2400 ARG_BIND_RES(struct pipe_resource
, ibuf
),
2401 ARG_VAL(void *, user_ibuf
),
2402 ARG_VAL(UINT
, index_offset
),
2403 ARG_VAL(UINT
, index_size
))
2405 struct nine_context
*context
= &device
->context
;
2406 struct pipe_draw_info info
;
2408 nine_update_state(device
);
2410 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2411 info
.index_size
= index_size
;
2412 info
.start
= index_offset
/ info
.index_size
;
2413 info
.index_bias
= 0;
2414 info
.min_index
= MinVertexIndex
;
2415 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2416 info
.has_user_indices
= ibuf
== NULL
;
2418 info
.index
.resource
= ibuf
;
2420 info
.index
.user
= user_ibuf
;
2422 context
->pipe
->set_vertex_buffers(context
->pipe
, 0, 1, vbuf
);
2424 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2427 CSMT_ITEM_NO_WAIT(nine_context_resource_copy_region
,
2428 ARG_BIND_REF(struct NineUnknown
, dst
),
2429 ARG_BIND_REF(struct NineUnknown
, src
),
2430 ARG_BIND_RES(struct pipe_resource
, dst_res
),
2431 ARG_VAL(unsigned, dst_level
),
2432 ARG_COPY_REF(struct pipe_box
, dst_box
),
2433 ARG_BIND_RES(struct pipe_resource
, src_res
),
2434 ARG_VAL(unsigned, src_level
),
2435 ARG_COPY_REF(struct pipe_box
, src_box
))
2437 struct nine_context
*context
= &device
->context
;
2442 context
->pipe
->resource_copy_region(context
->pipe
,
2444 dst_box
->x
, dst_box
->y
, dst_box
->z
,
2449 CSMT_ITEM_NO_WAIT(nine_context_blit
,
2450 ARG_BIND_REF(struct NineUnknown
, dst
),
2451 ARG_BIND_REF(struct NineUnknown
, src
),
2452 ARG_BIND_BLIT(struct pipe_blit_info
, blit
))
2454 struct nine_context
*context
= &device
->context
;
2459 context
->pipe
->blit(context
->pipe
, blit
);
2462 CSMT_ITEM_NO_WAIT(nine_context_clear_render_target
,
2463 ARG_BIND_REF(struct NineSurface9
, surface
),
2464 ARG_VAL(D3DCOLOR
, color
),
2467 ARG_VAL(UINT
, width
),
2468 ARG_VAL(UINT
, height
))
2470 struct nine_context
*context
= &device
->context
;
2471 struct pipe_surface
*surf
;
2472 union pipe_color_union rgba
;
2474 d3dcolor_to_pipe_color_union(&rgba
, color
);
2475 surf
= NineSurface9_GetSurface(surface
, 0);
2476 context
->pipe
->clear_render_target(context
->pipe
, surf
, &rgba
, x
, y
, width
, height
, false);
2479 CSMT_ITEM_NO_WAIT(nine_context_gen_mipmap
,
2480 ARG_BIND_REF(struct NineUnknown
, dst
),
2481 ARG_BIND_RES(struct pipe_resource
, res
),
2482 ARG_VAL(UINT
, base_level
),
2483 ARG_VAL(UINT
, last_level
),
2484 ARG_VAL(UINT
, first_layer
),
2485 ARG_VAL(UINT
, last_layer
),
2486 ARG_VAL(UINT
, filter
))
2488 struct nine_context
*context
= &device
->context
;
2490 /* We just bind dst for the bind count */
2493 util_gen_mipmap(context
->pipe
, res
, res
->format
, base_level
,
2494 last_level
, first_layer
, last_layer
, filter
);
2497 CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_range_upload
,
2498 ARG_BIND_REF(struct NineUnknown
, src_ref
),
2499 ARG_BIND_RES(struct pipe_resource
, res
),
2500 ARG_VAL(unsigned, offset
),
2501 ARG_VAL(unsigned, size
),
2502 ARG_VAL(const void *, data
))
2504 struct nine_context
*context
= &device
->context
;
2506 /* Binding src_ref avoids release before upload */
2509 context
->pipe
->buffer_subdata(context
->pipe
, res
, 0, offset
, size
, data
);
2512 CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_box_upload
,
2513 ARG_BIND_REF(struct NineUnknown
, src_ref
),
2514 ARG_BIND_RES(struct pipe_resource
, res
),
2515 ARG_VAL(unsigned, level
),
2516 ARG_COPY_REF(struct pipe_box
, dst_box
),
2517 ARG_VAL(enum pipe_format
, src_format
),
2518 ARG_VAL(const void *, src
),
2519 ARG_VAL(unsigned, src_stride
),
2520 ARG_VAL(unsigned, src_layer_stride
),
2521 ARG_COPY_REF(struct pipe_box
, src_box
))
2523 struct nine_context
*context
= &device
->context
;
2524 struct pipe_context
*pipe
= context
->pipe
;
2525 struct pipe_transfer
*transfer
= NULL
;
2528 /* Binding src_ref avoids release before upload */
2531 map
= pipe
->transfer_map(pipe
,
2534 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
,
2535 dst_box
, &transfer
);
2539 /* Note: if formats are the sames, it will revert
2540 * to normal memcpy */
2541 (void) util_format_translate_3d(res
->format
,
2542 map
, transfer
->stride
,
2543 transfer
->layer_stride
,
2548 src_box
->x
, src_box
->y
, src_box
->z
,
2549 dst_box
->width
, dst_box
->height
,
2552 pipe_transfer_unmap(pipe
, transfer
);
2556 nine_context_create_query(struct NineDevice9
*device
, unsigned query_type
)
2558 struct pipe_context
*pipe
;
2559 struct pipe_query
*res
;
2561 pipe
= nine_context_get_pipe_acquire(device
);
2562 res
= pipe
->create_query(pipe
, query_type
, 0);
2563 nine_context_get_pipe_release(device
);
2567 CSMT_ITEM_DO_WAIT(nine_context_destroy_query
,
2568 ARG_REF(struct pipe_query
, query
))
2570 struct nine_context
*context
= &device
->context
;
2572 context
->pipe
->destroy_query(context
->pipe
, query
);
2575 CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_begin_query
,
2576 ARG_REF(struct pipe_query
, query
))
2578 struct nine_context
*context
= &device
->context
;
2580 (void) context
->pipe
->begin_query(context
->pipe
, query
);
2583 CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_end_query
,
2584 ARG_REF(struct pipe_query
, query
))
2586 struct nine_context
*context
= &device
->context
;
2588 (void) context
->pipe
->end_query(context
->pipe
, query
);
2592 nine_context_get_query_result(struct NineDevice9
*device
, struct pipe_query
*query
,
2593 unsigned *counter
, boolean flush
, boolean wait
,
2594 union pipe_query_result
*result
)
2596 struct pipe_context
*pipe
;
2600 nine_csmt_process(device
);
2601 else if (p_atomic_read(counter
) > 0) {
2602 if (flush
&& device
->csmt_active
)
2603 nine_queue_flush(device
->csmt_ctx
->pool
);
2604 DBG("Pending begin/end. Returning\n");
2608 pipe
= nine_context_get_pipe_acquire(device
);
2609 ret
= pipe
->get_query_result(pipe
, query
, wait
, result
);
2610 nine_context_get_pipe_release(device
);
2612 DBG("Query result %s\n", ret
? "found" : "not yet available");
2616 /* State defaults */
2618 static const DWORD nine_render_state_defaults
[NINED3DRS_LAST
+ 1] =
2620 /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */
2621 [D3DRS_ZENABLE
] = D3DZB_FALSE
,
2622 [D3DRS_FILLMODE
] = D3DFILL_SOLID
,
2623 [D3DRS_SHADEMODE
] = D3DSHADE_GOURAUD
,
2624 /* [D3DRS_LINEPATTERN] = 0x00000000, */
2625 [D3DRS_ZWRITEENABLE
] = TRUE
,
2626 [D3DRS_ALPHATESTENABLE
] = FALSE
,
2627 [D3DRS_LASTPIXEL
] = TRUE
,
2628 [D3DRS_SRCBLEND
] = D3DBLEND_ONE
,
2629 [D3DRS_DESTBLEND
] = D3DBLEND_ZERO
,
2630 [D3DRS_CULLMODE
] = D3DCULL_CCW
,
2631 [D3DRS_ZFUNC
] = D3DCMP_LESSEQUAL
,
2632 [D3DRS_ALPHAFUNC
] = D3DCMP_ALWAYS
,
2633 [D3DRS_ALPHAREF
] = 0,
2634 [D3DRS_DITHERENABLE
] = FALSE
,
2635 [D3DRS_ALPHABLENDENABLE
] = FALSE
,
2636 [D3DRS_FOGENABLE
] = FALSE
,
2637 [D3DRS_SPECULARENABLE
] = FALSE
,
2638 /* [D3DRS_ZVISIBLE] = 0, */
2639 [D3DRS_FOGCOLOR
] = 0,
2640 [D3DRS_FOGTABLEMODE
] = D3DFOG_NONE
,
2641 [D3DRS_FOGSTART
] = 0x00000000,
2642 [D3DRS_FOGEND
] = 0x3F800000,
2643 [D3DRS_FOGDENSITY
] = 0x3F800000,
2644 /* [D3DRS_EDGEANTIALIAS] = FALSE, */
2645 [D3DRS_RANGEFOGENABLE
] = FALSE
,
2646 [D3DRS_STENCILENABLE
] = FALSE
,
2647 [D3DRS_STENCILFAIL
] = D3DSTENCILOP_KEEP
,
2648 [D3DRS_STENCILZFAIL
] = D3DSTENCILOP_KEEP
,
2649 [D3DRS_STENCILPASS
] = D3DSTENCILOP_KEEP
,
2650 [D3DRS_STENCILREF
] = 0,
2651 [D3DRS_STENCILMASK
] = 0xFFFFFFFF,
2652 [D3DRS_STENCILFUNC
] = D3DCMP_ALWAYS
,
2653 [D3DRS_STENCILWRITEMASK
] = 0xFFFFFFFF,
2654 [D3DRS_TEXTUREFACTOR
] = 0xFFFFFFFF,
2663 [D3DRS_CLIPPING
] = TRUE
,
2664 [D3DRS_LIGHTING
] = TRUE
,
2665 [D3DRS_AMBIENT
] = 0,
2666 [D3DRS_FOGVERTEXMODE
] = D3DFOG_NONE
,
2667 [D3DRS_COLORVERTEX
] = TRUE
,
2668 [D3DRS_LOCALVIEWER
] = TRUE
,
2669 [D3DRS_NORMALIZENORMALS
] = FALSE
,
2670 [D3DRS_DIFFUSEMATERIALSOURCE
] = D3DMCS_COLOR1
,
2671 [D3DRS_SPECULARMATERIALSOURCE
] = D3DMCS_COLOR2
,
2672 [D3DRS_AMBIENTMATERIALSOURCE
] = D3DMCS_MATERIAL
,
2673 [D3DRS_EMISSIVEMATERIALSOURCE
] = D3DMCS_MATERIAL
,
2674 [D3DRS_VERTEXBLEND
] = D3DVBF_DISABLE
,
2675 [D3DRS_CLIPPLANEENABLE
] = 0,
2676 /* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */
2677 [D3DRS_POINTSIZE
] = 0x3F800000,
2678 [D3DRS_POINTSIZE_MIN
] = 0x3F800000,
2679 [D3DRS_POINTSPRITEENABLE
] = FALSE
,
2680 [D3DRS_POINTSCALEENABLE
] = FALSE
,
2681 [D3DRS_POINTSCALE_A
] = 0x3F800000,
2682 [D3DRS_POINTSCALE_B
] = 0x00000000,
2683 [D3DRS_POINTSCALE_C
] = 0x00000000,
2684 [D3DRS_MULTISAMPLEANTIALIAS
] = TRUE
,
2685 [D3DRS_MULTISAMPLEMASK
] = 0xFFFFFFFF,
2686 [D3DRS_PATCHEDGESTYLE
] = D3DPATCHEDGE_DISCRETE
,
2687 /* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */
2688 [D3DRS_DEBUGMONITORTOKEN
] = 0xDEADCAFE,
2689 [D3DRS_POINTSIZE_MAX
] = 0x3F800000, /* depends on cap */
2690 [D3DRS_INDEXEDVERTEXBLENDENABLE
] = FALSE
,
2691 [D3DRS_COLORWRITEENABLE
] = 0x0000000f,
2692 [D3DRS_TWEENFACTOR
] = 0x00000000,
2693 [D3DRS_BLENDOP
] = D3DBLENDOP_ADD
,
2694 [D3DRS_POSITIONDEGREE
] = D3DDEGREE_CUBIC
,
2695 [D3DRS_NORMALDEGREE
] = D3DDEGREE_LINEAR
,
2696 [D3DRS_SCISSORTESTENABLE
] = FALSE
,
2697 [D3DRS_SLOPESCALEDEPTHBIAS
] = 0,
2698 [D3DRS_MINTESSELLATIONLEVEL
] = 0x3F800000,
2699 [D3DRS_MAXTESSELLATIONLEVEL
] = 0x3F800000,
2700 [D3DRS_ANTIALIASEDLINEENABLE
] = FALSE
,
2701 [D3DRS_ADAPTIVETESS_X
] = 0x00000000,
2702 [D3DRS_ADAPTIVETESS_Y
] = 0x00000000,
2703 [D3DRS_ADAPTIVETESS_Z
] = 0x3F800000,
2704 [D3DRS_ADAPTIVETESS_W
] = 0x00000000,
2705 [D3DRS_ENABLEADAPTIVETESSELLATION
] = FALSE
,
2706 [D3DRS_TWOSIDEDSTENCILMODE
] = FALSE
,
2707 [D3DRS_CCW_STENCILFAIL
] = D3DSTENCILOP_KEEP
,
2708 [D3DRS_CCW_STENCILZFAIL
] = D3DSTENCILOP_KEEP
,
2709 [D3DRS_CCW_STENCILPASS
] = D3DSTENCILOP_KEEP
,
2710 [D3DRS_CCW_STENCILFUNC
] = D3DCMP_ALWAYS
,
2711 [D3DRS_COLORWRITEENABLE1
] = 0x0000000F,
2712 [D3DRS_COLORWRITEENABLE2
] = 0x0000000F,
2713 [D3DRS_COLORWRITEENABLE3
] = 0x0000000F,
2714 [D3DRS_BLENDFACTOR
] = 0xFFFFFFFF,
2715 [D3DRS_SRGBWRITEENABLE
] = 0,
2716 [D3DRS_DEPTHBIAS
] = 0,
2725 [D3DRS_SEPARATEALPHABLENDENABLE
] = FALSE
,
2726 [D3DRS_SRCBLENDALPHA
] = D3DBLEND_ONE
,
2727 [D3DRS_DESTBLENDALPHA
] = D3DBLEND_ZERO
,
2728 [D3DRS_BLENDOPALPHA
] = D3DBLENDOP_ADD
,
2729 [NINED3DRS_VSPOINTSIZE
] = FALSE
,
2730 [NINED3DRS_RTMASK
] = 0xf,
2731 [NINED3DRS_ALPHACOVERAGE
] = FALSE
,
2732 [NINED3DRS_MULTISAMPLE
] = FALSE
2734 static const DWORD nine_tex_stage_state_defaults
[NINED3DTSS_LAST
+ 1] =
2736 [D3DTSS_COLOROP
] = D3DTOP_DISABLE
,
2737 [D3DTSS_ALPHAOP
] = D3DTOP_DISABLE
,
2738 [D3DTSS_COLORARG1
] = D3DTA_TEXTURE
,
2739 [D3DTSS_COLORARG2
] = D3DTA_CURRENT
,
2740 [D3DTSS_COLORARG0
] = D3DTA_CURRENT
,
2741 [D3DTSS_ALPHAARG1
] = D3DTA_TEXTURE
,
2742 [D3DTSS_ALPHAARG2
] = D3DTA_CURRENT
,
2743 [D3DTSS_ALPHAARG0
] = D3DTA_CURRENT
,
2744 [D3DTSS_RESULTARG
] = D3DTA_CURRENT
,
2745 [D3DTSS_BUMPENVMAT00
] = 0,
2746 [D3DTSS_BUMPENVMAT01
] = 0,
2747 [D3DTSS_BUMPENVMAT10
] = 0,
2748 [D3DTSS_BUMPENVMAT11
] = 0,
2749 [D3DTSS_BUMPENVLSCALE
] = 0,
2750 [D3DTSS_BUMPENVLOFFSET
] = 0,
2751 [D3DTSS_TEXCOORDINDEX
] = 0,
2752 [D3DTSS_TEXTURETRANSFORMFLAGS
] = D3DTTFF_DISABLE
,
2754 static const DWORD nine_samp_state_defaults
[NINED3DSAMP_LAST
+ 1] =
2756 [D3DSAMP_ADDRESSU
] = D3DTADDRESS_WRAP
,
2757 [D3DSAMP_ADDRESSV
] = D3DTADDRESS_WRAP
,
2758 [D3DSAMP_ADDRESSW
] = D3DTADDRESS_WRAP
,
2759 [D3DSAMP_BORDERCOLOR
] = 0,
2760 [D3DSAMP_MAGFILTER
] = D3DTEXF_POINT
,
2761 [D3DSAMP_MINFILTER
] = D3DTEXF_POINT
,
2762 [D3DSAMP_MIPFILTER
] = D3DTEXF_NONE
,
2763 [D3DSAMP_MIPMAPLODBIAS
] = 0,
2764 [D3DSAMP_MAXMIPLEVEL
] = 0,
2765 [D3DSAMP_MAXANISOTROPY
] = 1,
2766 [D3DSAMP_SRGBTEXTURE
] = 0,
2767 [D3DSAMP_ELEMENTINDEX
] = 0,
2768 [D3DSAMP_DMAPOFFSET
] = 0,
2769 [NINED3DSAMP_MINLOD
] = 0,
2770 [NINED3DSAMP_SHADOW
] = 0,
2771 [NINED3DSAMP_CUBETEX
] = 0
2774 /* Note: The following 4 functions assume there is no
2775 * pending commands */
2777 void nine_state_restore_non_cso(struct NineDevice9
*device
)
2779 struct nine_context
*context
= &device
->context
;
2781 context
->changed
.group
= NINE_STATE_ALL
;
2782 context
->changed
.vtxbuf
= (1ULL << device
->caps
.MaxStreams
) - 1;
2783 context
->changed
.ucp
= TRUE
;
2784 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
| NINE_STATE_COMMIT_CONST_PS
;
2788 nine_state_set_defaults(struct NineDevice9
*device
, const D3DCAPS9
*caps
,
2791 struct nine_state
*state
= &device
->state
;
2792 struct nine_context
*context
= &device
->context
;
2795 /* Initialize defaults.
2797 memcpy(context
->rs
, nine_render_state_defaults
, sizeof(context
->rs
));
2799 for (s
= 0; s
< ARRAY_SIZE(state
->ff
.tex_stage
); ++s
) {
2800 memcpy(&state
->ff
.tex_stage
[s
], nine_tex_stage_state_defaults
,
2801 sizeof(state
->ff
.tex_stage
[s
]));
2802 state
->ff
.tex_stage
[s
][D3DTSS_TEXCOORDINDEX
] = s
;
2804 state
->ff
.tex_stage
[0][D3DTSS_COLOROP
] = D3DTOP_MODULATE
;
2805 state
->ff
.tex_stage
[0][D3DTSS_ALPHAOP
] = D3DTOP_SELECTARG1
;
2807 for (s
= 0; s
< ARRAY_SIZE(state
->ff
.tex_stage
); ++s
)
2808 memcpy(&context
->ff
.tex_stage
[s
], state
->ff
.tex_stage
[s
],
2809 sizeof(state
->ff
.tex_stage
[s
]));
2811 memset(&context
->bumpmap_vars
, 0, sizeof(context
->bumpmap_vars
));
2813 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
2814 memcpy(&context
->samp
[s
], nine_samp_state_defaults
,
2815 sizeof(context
->samp
[s
]));
2816 memcpy(&state
->samp_advertised
[s
], nine_samp_state_defaults
,
2817 sizeof(state
->samp_advertised
[s
]));
2820 memset(state
->vs_const_f
, 0, VS_CONST_F_SIZE(device
));
2821 memset(context
->vs_const_f
, 0, device
->vs_const_size
);
2822 if (context
->vs_const_f_swvp
)
2823 memset(context
->vs_const_f_swvp
, 0, NINE_MAX_CONST_F_SWVP
* sizeof(float[4]));
2824 memset(state
->vs_const_i
, 0, VS_CONST_I_SIZE(device
));
2825 memset(context
->vs_const_i
, 0, VS_CONST_I_SIZE(device
));
2826 memset(state
->vs_const_b
, 0, VS_CONST_B_SIZE(device
));
2827 memset(context
->vs_const_b
, 0, VS_CONST_B_SIZE(device
));
2828 memset(state
->ps_const_f
, 0, device
->ps_const_size
);
2829 memset(context
->ps_const_f
, 0, device
->ps_const_size
);
2830 memset(state
->ps_const_i
, 0, sizeof(state
->ps_const_i
));
2831 memset(context
->ps_const_i
, 0, sizeof(context
->ps_const_i
));
2832 memset(state
->ps_const_b
, 0, sizeof(state
->ps_const_b
));
2833 memset(context
->ps_const_b
, 0, sizeof(context
->ps_const_b
));
2835 /* Cap dependent initial state:
2837 context
->rs
[D3DRS_POINTSIZE_MAX
] = fui(caps
->MaxPointSize
);
2839 memcpy(state
->rs_advertised
, context
->rs
, sizeof(context
->rs
));
2841 /* Set changed flags to initialize driver.
2843 context
->changed
.group
= NINE_STATE_ALL
;
2844 context
->changed
.vtxbuf
= (1ULL << device
->caps
.MaxStreams
) - 1;
2845 context
->changed
.ucp
= TRUE
;
2847 context
->ff
.changed
.transform
[0] = ~0;
2848 context
->ff
.changed
.transform
[D3DTS_WORLD
/ 32] |= 1 << (D3DTS_WORLD
% 32);
2851 state
->viewport
.MinZ
= context
->viewport
.MinZ
= 0.0f
;
2852 state
->viewport
.MaxZ
= context
->viewport
.MaxZ
= 1.0f
;
2855 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2856 context
->changed
.sampler
[s
] = ~0;
2859 context
->dummy_vbo_bound_at
= -1;
2860 context
->vbo_bound_done
= FALSE
;
2865 nine_device_state_clear(struct NineDevice9
*device
)
2867 struct nine_state
*state
= &device
->state
;
2870 for (i
= 0; i
< ARRAY_SIZE(state
->rt
); ++i
)
2871 nine_bind(&state
->rt
[i
], NULL
);
2872 nine_bind(&state
->ds
, NULL
);
2873 nine_bind(&state
->vs
, NULL
);
2874 nine_bind(&state
->ps
, NULL
);
2875 nine_bind(&state
->vdecl
, NULL
);
2876 for (i
= 0; i
< PIPE_MAX_ATTRIBS
; ++i
)
2877 NineBindBufferToDevice(device
,
2878 (struct NineBuffer9
**)&state
->stream
[i
],
2880 NineBindBufferToDevice(device
,
2881 (struct NineBuffer9
**)&state
->idxbuf
,
2884 for (i
= 0; i
< NINE_MAX_SAMPLERS
; ++i
)
2885 NineBindTextureToDevice(device
, &state
->texture
[i
], NULL
);
2889 nine_context_clear(struct NineDevice9
*device
)
2891 struct nine_context
*context
= &device
->context
;
2892 struct pipe_context
*pipe
= context
->pipe
;
2893 struct cso_context
*cso
= context
->cso
;
2896 /* Early device ctor failure. Nothing to do */
2900 pipe
->bind_vs_state(pipe
, NULL
);
2901 pipe
->bind_fs_state(pipe
, NULL
);
2903 /* Don't unbind constant buffers, they're device-private and
2904 * do not change on Reset.
2907 cso_set_samplers(cso
, PIPE_SHADER_VERTEX
, 0, NULL
);
2908 cso_set_samplers(cso
, PIPE_SHADER_FRAGMENT
, 0, NULL
);
2910 cso_set_sampler_views(cso
, PIPE_SHADER_VERTEX
, 0, NULL
);
2911 cso_set_sampler_views(cso
, PIPE_SHADER_FRAGMENT
, 0, NULL
);
2913 pipe
->set_vertex_buffers(pipe
, 0, device
->caps
.MaxStreams
, NULL
);
2915 for (i
= 0; i
< ARRAY_SIZE(context
->rt
); ++i
)
2916 nine_bind(&context
->rt
[i
], NULL
);
2917 nine_bind(&context
->ds
, NULL
);
2918 nine_bind(&context
->vs
, NULL
);
2919 nine_bind(&context
->ps
, NULL
);
2920 nine_bind(&context
->vdecl
, NULL
);
2921 for (i
= 0; i
< PIPE_MAX_ATTRIBS
; ++i
)
2922 pipe_vertex_buffer_unreference(&context
->vtxbuf
[i
]);
2923 pipe_resource_reference(&context
->idxbuf
, NULL
);
2924 pipe_resource_reference(&context
->pipe_data
.cb_vs
.buffer
, NULL
);
2925 pipe_resource_reference(&context
->pipe_data
.cb_ps
.buffer
, NULL
);
2927 for (i
= 0; i
< NINE_MAX_SAMPLERS
; ++i
) {
2928 context
->texture
[i
].enabled
= FALSE
;
2929 pipe_resource_reference(&context
->texture
[i
].resource
,
2931 pipe_sampler_view_reference(&context
->texture
[i
].view
[0],
2933 pipe_sampler_view_reference(&context
->texture
[i
].view
[1],
2939 nine_context_update_state(struct NineDevice9
*device
)
2941 nine_update_state(device
);
2945 nine_state_init_sw(struct NineDevice9
*device
)
2947 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
2948 struct pipe_rasterizer_state rast
;
2949 struct pipe_blend_state blend
;
2950 struct pipe_depth_stencil_alpha_state dsa
;
2951 struct pipe_framebuffer_state fb
;
2953 /* Only used with Streamout */
2954 memset(&rast
, 0, sizeof(rast
));
2955 rast
.rasterizer_discard
= true;
2956 rast
.point_quad_rasterization
= 1; /* to make llvmpipe happy */
2957 cso_set_rasterizer(device
->cso_sw
, &rast
);
2959 /* dummy settings */
2960 memset(&blend
, 0, sizeof(blend
));
2961 memset(&dsa
, 0, sizeof(dsa
));
2962 memset(&fb
, 0, sizeof(fb
));
2963 cso_set_blend(device
->cso_sw
, &blend
);
2964 cso_set_depth_stencil_alpha(device
->cso_sw
, &dsa
);
2965 cso_set_framebuffer(device
->cso_sw
, &fb
);
2966 cso_set_viewport_dims(device
->cso_sw
, 1.0, 1.0, false);
2967 cso_set_fragment_shader_handle(device
->cso_sw
, util_make_empty_fragment_shader(pipe_sw
));
2970 /* There is duplication with update_vertex_elements.
2971 * TODO: Share the code */
2974 update_vertex_elements_sw(struct NineDevice9
*device
)
2976 struct nine_state
*state
= &device
->state
;
2977 const struct NineVertexDeclaration9
*vdecl
= device
->state
.vdecl
;
2978 const struct NineVertexShader9
*vs
;
2981 char vdecl_index_map
[16]; /* vs->num_inputs <= 16 */
2982 char used_streams
[device
->caps
.MaxStreams
];
2983 int dummy_vbo_stream
= -1;
2984 BOOL need_dummy_vbo
= FALSE
;
2985 struct cso_velems_state ve
;
2986 bool programmable_vs
= state
->vs
&& !(state
->vdecl
&& state
->vdecl
->position_t
);
2988 memset(vdecl_index_map
, -1, 16);
2989 memset(used_streams
, 0, device
->caps
.MaxStreams
);
2990 vs
= programmable_vs
? device
->state
.vs
: device
->ff
.vs
;
2993 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
2994 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
2995 n
, vs
->input_map
[n
].ndecl
, vdecl
);
2997 for (i
= 0; i
< vdecl
->nelems
; i
++) {
2998 if (vdecl
->usage_map
[i
] == vs
->input_map
[n
].ndecl
) {
2999 vdecl_index_map
[n
] = i
;
3000 used_streams
[vdecl
->elems
[i
].vertex_buffer_index
] = 1;
3004 if (vdecl_index_map
[n
] < 0)
3005 need_dummy_vbo
= TRUE
;
3008 /* No vertex declaration. Likely will never happen in practice,
3009 * but we need not crash on this */
3010 need_dummy_vbo
= TRUE
;
3013 if (need_dummy_vbo
) {
3014 for (i
= 0; i
< device
->caps
.MaxStreams
; i
++ ) {
3015 if (!used_streams
[i
]) {
3016 dummy_vbo_stream
= i
;
3021 /* TODO handle dummy_vbo */
3022 assert (!need_dummy_vbo
);
3024 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
3025 index
= vdecl_index_map
[n
];
3027 ve
.velems
[n
] = vdecl
->elems
[index
];
3028 b
= ve
.velems
[n
].vertex_buffer_index
;
3029 /* XXX wine just uses 1 here: */
3030 if (state
->stream_freq
[b
] & D3DSTREAMSOURCE_INSTANCEDATA
)
3031 ve
.velems
[n
].instance_divisor
= state
->stream_freq
[b
] & 0x7FFFFF;
3033 /* if the vertex declaration is incomplete compared to what the
3034 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
3035 * This is not precised by the spec, but is the behaviour
3037 ve
.velems
[n
].vertex_buffer_index
= dummy_vbo_stream
;
3038 ve
.velems
[n
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
3039 ve
.velems
[n
].src_offset
= 0;
3040 ve
.velems
[n
].instance_divisor
= 0;
3044 ve
.count
= vs
->num_inputs
;
3045 cso_set_vertex_elements(device
->cso_sw
, &ve
);
3049 update_vertex_buffers_sw(struct NineDevice9
*device
, int start_vertice
, int num_vertices
)
3051 struct pipe_context
*pipe
= nine_context_get_pipe_acquire(device
);
3052 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
3053 struct nine_state
*state
= &device
->state
;
3054 struct nine_state_sw_internal
*sw_internal
= &device
->state_sw_internal
;
3055 struct pipe_vertex_buffer vtxbuf
;
3056 uint32_t mask
= 0xf;
3059 DBG("mask=%x\n", mask
);
3061 /* TODO: handle dummy_vbo_bound_at */
3063 for (i
= 0; mask
; mask
>>= 1, ++i
) {
3065 if (state
->stream
[i
]) {
3067 struct pipe_resource
*buf
;
3068 struct pipe_box box
;
3071 vtxbuf
= state
->vtxbuf
[i
];
3072 buf
= NineVertexBuffer9_GetResource(state
->stream
[i
], &offset
);
3074 DBG("Locking %p (offset %d, length %d)\n", buf
,
3075 vtxbuf
.buffer_offset
, num_vertices
* vtxbuf
.stride
);
3077 u_box_1d(vtxbuf
.buffer_offset
+ offset
+ start_vertice
* vtxbuf
.stride
,
3078 num_vertices
* vtxbuf
.stride
, &box
);
3080 userbuf
= pipe
->transfer_map(pipe
, buf
, 0, PIPE_TRANSFER_READ
, &box
,
3081 &(sw_internal
->transfers_so
[i
]));
3082 vtxbuf
.is_user_buffer
= true;
3083 vtxbuf
.buffer
.user
= userbuf
;
3085 if (!device
->driver_caps
.user_sw_vbufs
) {
3086 vtxbuf
.buffer
.resource
= NULL
;
3087 vtxbuf
.is_user_buffer
= false;
3088 u_upload_data(device
->pipe_sw
->stream_uploader
,
3093 &(vtxbuf
.buffer_offset
),
3094 &(vtxbuf
.buffer
.resource
));
3095 u_upload_unmap(device
->pipe_sw
->stream_uploader
);
3097 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, &vtxbuf
);
3098 pipe_vertex_buffer_unreference(&vtxbuf
);
3100 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, NULL
);
3103 nine_context_get_pipe_release(device
);
3107 update_vs_constants_sw(struct NineDevice9
*device
)
3109 struct nine_state
*state
= &device
->state
;
3110 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
3115 struct pipe_constant_buffer cb
;
3119 cb
.buffer_offset
= 0;
3120 cb
.buffer_size
= 4096 * sizeof(float[4]);
3121 cb
.user_buffer
= state
->vs_const_f
;
3123 if (state
->vs
->lconstf
.ranges
) {
3124 const struct nine_lconstf
*lconstf
= &device
->state
.vs
->lconstf
;
3125 const struct nine_range
*r
= lconstf
->ranges
;
3127 float *dst
= device
->state
.vs_lconstf_temp
;
3128 float *src
= (float *)cb
.user_buffer
;
3129 memcpy(dst
, src
, 8192 * sizeof(float[4]));
3131 unsigned p
= r
->bgn
;
3132 unsigned c
= r
->end
- r
->bgn
;
3133 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
3137 cb
.user_buffer
= dst
;
3140 buf
= cb
.user_buffer
;
3142 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 0, &cb
);
3144 pipe_resource_reference(&cb
.buffer
, NULL
);
3146 cb
.user_buffer
= (char *)buf
+ 4096 * sizeof(float[4]);
3148 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 1, &cb
);
3150 pipe_resource_reference(&cb
.buffer
, NULL
);
3154 struct pipe_constant_buffer cb
;
3157 cb
.buffer_offset
= 0;
3158 cb
.buffer_size
= 2048 * sizeof(float[4]);
3159 cb
.user_buffer
= state
->vs_const_i
;
3161 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 2, &cb
);
3163 pipe_resource_reference(&cb
.buffer
, NULL
);
3167 struct pipe_constant_buffer cb
;
3170 cb
.buffer_offset
= 0;
3171 cb
.buffer_size
= 512 * sizeof(float[4]);
3172 cb
.user_buffer
= state
->vs_const_b
;
3174 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 3, &cb
);
3176 pipe_resource_reference(&cb
.buffer
, NULL
);
3180 struct pipe_constant_buffer cb
;
3181 const D3DVIEWPORT9
*vport
= &device
->state
.viewport
;
3182 float viewport_data
[8] = {(float)vport
->Width
* 0.5f
,
3183 (float)vport
->Height
* -0.5f
, vport
->MaxZ
- vport
->MinZ
, 0.f
,
3184 (float)vport
->Width
* 0.5f
+ (float)vport
->X
,
3185 (float)vport
->Height
* 0.5f
+ (float)vport
->Y
,
3189 cb
.buffer_offset
= 0;
3190 cb
.buffer_size
= 2 * sizeof(float[4]);
3191 cb
.user_buffer
= viewport_data
;
3194 u_upload_data(device
->pipe_sw
->const_uploader
,
3199 &(cb
.buffer_offset
),
3201 u_upload_unmap(device
->pipe_sw
->const_uploader
);
3202 cb
.user_buffer
= NULL
;
3205 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 4, &cb
);
3207 pipe_resource_reference(&cb
.buffer
, NULL
);
3213 nine_state_prepare_draw_sw(struct NineDevice9
*device
, struct NineVertexDeclaration9
*vdecl_out
,
3214 int start_vertice
, int num_vertices
, struct pipe_stream_output_info
*so
)
3216 struct nine_state
*state
= &device
->state
;
3217 bool programmable_vs
= state
->vs
&& !(state
->vdecl
&& state
->vdecl
->position_t
);
3218 struct NineVertexShader9
*vs
= programmable_vs
? device
->state
.vs
: device
->ff
.vs
;
3220 assert(programmable_vs
);
3222 DBG("Preparing draw\n");
3223 cso_set_vertex_shader_handle(device
->cso_sw
,
3224 NineVertexShader9_GetVariantProcessVertices(vs
, vdecl_out
, so
));
3225 update_vertex_elements_sw(device
);
3226 update_vertex_buffers_sw(device
, start_vertice
, num_vertices
);
3227 update_vs_constants_sw(device
);
3228 DBG("Preparation succeeded\n");
3232 nine_state_after_draw_sw(struct NineDevice9
*device
)
3234 struct nine_state_sw_internal
*sw_internal
= &device
->state_sw_internal
;
3235 struct pipe_context
*pipe
= nine_context_get_pipe_acquire(device
);
3236 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
3239 for (i
= 0; i
< 4; i
++) {
3240 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, NULL
);
3241 if (sw_internal
->transfers_so
[i
])
3242 pipe
->transfer_unmap(pipe
, sw_internal
->transfers_so
[i
]);
3243 sw_internal
->transfers_so
[i
] = NULL
;
3245 nine_context_get_pipe_release(device
);
3249 nine_state_destroy_sw(struct NineDevice9
*device
)
3252 /* Everything destroyed with cso */
3256 static const DWORD nine_render_states_pixel[] =
3258 D3DRS_ALPHABLENDENABLE,
3261 D3DRS_ALPHATESTENABLE,
3262 D3DRS_ANTIALIASEDLINEENABLE,
3266 D3DRS_CCW_STENCILFAIL,
3267 D3DRS_CCW_STENCILPASS,
3268 D3DRS_CCW_STENCILZFAIL,
3269 D3DRS_COLORWRITEENABLE,
3270 D3DRS_COLORWRITEENABLE1,
3271 D3DRS_COLORWRITEENABLE2,
3272 D3DRS_COLORWRITEENABLE3,
3275 D3DRS_DESTBLENDALPHA,
3282 D3DRS_SCISSORTESTENABLE,
3283 D3DRS_SEPARATEALPHABLENDENABLE,
3285 D3DRS_SLOPESCALEDEPTHBIAS,
3287 D3DRS_SRCBLENDALPHA,
3288 D3DRS_SRGBWRITEENABLE,
3289 D3DRS_STENCILENABLE,
3295 D3DRS_STENCILWRITEMASK,
3297 D3DRS_TEXTUREFACTOR,
3298 D3DRS_TWOSIDEDSTENCILMODE,
3320 const uint32_t nine_render_states_pixel
[(NINED3DRS_LAST
+ 31) / 32] =
3322 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000,
3323 0x000000ff, 0xde01c900, 0x0003ffcf
3327 static const DWORD nine_render_states_vertex[] =
3329 D3DRS_ADAPTIVETESS_W,
3330 D3DRS_ADAPTIVETESS_X,
3331 D3DRS_ADAPTIVETESS_Y,
3332 D3DRS_ADAPTIVETESS_Z,
3334 D3DRS_AMBIENTMATERIALSOURCE,
3336 D3DRS_CLIPPLANEENABLE,
3339 D3DRS_DIFFUSEMATERIALSOURCE,
3340 D3DRS_EMISSIVEMATERIALSOURCE,
3341 D3DRS_ENABLEADAPTIVETESSELLATION,
3348 D3DRS_FOGVERTEXMODE,
3349 D3DRS_INDEXEDVERTEXBLENDENABLE,
3352 D3DRS_MAXTESSELLATIONLEVEL,
3353 D3DRS_MINTESSELLATIONLEVEL,
3354 D3DRS_MULTISAMPLEANTIALIAS,
3355 D3DRS_MULTISAMPLEMASK,
3357 D3DRS_NORMALIZENORMALS,
3358 D3DRS_PATCHEDGESTYLE,
3362 D3DRS_POINTSCALEENABLE,
3364 D3DRS_POINTSIZE_MAX,
3365 D3DRS_POINTSIZE_MIN,
3366 D3DRS_POINTSPRITEENABLE,
3367 D3DRS_POSITIONDEGREE,
3368 D3DRS_RANGEFOGENABLE,
3370 D3DRS_SPECULARENABLE,
3371 D3DRS_SPECULARMATERIALSOURCE,
3376 const uint32_t nine_render_states_vertex
[(NINED3DRS_LAST
+ 31) / 32] =
3378 0x30400200, 0x0001007c, 0x00000000, 0x00000000,
3379 0xfd9efb00, 0x01fc34cf, 0x00000000
3382 /* TODO: put in the right values */
3383 const uint32_t nine_render_state_group
[NINED3DRS_LAST
+ 1] =
3385 [D3DRS_ZENABLE
] = NINE_STATE_DSA
| NINE_STATE_MULTISAMPLE
,
3386 [D3DRS_FILLMODE
] = NINE_STATE_RASTERIZER
,
3387 [D3DRS_SHADEMODE
] = NINE_STATE_RASTERIZER
,
3388 [D3DRS_ZWRITEENABLE
] = NINE_STATE_DSA
,
3389 [D3DRS_ALPHATESTENABLE
] = NINE_STATE_DSA
,
3390 [D3DRS_LASTPIXEL
] = NINE_STATE_RASTERIZER
,
3391 [D3DRS_SRCBLEND
] = NINE_STATE_BLEND
,
3392 [D3DRS_DESTBLEND
] = NINE_STATE_BLEND
,
3393 [D3DRS_CULLMODE
] = NINE_STATE_RASTERIZER
,
3394 [D3DRS_ZFUNC
] = NINE_STATE_DSA
,
3395 [D3DRS_ALPHAREF
] = NINE_STATE_DSA
,
3396 [D3DRS_ALPHAFUNC
] = NINE_STATE_DSA
,
3397 [D3DRS_DITHERENABLE
] = NINE_STATE_BLEND
,
3398 [D3DRS_ALPHABLENDENABLE
] = NINE_STATE_BLEND
,
3399 [D3DRS_FOGENABLE
] = NINE_STATE_FF_SHADER
| NINE_STATE_VS_PARAMS_MISC
| NINE_STATE_PS_PARAMS_MISC
| NINE_STATE_PS_CONST
,
3400 [D3DRS_SPECULARENABLE
] = NINE_STATE_FF_LIGHTING
,
3401 [D3DRS_FOGCOLOR
] = NINE_STATE_FF_PS_CONSTS
| NINE_STATE_PS_CONST
,
3402 [D3DRS_FOGTABLEMODE
] = NINE_STATE_FF_SHADER
| NINE_STATE_PS_PARAMS_MISC
| NINE_STATE_PS_CONST
,
3403 [D3DRS_FOGSTART
] = NINE_STATE_FF_VS_OTHER
| NINE_STATE_FF_PS_CONSTS
| NINE_STATE_PS_CONST
,
3404 [D3DRS_FOGEND
] = NINE_STATE_FF_VS_OTHER
| NINE_STATE_FF_PS_CONSTS
| NINE_STATE_PS_CONST
,
3405 [D3DRS_FOGDENSITY
] = NINE_STATE_FF_VS_OTHER
| NINE_STATE_FF_PS_CONSTS
| NINE_STATE_PS_CONST
,
3406 [D3DRS_RANGEFOGENABLE
] = NINE_STATE_FF_SHADER
,
3407 [D3DRS_STENCILENABLE
] = NINE_STATE_DSA
| NINE_STATE_MULTISAMPLE
,
3408 [D3DRS_STENCILFAIL
] = NINE_STATE_DSA
,
3409 [D3DRS_STENCILZFAIL
] = NINE_STATE_DSA
,
3410 [D3DRS_STENCILPASS
] = NINE_STATE_DSA
,
3411 [D3DRS_STENCILFUNC
] = NINE_STATE_DSA
,
3412 [D3DRS_STENCILREF
] = NINE_STATE_STENCIL_REF
,
3413 [D3DRS_STENCILMASK
] = NINE_STATE_DSA
,
3414 [D3DRS_STENCILWRITEMASK
] = NINE_STATE_DSA
,
3415 [D3DRS_TEXTUREFACTOR
] = NINE_STATE_FF_PS_CONSTS
,
3416 [D3DRS_WRAP0
] = NINE_STATE_UNHANDLED
, /* cylindrical wrap is crazy */
3417 [D3DRS_WRAP1
] = NINE_STATE_UNHANDLED
,
3418 [D3DRS_WRAP2
] = NINE_STATE_UNHANDLED
,
3419 [D3DRS_WRAP3
] = NINE_STATE_UNHANDLED
,
3420 [D3DRS_WRAP4
] = NINE_STATE_UNHANDLED
,
3421 [D3DRS_WRAP5
] = NINE_STATE_UNHANDLED
,
3422 [D3DRS_WRAP6
] = NINE_STATE_UNHANDLED
,
3423 [D3DRS_WRAP7
] = NINE_STATE_UNHANDLED
,
3424 [D3DRS_CLIPPING
] = 0, /* software vertex processing only */
3425 [D3DRS_LIGHTING
] = NINE_STATE_FF_LIGHTING
,
3426 [D3DRS_AMBIENT
] = NINE_STATE_FF_LIGHTING
| NINE_STATE_FF_MATERIAL
,
3427 [D3DRS_FOGVERTEXMODE
] = NINE_STATE_FF_SHADER
,
3428 [D3DRS_COLORVERTEX
] = NINE_STATE_FF_LIGHTING
,
3429 [D3DRS_LOCALVIEWER
] = NINE_STATE_FF_LIGHTING
,
3430 [D3DRS_NORMALIZENORMALS
] = NINE_STATE_FF_SHADER
,
3431 [D3DRS_DIFFUSEMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3432 [D3DRS_SPECULARMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3433 [D3DRS_AMBIENTMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3434 [D3DRS_EMISSIVEMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3435 [D3DRS_VERTEXBLEND
] = NINE_STATE_FF_SHADER
,
3436 [D3DRS_CLIPPLANEENABLE
] = NINE_STATE_RASTERIZER
,
3437 [D3DRS_POINTSIZE
] = NINE_STATE_RASTERIZER
| NINE_STATE_FF_VS_OTHER
,
3438 [D3DRS_POINTSIZE_MIN
] = NINE_STATE_RASTERIZER
| NINE_STATE_FF_VS_OTHER
| NINE_STATE_VS_PARAMS_MISC
,
3439 [D3DRS_POINTSPRITEENABLE
] = NINE_STATE_RASTERIZER
,
3440 [D3DRS_POINTSCALEENABLE
] = NINE_STATE_FF_SHADER
,
3441 [D3DRS_POINTSCALE_A
] = NINE_STATE_FF_VS_OTHER
,
3442 [D3DRS_POINTSCALE_B
] = NINE_STATE_FF_VS_OTHER
,
3443 [D3DRS_POINTSCALE_C
] = NINE_STATE_FF_VS_OTHER
,
3444 [D3DRS_MULTISAMPLEANTIALIAS
] = NINE_STATE_MULTISAMPLE
,
3445 [D3DRS_MULTISAMPLEMASK
] = NINE_STATE_SAMPLE_MASK
,
3446 [D3DRS_PATCHEDGESTYLE
] = NINE_STATE_UNHANDLED
,
3447 [D3DRS_DEBUGMONITORTOKEN
] = NINE_STATE_UNHANDLED
,
3448 [D3DRS_POINTSIZE_MAX
] = NINE_STATE_RASTERIZER
| NINE_STATE_FF_VS_OTHER
| NINE_STATE_VS_PARAMS_MISC
,
3449 [D3DRS_INDEXEDVERTEXBLENDENABLE
] = NINE_STATE_FF_SHADER
,
3450 [D3DRS_COLORWRITEENABLE
] = NINE_STATE_BLEND
,
3451 [D3DRS_TWEENFACTOR
] = NINE_STATE_FF_VS_OTHER
,
3452 [D3DRS_BLENDOP
] = NINE_STATE_BLEND
,
3453 [D3DRS_POSITIONDEGREE
] = NINE_STATE_UNHANDLED
,
3454 [D3DRS_NORMALDEGREE
] = NINE_STATE_UNHANDLED
,
3455 [D3DRS_SCISSORTESTENABLE
] = NINE_STATE_RASTERIZER
,
3456 [D3DRS_SLOPESCALEDEPTHBIAS
] = NINE_STATE_RASTERIZER
,
3457 [D3DRS_ANTIALIASEDLINEENABLE
] = NINE_STATE_RASTERIZER
,
3458 [D3DRS_MINTESSELLATIONLEVEL
] = NINE_STATE_UNHANDLED
,
3459 [D3DRS_MAXTESSELLATIONLEVEL
] = NINE_STATE_UNHANDLED
,
3460 [D3DRS_ADAPTIVETESS_X
] = NINE_STATE_UNHANDLED
,
3461 [D3DRS_ADAPTIVETESS_Y
] = NINE_STATE_UNHANDLED
,
3462 [D3DRS_ADAPTIVETESS_Z
] = NINE_STATE_UNHANDLED
,
3463 [D3DRS_ADAPTIVETESS_W
] = NINE_STATE_UNHANDLED
,
3464 [D3DRS_ENABLEADAPTIVETESSELLATION
] = NINE_STATE_UNHANDLED
,
3465 [D3DRS_TWOSIDEDSTENCILMODE
] = NINE_STATE_DSA
,
3466 [D3DRS_CCW_STENCILFAIL
] = NINE_STATE_DSA
,
3467 [D3DRS_CCW_STENCILZFAIL
] = NINE_STATE_DSA
,
3468 [D3DRS_CCW_STENCILPASS
] = NINE_STATE_DSA
,
3469 [D3DRS_CCW_STENCILFUNC
] = NINE_STATE_DSA
,
3470 [D3DRS_COLORWRITEENABLE1
] = NINE_STATE_BLEND
,
3471 [D3DRS_COLORWRITEENABLE2
] = NINE_STATE_BLEND
,
3472 [D3DRS_COLORWRITEENABLE3
] = NINE_STATE_BLEND
,
3473 [D3DRS_BLENDFACTOR
] = NINE_STATE_BLEND_COLOR
,
3474 [D3DRS_SRGBWRITEENABLE
] = NINE_STATE_FB
,
3475 [D3DRS_DEPTHBIAS
] = NINE_STATE_RASTERIZER
,
3476 [D3DRS_WRAP8
] = NINE_STATE_UNHANDLED
, /* cylwrap has to be done via GP */
3477 [D3DRS_WRAP9
] = NINE_STATE_UNHANDLED
,
3478 [D3DRS_WRAP10
] = NINE_STATE_UNHANDLED
,
3479 [D3DRS_WRAP11
] = NINE_STATE_UNHANDLED
,
3480 [D3DRS_WRAP12
] = NINE_STATE_UNHANDLED
,
3481 [D3DRS_WRAP13
] = NINE_STATE_UNHANDLED
,
3482 [D3DRS_WRAP14
] = NINE_STATE_UNHANDLED
,
3483 [D3DRS_WRAP15
] = NINE_STATE_UNHANDLED
,
3484 [D3DRS_SEPARATEALPHABLENDENABLE
] = NINE_STATE_BLEND
,
3485 [D3DRS_SRCBLENDALPHA
] = NINE_STATE_BLEND
,
3486 [D3DRS_DESTBLENDALPHA
] = NINE_STATE_BLEND
,
3487 [D3DRS_BLENDOPALPHA
] = NINE_STATE_BLEND
3492 static D3DMATRIX nine_state_identity
= { .m
[0] = { 1, 0, 0, 0 },
3493 .m
[1] = { 0, 1, 0, 0 },
3494 .m
[2] = { 0, 0, 1, 0 },
3495 .m
[3] = { 0, 0, 0, 1 } };
3498 nine_state_resize_transform(struct nine_ff_state
*ff_state
, unsigned N
)
3500 unsigned n
= ff_state
->num_transforms
;
3505 ff_state
->transform
= REALLOC(ff_state
->transform
,
3506 n
* sizeof(D3DMATRIX
),
3507 N
* sizeof(D3DMATRIX
));
3509 ff_state
->transform
[n
] = nine_state_identity
;
3510 ff_state
->num_transforms
= N
;
3514 nine_state_access_transform(struct nine_ff_state
*ff_state
, D3DTRANSFORMSTATETYPE t
,
3520 case D3DTS_VIEW
: index
= 0; break;
3521 case D3DTS_PROJECTION
: index
= 1; break;
3522 case D3DTS_TEXTURE0
: index
= 2; break;
3523 case D3DTS_TEXTURE1
: index
= 3; break;
3524 case D3DTS_TEXTURE2
: index
= 4; break;
3525 case D3DTS_TEXTURE3
: index
= 5; break;
3526 case D3DTS_TEXTURE4
: index
= 6; break;
3527 case D3DTS_TEXTURE5
: index
= 7; break;
3528 case D3DTS_TEXTURE6
: index
= 8; break;
3529 case D3DTS_TEXTURE7
: index
= 9; break;
3531 if (!(t
>= D3DTS_WORLDMATRIX(0) && t
<= D3DTS_WORLDMATRIX(255)))
3533 index
= 10 + (t
- D3DTS_WORLDMATRIX(0));
3537 if (index
>= ff_state
->num_transforms
) {
3539 return &nine_state_identity
;
3540 nine_state_resize_transform(ff_state
, index
+ 1);
3542 return &ff_state
->transform
[index
];
3546 nine_state_set_light(struct nine_ff_state
*ff_state
, DWORD Index
,
3547 const D3DLIGHT9
*pLight
)
3549 if (Index
>= ff_state
->num_lights
) {
3550 unsigned n
= ff_state
->num_lights
;
3551 unsigned N
= Index
+ 1;
3553 ff_state
->light
= REALLOC(ff_state
->light
, n
* sizeof(D3DLIGHT9
),
3554 N
* sizeof(D3DLIGHT9
));
3555 if (!ff_state
->light
)
3556 return E_OUTOFMEMORY
;
3557 ff_state
->num_lights
= N
;
3559 for (; n
< Index
; ++n
) {
3560 memset(&ff_state
->light
[n
], 0, sizeof(D3DLIGHT9
));
3561 ff_state
->light
[n
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
3564 ff_state
->light
[Index
] = *pLight
;
3566 if (pLight
->Type
== D3DLIGHT_SPOT
&& pLight
->Theta
>= pLight
->Phi
) {
3567 DBG("Warning: clamping D3DLIGHT9.Theta\n");
3568 ff_state
->light
[Index
].Theta
= ff_state
->light
[Index
].Phi
;
3574 nine_state_light_enable(struct nine_ff_state
*ff_state
,
3575 DWORD Index
, BOOL Enable
)
3579 user_assert(Index
< ff_state
->num_lights
, D3DERR_INVALIDCALL
);
3581 for (i
= 0; i
< ff_state
->num_lights_active
; ++i
) {
3582 if (ff_state
->active_light
[i
] == Index
)
3587 if (i
< ff_state
->num_lights_active
)
3589 /* XXX wine thinks this should still succeed:
3591 user_assert(i
< NINE_MAX_LIGHTS_ACTIVE
, D3DERR_INVALIDCALL
);
3593 ff_state
->active_light
[i
] = Index
;
3594 ff_state
->num_lights_active
++;
3596 if (i
== ff_state
->num_lights_active
)
3598 --ff_state
->num_lights_active
;
3599 for (; i
< ff_state
->num_lights_active
; ++i
)
3600 ff_state
->active_light
[i
] = ff_state
->active_light
[i
+ 1];
3606 #define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n
3607 const char *nine_d3drs_to_string(DWORD State
)
3610 D3DRS_TO_STRING_CASE(ZENABLE
);
3611 D3DRS_TO_STRING_CASE(FILLMODE
);
3612 D3DRS_TO_STRING_CASE(SHADEMODE
);
3613 D3DRS_TO_STRING_CASE(ZWRITEENABLE
);
3614 D3DRS_TO_STRING_CASE(ALPHATESTENABLE
);
3615 D3DRS_TO_STRING_CASE(LASTPIXEL
);
3616 D3DRS_TO_STRING_CASE(SRCBLEND
);
3617 D3DRS_TO_STRING_CASE(DESTBLEND
);
3618 D3DRS_TO_STRING_CASE(CULLMODE
);
3619 D3DRS_TO_STRING_CASE(ZFUNC
);
3620 D3DRS_TO_STRING_CASE(ALPHAREF
);
3621 D3DRS_TO_STRING_CASE(ALPHAFUNC
);
3622 D3DRS_TO_STRING_CASE(DITHERENABLE
);
3623 D3DRS_TO_STRING_CASE(ALPHABLENDENABLE
);
3624 D3DRS_TO_STRING_CASE(FOGENABLE
);
3625 D3DRS_TO_STRING_CASE(SPECULARENABLE
);
3626 D3DRS_TO_STRING_CASE(FOGCOLOR
);
3627 D3DRS_TO_STRING_CASE(FOGTABLEMODE
);
3628 D3DRS_TO_STRING_CASE(FOGSTART
);
3629 D3DRS_TO_STRING_CASE(FOGEND
);
3630 D3DRS_TO_STRING_CASE(FOGDENSITY
);
3631 D3DRS_TO_STRING_CASE(RANGEFOGENABLE
);
3632 D3DRS_TO_STRING_CASE(STENCILENABLE
);
3633 D3DRS_TO_STRING_CASE(STENCILFAIL
);
3634 D3DRS_TO_STRING_CASE(STENCILZFAIL
);
3635 D3DRS_TO_STRING_CASE(STENCILPASS
);
3636 D3DRS_TO_STRING_CASE(STENCILFUNC
);
3637 D3DRS_TO_STRING_CASE(STENCILREF
);
3638 D3DRS_TO_STRING_CASE(STENCILMASK
);
3639 D3DRS_TO_STRING_CASE(STENCILWRITEMASK
);
3640 D3DRS_TO_STRING_CASE(TEXTUREFACTOR
);
3641 D3DRS_TO_STRING_CASE(WRAP0
);
3642 D3DRS_TO_STRING_CASE(WRAP1
);
3643 D3DRS_TO_STRING_CASE(WRAP2
);
3644 D3DRS_TO_STRING_CASE(WRAP3
);
3645 D3DRS_TO_STRING_CASE(WRAP4
);
3646 D3DRS_TO_STRING_CASE(WRAP5
);
3647 D3DRS_TO_STRING_CASE(WRAP6
);
3648 D3DRS_TO_STRING_CASE(WRAP7
);
3649 D3DRS_TO_STRING_CASE(CLIPPING
);
3650 D3DRS_TO_STRING_CASE(LIGHTING
);
3651 D3DRS_TO_STRING_CASE(AMBIENT
);
3652 D3DRS_TO_STRING_CASE(FOGVERTEXMODE
);
3653 D3DRS_TO_STRING_CASE(COLORVERTEX
);
3654 D3DRS_TO_STRING_CASE(LOCALVIEWER
);
3655 D3DRS_TO_STRING_CASE(NORMALIZENORMALS
);
3656 D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE
);
3657 D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE
);
3658 D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE
);
3659 D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE
);
3660 D3DRS_TO_STRING_CASE(VERTEXBLEND
);
3661 D3DRS_TO_STRING_CASE(CLIPPLANEENABLE
);
3662 D3DRS_TO_STRING_CASE(POINTSIZE
);
3663 D3DRS_TO_STRING_CASE(POINTSIZE_MIN
);
3664 D3DRS_TO_STRING_CASE(POINTSPRITEENABLE
);
3665 D3DRS_TO_STRING_CASE(POINTSCALEENABLE
);
3666 D3DRS_TO_STRING_CASE(POINTSCALE_A
);
3667 D3DRS_TO_STRING_CASE(POINTSCALE_B
);
3668 D3DRS_TO_STRING_CASE(POINTSCALE_C
);
3669 D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS
);
3670 D3DRS_TO_STRING_CASE(MULTISAMPLEMASK
);
3671 D3DRS_TO_STRING_CASE(PATCHEDGESTYLE
);
3672 D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN
);
3673 D3DRS_TO_STRING_CASE(POINTSIZE_MAX
);
3674 D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE
);
3675 D3DRS_TO_STRING_CASE(COLORWRITEENABLE
);
3676 D3DRS_TO_STRING_CASE(TWEENFACTOR
);
3677 D3DRS_TO_STRING_CASE(BLENDOP
);
3678 D3DRS_TO_STRING_CASE(POSITIONDEGREE
);
3679 D3DRS_TO_STRING_CASE(NORMALDEGREE
);
3680 D3DRS_TO_STRING_CASE(SCISSORTESTENABLE
);
3681 D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS
);
3682 D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE
);
3683 D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL
);
3684 D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL
);
3685 D3DRS_TO_STRING_CASE(ADAPTIVETESS_X
);
3686 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y
);
3687 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z
);
3688 D3DRS_TO_STRING_CASE(ADAPTIVETESS_W
);
3689 D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION
);
3690 D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE
);
3691 D3DRS_TO_STRING_CASE(CCW_STENCILFAIL
);
3692 D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL
);
3693 D3DRS_TO_STRING_CASE(CCW_STENCILPASS
);
3694 D3DRS_TO_STRING_CASE(CCW_STENCILFUNC
);
3695 D3DRS_TO_STRING_CASE(COLORWRITEENABLE1
);
3696 D3DRS_TO_STRING_CASE(COLORWRITEENABLE2
);
3697 D3DRS_TO_STRING_CASE(COLORWRITEENABLE3
);
3698 D3DRS_TO_STRING_CASE(BLENDFACTOR
);
3699 D3DRS_TO_STRING_CASE(SRGBWRITEENABLE
);
3700 D3DRS_TO_STRING_CASE(DEPTHBIAS
);
3701 D3DRS_TO_STRING_CASE(WRAP8
);
3702 D3DRS_TO_STRING_CASE(WRAP9
);
3703 D3DRS_TO_STRING_CASE(WRAP10
);
3704 D3DRS_TO_STRING_CASE(WRAP11
);
3705 D3DRS_TO_STRING_CASE(WRAP12
);
3706 D3DRS_TO_STRING_CASE(WRAP13
);
3707 D3DRS_TO_STRING_CASE(WRAP14
);
3708 D3DRS_TO_STRING_CASE(WRAP15
);
3709 D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE
);
3710 D3DRS_TO_STRING_CASE(SRCBLENDALPHA
);
3711 D3DRS_TO_STRING_CASE(DESTBLENDALPHA
);
3712 D3DRS_TO_STRING_CASE(BLENDOPALPHA
);