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"
49 #include "nine_queue.h"
50 #include "nine_csmt_helper.h"
51 #include "os/os_thread.h"
53 #define DBG_CHANNEL DBG_DEVICE
57 struct csmt_instruction
{
58 int (* func
)(struct NineDevice9
*This
, struct csmt_instruction
*instr
);
63 struct nine_queue_pool
* pool
;
65 pipe_condvar event_processed
;
66 pipe_mutex mutex_processed
;
67 struct NineDevice9
*device
;
71 /* Wait for instruction to be processed.
72 * Caller has to ensure that only one thread waits at time.
75 nine_csmt_wait_processed(struct csmt_context
*ctx
)
77 pipe_mutex_lock(ctx
->mutex_processed
);
78 while (!p_atomic_read(&ctx
->processed
)) {
79 pipe_condvar_wait(ctx
->event_processed
, ctx
->mutex_processed
);
81 pipe_mutex_unlock(ctx
->mutex_processed
);
84 /* CSMT worker thread */
86 PIPE_THREAD_ROUTINE(nine_csmt_worker
, arg
)
88 struct csmt_context
*ctx
= arg
;
89 struct csmt_instruction
*instr
;
90 DBG("CSMT worker spawned\n");
92 pipe_thread_setname("CSMT-Worker");
95 nine_queue_wait_flush(ctx
->pool
);
97 /* Get instruction. NULL on empty cmdbuf. */
98 while (!p_atomic_read(&ctx
->terminate
) &&
99 (instr
= (struct csmt_instruction
*)nine_queue_get(ctx
->pool
))) {
102 if (instr
->func(ctx
->device
, instr
)) {
103 pipe_mutex_lock(ctx
->mutex_processed
);
104 p_atomic_set(&ctx
->processed
, TRUE
);
105 pipe_condvar_signal(ctx
->event_processed
);
106 pipe_mutex_unlock(ctx
->mutex_processed
);
109 if (p_atomic_read(&ctx
->terminate
)) {
110 pipe_mutex_lock(ctx
->mutex_processed
);
111 p_atomic_set(&ctx
->processed
, TRUE
);
112 pipe_condvar_signal(ctx
->event_processed
);
113 pipe_mutex_unlock(ctx
->mutex_processed
);
118 DBG("CSMT worker destroyed\n");
122 /* Create a CSMT context.
123 * Spawns a worker thread.
125 struct csmt_context
*
126 nine_csmt_create( struct NineDevice9
*This
)
128 struct csmt_context
*ctx
;
130 ctx
= CALLOC_STRUCT(csmt_context
);
134 ctx
->pool
= nine_queue_create();
139 pipe_condvar_init(ctx
->event_processed
);
140 pipe_mutex_init(ctx
->mutex_processed
);
143 pipe_thread_setname("Main thread");
148 ctx
->worker
= pipe_thread_create(nine_csmt_worker
, ctx
);
150 nine_queue_delete(ctx
->pool
);
155 DBG("Returning context %p\n", ctx
);
161 nop_func( struct NineDevice9
*This
, struct csmt_instruction
*instr
)
169 /* Push nop instruction and flush the queue.
170 * Waits for the worker to complete. */
172 nine_csmt_process( struct NineDevice9
*device
)
174 struct csmt_instruction
* instr
;
175 struct csmt_context
*ctx
= device
->csmt_ctx
;
177 if (!device
->csmt_active
)
180 if (nine_queue_isempty(ctx
->pool
))
183 DBG("device=%p\n", device
);
186 instr
= nine_queue_alloc(ctx
->pool
, sizeof(struct csmt_instruction
));
188 instr
->func
= nop_func
;
190 p_atomic_set(&ctx
->processed
, FALSE
);
191 nine_queue_flush(ctx
->pool
);
193 nine_csmt_wait_processed(ctx
);
196 /* Destroys a CSMT context.
197 * Waits for the worker thread to terminate.
200 nine_csmt_destroy( struct NineDevice9
*device
, struct csmt_context
*ctx
)
202 struct csmt_instruction
* instr
;
203 pipe_thread render_thread
= ctx
->worker
;
205 DBG("device=%p ctx=%p\n", device
, ctx
);
207 /* Push nop and flush the queue. */
208 instr
= nine_queue_alloc(ctx
->pool
, sizeof(struct csmt_instruction
));
210 instr
->func
= nop_func
;
212 p_atomic_set(&ctx
->processed
, FALSE
);
213 /* Signal worker to terminate. */
214 p_atomic_set(&ctx
->terminate
, TRUE
);
215 nine_queue_flush(ctx
->pool
);
217 nine_csmt_wait_processed(ctx
);
218 nine_queue_delete(ctx
->pool
);
219 pipe_mutex_destroy(ctx
->mutex_processed
);
223 pipe_thread_wait(render_thread
);
226 struct pipe_context
*
227 nine_context_get_pipe( struct NineDevice9
*device
)
229 if (device
->csmt_active
)
230 nine_csmt_process(device
);
231 return device
->context
.pipe
;
234 struct pipe_context
*
235 nine_context_get_pipe_multithread( struct NineDevice9
*device
)
237 struct csmt_context
*ctx
= device
->csmt_ctx
;
239 if (!device
->csmt_active
)
240 return device
->context
.pipe
;
242 if (!pipe_thread_is_self(ctx
->worker
))
243 nine_csmt_process(device
);
245 return device
->context
.pipe
;
247 /* Nine state functions */
249 /* Check if some states need to be set dirty */
252 check_multisample(struct NineDevice9
*device
)
254 DWORD
*rs
= device
->context
.rs
;
255 DWORD new_value
= (rs
[D3DRS_ZENABLE
] || rs
[D3DRS_STENCILENABLE
]) &&
256 device
->context
.rt
[0]->desc
.MultiSampleType
>= 1 &&
257 rs
[D3DRS_MULTISAMPLEANTIALIAS
];
258 if (rs
[NINED3DRS_MULTISAMPLE
] != new_value
) {
259 rs
[NINED3DRS_MULTISAMPLE
] = new_value
;
260 return NINE_STATE_RASTERIZER
;
265 /* State preparation only */
268 prepare_blend(struct NineDevice9
*device
)
270 nine_convert_blend_state(&device
->context
.pipe_data
.blend
, device
->context
.rs
);
271 device
->context
.commit
|= NINE_STATE_COMMIT_BLEND
;
275 prepare_dsa(struct NineDevice9
*device
)
277 nine_convert_dsa_state(&device
->context
.pipe_data
.dsa
, device
->context
.rs
);
278 device
->context
.commit
|= NINE_STATE_COMMIT_DSA
;
282 prepare_rasterizer(struct NineDevice9
*device
)
284 nine_convert_rasterizer_state(device
, &device
->context
.pipe_data
.rast
, device
->context
.rs
);
285 device
->context
.commit
|= NINE_STATE_COMMIT_RASTERIZER
;
289 prepare_vs_constants_userbuf_swvp(struct NineDevice9
*device
)
291 struct nine_context
*context
= &device
->context
;
293 if (context
->changed
.vs_const_f
|| context
->changed
.group
& NINE_STATE_SWVP
) {
294 struct pipe_constant_buffer cb
;
296 cb
.buffer_offset
= 0;
297 cb
.buffer_size
= 4096 * sizeof(float[4]);
298 cb
.user_buffer
= context
->vs_const_f_swvp
;
300 if (context
->vs
->lconstf
.ranges
) {
301 const struct nine_lconstf
*lconstf
= &(context
->vs
->lconstf
);
302 const struct nine_range
*r
= lconstf
->ranges
;
304 float *dst
= context
->vs_lconstf_temp
;
305 float *src
= (float *)cb
.user_buffer
;
306 memcpy(dst
, src
, cb
.buffer_size
);
309 unsigned c
= r
->end
- r
->bgn
;
310 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
314 cb
.user_buffer
= dst
;
317 /* Do not erase the buffer field.
318 * It is either NULL (user_cbufs), or a resource.
319 * u_upload_data will do the proper refcount */
320 context
->pipe_data
.cb0_swvp
.buffer_offset
= cb
.buffer_offset
;
321 context
->pipe_data
.cb0_swvp
.buffer_size
= cb
.buffer_size
;
322 context
->pipe_data
.cb0_swvp
.user_buffer
= cb
.user_buffer
;
324 cb
.user_buffer
= (char *)cb
.user_buffer
+ 4096 * sizeof(float[4]);
325 context
->pipe_data
.cb1_swvp
.buffer_offset
= cb
.buffer_offset
;
326 context
->pipe_data
.cb1_swvp
.buffer_size
= cb
.buffer_size
;
327 context
->pipe_data
.cb1_swvp
.user_buffer
= cb
.user_buffer
;
329 context
->changed
.vs_const_f
= 0;
332 if (context
->changed
.vs_const_i
|| context
->changed
.group
& NINE_STATE_SWVP
) {
333 struct pipe_constant_buffer cb
;
335 cb
.buffer_offset
= 0;
336 cb
.buffer_size
= 2048 * sizeof(float[4]);
337 cb
.user_buffer
= context
->vs_const_i
;
339 context
->pipe_data
.cb2_swvp
.buffer_offset
= cb
.buffer_offset
;
340 context
->pipe_data
.cb2_swvp
.buffer_size
= cb
.buffer_size
;
341 context
->pipe_data
.cb2_swvp
.user_buffer
= cb
.user_buffer
;
342 context
->changed
.vs_const_i
= 0;
345 if (context
->changed
.vs_const_b
|| context
->changed
.group
& NINE_STATE_SWVP
) {
346 struct pipe_constant_buffer cb
;
348 cb
.buffer_offset
= 0;
349 cb
.buffer_size
= 512 * sizeof(float[4]);
350 cb
.user_buffer
= context
->vs_const_b
;
352 context
->pipe_data
.cb3_swvp
.buffer_offset
= cb
.buffer_offset
;
353 context
->pipe_data
.cb3_swvp
.buffer_size
= cb
.buffer_size
;
354 context
->pipe_data
.cb3_swvp
.user_buffer
= cb
.user_buffer
;
355 context
->changed
.vs_const_b
= 0;
358 if (!device
->driver_caps
.user_cbufs
) {
359 struct pipe_constant_buffer
*cb
= &(context
->pipe_data
.cb0_swvp
);
360 u_upload_data(device
->constbuf_uploader
,
363 device
->constbuf_alignment
,
365 &(cb
->buffer_offset
),
367 u_upload_unmap(device
->constbuf_uploader
);
368 cb
->user_buffer
= NULL
;
370 cb
= &(context
->pipe_data
.cb1_swvp
);
371 u_upload_data(device
->constbuf_uploader
,
374 device
->constbuf_alignment
,
376 &(cb
->buffer_offset
),
378 u_upload_unmap(device
->constbuf_uploader
);
379 cb
->user_buffer
= NULL
;
381 cb
= &(context
->pipe_data
.cb2_swvp
);
382 u_upload_data(device
->constbuf_uploader
,
385 device
->constbuf_alignment
,
387 &(cb
->buffer_offset
),
389 u_upload_unmap(device
->constbuf_uploader
);
390 cb
->user_buffer
= NULL
;
392 cb
= &(context
->pipe_data
.cb3_swvp
);
393 u_upload_data(device
->constbuf_uploader
,
396 device
->constbuf_alignment
,
398 &(cb
->buffer_offset
),
400 u_upload_unmap(device
->constbuf_uploader
);
401 cb
->user_buffer
= NULL
;
404 context
->changed
.group
&= ~NINE_STATE_VS_CONST
;
405 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
409 prepare_vs_constants_userbuf(struct NineDevice9
*device
)
411 struct nine_context
*context
= &device
->context
;
412 struct pipe_constant_buffer cb
;
414 cb
.buffer_offset
= 0;
415 cb
.buffer_size
= context
->vs
->const_used_size
;
416 cb
.user_buffer
= context
->vs_const_f
;
419 prepare_vs_constants_userbuf_swvp(device
);
423 if (context
->changed
.vs_const_i
|| context
->changed
.group
& NINE_STATE_SWVP
) {
424 int *idst
= (int *)&context
->vs_const_f
[4 * device
->max_vs_const_f
];
425 memcpy(idst
, context
->vs_const_i
, NINE_MAX_CONST_I
* sizeof(int[4]));
426 context
->changed
.vs_const_i
= 0;
429 if (context
->changed
.vs_const_b
|| context
->changed
.group
& NINE_STATE_SWVP
) {
430 int *idst
= (int *)&context
->vs_const_f
[4 * device
->max_vs_const_f
];
431 uint32_t *bdst
= (uint32_t *)&idst
[4 * NINE_MAX_CONST_I
];
432 memcpy(bdst
, context
->vs_const_b
, NINE_MAX_CONST_B
* sizeof(BOOL
));
433 context
->changed
.vs_const_b
= 0;
439 if (context
->vs
->lconstf
.ranges
) {
440 /* TODO: Can we make it so that we don't have to copy everything ? */
441 const struct nine_lconstf
*lconstf
= &(context
->vs
->lconstf
);
442 const struct nine_range
*r
= lconstf
->ranges
;
444 float *dst
= context
->vs_lconstf_temp
;
445 float *src
= (float *)cb
.user_buffer
;
446 memcpy(dst
, src
, cb
.buffer_size
);
449 unsigned c
= r
->end
- r
->bgn
;
450 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
454 cb
.user_buffer
= dst
;
457 if (!device
->driver_caps
.user_cbufs
) {
458 context
->pipe_data
.cb_vs
.buffer_size
= cb
.buffer_size
;
459 u_upload_data(device
->constbuf_uploader
,
462 device
->constbuf_alignment
,
464 &context
->pipe_data
.cb_vs
.buffer_offset
,
465 &context
->pipe_data
.cb_vs
.buffer
);
466 u_upload_unmap(device
->constbuf_uploader
);
467 context
->pipe_data
.cb_vs
.user_buffer
= NULL
;
469 context
->pipe_data
.cb_vs
= cb
;
471 context
->changed
.vs_const_f
= 0;
473 context
->changed
.group
&= ~NINE_STATE_VS_CONST
;
474 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
478 prepare_ps_constants_userbuf(struct NineDevice9
*device
)
480 struct nine_context
*context
= &device
->context
;
481 struct pipe_constant_buffer cb
;
483 cb
.buffer_offset
= 0;
484 cb
.buffer_size
= context
->ps
->const_used_size
;
485 cb
.user_buffer
= context
->ps_const_f
;
487 if (context
->changed
.ps_const_i
) {
488 int *idst
= (int *)&context
->ps_const_f
[4 * device
->max_ps_const_f
];
489 memcpy(idst
, context
->ps_const_i
, sizeof(context
->ps_const_i
));
490 context
->changed
.ps_const_i
= 0;
492 if (context
->changed
.ps_const_b
) {
493 int *idst
= (int *)&context
->ps_const_f
[4 * device
->max_ps_const_f
];
494 uint32_t *bdst
= (uint32_t *)&idst
[4 * NINE_MAX_CONST_I
];
495 memcpy(bdst
, context
->ps_const_b
, sizeof(context
->ps_const_b
));
496 context
->changed
.ps_const_b
= 0;
499 /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */
500 if (context
->ps
->bumpenvmat_needed
) {
501 memcpy(context
->ps_lconstf_temp
, cb
.user_buffer
, cb
.buffer_size
);
502 memcpy(&context
->ps_lconstf_temp
[4 * 8], &device
->context
.bumpmap_vars
, sizeof(device
->context
.bumpmap_vars
));
504 cb
.user_buffer
= context
->ps_lconstf_temp
;
507 if (context
->ps
->byte_code
.version
< 0x30 &&
508 context
->rs
[D3DRS_FOGENABLE
]) {
509 float *dst
= &context
->ps_lconstf_temp
[4 * 32];
510 if (cb
.user_buffer
!= context
->ps_lconstf_temp
) {
511 memcpy(context
->ps_lconstf_temp
, cb
.user_buffer
, cb
.buffer_size
);
512 cb
.user_buffer
= context
->ps_lconstf_temp
;
515 d3dcolor_to_rgba(dst
, context
->rs
[D3DRS_FOGCOLOR
]);
516 if (context
->rs
[D3DRS_FOGTABLEMODE
] == D3DFOG_LINEAR
) {
517 dst
[4] = asfloat(context
->rs
[D3DRS_FOGEND
]);
518 dst
[5] = 1.0f
/ (asfloat(context
->rs
[D3DRS_FOGEND
]) - asfloat(context
->rs
[D3DRS_FOGSTART
]));
519 } else if (context
->rs
[D3DRS_FOGTABLEMODE
] != D3DFOG_NONE
) {
520 dst
[4] = asfloat(context
->rs
[D3DRS_FOGDENSITY
]);
522 cb
.buffer_size
= 4 * 4 * 34;
528 if (!device
->driver_caps
.user_cbufs
) {
529 context
->pipe_data
.cb_ps
.buffer_size
= cb
.buffer_size
;
530 u_upload_data(device
->constbuf_uploader
,
533 device
->constbuf_alignment
,
535 &context
->pipe_data
.cb_ps
.buffer_offset
,
536 &context
->pipe_data
.cb_ps
.buffer
);
537 u_upload_unmap(device
->constbuf_uploader
);
538 context
->pipe_data
.cb_ps
.user_buffer
= NULL
;
540 context
->pipe_data
.cb_ps
= cb
;
542 context
->changed
.ps_const_f
= 0;
544 context
->changed
.group
&= ~NINE_STATE_PS_CONST
;
545 context
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
548 static inline uint32_t
549 prepare_vs(struct NineDevice9
*device
, uint8_t shader_changed
)
551 struct nine_context
*context
= &device
->context
;
552 struct NineVertexShader9
*vs
= context
->vs
;
553 uint32_t changed_group
= 0;
554 int has_key_changed
= 0;
556 if (likely(context
->programmable_vs
))
557 has_key_changed
= NineVertexShader9_UpdateKey(vs
, device
);
559 if (!shader_changed
&& !has_key_changed
)
562 /* likely because we dislike FF */
563 if (likely(context
->programmable_vs
)) {
564 context
->cso_shader
.vs
= NineVertexShader9_GetVariant(vs
);
567 context
->cso_shader
.vs
= vs
->ff_cso
;
570 if (context
->rs
[NINED3DRS_VSPOINTSIZE
] != vs
->point_size
) {
571 context
->rs
[NINED3DRS_VSPOINTSIZE
] = vs
->point_size
;
572 changed_group
|= NINE_STATE_RASTERIZER
;
575 if ((context
->bound_samplers_mask_vs
& vs
->sampler_mask
) != vs
->sampler_mask
)
576 /* Bound dummy sampler. */
577 changed_group
|= NINE_STATE_SAMPLER
;
579 context
->commit
|= NINE_STATE_COMMIT_VS
;
580 return changed_group
;
583 static inline uint32_t
584 prepare_ps(struct NineDevice9
*device
, uint8_t shader_changed
)
586 struct nine_context
*context
= &device
->context
;
587 struct NinePixelShader9
*ps
= context
->ps
;
588 uint32_t changed_group
= 0;
589 int has_key_changed
= 0;
592 has_key_changed
= NinePixelShader9_UpdateKey(ps
, context
);
594 if (!shader_changed
&& !has_key_changed
)
598 context
->cso_shader
.ps
= NinePixelShader9_GetVariant(ps
);
601 context
->cso_shader
.ps
= ps
->ff_cso
;
604 if ((context
->bound_samplers_mask_ps
& ps
->sampler_mask
) != ps
->sampler_mask
)
605 /* Bound dummy sampler. */
606 changed_group
|= NINE_STATE_SAMPLER
;
608 context
->commit
|= NINE_STATE_COMMIT_PS
;
609 return changed_group
;
612 /* State preparation incremental */
614 /* State preparation + State commit */
617 update_framebuffer(struct NineDevice9
*device
, bool is_clear
)
619 struct nine_context
*context
= &device
->context
;
620 struct pipe_context
*pipe
= context
->pipe
;
621 struct pipe_framebuffer_state
*fb
= &context
->pipe_data
.fb
;
623 struct NineSurface9
*rt0
= context
->rt
[0];
624 unsigned w
= rt0
->desc
.Width
;
625 unsigned h
= rt0
->desc
.Height
;
626 unsigned nr_samples
= rt0
->base
.info
.nr_samples
;
627 unsigned ps_mask
= context
->ps
? context
->ps
->rt_mask
: 1;
628 unsigned mask
= is_clear
? 0xf : ps_mask
;
629 const int sRGB
= context
->rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
633 context
->rt_mask
= 0x0;
636 /* all render targets must have the same size and the depth buffer must be
637 * bigger. Multisample has to match, according to spec. But some apps do
638 * things wrong there, and no error is returned. The behaviour they get
639 * apparently is that depth buffer is disabled if it doesn't match.
640 * Surely the same for render targets. */
642 /* Special case: D3DFMT_NULL is used to bound no real render target,
643 * but render to depth buffer. We have to not take into account the render
644 * target info. TODO: know what should happen when there are several render targers
645 * and the first one is D3DFMT_NULL */
646 if (rt0
->desc
.Format
== D3DFMT_NULL
&& context
->ds
) {
647 w
= context
->ds
->desc
.Width
;
648 h
= context
->ds
->desc
.Height
;
649 nr_samples
= context
->ds
->base
.info
.nr_samples
;
652 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
653 struct NineSurface9
*rt
= context
->rt
[i
];
655 if (rt
&& rt
->desc
.Format
!= D3DFMT_NULL
&& (mask
& (1 << i
)) &&
656 rt
->desc
.Width
== w
&& rt
->desc
.Height
== h
&&
657 rt
->base
.info
.nr_samples
== nr_samples
) {
658 fb
->cbufs
[i
] = NineSurface9_GetSurface(rt
, sRGB
);
659 context
->rt_mask
|= 1 << i
;
660 fb
->nr_cbufs
= i
+ 1;
662 /* Color outputs must match RT slot,
663 * drivers will have to handle NULL entries for GL, too.
669 if (context
->ds
&& context
->ds
->desc
.Width
>= w
&&
670 context
->ds
->desc
.Height
>= h
&&
671 context
->ds
->base
.info
.nr_samples
== nr_samples
) {
672 fb
->zsbuf
= NineSurface9_GetSurface(context
->ds
, 0);
680 pipe
->set_framebuffer_state(pipe
, fb
); /* XXX: cso ? */
682 if (is_clear
&& context
->rt_mask
== ps_mask
)
683 context
->changed
.group
&= ~NINE_STATE_FB
;
687 update_viewport(struct NineDevice9
*device
)
689 struct nine_context
*context
= &device
->context
;
690 const D3DVIEWPORT9
*vport
= &context
->viewport
;
691 struct pipe_viewport_state pvport
;
693 /* D3D coordinates are:
694 * -1 .. +1 for X,Y and
695 * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz)
697 pvport
.scale
[0] = (float)vport
->Width
* 0.5f
;
698 pvport
.scale
[1] = (float)vport
->Height
* -0.5f
;
699 pvport
.scale
[2] = vport
->MaxZ
- vport
->MinZ
;
700 pvport
.translate
[0] = (float)vport
->Width
* 0.5f
+ (float)vport
->X
;
701 pvport
.translate
[1] = (float)vport
->Height
* 0.5f
+ (float)vport
->Y
;
702 pvport
.translate
[2] = vport
->MinZ
;
704 /* We found R600 and SI cards have some imprecision
705 * on the barycentric coordinates used for interpolation.
706 * Some shaders rely on having something precise.
707 * We found that the proprietary driver has the imprecision issue,
708 * except when the render target width and height are powers of two.
709 * It is using some sort of workaround for these cases
710 * which covers likely all the cases the applications rely
711 * on something precise.
712 * We haven't found the workaround, but it seems like it's better
713 * for applications if the imprecision is biased towards infinity
714 * instead of -infinity (which is what measured). So shift slightly
715 * the viewport: not enough to change rasterization result (in particular
716 * for multisampling), but enough to make the imprecision biased
717 * towards infinity. We do this shift only if render target width and
718 * height are powers of two.
719 * Solves 'red shadows' bug on UE3 games.
721 if (device
->driver_bugs
.buggy_barycentrics
&&
722 ((vport
->Width
& (vport
->Width
-1)) == 0) &&
723 ((vport
->Height
& (vport
->Height
-1)) == 0)) {
724 pvport
.translate
[0] -= 1.0f
/ 128.0f
;
725 pvport
.translate
[1] -= 1.0f
/ 128.0f
;
728 cso_set_viewport(context
->cso
, &pvport
);
731 /* Loop through VS inputs and pick the vertex elements with the declared
732 * usage from the vertex declaration, then insert the instance divisor from
733 * the stream source frequency setting.
736 update_vertex_elements(struct NineDevice9
*device
)
738 struct nine_context
*context
= &device
->context
;
739 const struct NineVertexDeclaration9
*vdecl
= device
->context
.vdecl
;
740 const struct NineVertexShader9
*vs
;
743 char vdecl_index_map
[16]; /* vs->num_inputs <= 16 */
744 char used_streams
[device
->caps
.MaxStreams
];
745 int dummy_vbo_stream
= -1;
746 BOOL need_dummy_vbo
= FALSE
;
747 struct pipe_vertex_element ve
[PIPE_MAX_ATTRIBS
];
749 context
->stream_usage_mask
= 0;
750 memset(vdecl_index_map
, -1, 16);
751 memset(used_streams
, 0, device
->caps
.MaxStreams
);
752 vs
= context
->programmable_vs
? context
->vs
: device
->ff
.vs
;
755 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
756 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
757 n
, vs
->input_map
[n
].ndecl
, vdecl
);
759 for (i
= 0; i
< vdecl
->nelems
; i
++) {
760 if (vdecl
->usage_map
[i
] == vs
->input_map
[n
].ndecl
) {
761 vdecl_index_map
[n
] = i
;
762 used_streams
[vdecl
->elems
[i
].vertex_buffer_index
] = 1;
766 if (vdecl_index_map
[n
] < 0)
767 need_dummy_vbo
= TRUE
;
770 /* No vertex declaration. Likely will never happen in practice,
771 * but we need not crash on this */
772 need_dummy_vbo
= TRUE
;
775 if (need_dummy_vbo
) {
776 for (i
= 0; i
< device
->caps
.MaxStreams
; i
++ ) {
777 if (!used_streams
[i
]) {
778 dummy_vbo_stream
= i
;
783 /* there are less vertex shader inputs than stream slots,
784 * so if we need a slot for the dummy vbo, we should have found one */
785 assert (!need_dummy_vbo
|| dummy_vbo_stream
!= -1);
787 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
788 index
= vdecl_index_map
[n
];
790 ve
[n
] = vdecl
->elems
[index
];
791 b
= ve
[n
].vertex_buffer_index
;
792 context
->stream_usage_mask
|= 1 << b
;
793 /* XXX wine just uses 1 here: */
794 if (context
->stream_freq
[b
] & D3DSTREAMSOURCE_INSTANCEDATA
)
795 ve
[n
].instance_divisor
= context
->stream_freq
[b
] & 0x7FFFFF;
797 /* if the vertex declaration is incomplete compared to what the
798 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
799 * This is not precised by the spec, but is the behaviour
801 ve
[n
].vertex_buffer_index
= dummy_vbo_stream
;
802 ve
[n
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
803 ve
[n
].src_offset
= 0;
804 ve
[n
].instance_divisor
= 0;
808 if (context
->dummy_vbo_bound_at
!= dummy_vbo_stream
) {
809 if (context
->dummy_vbo_bound_at
>= 0)
810 context
->changed
.vtxbuf
|= 1 << context
->dummy_vbo_bound_at
;
811 if (dummy_vbo_stream
>= 0) {
812 context
->changed
.vtxbuf
|= 1 << dummy_vbo_stream
;
813 context
->vbo_bound_done
= FALSE
;
815 context
->dummy_vbo_bound_at
= dummy_vbo_stream
;
818 cso_set_vertex_elements(context
->cso
, vs
->num_inputs
, ve
);
822 update_vertex_buffers(struct NineDevice9
*device
)
824 struct nine_context
*context
= &device
->context
;
825 struct pipe_context
*pipe
= context
->pipe
;
826 struct pipe_vertex_buffer dummy_vtxbuf
;
827 uint32_t mask
= context
->changed
.vtxbuf
;
830 DBG("mask=%x\n", mask
);
832 if (context
->dummy_vbo_bound_at
>= 0) {
833 if (!context
->vbo_bound_done
) {
834 dummy_vtxbuf
.buffer
= device
->dummy_vbo
;
835 dummy_vtxbuf
.stride
= 0;
836 dummy_vtxbuf
.user_buffer
= NULL
;
837 dummy_vtxbuf
.buffer_offset
= 0;
838 pipe
->set_vertex_buffers(pipe
, context
->dummy_vbo_bound_at
,
840 context
->vbo_bound_done
= TRUE
;
842 mask
&= ~(1 << context
->dummy_vbo_bound_at
);
845 for (i
= 0; mask
; mask
>>= 1, ++i
) {
847 if (context
->vtxbuf
[i
].buffer
)
848 pipe
->set_vertex_buffers(pipe
, i
, 1, &context
->vtxbuf
[i
]);
850 pipe
->set_vertex_buffers(pipe
, i
, 1, NULL
);
854 context
->changed
.vtxbuf
= 0;
857 static inline boolean
858 update_sampler_derived(struct nine_context
*context
, unsigned s
)
860 boolean changed
= FALSE
;
862 if (context
->samp
[s
][NINED3DSAMP_SHADOW
] != context
->texture
[s
].shadow
) {
864 context
->samp
[s
][NINED3DSAMP_SHADOW
] = context
->texture
[s
].shadow
;
867 if (context
->samp
[s
][NINED3DSAMP_CUBETEX
] !=
868 (context
->texture
[s
].type
== D3DRTYPE_CUBETEXTURE
)) {
870 context
->samp
[s
][NINED3DSAMP_CUBETEX
] =
871 context
->texture
[s
].type
== D3DRTYPE_CUBETEXTURE
;
874 if (context
->samp
[s
][D3DSAMP_MIPFILTER
] != D3DTEXF_NONE
) {
875 int lod
= context
->samp
[s
][D3DSAMP_MAXMIPLEVEL
] - context
->texture
[s
].lod
;
878 if (context
->samp
[s
][NINED3DSAMP_MINLOD
] != lod
) {
880 context
->samp
[s
][NINED3DSAMP_MINLOD
] = lod
;
883 context
->changed
.sampler
[s
] &= ~0x300; /* lod changes irrelevant */
889 /* TODO: add sRGB override to pipe_sampler_state ? */
891 update_textures_and_samplers(struct NineDevice9
*device
)
893 struct nine_context
*context
= &device
->context
;
894 struct pipe_sampler_view
*view
[NINE_MAX_SAMPLERS
];
895 unsigned num_textures
;
897 boolean commit_samplers
;
898 uint16_t sampler_mask
= context
->ps
? context
->ps
->sampler_mask
:
899 device
->ff
.ps
->sampler_mask
;
901 /* TODO: Can we reduce iterations here ? */
903 commit_samplers
= FALSE
;
904 context
->bound_samplers_mask_ps
= 0;
905 for (num_textures
= 0, i
= 0; i
< NINE_MAX_SAMPLERS_PS
; ++i
) {
906 const unsigned s
= NINE_SAMPLER_PS(i
);
909 if (!context
->texture
[s
].enabled
&& !(sampler_mask
& (1 << i
))) {
914 if (context
->texture
[s
].enabled
) {
915 sRGB
= context
->samp
[s
][D3DSAMP_SRGBTEXTURE
] ? 1 : 0;
917 view
[i
] = context
->texture
[s
].view
[sRGB
];
918 num_textures
= i
+ 1;
920 if (update_sampler_derived(context
, s
) || (context
->changed
.sampler
[s
] & 0x05fe)) {
921 context
->changed
.sampler
[s
] = 0;
922 commit_samplers
= TRUE
;
923 nine_convert_sampler_state(context
->cso
, s
, context
->samp
[s
]);
926 /* Bind dummy sampler. We do not bind dummy sampler when
927 * it is not needed because it could add overhead. The
928 * dummy sampler should have r=g=b=0 and a=1. We do not
929 * unbind dummy sampler directly when they are not needed
930 * anymore, but they're going to be removed as long as texture
931 * or sampler states are changed. */
932 view
[i
] = device
->dummy_sampler_view
;
933 num_textures
= i
+ 1;
935 cso_single_sampler(context
->cso
, PIPE_SHADER_FRAGMENT
,
936 s
- NINE_SAMPLER_PS(0), &device
->dummy_sampler_state
);
938 commit_samplers
= TRUE
;
939 context
->changed
.sampler
[s
] = ~0;
942 context
->bound_samplers_mask_ps
|= (1 << s
);
945 cso_set_sampler_views(context
->cso
, PIPE_SHADER_FRAGMENT
, num_textures
, view
);
948 cso_single_sampler_done(context
->cso
, PIPE_SHADER_FRAGMENT
);
950 commit_samplers
= FALSE
;
951 sampler_mask
= context
->programmable_vs
? context
->vs
->sampler_mask
: 0;
952 context
->bound_samplers_mask_vs
= 0;
953 for (num_textures
= 0, i
= 0; i
< NINE_MAX_SAMPLERS_VS
; ++i
) {
954 const unsigned s
= NINE_SAMPLER_VS(i
);
957 if (!context
->texture
[s
].enabled
&& !(sampler_mask
& (1 << i
))) {
962 if (context
->texture
[s
].enabled
) {
963 sRGB
= context
->samp
[s
][D3DSAMP_SRGBTEXTURE
] ? 1 : 0;
965 view
[i
] = context
->texture
[s
].view
[sRGB
];
966 num_textures
= i
+ 1;
968 if (update_sampler_derived(context
, s
) || (context
->changed
.sampler
[s
] & 0x05fe)) {
969 context
->changed
.sampler
[s
] = 0;
970 commit_samplers
= TRUE
;
971 nine_convert_sampler_state(context
->cso
, s
, context
->samp
[s
]);
974 /* Bind dummy sampler. We do not bind dummy sampler when
975 * it is not needed because it could add overhead. The
976 * dummy sampler should have r=g=b=0 and a=1. We do not
977 * unbind dummy sampler directly when they are not needed
978 * anymore, but they're going to be removed as long as texture
979 * or sampler states are changed. */
980 view
[i
] = device
->dummy_sampler_view
;
981 num_textures
= i
+ 1;
983 cso_single_sampler(context
->cso
, PIPE_SHADER_VERTEX
,
984 s
- NINE_SAMPLER_VS(0), &device
->dummy_sampler_state
);
986 commit_samplers
= TRUE
;
987 context
->changed
.sampler
[s
] = ~0;
990 context
->bound_samplers_mask_vs
|= (1 << s
);
993 cso_set_sampler_views(context
->cso
, PIPE_SHADER_VERTEX
, num_textures
, view
);
996 cso_single_sampler_done(context
->cso
, PIPE_SHADER_VERTEX
);
999 /* State commit only */
1002 commit_blend(struct NineDevice9
*device
)
1004 struct nine_context
*context
= &device
->context
;
1006 cso_set_blend(context
->cso
, &context
->pipe_data
.blend
);
1010 commit_dsa(struct NineDevice9
*device
)
1012 struct nine_context
*context
= &device
->context
;
1014 cso_set_depth_stencil_alpha(context
->cso
, &context
->pipe_data
.dsa
);
1018 commit_scissor(struct NineDevice9
*device
)
1020 struct nine_context
*context
= &device
->context
;
1021 struct pipe_context
*pipe
= context
->pipe
;
1023 pipe
->set_scissor_states(pipe
, 0, 1, &context
->scissor
);
1027 commit_rasterizer(struct NineDevice9
*device
)
1029 struct nine_context
*context
= &device
->context
;
1031 cso_set_rasterizer(context
->cso
, &context
->pipe_data
.rast
);
1035 commit_index_buffer(struct NineDevice9
*device
)
1037 struct nine_context
*context
= &device
->context
;
1038 struct pipe_context
*pipe
= context
->pipe
;
1039 if (context
->idxbuf
.buffer
)
1040 pipe
->set_index_buffer(pipe
, &context
->idxbuf
);
1042 pipe
->set_index_buffer(pipe
, NULL
);
1046 commit_vs_constants(struct NineDevice9
*device
)
1048 struct nine_context
*context
= &device
->context
;
1049 struct pipe_context
*pipe
= context
->pipe
;
1051 if (unlikely(!context
->programmable_vs
))
1052 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &context
->pipe_data
.cb_vs_ff
);
1054 if (context
->swvp
) {
1055 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &context
->pipe_data
.cb0_swvp
);
1056 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 1, &context
->pipe_data
.cb1_swvp
);
1057 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 2, &context
->pipe_data
.cb2_swvp
);
1058 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 3, &context
->pipe_data
.cb3_swvp
);
1060 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &context
->pipe_data
.cb_vs
);
1066 commit_ps_constants(struct NineDevice9
*device
)
1068 struct nine_context
*context
= &device
->context
;
1069 struct pipe_context
*pipe
= context
->pipe
;
1071 if (unlikely(!context
->ps
))
1072 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &context
->pipe_data
.cb_ps_ff
);
1074 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &context
->pipe_data
.cb_ps
);
1078 commit_vs(struct NineDevice9
*device
)
1080 struct nine_context
*context
= &device
->context
;
1082 context
->pipe
->bind_vs_state(context
->pipe
, context
->cso_shader
.vs
);
1087 commit_ps(struct NineDevice9
*device
)
1089 struct nine_context
*context
= &device
->context
;
1091 context
->pipe
->bind_fs_state(context
->pipe
, context
->cso_shader
.ps
);
1095 #define NINE_STATE_SHADER_CHANGE_VS \
1097 NINE_STATE_TEXTURE | \
1098 NINE_STATE_FOG_SHADER | \
1099 NINE_STATE_POINTSIZE_SHADER | \
1102 #define NINE_STATE_SHADER_CHANGE_PS \
1104 NINE_STATE_TEXTURE | \
1105 NINE_STATE_FOG_SHADER | \
1106 NINE_STATE_PS1X_SHADER)
1108 #define NINE_STATE_FREQUENT \
1109 (NINE_STATE_RASTERIZER | \
1110 NINE_STATE_TEXTURE | \
1111 NINE_STATE_SAMPLER | \
1112 NINE_STATE_VS_CONST | \
1113 NINE_STATE_PS_CONST | \
1114 NINE_STATE_MULTISAMPLE)
1116 #define NINE_STATE_COMMON \
1118 NINE_STATE_BLEND | \
1120 NINE_STATE_VIEWPORT | \
1121 NINE_STATE_VDECL | \
1122 NINE_STATE_IDXBUF | \
1123 NINE_STATE_STREAMFREQ)
1125 #define NINE_STATE_RARE \
1126 (NINE_STATE_SCISSOR | \
1127 NINE_STATE_BLEND_COLOR | \
1128 NINE_STATE_STENCIL_REF | \
1129 NINE_STATE_SAMPLE_MASK)
1132 nine_update_state(struct NineDevice9
*device
)
1134 struct nine_context
*context
= &device
->context
;
1135 struct pipe_context
*pipe
= context
->pipe
;
1138 DBG("changed state groups: %x\n", context
->changed
.group
);
1140 /* NOTE: We may want to use the cso cache for everything, or let
1141 * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't
1142 * have to care about state being clobbered here and could merge this back
1143 * into update_textures. Except, we also need to re-validate textures that
1144 * may be dirty anyway, even if no texture bindings changed.
1147 /* ff_update may change VS/PS dirty bits */
1148 if (unlikely(!context
->programmable_vs
|| !context
->ps
))
1149 nine_ff_update(device
);
1150 group
= context
->changed
.group
;
1152 if (group
& (NINE_STATE_SHADER_CHANGE_VS
| NINE_STATE_SHADER_CHANGE_PS
)) {
1153 if (group
& NINE_STATE_SHADER_CHANGE_VS
)
1154 group
|= prepare_vs(device
, (group
& NINE_STATE_VS
) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/
1155 if (group
& NINE_STATE_SHADER_CHANGE_PS
)
1156 group
|= prepare_ps(device
, (group
& NINE_STATE_PS
) != 0);
1159 if (group
& (NINE_STATE_COMMON
| NINE_STATE_VS
)) {
1160 if (group
& NINE_STATE_FB
)
1161 update_framebuffer(device
, FALSE
);
1162 if (group
& NINE_STATE_BLEND
)
1163 prepare_blend(device
);
1164 if (group
& NINE_STATE_DSA
)
1165 prepare_dsa(device
);
1166 if (group
& NINE_STATE_VIEWPORT
)
1167 update_viewport(device
);
1168 if (group
& (NINE_STATE_VDECL
| NINE_STATE_VS
| NINE_STATE_STREAMFREQ
))
1169 update_vertex_elements(device
);
1170 if (group
& NINE_STATE_IDXBUF
)
1171 commit_index_buffer(device
);
1174 if (likely(group
& (NINE_STATE_FREQUENT
| NINE_STATE_VS
| NINE_STATE_PS
| NINE_STATE_SWVP
))) {
1175 if (group
& NINE_STATE_MULTISAMPLE
)
1176 group
|= check_multisample(device
);
1177 if (group
& NINE_STATE_RASTERIZER
)
1178 prepare_rasterizer(device
);
1179 if (group
& (NINE_STATE_TEXTURE
| NINE_STATE_SAMPLER
))
1180 update_textures_and_samplers(device
);
1181 if ((group
& (NINE_STATE_VS_CONST
| NINE_STATE_VS
| NINE_STATE_SWVP
)) && context
->programmable_vs
)
1182 prepare_vs_constants_userbuf(device
);
1183 if ((group
& (NINE_STATE_PS_CONST
| NINE_STATE_PS
)) && context
->ps
)
1184 prepare_ps_constants_userbuf(device
);
1187 if (context
->changed
.vtxbuf
)
1188 update_vertex_buffers(device
);
1190 if (context
->commit
& NINE_STATE_COMMIT_BLEND
)
1191 commit_blend(device
);
1192 if (context
->commit
& NINE_STATE_COMMIT_DSA
)
1194 if (context
->commit
& NINE_STATE_COMMIT_RASTERIZER
)
1195 commit_rasterizer(device
);
1196 if (context
->commit
& NINE_STATE_COMMIT_CONST_VS
)
1197 commit_vs_constants(device
);
1198 if (context
->commit
& NINE_STATE_COMMIT_CONST_PS
)
1199 commit_ps_constants(device
);
1200 if (context
->commit
& NINE_STATE_COMMIT_VS
)
1202 if (context
->commit
& NINE_STATE_COMMIT_PS
)
1205 context
->commit
= 0;
1207 if (unlikely(context
->changed
.ucp
)) {
1208 pipe
->set_clip_state(pipe
, &context
->clip
);
1209 context
->changed
.ucp
= FALSE
;
1212 if (unlikely(group
& NINE_STATE_RARE
)) {
1213 if (group
& NINE_STATE_SCISSOR
)
1214 commit_scissor(device
);
1215 if (group
& NINE_STATE_BLEND_COLOR
) {
1216 struct pipe_blend_color color
;
1217 d3dcolor_to_rgba(&color
.color
[0], context
->rs
[D3DRS_BLENDFACTOR
]);
1218 pipe
->set_blend_color(pipe
, &color
);
1220 if (group
& NINE_STATE_SAMPLE_MASK
) {
1221 if (context
->rt
[0]->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
) {
1222 pipe
->set_sample_mask(pipe
, ~0);
1224 pipe
->set_sample_mask(pipe
, context
->rs
[D3DRS_MULTISAMPLEMASK
]);
1227 if (group
& NINE_STATE_STENCIL_REF
) {
1228 struct pipe_stencil_ref ref
;
1229 ref
.ref_value
[0] = context
->rs
[D3DRS_STENCILREF
];
1230 ref
.ref_value
[1] = ref
.ref_value
[0];
1231 pipe
->set_stencil_ref(pipe
, &ref
);
1235 context
->changed
.group
&=
1236 (NINE_STATE_FF
| NINE_STATE_VS_CONST
| NINE_STATE_PS_CONST
);
1241 #define RESZ_CODE 0x7fa05000
1244 NineDevice9_ResolveZ( struct NineDevice9
*device
)
1246 struct nine_context
*context
= &device
->context
;
1247 const struct util_format_description
*desc
;
1248 struct NineSurface9
*source
= context
->ds
;
1249 struct pipe_resource
*src
, *dst
;
1250 struct pipe_blit_info blit
;
1252 DBG("RESZ resolve\n");
1254 if (!source
|| !context
->texture
[0].enabled
||
1255 context
->texture
[0].type
!= D3DRTYPE_TEXTURE
)
1258 src
= source
->base
.resource
;
1259 dst
= context
->texture
[0].resource
;
1264 /* check dst is depth format. we know already for src */
1265 desc
= util_format_description(dst
->format
);
1266 if (desc
->colorspace
!= UTIL_FORMAT_COLORSPACE_ZS
)
1269 memset(&blit
, 0, sizeof(blit
));
1270 blit
.src
.resource
= src
;
1272 blit
.src
.format
= src
->format
;
1274 blit
.src
.box
.depth
= 1;
1277 blit
.src
.box
.width
= src
->width0
;
1278 blit
.src
.box
.height
= src
->height0
;
1280 blit
.dst
.resource
= dst
;
1282 blit
.dst
.format
= dst
->format
;
1284 blit
.dst
.box
.depth
= 1;
1287 blit
.dst
.box
.width
= dst
->width0
;
1288 blit
.dst
.box
.height
= dst
->height0
;
1290 blit
.mask
= PIPE_MASK_ZS
;
1291 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
1292 blit
.scissor_enable
= FALSE
;
1294 context
->pipe
->blit(context
->pipe
, &blit
);
1297 #define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1')
1298 #define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0')
1300 /* Nine_context functions.
1301 * Serialized through CSMT macros.
1305 nine_context_set_texture_apply(struct NineDevice9
*device
,
1310 D3DRESOURCETYPE type
,
1312 struct pipe_resource
*res
,
1313 struct pipe_sampler_view
*view0
,
1314 struct pipe_sampler_view
*view1
);
1316 nine_context_set_stream_source_apply(struct NineDevice9
*device
,
1318 struct pipe_resource
*res
,
1323 nine_context_set_indices_apply(struct NineDevice9
*device
,
1324 struct pipe_resource
*res
,
1326 UINT OffsetInBytes
);
1329 nine_context_set_pixel_shader_constant_i_transformed(struct NineDevice9
*device
,
1331 const int *pConstantData
,
1332 unsigned pConstantData_size
,
1333 UINT Vector4iCount
);
1335 CSMT_ITEM_NO_WAIT(nine_context_set_render_state
,
1336 ARG_VAL(D3DRENDERSTATETYPE
, State
),
1337 ARG_VAL(DWORD
, Value
))
1339 struct nine_context
*context
= &device
->context
;
1341 /* Amd hacks (equivalent to GL extensions) */
1342 if (unlikely(State
== D3DRS_POINTSIZE
)) {
1343 if (Value
== RESZ_CODE
) {
1344 NineDevice9_ResolveZ(device
);
1348 if (Value
== ALPHA_TO_COVERAGE_ENABLE
||
1349 Value
== ALPHA_TO_COVERAGE_DISABLE
) {
1350 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== ALPHA_TO_COVERAGE_ENABLE
);
1351 context
->changed
.group
|= NINE_STATE_BLEND
;
1357 if (unlikely(State
== D3DRS_ADAPTIVETESS_Y
)) {
1358 if (Value
== D3DFMT_ATOC
|| (Value
== D3DFMT_UNKNOWN
&& context
->rs
[NINED3DRS_ALPHACOVERAGE
])) {
1359 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== D3DFMT_ATOC
) ? 3 : 0;
1360 context
->rs
[NINED3DRS_ALPHACOVERAGE
] &= context
->rs
[D3DRS_ALPHATESTENABLE
] ? 3 : 2;
1361 context
->changed
.group
|= NINE_STATE_BLEND
;
1365 if (unlikely(State
== D3DRS_ALPHATESTENABLE
&& (context
->rs
[NINED3DRS_ALPHACOVERAGE
] & 2))) {
1366 DWORD alphacoverage_prev
= context
->rs
[NINED3DRS_ALPHACOVERAGE
];
1367 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
? 3 : 2);
1368 if (context
->rs
[NINED3DRS_ALPHACOVERAGE
] != alphacoverage_prev
)
1369 context
->changed
.group
|= NINE_STATE_BLEND
;
1372 context
->rs
[State
] = nine_fix_render_state_value(State
, Value
);
1373 context
->changed
.group
|= nine_render_state_group
[State
];
1376 CSMT_ITEM_NO_WAIT(nine_context_set_texture_apply
,
1377 ARG_VAL(DWORD
, stage
),
1378 ARG_VAL(BOOL
, enabled
),
1379 ARG_VAL(BOOL
, shadow
),
1380 ARG_VAL(DWORD
, lod
),
1381 ARG_VAL(D3DRESOURCETYPE
, type
),
1382 ARG_VAL(uint8_t, pstype
),
1383 ARG_BIND_RES(struct pipe_resource
, res
),
1384 ARG_BIND_VIEW(struct pipe_sampler_view
, view0
),
1385 ARG_BIND_VIEW(struct pipe_sampler_view
, view1
))
1387 struct nine_context
*context
= &device
->context
;
1389 context
->texture
[stage
].enabled
= enabled
;
1390 context
->samplers_shadow
&= ~(1 << stage
);
1391 context
->samplers_shadow
|= shadow
<< stage
;
1392 context
->texture
[stage
].shadow
= shadow
;
1393 context
->texture
[stage
].lod
= lod
;
1394 context
->texture
[stage
].type
= type
;
1395 context
->texture
[stage
].pstype
= pstype
;
1396 pipe_resource_reference(&context
->texture
[stage
].resource
, res
);
1397 pipe_sampler_view_reference(&context
->texture
[stage
].view
[0], view0
);
1398 pipe_sampler_view_reference(&context
->texture
[stage
].view
[1], view1
);
1400 context
->changed
.group
|= NINE_STATE_TEXTURE
;
1404 nine_context_set_texture(struct NineDevice9
*device
,
1406 struct NineBaseTexture9
*tex
)
1408 BOOL enabled
= FALSE
;
1409 BOOL shadow
= FALSE
;
1411 D3DRESOURCETYPE type
= D3DRTYPE_TEXTURE
;
1413 struct pipe_resource
*res
= NULL
;
1414 struct pipe_sampler_view
*view0
= NULL
, *view1
= NULL
;
1416 /* For managed pool, the data can be initially incomplete.
1417 * In that case, the texture is rebound later
1418 * (in NineBaseTexture9_Validate/NineBaseTexture9_UploadSelf). */
1419 if (tex
&& tex
->base
.resource
) {
1421 shadow
= tex
->shadow
;
1422 lod
= tex
->managed
.lod
;
1423 type
= tex
->base
.type
;
1424 pstype
= tex
->pstype
;
1425 res
= tex
->base
.resource
;
1426 view0
= NineBaseTexture9_GetSamplerView(tex
, 0);
1427 view1
= NineBaseTexture9_GetSamplerView(tex
, 1);
1430 nine_context_set_texture_apply(device
, Stage
, enabled
,
1431 shadow
, lod
, type
, pstype
,
1435 CSMT_ITEM_NO_WAIT(nine_context_set_sampler_state
,
1436 ARG_VAL(DWORD
, Sampler
),
1437 ARG_VAL(D3DSAMPLERSTATETYPE
, Type
),
1438 ARG_VAL(DWORD
, Value
))
1440 struct nine_context
*context
= &device
->context
;
1442 if (unlikely(!nine_check_sampler_state_value(Type
, Value
)))
1445 context
->samp
[Sampler
][Type
] = Value
;
1446 context
->changed
.group
|= NINE_STATE_SAMPLER
;
1447 context
->changed
.sampler
[Sampler
] |= 1 << Type
;
1450 CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_apply
,
1451 ARG_VAL(UINT
, StreamNumber
),
1452 ARG_BIND_RES(struct pipe_resource
, res
),
1453 ARG_VAL(UINT
, OffsetInBytes
),
1454 ARG_VAL(UINT
, Stride
))
1456 struct nine_context
*context
= &device
->context
;
1457 const unsigned i
= StreamNumber
;
1459 context
->vtxbuf
[i
].stride
= Stride
;
1460 context
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
1461 pipe_resource_reference(&context
->vtxbuf
[i
].buffer
, res
);
1463 context
->changed
.vtxbuf
|= 1 << StreamNumber
;
1467 nine_context_set_stream_source(struct NineDevice9
*device
,
1469 struct NineVertexBuffer9
*pVBuf9
,
1473 struct pipe_resource
*res
= NULL
;
1476 res
= NineVertexBuffer9_GetResource(pVBuf9
);
1477 /* in the future when there is internal offset, add it
1478 * to OffsetInBytes */
1480 nine_context_set_stream_source_apply(device
, StreamNumber
,
1485 CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_freq
,
1486 ARG_VAL(UINT
, StreamNumber
),
1487 ARG_VAL(UINT
, Setting
))
1489 struct nine_context
*context
= &device
->context
;
1491 context
->stream_freq
[StreamNumber
] = Setting
;
1493 if (Setting
& D3DSTREAMSOURCE_INSTANCEDATA
)
1494 context
->stream_instancedata_mask
|= 1 << StreamNumber
;
1496 context
->stream_instancedata_mask
&= ~(1 << StreamNumber
);
1498 if (StreamNumber
!= 0)
1499 context
->changed
.group
|= NINE_STATE_STREAMFREQ
;
1502 CSMT_ITEM_NO_WAIT(nine_context_set_indices_apply
,
1503 ARG_BIND_RES(struct pipe_resource
, res
),
1504 ARG_VAL(UINT
, IndexSize
),
1505 ARG_VAL(UINT
, OffsetInBytes
))
1507 struct nine_context
*context
= &device
->context
;
1509 context
->idxbuf
.index_size
= IndexSize
;
1510 context
->idxbuf
.offset
= OffsetInBytes
;
1511 pipe_resource_reference(&context
->idxbuf
.buffer
, res
);
1512 context
->idxbuf
.user_buffer
= NULL
;
1514 context
->changed
.group
|= NINE_STATE_IDXBUF
;
1518 nine_context_set_indices(struct NineDevice9
*device
,
1519 struct NineIndexBuffer9
*idxbuf
)
1521 const struct pipe_index_buffer
*pipe_idxbuf
;
1522 struct pipe_resource
*res
= NULL
;
1524 UINT OffsetInBytes
= 0;
1527 pipe_idxbuf
= NineIndexBuffer9_GetBuffer(idxbuf
);
1528 IndexSize
= pipe_idxbuf
->index_size
;
1529 res
= pipe_idxbuf
->buffer
;
1530 OffsetInBytes
= pipe_idxbuf
->offset
;
1533 nine_context_set_indices_apply(device
, res
, IndexSize
, OffsetInBytes
);
1536 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_declaration
,
1537 ARG_BIND_REF(struct NineVertexDeclaration9
, vdecl
))
1539 struct nine_context
*context
= &device
->context
;
1540 BOOL was_programmable_vs
= context
->programmable_vs
;
1542 nine_bind(&context
->vdecl
, vdecl
);
1544 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
1545 if (was_programmable_vs
!= context
->programmable_vs
) {
1546 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
1547 context
->changed
.group
|= NINE_STATE_VS
;
1550 context
->changed
.group
|= NINE_STATE_VDECL
;
1553 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader
,
1554 ARG_BIND_REF(struct NineVertexShader9
, pShader
))
1556 struct nine_context
*context
= &device
->context
;
1557 BOOL was_programmable_vs
= context
->programmable_vs
;
1559 nine_bind(&context
->vs
, pShader
);
1561 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
1563 /* ff -> non-ff: commit back non-ff constants */
1564 if (!was_programmable_vs
&& context
->programmable_vs
)
1565 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
1567 context
->changed
.group
|= NINE_STATE_VS
;
1570 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_f
,
1571 ARG_VAL(UINT
, StartRegister
),
1572 ARG_MEM(float, pConstantData
),
1573 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1574 ARG_VAL(UINT
, Vector4fCount
))
1576 struct nine_context
*context
= &device
->context
;
1577 float *vs_const_f
= device
->may_swvp
? context
->vs_const_f_swvp
: context
->vs_const_f
;
1579 memcpy(&vs_const_f
[StartRegister
* 4],
1581 pConstantData_size
);
1583 if (device
->may_swvp
) {
1584 Vector4fCount
= MIN2(StartRegister
+ Vector4fCount
, NINE_MAX_CONST_F
) - StartRegister
;
1585 if (StartRegister
< NINE_MAX_CONST_F
)
1586 memcpy(&context
->vs_const_f
[StartRegister
* 4],
1588 Vector4fCount
* 4 * sizeof(context
->vs_const_f
[0]));
1591 context
->changed
.vs_const_f
= TRUE
;
1592 context
->changed
.group
|= NINE_STATE_VS_CONST
;
1595 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_i
,
1596 ARG_VAL(UINT
, StartRegister
),
1597 ARG_MEM(int, pConstantData
),
1598 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1599 ARG_VAL(UINT
, Vector4iCount
))
1601 struct nine_context
*context
= &device
->context
;
1604 if (device
->driver_caps
.vs_integer
) {
1605 memcpy(&context
->vs_const_i
[4 * StartRegister
],
1607 pConstantData_size
);
1609 for (i
= 0; i
< Vector4iCount
; i
++) {
1610 context
->vs_const_i
[4 * (StartRegister
+ i
)] = fui((float)(pConstantData
[4 * i
]));
1611 context
->vs_const_i
[4 * (StartRegister
+ i
) + 1] = fui((float)(pConstantData
[4 * i
+ 1]));
1612 context
->vs_const_i
[4 * (StartRegister
+ i
) + 2] = fui((float)(pConstantData
[4 * i
+ 2]));
1613 context
->vs_const_i
[4 * (StartRegister
+ i
) + 3] = fui((float)(pConstantData
[4 * i
+ 3]));
1617 context
->changed
.vs_const_i
= TRUE
;
1618 context
->changed
.group
|= NINE_STATE_VS_CONST
;
1621 CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_b
,
1622 ARG_VAL(UINT
, StartRegister
),
1623 ARG_MEM(BOOL
, pConstantData
),
1624 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1625 ARG_VAL(UINT
, BoolCount
))
1627 struct nine_context
*context
= &device
->context
;
1629 uint32_t bool_true
= device
->driver_caps
.vs_integer
? 0xFFFFFFFF : fui(1.0f
);
1631 (void) pConstantData_size
;
1633 for (i
= 0; i
< BoolCount
; i
++)
1634 context
->vs_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
1636 context
->changed
.vs_const_b
= TRUE
;
1637 context
->changed
.group
|= NINE_STATE_VS_CONST
;
1640 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader
,
1641 ARG_BIND_REF(struct NinePixelShader9
, ps
))
1643 struct nine_context
*context
= &device
->context
;
1644 unsigned old_mask
= context
->ps
? context
->ps
->rt_mask
: 1;
1647 /* ff -> non-ff: commit back non-ff constants */
1648 if (!context
->ps
&& ps
)
1649 context
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
1651 nine_bind(&context
->ps
, ps
);
1653 context
->changed
.group
|= NINE_STATE_PS
;
1655 mask
= context
->ps
? context
->ps
->rt_mask
: 1;
1656 /* We need to update cbufs if the pixel shader would
1657 * write to different render targets */
1658 if (mask
!= old_mask
)
1659 context
->changed
.group
|= NINE_STATE_FB
;
1662 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_f
,
1663 ARG_VAL(UINT
, StartRegister
),
1664 ARG_MEM(float, pConstantData
),
1665 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1666 ARG_VAL(UINT
, Vector4fCount
))
1668 struct nine_context
*context
= &device
->context
;
1670 memcpy(&context
->ps_const_f
[StartRegister
* 4],
1672 pConstantData_size
);
1674 context
->changed
.ps_const_f
= TRUE
;
1675 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1678 /* For stateblocks */
1679 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i_transformed
,
1680 ARG_VAL(UINT
, StartRegister
),
1681 ARG_MEM(int, pConstantData
),
1682 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1683 ARG_VAL(UINT
, Vector4iCount
))
1685 struct nine_context
*context
= &device
->context
;
1687 memcpy(&context
->ps_const_i
[StartRegister
][0],
1689 Vector4iCount
* sizeof(context
->ps_const_i
[0]));
1691 context
->changed
.ps_const_i
= TRUE
;
1692 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1695 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i
,
1696 ARG_VAL(UINT
, StartRegister
),
1697 ARG_MEM(int, pConstantData
),
1698 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1699 ARG_VAL(UINT
, Vector4iCount
))
1701 struct nine_context
*context
= &device
->context
;
1704 if (device
->driver_caps
.ps_integer
) {
1705 memcpy(&context
->ps_const_i
[StartRegister
][0],
1707 pConstantData_size
);
1709 for (i
= 0; i
< Vector4iCount
; i
++) {
1710 context
->ps_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
1711 context
->ps_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
1712 context
->ps_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
1713 context
->ps_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
1716 context
->changed
.ps_const_i
= TRUE
;
1717 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1720 CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_b
,
1721 ARG_VAL(UINT
, StartRegister
),
1722 ARG_MEM(BOOL
, pConstantData
),
1723 ARG_MEM_SIZE(unsigned, pConstantData_size
),
1724 ARG_VAL(UINT
, BoolCount
))
1726 struct nine_context
*context
= &device
->context
;
1728 uint32_t bool_true
= device
->driver_caps
.ps_integer
? 0xFFFFFFFF : fui(1.0f
);
1730 (void) pConstantData_size
;
1732 for (i
= 0; i
< BoolCount
; i
++)
1733 context
->ps_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
1735 context
->changed
.ps_const_b
= TRUE
;
1736 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1739 /* XXX: use resource, as resource might change */
1740 CSMT_ITEM_NO_WAIT(nine_context_set_render_target
,
1741 ARG_VAL(DWORD
, RenderTargetIndex
),
1742 ARG_BIND_REF(struct NineSurface9
, rt
))
1744 struct nine_context
*context
= &device
->context
;
1745 const unsigned i
= RenderTargetIndex
;
1748 context
->viewport
.X
= 0;
1749 context
->viewport
.Y
= 0;
1750 context
->viewport
.Width
= rt
->desc
.Width
;
1751 context
->viewport
.Height
= rt
->desc
.Height
;
1752 context
->viewport
.MinZ
= 0.0f
;
1753 context
->viewport
.MaxZ
= 1.0f
;
1755 context
->scissor
.minx
= 0;
1756 context
->scissor
.miny
= 0;
1757 context
->scissor
.maxx
= rt
->desc
.Width
;
1758 context
->scissor
.maxy
= rt
->desc
.Height
;
1760 context
->changed
.group
|= NINE_STATE_VIEWPORT
| NINE_STATE_SCISSOR
| NINE_STATE_MULTISAMPLE
;
1762 if (context
->rt
[0] &&
1763 (context
->rt
[0]->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
) !=
1764 (rt
->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
))
1765 context
->changed
.group
|= NINE_STATE_SAMPLE_MASK
;
1768 if (context
->rt
[i
] != rt
) {
1769 nine_bind(&context
->rt
[i
], rt
);
1770 context
->changed
.group
|= NINE_STATE_FB
;
1774 /* XXX: use resource instead of ds, as resource might change */
1775 CSMT_ITEM_NO_WAIT(nine_context_set_depth_stencil
,
1776 ARG_BIND_REF(struct NineSurface9
, ds
))
1778 struct nine_context
*context
= &device
->context
;
1780 nine_bind(&context
->ds
, ds
);
1781 context
->changed
.group
|= NINE_STATE_FB
;
1784 CSMT_ITEM_NO_WAIT(nine_context_set_viewport
,
1785 ARG_COPY_REF(D3DVIEWPORT9
, viewport
))
1787 struct nine_context
*context
= &device
->context
;
1789 context
->viewport
= *viewport
;
1790 context
->changed
.group
|= NINE_STATE_VIEWPORT
;
1793 CSMT_ITEM_NO_WAIT(nine_context_set_scissor
,
1794 ARG_COPY_REF(struct pipe_scissor_state
, scissor
))
1796 struct nine_context
*context
= &device
->context
;
1798 context
->scissor
= *scissor
;
1799 context
->changed
.group
|= NINE_STATE_SCISSOR
;
1802 CSMT_ITEM_NO_WAIT(nine_context_set_transform
,
1803 ARG_VAL(D3DTRANSFORMSTATETYPE
, State
),
1804 ARG_COPY_REF(D3DMATRIX
, pMatrix
))
1806 struct nine_context
*context
= &device
->context
;
1807 D3DMATRIX
*M
= nine_state_access_transform(&context
->ff
, State
, TRUE
);
1810 context
->ff
.changed
.transform
[State
/ 32] |= 1 << (State
% 32);
1811 context
->changed
.group
|= NINE_STATE_FF
;
1814 CSMT_ITEM_NO_WAIT(nine_context_set_material
,
1815 ARG_COPY_REF(D3DMATERIAL9
, pMaterial
))
1817 struct nine_context
*context
= &device
->context
;
1819 context
->ff
.material
= *pMaterial
;
1820 context
->changed
.group
|= NINE_STATE_FF_MATERIAL
;
1823 CSMT_ITEM_NO_WAIT(nine_context_set_light
,
1824 ARG_VAL(DWORD
, Index
),
1825 ARG_COPY_REF(D3DLIGHT9
, pLight
))
1827 struct nine_context
*context
= &device
->context
;
1829 (void)nine_state_set_light(&context
->ff
, Index
, pLight
);
1830 context
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
1834 /* For stateblocks */
1836 nine_context_light_enable_stateblock(struct NineDevice9
*device
,
1837 const uint16_t active_light
[NINE_MAX_LIGHTS_ACTIVE
], /* TODO: use pointer that convey size for csmt */
1838 unsigned int num_lights_active
)
1840 struct nine_context
*context
= &device
->context
;
1842 if (device
->csmt_active
) /* TODO: fix */
1843 nine_csmt_process(device
);
1844 memcpy(context
->ff
.active_light
, active_light
, NINE_MAX_LIGHTS_ACTIVE
* sizeof(context
->ff
.active_light
[0]));
1845 context
->ff
.num_lights_active
= num_lights_active
;
1846 context
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
1849 CSMT_ITEM_NO_WAIT(nine_context_light_enable
,
1850 ARG_VAL(DWORD
, Index
),
1851 ARG_VAL(BOOL
, Enable
))
1853 struct nine_context
*context
= &device
->context
;
1855 nine_state_light_enable(&context
->ff
, &context
->changed
.group
, Index
, Enable
);
1858 CSMT_ITEM_NO_WAIT(nine_context_set_texture_stage_state
,
1859 ARG_VAL(DWORD
, Stage
),
1860 ARG_VAL(D3DTEXTURESTAGESTATETYPE
, Type
),
1861 ARG_VAL(DWORD
, Value
))
1863 struct nine_context
*context
= &device
->context
;
1864 int bumpmap_index
= -1;
1866 context
->ff
.tex_stage
[Stage
][Type
] = Value
;
1868 case D3DTSS_BUMPENVMAT00
:
1869 bumpmap_index
= 4 * Stage
;
1871 case D3DTSS_BUMPENVMAT01
:
1872 bumpmap_index
= 4 * Stage
+ 1;
1874 case D3DTSS_BUMPENVMAT10
:
1875 bumpmap_index
= 4 * Stage
+ 2;
1877 case D3DTSS_BUMPENVMAT11
:
1878 bumpmap_index
= 4 * Stage
+ 3;
1880 case D3DTSS_BUMPENVLSCALE
:
1881 bumpmap_index
= 4 * 8 + 2 * Stage
;
1883 case D3DTSS_BUMPENVLOFFSET
:
1884 bumpmap_index
= 4 * 8 + 2 * Stage
+ 1;
1886 case D3DTSS_TEXTURETRANSFORMFLAGS
:
1887 context
->changed
.group
|= NINE_STATE_PS1X_SHADER
;
1893 if (bumpmap_index
>= 0) {
1894 context
->bumpmap_vars
[bumpmap_index
] = Value
;
1895 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1898 context
->changed
.group
|= NINE_STATE_FF_PSSTAGES
;
1899 context
->ff
.changed
.tex_stage
[Stage
][Type
/ 32] |= 1 << (Type
% 32);
1902 CSMT_ITEM_NO_WAIT(nine_context_set_clip_plane
,
1903 ARG_VAL(DWORD
, Index
),
1904 ARG_COPY_REF(struct nine_clipplane
, pPlane
))
1906 struct nine_context
*context
= &device
->context
;
1908 memcpy(&context
->clip
.ucp
[Index
][0], pPlane
, sizeof(context
->clip
.ucp
[0]));
1909 context
->changed
.ucp
= TRUE
;
1912 CSMT_ITEM_NO_WAIT(nine_context_set_swvp
,
1913 ARG_VAL(boolean
, swvp
))
1915 struct nine_context
*context
= &device
->context
;
1917 context
->swvp
= swvp
;
1918 context
->changed
.group
|= NINE_STATE_SWVP
;
1924 nine_context_apply_stateblock(struct NineDevice9
*device
,
1925 const struct nine_state
*src
)
1927 struct nine_context
*context
= &device
->context
;
1930 context
->changed
.group
|= src
->changed
.group
;
1932 for (i
= 0; i
< ARRAY_SIZE(src
->changed
.rs
); ++i
) {
1933 uint32_t m
= src
->changed
.rs
[i
];
1935 const int r
= ffs(m
) - 1;
1937 context
->rs
[i
* 32 + r
] = nine_fix_render_state_value(i
* 32 + r
, src
->rs_advertised
[i
* 32 + r
]);
1942 if (src
->changed
.texture
) {
1943 uint32_t m
= src
->changed
.texture
;
1946 for (s
= 0; m
; ++s
, m
>>= 1) {
1947 struct NineBaseTexture9
*tex
= src
->texture
[s
];
1950 nine_context_set_texture(device
, s
, tex
);
1955 if (src
->changed
.group
& NINE_STATE_SAMPLER
) {
1958 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
1959 uint32_t m
= src
->changed
.sampler
[s
];
1961 const int i
= ffs(m
) - 1;
1963 if (nine_check_sampler_state_value(i
, src
->samp_advertised
[s
][i
]))
1964 context
->samp
[s
][i
] = src
->samp_advertised
[s
][i
];
1966 context
->changed
.sampler
[s
] |= src
->changed
.sampler
[s
];
1970 /* Vertex buffers */
1971 if (src
->changed
.vtxbuf
| src
->changed
.stream_freq
) {
1972 uint32_t m
= src
->changed
.vtxbuf
| src
->changed
.stream_freq
;
1973 for (i
= 0; m
; ++i
, m
>>= 1) {
1974 if (src
->changed
.vtxbuf
& (1 << i
)) {
1975 if (src
->stream
[i
]) {
1976 context
->vtxbuf
[i
].buffer_offset
= src
->vtxbuf
[i
].buffer_offset
;
1977 pipe_resource_reference(&context
->vtxbuf
[i
].buffer
,
1978 src
->stream
[i
] ? NineVertexBuffer9_GetResource(src
->stream
[i
]) : NULL
);
1979 context
->vtxbuf
[i
].stride
= src
->vtxbuf
[i
].stride
;
1982 if (src
->changed
.stream_freq
& (1 << i
)) {
1983 context
->stream_freq
[i
] = src
->stream_freq
[i
];
1984 if (src
->stream_freq
[i
] & D3DSTREAMSOURCE_INSTANCEDATA
)
1985 context
->stream_instancedata_mask
|= 1 << i
;
1987 context
->stream_instancedata_mask
&= ~(1 << i
);
1990 context
->changed
.vtxbuf
|= src
->changed
.vtxbuf
;
1994 if (src
->changed
.group
& NINE_STATE_IDXBUF
)
1995 nine_context_set_indices(device
, src
->idxbuf
);
1997 /* Vertex declaration */
1998 if ((src
->changed
.group
& NINE_STATE_VDECL
) && src
->vdecl
)
1999 nine_context_set_vertex_declaration(device
, src
->vdecl
);
2002 if (src
->changed
.group
& NINE_STATE_VS
)
2003 nine_bind(&context
->vs
, src
->vs
);
2005 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
2008 if (src
->changed
.group
& NINE_STATE_PS
)
2009 nine_bind(&context
->ps
, src
->ps
);
2011 /* Vertex constants */
2012 if (src
->changed
.group
& NINE_STATE_VS_CONST
) {
2013 struct nine_range
*r
;
2014 if (device
->may_swvp
) {
2015 for (r
= src
->changed
.vs_const_f
; r
; r
= r
->next
) {
2018 memcpy(&context
->vs_const_f_swvp
[bgn
* 4],
2019 &src
->vs_const_f
[bgn
* 4],
2020 (end
- bgn
) * 4 * sizeof(float));
2021 if (bgn
< device
->max_vs_const_f
) {
2022 end
= MIN2(end
, device
->max_vs_const_f
);
2023 memcpy(&context
->vs_const_f
[bgn
* 4],
2024 &src
->vs_const_f
[bgn
* 4],
2025 (end
- bgn
) * 4 * sizeof(float));
2029 for (r
= src
->changed
.vs_const_f
; r
; r
= r
->next
) {
2030 memcpy(&context
->vs_const_f
[r
->bgn
* 4],
2031 &src
->vs_const_f
[r
->bgn
* 4],
2032 (r
->end
- r
->bgn
) * 4 * sizeof(float));
2035 for (r
= src
->changed
.vs_const_i
; r
; r
= r
->next
) {
2036 memcpy(&context
->vs_const_i
[r
->bgn
* 4],
2037 &src
->vs_const_i
[r
->bgn
* 4],
2038 (r
->end
- r
->bgn
) * 4 * sizeof(int));
2040 for (r
= src
->changed
.vs_const_b
; r
; r
= r
->next
) {
2041 memcpy(&context
->vs_const_b
[r
->bgn
],
2042 &src
->vs_const_b
[r
->bgn
],
2043 (r
->end
- r
->bgn
) * sizeof(int));
2045 context
->changed
.vs_const_f
= !!src
->changed
.vs_const_f
;
2046 context
->changed
.vs_const_i
= !!src
->changed
.vs_const_i
;
2047 context
->changed
.vs_const_b
= !!src
->changed
.vs_const_b
;
2050 /* Pixel constants */
2051 if (src
->changed
.group
& NINE_STATE_PS_CONST
) {
2052 struct nine_range
*r
;
2053 for (r
= src
->changed
.ps_const_f
; r
; r
= r
->next
) {
2054 memcpy(&context
->ps_const_f
[r
->bgn
* 4],
2055 &src
->ps_const_f
[r
->bgn
* 4],
2056 (r
->end
- r
->bgn
) * 4 * sizeof(float));
2058 if (src
->changed
.ps_const_i
) {
2059 uint16_t m
= src
->changed
.ps_const_i
;
2060 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
2062 memcpy(context
->ps_const_i
[i
], src
->ps_const_i
[i
], 4 * sizeof(int));
2064 if (src
->changed
.ps_const_b
) {
2065 uint16_t m
= src
->changed
.ps_const_b
;
2066 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
2068 context
->ps_const_b
[i
] = src
->ps_const_b
[i
];
2070 context
->changed
.ps_const_f
= !!src
->changed
.ps_const_f
;
2071 context
->changed
.ps_const_i
= !!src
->changed
.ps_const_i
;
2072 context
->changed
.ps_const_b
= !!src
->changed
.ps_const_b
;
2076 if (src
->changed
.group
& NINE_STATE_VIEWPORT
)
2077 context
->viewport
= src
->viewport
;
2080 if (src
->changed
.group
& NINE_STATE_SCISSOR
)
2081 context
->scissor
= src
->scissor
;
2083 /* User Clip Planes */
2084 if (src
->changed
.ucp
) {
2085 for (i
= 0; i
< PIPE_MAX_CLIP_PLANES
; ++i
)
2086 if (src
->changed
.ucp
& (1 << i
))
2087 memcpy(context
->clip
.ucp
[i
],
2088 src
->clip
.ucp
[i
], sizeof(src
->clip
.ucp
[0]));
2089 context
->changed
.ucp
= TRUE
;
2092 if (!(src
->changed
.group
& NINE_STATE_FF
))
2095 /* Fixed function state. */
2097 if (src
->changed
.group
& NINE_STATE_FF_MATERIAL
)
2098 context
->ff
.material
= src
->ff
.material
;
2100 if (src
->changed
.group
& NINE_STATE_FF_PSSTAGES
) {
2102 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
2103 for (i
= 0; i
< NINED3DTSS_COUNT
; ++i
)
2104 if (src
->ff
.changed
.tex_stage
[s
][i
/ 32] & (1 << (i
% 32)))
2105 context
->ff
.tex_stage
[s
][i
] = src
->ff
.tex_stage
[s
][i
];
2108 if (src
->changed
.group
& NINE_STATE_FF_LIGHTING
) {
2109 unsigned num_lights
= MAX2(context
->ff
.num_lights
, src
->ff
.num_lights
);
2110 /* Can happen if the stateblock had recorded the creation of
2112 if (context
->ff
.num_lights
< num_lights
) {
2113 context
->ff
.light
= REALLOC(context
->ff
.light
,
2114 context
->ff
.num_lights
* sizeof(D3DLIGHT9
),
2115 num_lights
* sizeof(D3DLIGHT9
));
2116 memset(&context
->ff
.light
[context
->ff
.num_lights
], 0, (num_lights
- context
->ff
.num_lights
) * sizeof(D3DLIGHT9
));
2117 for (i
= context
->ff
.num_lights
; i
< num_lights
; ++i
)
2118 context
->ff
.light
[i
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
2119 context
->ff
.num_lights
= num_lights
;
2121 /* src->ff.num_lights < num_lights has been handled before */
2122 assert (src
->ff
.num_lights
== num_lights
);
2124 for (i
= 0; i
< num_lights
; ++i
)
2125 if (src
->ff
.light
[i
].Type
!= NINED3DLIGHT_INVALID
)
2126 context
->ff
.light
[i
] = src
->ff
.light
[i
];
2128 memcpy(context
->ff
.active_light
, src
->ff
.active_light
, sizeof(src
->ff
.active_light
) );
2129 context
->ff
.num_lights_active
= src
->ff
.num_lights_active
;
2131 if (src
->changed
.group
& NINE_STATE_FF_VSTRANSF
) {
2132 for (i
= 0; i
< ARRAY_SIZE(src
->ff
.changed
.transform
); ++i
) {
2134 if (!src
->ff
.changed
.transform
[i
])
2136 for (s
= i
* 32; s
< (i
* 32 + 32); ++s
) {
2137 if (!(src
->ff
.changed
.transform
[i
] & (1 << (s
% 32))))
2139 *nine_state_access_transform(&context
->ff
, s
, TRUE
) =
2140 *nine_state_access_transform( /* const because !alloc */
2141 (struct nine_ff_state
*)&src
->ff
, s
, FALSE
);
2143 context
->ff
.changed
.transform
[i
] |= src
->ff
.changed
.transform
[i
];
2150 /* Do not write to nine_context directly. Slower,
2151 * but works with csmt. TODO: write a special csmt version that
2152 * would record the list of commands as much as possible,
2153 * and use the version above else.
2156 nine_context_apply_stateblock(struct NineDevice9
*device
,
2157 const struct nine_state
*src
)
2161 /* No need to apply src->changed.group, since all calls do
2162 * set context->changed.group */
2164 for (i
= 0; i
< ARRAY_SIZE(src
->changed
.rs
); ++i
) {
2165 uint32_t m
= src
->changed
.rs
[i
];
2167 const int r
= ffs(m
) - 1;
2169 nine_context_set_render_state(device
, i
* 32 + r
, src
->rs_advertised
[i
* 32 + r
]);
2174 if (src
->changed
.texture
) {
2175 uint32_t m
= src
->changed
.texture
;
2178 for (s
= 0; m
; ++s
, m
>>= 1) {
2179 struct NineBaseTexture9
*tex
= src
->texture
[s
];
2182 nine_context_set_texture(device
, s
, tex
);
2187 if (src
->changed
.group
& NINE_STATE_SAMPLER
) {
2190 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
2191 uint32_t m
= src
->changed
.sampler
[s
];
2193 const int i
= ffs(m
) - 1;
2195 nine_context_set_sampler_state(device
, s
, i
, src
->samp_advertised
[s
][i
]);
2200 /* Vertex buffers */
2201 if (src
->changed
.vtxbuf
| src
->changed
.stream_freq
) {
2202 uint32_t m
= src
->changed
.vtxbuf
| src
->changed
.stream_freq
;
2203 for (i
= 0; m
; ++i
, m
>>= 1) {
2204 if (src
->changed
.vtxbuf
& (1 << i
))
2205 nine_context_set_stream_source(device
, i
, src
->stream
[i
], src
->vtxbuf
[i
].buffer_offset
, src
->vtxbuf
[i
].stride
);
2206 if (src
->changed
.stream_freq
& (1 << i
))
2207 nine_context_set_stream_source_freq(device
, i
, src
->stream_freq
[i
]);
2212 if (src
->changed
.group
& NINE_STATE_IDXBUF
)
2213 nine_context_set_indices(device
, src
->idxbuf
);
2215 /* Vertex declaration */
2216 if ((src
->changed
.group
& NINE_STATE_VDECL
) && src
->vdecl
)
2217 nine_context_set_vertex_declaration(device
, src
->vdecl
);
2220 if (src
->changed
.group
& NINE_STATE_VS
)
2221 nine_context_set_vertex_shader(device
, src
->vs
);
2224 if (src
->changed
.group
& NINE_STATE_PS
)
2225 nine_context_set_pixel_shader(device
, src
->ps
);
2227 /* Vertex constants */
2228 if (src
->changed
.group
& NINE_STATE_VS_CONST
) {
2229 struct nine_range
*r
;
2230 for (r
= src
->changed
.vs_const_f
; r
; r
= r
->next
)
2231 nine_context_set_vertex_shader_constant_f(device
, r
->bgn
,
2232 &src
->vs_const_f
[r
->bgn
* 4],
2233 sizeof(float[4]) * (r
->end
- r
->bgn
),
2235 for (r
= src
->changed
.vs_const_i
; r
; r
= r
->next
)
2236 nine_context_set_vertex_shader_constant_i(device
, r
->bgn
,
2237 &src
->vs_const_i
[r
->bgn
* 4],
2238 sizeof(int[4]) * (r
->end
- r
->bgn
),
2240 for (r
= src
->changed
.vs_const_b
; r
; r
= r
->next
)
2241 nine_context_set_vertex_shader_constant_b(device
, r
->bgn
,
2242 &src
->vs_const_b
[r
->bgn
* 4],
2243 sizeof(BOOL
) * (r
->end
- r
->bgn
),
2247 /* Pixel constants */
2248 if (src
->changed
.group
& NINE_STATE_PS_CONST
) {
2249 struct nine_range
*r
;
2250 for (r
= src
->changed
.ps_const_f
; r
; r
= r
->next
)
2251 nine_context_set_pixel_shader_constant_f(device
, r
->bgn
,
2252 &src
->ps_const_f
[r
->bgn
* 4],
2253 sizeof(float[4]) * (r
->end
- r
->bgn
),
2255 if (src
->changed
.ps_const_i
) {
2256 uint16_t m
= src
->changed
.ps_const_i
;
2257 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
2259 nine_context_set_pixel_shader_constant_i_transformed(device
, i
,
2260 src
->ps_const_i
[i
], sizeof(int[4]), 1);
2262 if (src
->changed
.ps_const_b
) {
2263 uint16_t m
= src
->changed
.ps_const_b
;
2264 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
2266 nine_context_set_pixel_shader_constant_b(device
, i
,
2267 &src
->ps_const_b
[i
], sizeof(BOOL
), 1);
2272 if (src
->changed
.group
& NINE_STATE_VIEWPORT
)
2273 nine_context_set_viewport(device
, &src
->viewport
);
2276 if (src
->changed
.group
& NINE_STATE_SCISSOR
)
2277 nine_context_set_scissor(device
, &src
->scissor
);
2279 /* User Clip Planes */
2280 if (src
->changed
.ucp
)
2281 for (i
= 0; i
< PIPE_MAX_CLIP_PLANES
; ++i
)
2282 if (src
->changed
.ucp
& (1 << i
))
2283 nine_context_set_clip_plane(device
, i
, (struct nine_clipplane
*)&src
->clip
.ucp
[i
][0]);
2285 if (!(src
->changed
.group
& NINE_STATE_FF
))
2288 /* Fixed function state. */
2290 if (src
->changed
.group
& NINE_STATE_FF_MATERIAL
)
2291 nine_context_set_material(device
, &src
->ff
.material
);
2293 if (src
->changed
.group
& NINE_STATE_FF_PSSTAGES
) {
2295 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
2296 for (i
= 0; i
< NINED3DTSS_COUNT
; ++i
)
2297 if (src
->ff
.changed
.tex_stage
[s
][i
/ 32] & (1 << (i
% 32)))
2298 nine_context_set_texture_stage_state(device
, s
, i
, src
->ff
.tex_stage
[s
][i
]);
2301 if (src
->changed
.group
& NINE_STATE_FF_LIGHTING
) {
2302 for (i
= 0; i
< src
->ff
.num_lights
; ++i
)
2303 if (src
->ff
.light
[i
].Type
!= NINED3DLIGHT_INVALID
)
2304 nine_context_set_light(device
, i
, &src
->ff
.light
[i
]);
2306 nine_context_light_enable_stateblock(device
, src
->ff
.active_light
, src
->ff
.num_lights_active
);
2308 if (src
->changed
.group
& NINE_STATE_FF_VSTRANSF
) {
2309 for (i
= 0; i
< ARRAY_SIZE(src
->ff
.changed
.transform
); ++i
) {
2311 if (!src
->ff
.changed
.transform
[i
])
2313 for (s
= i
* 32; s
< (i
* 32 + 32); ++s
) {
2314 if (!(src
->ff
.changed
.transform
[i
] & (1 << (s
% 32))))
2316 nine_context_set_transform(device
, s
,
2317 nine_state_access_transform(
2318 (struct nine_ff_state
*)&src
->ff
,
2326 nine_update_state_framebuffer_clear(struct NineDevice9
*device
)
2328 struct nine_context
*context
= &device
->context
;
2330 if (context
->changed
.group
& NINE_STATE_FB
)
2331 update_framebuffer(device
, TRUE
);
2334 CSMT_ITEM_NO_WAIT(nine_context_clear_fb
,
2335 ARG_VAL(DWORD
, Count
),
2336 ARG_COPY_REF(D3DRECT
, pRects
),
2337 ARG_VAL(DWORD
, Flags
),
2338 ARG_VAL(D3DCOLOR
, Color
),
2340 ARG_VAL(DWORD
, Stencil
))
2342 struct nine_context
*context
= &device
->context
;
2343 const int sRGB
= context
->rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
2344 struct pipe_surface
*cbuf
, *zsbuf
;
2345 struct pipe_context
*pipe
= context
->pipe
;
2346 struct NineSurface9
*zsbuf_surf
= context
->ds
;
2347 struct NineSurface9
*rt
;
2350 union pipe_color_union rgba
;
2351 unsigned rt_mask
= 0;
2354 nine_update_state_framebuffer_clear(device
);
2356 if (Flags
& D3DCLEAR_TARGET
) bufs
|= PIPE_CLEAR_COLOR
;
2357 /* Ignore Z buffer if not bound */
2358 if (context
->pipe_data
.fb
.zsbuf
!= NULL
) {
2359 if (Flags
& D3DCLEAR_ZBUFFER
) bufs
|= PIPE_CLEAR_DEPTH
;
2360 if (Flags
& D3DCLEAR_STENCIL
) bufs
|= PIPE_CLEAR_STENCIL
;
2364 d3dcolor_to_pipe_color_union(&rgba
, Color
);
2366 rect
.x1
= context
->viewport
.X
;
2367 rect
.y1
= context
->viewport
.Y
;
2368 rect
.x2
= context
->viewport
.Width
+ rect
.x1
;
2369 rect
.y2
= context
->viewport
.Height
+ rect
.y1
;
2371 /* Both rectangles apply, which is weird, but that's D3D9. */
2372 if (context
->rs
[D3DRS_SCISSORTESTENABLE
]) {
2373 rect
.x1
= MAX2(rect
.x1
, context
->scissor
.minx
);
2374 rect
.y1
= MAX2(rect
.y1
, context
->scissor
.miny
);
2375 rect
.x2
= MIN2(rect
.x2
, context
->scissor
.maxx
);
2376 rect
.y2
= MIN2(rect
.y2
, context
->scissor
.maxy
);
2380 /* Maybe apps like to specify a large rect ? */
2381 if (pRects
[0].x1
<= rect
.x1
&& pRects
[0].x2
>= rect
.x2
&&
2382 pRects
[0].y1
<= rect
.y1
&& pRects
[0].y2
>= rect
.y2
) {
2383 DBG("First rect covers viewport.\n");
2389 if (rect
.x1
>= context
->pipe_data
.fb
.width
|| rect
.y1
>= context
->pipe_data
.fb
.height
)
2392 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
2393 if (context
->rt
[i
] && context
->rt
[i
]->desc
.Format
!= D3DFMT_NULL
)
2397 /* fast path, clears everything at once */
2399 (!(bufs
& PIPE_CLEAR_COLOR
) || (rt_mask
== context
->rt_mask
)) &&
2400 rect
.x1
== 0 && rect
.y1
== 0 &&
2401 /* Case we clear only render target. Check clear region vs rt. */
2402 ((!(bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
2403 rect
.x2
>= context
->pipe_data
.fb
.width
&&
2404 rect
.y2
>= context
->pipe_data
.fb
.height
) ||
2405 /* Case we clear depth buffer (and eventually rt too).
2406 * depth buffer size is always >= rt size. Compare to clear region */
2407 ((bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
2408 rect
.x2
>= zsbuf_surf
->desc
.Width
&&
2409 rect
.y2
>= zsbuf_surf
->desc
.Height
))) {
2410 DBG("Clear fast path\n");
2411 pipe
->clear(pipe
, bufs
, &rgba
, Z
, Stencil
);
2420 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
2421 rt
= context
->rt
[i
];
2422 if (!rt
|| rt
->desc
.Format
== D3DFMT_NULL
||
2423 !(bufs
& PIPE_CLEAR_COLOR
))
2424 continue; /* save space, compiler should hoist this */
2425 cbuf
= NineSurface9_GetSurface(rt
, sRGB
);
2426 for (r
= 0; r
< Count
; ++r
) {
2427 /* Don't trust users to pass these in the right order. */
2428 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
2429 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
2430 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
2431 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
2433 /* Drop negative rectangles (like wine expects). */
2434 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
2435 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2438 x1
= MAX2(x1
, rect
.x1
);
2439 y1
= MAX2(y1
, rect
.y1
);
2440 x2
= MIN3(x2
, rect
.x2
, rt
->desc
.Width
);
2441 y2
= MIN3(y2
, rect
.y2
, rt
->desc
.Height
);
2443 DBG("Clearing (%u..%u)x(%u..%u)\n", x1
, x2
, y1
, y2
);
2444 pipe
->clear_render_target(pipe
, cbuf
, &rgba
,
2445 x1
, y1
, x2
- x1
, y2
- y1
, false);
2448 if (!(bufs
& PIPE_CLEAR_DEPTHSTENCIL
))
2451 bufs
&= PIPE_CLEAR_DEPTHSTENCIL
;
2453 for (r
= 0; r
< Count
; ++r
) {
2454 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
2455 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
2456 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
2457 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
2459 /* Drop negative rectangles. */
2460 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
2461 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
2464 x1
= MIN2(x1
, rect
.x1
);
2465 y1
= MIN2(y1
, rect
.y1
);
2466 x2
= MIN3(x2
, rect
.x2
, zsbuf_surf
->desc
.Width
);
2467 y2
= MIN3(y2
, rect
.y2
, zsbuf_surf
->desc
.Height
);
2469 zsbuf
= NineSurface9_GetSurface(zsbuf_surf
, 0);
2471 pipe
->clear_depth_stencil(pipe
, zsbuf
, bufs
, Z
, Stencil
,
2472 x1
, y1
, x2
- x1
, y2
- y1
, false);
2479 init_draw_info(struct pipe_draw_info
*info
,
2480 struct NineDevice9
*dev
, D3DPRIMITIVETYPE type
, UINT count
)
2482 info
->mode
= d3dprimitivetype_to_pipe_prim(type
);
2483 info
->count
= prim_count_to_vertex_count(type
, count
);
2484 info
->start_instance
= 0;
2485 info
->instance_count
= 1;
2486 if (dev
->context
.stream_instancedata_mask
& dev
->context
.stream_usage_mask
)
2487 info
->instance_count
= MAX2(dev
->context
.stream_freq
[0] & 0x7FFFFF, 1);
2488 info
->primitive_restart
= FALSE
;
2489 info
->restart_index
= 0;
2490 info
->count_from_stream_output
= NULL
;
2491 info
->indirect
= NULL
;
2492 info
->indirect_params
= NULL
;
2495 CSMT_ITEM_NO_WAIT(nine_context_draw_primitive
,
2496 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2497 ARG_VAL(UINT
, StartVertex
),
2498 ARG_VAL(UINT
, PrimitiveCount
))
2500 struct nine_context
*context
= &device
->context
;
2501 struct pipe_draw_info info
;
2503 nine_update_state(device
);
2505 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2506 info
.indexed
= FALSE
;
2507 info
.start
= StartVertex
;
2508 info
.index_bias
= 0;
2509 info
.min_index
= info
.start
;
2510 info
.max_index
= info
.count
- 1;
2512 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2515 CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive
,
2516 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2517 ARG_VAL(INT
, BaseVertexIndex
),
2518 ARG_VAL(UINT
, MinVertexIndex
),
2519 ARG_VAL(UINT
, NumVertices
),
2520 ARG_VAL(UINT
, StartIndex
),
2521 ARG_VAL(UINT
, PrimitiveCount
))
2523 struct nine_context
*context
= &device
->context
;
2524 struct pipe_draw_info info
;
2526 nine_update_state(device
);
2528 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2529 info
.indexed
= TRUE
;
2530 info
.start
= StartIndex
;
2531 info
.index_bias
= BaseVertexIndex
;
2532 /* These don't include index bias: */
2533 info
.min_index
= MinVertexIndex
;
2534 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2536 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2539 CSMT_ITEM_NO_WAIT(nine_context_draw_primitive_from_vtxbuf
,
2540 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2541 ARG_VAL(UINT
, PrimitiveCount
),
2542 ARG_BIND_BUF(struct pipe_vertex_buffer
, vtxbuf
))
2544 struct nine_context
*context
= &device
->context
;
2545 struct pipe_draw_info info
;
2547 nine_update_state(device
);
2549 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2550 info
.indexed
= FALSE
;
2552 info
.index_bias
= 0;
2554 info
.max_index
= info
.count
- 1;
2556 context
->pipe
->set_vertex_buffers(context
->pipe
, 0, 1, vtxbuf
);
2558 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2561 CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf
,
2562 ARG_VAL(D3DPRIMITIVETYPE
, PrimitiveType
),
2563 ARG_VAL(UINT
, MinVertexIndex
),
2564 ARG_VAL(UINT
, NumVertices
),
2565 ARG_VAL(UINT
, PrimitiveCount
),
2566 ARG_BIND_BUF(struct pipe_vertex_buffer
, vbuf
),
2567 ARG_BIND_BUF(struct pipe_index_buffer
, ibuf
))
2569 struct nine_context
*context
= &device
->context
;
2570 struct pipe_draw_info info
;
2572 nine_update_state(device
);
2574 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2575 info
.indexed
= TRUE
;
2577 info
.index_bias
= 0;
2578 info
.min_index
= MinVertexIndex
;
2579 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2580 context
->pipe
->set_vertex_buffers(context
->pipe
, 0, 1, vbuf
);
2581 context
->pipe
->set_index_buffer(context
->pipe
, ibuf
);
2583 context
->pipe
->draw_vbo(context
->pipe
, &info
);
2586 CSMT_ITEM_NO_WAIT(nine_context_resource_copy_region
,
2587 ARG_BIND_RES(struct pipe_resource
, dst_res
),
2588 ARG_VAL(unsigned, dst_level
),
2589 ARG_COPY_REF(struct pipe_box
, dst_box
),
2590 ARG_BIND_RES(struct pipe_resource
, src_res
),
2591 ARG_VAL(unsigned, src_level
),
2592 ARG_COPY_REF(struct pipe_box
, src_box
))
2594 struct nine_context
*context
= &device
->context
;
2596 context
->pipe
->resource_copy_region(context
->pipe
,
2598 dst_box
->x
, dst_box
->y
, dst_box
->z
,
2603 CSMT_ITEM_NO_WAIT(nine_context_blit
,
2604 ARG_BIND_BLIT(struct pipe_blit_info
, blit
))
2606 struct nine_context
*context
= &device
->context
;
2608 context
->pipe
->blit(context
->pipe
, blit
);
2612 nine_context_create_query(struct NineDevice9
*device
, unsigned query_type
)
2614 struct nine_context
*context
= &device
->context
;
2616 if (device
->csmt_active
)
2617 nine_csmt_process(device
);
2618 return context
->pipe
->create_query(context
->pipe
, query_type
, 0);
2621 CSMT_ITEM_DO_WAIT(nine_context_destroy_query
,
2622 ARG_REF(struct pipe_query
, query
))
2624 struct nine_context
*context
= &device
->context
;
2626 context
->pipe
->destroy_query(context
->pipe
, query
);
2629 CSMT_ITEM_NO_WAIT(nine_context_begin_query
,
2630 ARG_REF(struct pipe_query
, query
))
2632 struct nine_context
*context
= &device
->context
;
2634 (void) context
->pipe
->begin_query(context
->pipe
, query
);
2637 CSMT_ITEM_NO_WAIT(nine_context_end_query
,
2638 ARG_REF(struct pipe_query
, query
))
2640 struct nine_context
*context
= &device
->context
;
2642 (void) context
->pipe
->end_query(context
->pipe
, query
);
2646 nine_context_get_query_result(struct NineDevice9
*device
, struct pipe_query
*query
,
2647 boolean flush
, boolean wait
,
2648 union pipe_query_result
*result
)
2650 struct nine_context
*context
= &device
->context
;
2653 if (device
->csmt_active
)
2654 nine_csmt_process(device
);
2655 return context
->pipe
->get_query_result(context
->pipe
, query
, wait
, result
);
2658 /* State defaults */
2660 static const DWORD nine_render_state_defaults
[NINED3DRS_LAST
+ 1] =
2662 /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */
2663 [D3DRS_ZENABLE
] = D3DZB_FALSE
,
2664 [D3DRS_FILLMODE
] = D3DFILL_SOLID
,
2665 [D3DRS_SHADEMODE
] = D3DSHADE_GOURAUD
,
2666 /* [D3DRS_LINEPATTERN] = 0x00000000, */
2667 [D3DRS_ZWRITEENABLE
] = TRUE
,
2668 [D3DRS_ALPHATESTENABLE
] = FALSE
,
2669 [D3DRS_LASTPIXEL
] = TRUE
,
2670 [D3DRS_SRCBLEND
] = D3DBLEND_ONE
,
2671 [D3DRS_DESTBLEND
] = D3DBLEND_ZERO
,
2672 [D3DRS_CULLMODE
] = D3DCULL_CCW
,
2673 [D3DRS_ZFUNC
] = D3DCMP_LESSEQUAL
,
2674 [D3DRS_ALPHAFUNC
] = D3DCMP_ALWAYS
,
2675 [D3DRS_ALPHAREF
] = 0,
2676 [D3DRS_DITHERENABLE
] = FALSE
,
2677 [D3DRS_ALPHABLENDENABLE
] = FALSE
,
2678 [D3DRS_FOGENABLE
] = FALSE
,
2679 [D3DRS_SPECULARENABLE
] = FALSE
,
2680 /* [D3DRS_ZVISIBLE] = 0, */
2681 [D3DRS_FOGCOLOR
] = 0,
2682 [D3DRS_FOGTABLEMODE
] = D3DFOG_NONE
,
2683 [D3DRS_FOGSTART
] = 0x00000000,
2684 [D3DRS_FOGEND
] = 0x3F800000,
2685 [D3DRS_FOGDENSITY
] = 0x3F800000,
2686 /* [D3DRS_EDGEANTIALIAS] = FALSE, */
2687 [D3DRS_RANGEFOGENABLE
] = FALSE
,
2688 [D3DRS_STENCILENABLE
] = FALSE
,
2689 [D3DRS_STENCILFAIL
] = D3DSTENCILOP_KEEP
,
2690 [D3DRS_STENCILZFAIL
] = D3DSTENCILOP_KEEP
,
2691 [D3DRS_STENCILPASS
] = D3DSTENCILOP_KEEP
,
2692 [D3DRS_STENCILREF
] = 0,
2693 [D3DRS_STENCILMASK
] = 0xFFFFFFFF,
2694 [D3DRS_STENCILFUNC
] = D3DCMP_ALWAYS
,
2695 [D3DRS_STENCILWRITEMASK
] = 0xFFFFFFFF,
2696 [D3DRS_TEXTUREFACTOR
] = 0xFFFFFFFF,
2705 [D3DRS_CLIPPING
] = TRUE
,
2706 [D3DRS_LIGHTING
] = TRUE
,
2707 [D3DRS_AMBIENT
] = 0,
2708 [D3DRS_FOGVERTEXMODE
] = D3DFOG_NONE
,
2709 [D3DRS_COLORVERTEX
] = TRUE
,
2710 [D3DRS_LOCALVIEWER
] = TRUE
,
2711 [D3DRS_NORMALIZENORMALS
] = FALSE
,
2712 [D3DRS_DIFFUSEMATERIALSOURCE
] = D3DMCS_COLOR1
,
2713 [D3DRS_SPECULARMATERIALSOURCE
] = D3DMCS_COLOR2
,
2714 [D3DRS_AMBIENTMATERIALSOURCE
] = D3DMCS_MATERIAL
,
2715 [D3DRS_EMISSIVEMATERIALSOURCE
] = D3DMCS_MATERIAL
,
2716 [D3DRS_VERTEXBLEND
] = D3DVBF_DISABLE
,
2717 [D3DRS_CLIPPLANEENABLE
] = 0,
2718 /* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */
2719 [D3DRS_POINTSIZE
] = 0x3F800000,
2720 [D3DRS_POINTSIZE_MIN
] = 0x3F800000,
2721 [D3DRS_POINTSPRITEENABLE
] = FALSE
,
2722 [D3DRS_POINTSCALEENABLE
] = FALSE
,
2723 [D3DRS_POINTSCALE_A
] = 0x3F800000,
2724 [D3DRS_POINTSCALE_B
] = 0x00000000,
2725 [D3DRS_POINTSCALE_C
] = 0x00000000,
2726 [D3DRS_MULTISAMPLEANTIALIAS
] = TRUE
,
2727 [D3DRS_MULTISAMPLEMASK
] = 0xFFFFFFFF,
2728 [D3DRS_PATCHEDGESTYLE
] = D3DPATCHEDGE_DISCRETE
,
2729 /* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */
2730 [D3DRS_DEBUGMONITORTOKEN
] = 0xDEADCAFE,
2731 [D3DRS_POINTSIZE_MAX
] = 0x3F800000, /* depends on cap */
2732 [D3DRS_INDEXEDVERTEXBLENDENABLE
] = FALSE
,
2733 [D3DRS_COLORWRITEENABLE
] = 0x0000000f,
2734 [D3DRS_TWEENFACTOR
] = 0x00000000,
2735 [D3DRS_BLENDOP
] = D3DBLENDOP_ADD
,
2736 [D3DRS_POSITIONDEGREE
] = D3DDEGREE_CUBIC
,
2737 [D3DRS_NORMALDEGREE
] = D3DDEGREE_LINEAR
,
2738 [D3DRS_SCISSORTESTENABLE
] = FALSE
,
2739 [D3DRS_SLOPESCALEDEPTHBIAS
] = 0,
2740 [D3DRS_MINTESSELLATIONLEVEL
] = 0x3F800000,
2741 [D3DRS_MAXTESSELLATIONLEVEL
] = 0x3F800000,
2742 [D3DRS_ANTIALIASEDLINEENABLE
] = FALSE
,
2743 [D3DRS_ADAPTIVETESS_X
] = 0x00000000,
2744 [D3DRS_ADAPTIVETESS_Y
] = 0x00000000,
2745 [D3DRS_ADAPTIVETESS_Z
] = 0x3F800000,
2746 [D3DRS_ADAPTIVETESS_W
] = 0x00000000,
2747 [D3DRS_ENABLEADAPTIVETESSELLATION
] = FALSE
,
2748 [D3DRS_TWOSIDEDSTENCILMODE
] = FALSE
,
2749 [D3DRS_CCW_STENCILFAIL
] = D3DSTENCILOP_KEEP
,
2750 [D3DRS_CCW_STENCILZFAIL
] = D3DSTENCILOP_KEEP
,
2751 [D3DRS_CCW_STENCILPASS
] = D3DSTENCILOP_KEEP
,
2752 [D3DRS_CCW_STENCILFUNC
] = D3DCMP_ALWAYS
,
2753 [D3DRS_COLORWRITEENABLE1
] = 0x0000000F,
2754 [D3DRS_COLORWRITEENABLE2
] = 0x0000000F,
2755 [D3DRS_COLORWRITEENABLE3
] = 0x0000000F,
2756 [D3DRS_BLENDFACTOR
] = 0xFFFFFFFF,
2757 [D3DRS_SRGBWRITEENABLE
] = 0,
2758 [D3DRS_DEPTHBIAS
] = 0,
2767 [D3DRS_SEPARATEALPHABLENDENABLE
] = FALSE
,
2768 [D3DRS_SRCBLENDALPHA
] = D3DBLEND_ONE
,
2769 [D3DRS_DESTBLENDALPHA
] = D3DBLEND_ZERO
,
2770 [D3DRS_BLENDOPALPHA
] = D3DBLENDOP_ADD
,
2771 [NINED3DRS_VSPOINTSIZE
] = FALSE
,
2772 [NINED3DRS_RTMASK
] = 0xf,
2773 [NINED3DRS_ALPHACOVERAGE
] = FALSE
,
2774 [NINED3DRS_MULTISAMPLE
] = FALSE
2776 static const DWORD nine_tex_stage_state_defaults
[NINED3DTSS_LAST
+ 1] =
2778 [D3DTSS_COLOROP
] = D3DTOP_DISABLE
,
2779 [D3DTSS_ALPHAOP
] = D3DTOP_DISABLE
,
2780 [D3DTSS_COLORARG1
] = D3DTA_TEXTURE
,
2781 [D3DTSS_COLORARG2
] = D3DTA_CURRENT
,
2782 [D3DTSS_COLORARG0
] = D3DTA_CURRENT
,
2783 [D3DTSS_ALPHAARG1
] = D3DTA_TEXTURE
,
2784 [D3DTSS_ALPHAARG2
] = D3DTA_CURRENT
,
2785 [D3DTSS_ALPHAARG0
] = D3DTA_CURRENT
,
2786 [D3DTSS_RESULTARG
] = D3DTA_CURRENT
,
2787 [D3DTSS_BUMPENVMAT00
] = 0,
2788 [D3DTSS_BUMPENVMAT01
] = 0,
2789 [D3DTSS_BUMPENVMAT10
] = 0,
2790 [D3DTSS_BUMPENVMAT11
] = 0,
2791 [D3DTSS_BUMPENVLSCALE
] = 0,
2792 [D3DTSS_BUMPENVLOFFSET
] = 0,
2793 [D3DTSS_TEXCOORDINDEX
] = 0,
2794 [D3DTSS_TEXTURETRANSFORMFLAGS
] = D3DTTFF_DISABLE
,
2796 static const DWORD nine_samp_state_defaults
[NINED3DSAMP_LAST
+ 1] =
2798 [D3DSAMP_ADDRESSU
] = D3DTADDRESS_WRAP
,
2799 [D3DSAMP_ADDRESSV
] = D3DTADDRESS_WRAP
,
2800 [D3DSAMP_ADDRESSW
] = D3DTADDRESS_WRAP
,
2801 [D3DSAMP_BORDERCOLOR
] = 0,
2802 [D3DSAMP_MAGFILTER
] = D3DTEXF_POINT
,
2803 [D3DSAMP_MINFILTER
] = D3DTEXF_POINT
,
2804 [D3DSAMP_MIPFILTER
] = D3DTEXF_NONE
,
2805 [D3DSAMP_MIPMAPLODBIAS
] = 0,
2806 [D3DSAMP_MAXMIPLEVEL
] = 0,
2807 [D3DSAMP_MAXANISOTROPY
] = 1,
2808 [D3DSAMP_SRGBTEXTURE
] = 0,
2809 [D3DSAMP_ELEMENTINDEX
] = 0,
2810 [D3DSAMP_DMAPOFFSET
] = 0,
2811 [NINED3DSAMP_MINLOD
] = 0,
2812 [NINED3DSAMP_SHADOW
] = 0,
2813 [NINED3DSAMP_CUBETEX
] = 0
2816 void nine_state_restore_non_cso(struct NineDevice9
*device
)
2818 struct nine_context
*context
= &device
->context
;
2820 context
->changed
.group
= NINE_STATE_ALL
;
2821 context
->changed
.vtxbuf
= (1ULL << device
->caps
.MaxStreams
) - 1;
2822 context
->changed
.ucp
= TRUE
;
2823 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
| NINE_STATE_COMMIT_CONST_PS
;
2827 nine_state_set_defaults(struct NineDevice9
*device
, const D3DCAPS9
*caps
,
2830 struct nine_state
*state
= &device
->state
;
2831 struct nine_context
*context
= &device
->context
;
2834 /* Initialize defaults.
2836 memcpy(context
->rs
, nine_render_state_defaults
, sizeof(context
->rs
));
2838 for (s
= 0; s
< ARRAY_SIZE(state
->ff
.tex_stage
); ++s
) {
2839 memcpy(&state
->ff
.tex_stage
[s
], nine_tex_stage_state_defaults
,
2840 sizeof(state
->ff
.tex_stage
[s
]));
2841 state
->ff
.tex_stage
[s
][D3DTSS_TEXCOORDINDEX
] = s
;
2843 state
->ff
.tex_stage
[0][D3DTSS_COLOROP
] = D3DTOP_MODULATE
;
2844 state
->ff
.tex_stage
[0][D3DTSS_ALPHAOP
] = D3DTOP_SELECTARG1
;
2846 for (s
= 0; s
< ARRAY_SIZE(state
->ff
.tex_stage
); ++s
)
2847 memcpy(&context
->ff
.tex_stage
[s
], state
->ff
.tex_stage
[s
],
2848 sizeof(state
->ff
.tex_stage
[s
]));
2850 memset(&context
->bumpmap_vars
, 0, sizeof(context
->bumpmap_vars
));
2852 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
2853 memcpy(&context
->samp
[s
], nine_samp_state_defaults
,
2854 sizeof(context
->samp
[s
]));
2855 memcpy(&state
->samp_advertised
[s
], nine_samp_state_defaults
,
2856 sizeof(state
->samp_advertised
[s
]));
2859 memset(state
->vs_const_f
, 0, VS_CONST_F_SIZE(device
));
2860 memset(context
->vs_const_f
, 0, device
->vs_const_size
);
2861 if (context
->vs_const_f_swvp
)
2862 memset(context
->vs_const_f_swvp
, 0, NINE_MAX_CONST_F_SWVP
* sizeof(float[4]));
2863 memset(state
->vs_const_i
, 0, VS_CONST_I_SIZE(device
));
2864 memset(context
->vs_const_i
, 0, VS_CONST_I_SIZE(device
));
2865 memset(state
->vs_const_b
, 0, VS_CONST_B_SIZE(device
));
2866 memset(context
->vs_const_b
, 0, VS_CONST_B_SIZE(device
));
2867 memset(state
->ps_const_f
, 0, device
->ps_const_size
);
2868 memset(context
->ps_const_f
, 0, device
->ps_const_size
);
2869 memset(state
->ps_const_i
, 0, sizeof(state
->ps_const_i
));
2870 memset(context
->ps_const_i
, 0, sizeof(context
->ps_const_i
));
2871 memset(state
->ps_const_b
, 0, sizeof(state
->ps_const_b
));
2872 memset(context
->ps_const_b
, 0, sizeof(context
->ps_const_b
));
2874 /* Cap dependent initial state:
2876 context
->rs
[D3DRS_POINTSIZE_MAX
] = fui(caps
->MaxPointSize
);
2878 memcpy(state
->rs_advertised
, context
->rs
, sizeof(context
->rs
));
2880 /* Set changed flags to initialize driver.
2882 context
->changed
.group
= NINE_STATE_ALL
;
2883 context
->changed
.vtxbuf
= (1ULL << device
->caps
.MaxStreams
) - 1;
2884 context
->changed
.ucp
= TRUE
;
2886 context
->ff
.changed
.transform
[0] = ~0;
2887 context
->ff
.changed
.transform
[D3DTS_WORLD
/ 32] |= 1 << (D3DTS_WORLD
% 32);
2890 state
->viewport
.MinZ
= context
->viewport
.MinZ
= 0.0f
;
2891 state
->viewport
.MaxZ
= context
->viewport
.MaxZ
= 1.0f
;
2894 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2895 context
->changed
.sampler
[s
] = ~0;
2898 context
->dummy_vbo_bound_at
= -1;
2899 context
->vbo_bound_done
= FALSE
;
2904 nine_state_clear(struct nine_state
*state
, const boolean device
)
2908 for (i
= 0; i
< ARRAY_SIZE(state
->rt
); ++i
)
2909 nine_bind(&state
->rt
[i
], NULL
);
2910 nine_bind(&state
->ds
, NULL
);
2911 nine_bind(&state
->vs
, NULL
);
2912 nine_bind(&state
->ps
, NULL
);
2913 nine_bind(&state
->vdecl
, NULL
);
2914 for (i
= 0; i
< PIPE_MAX_ATTRIBS
; ++i
)
2915 nine_bind(&state
->stream
[i
], NULL
);
2917 nine_bind(&state
->idxbuf
, NULL
);
2918 for (i
= 0; i
< NINE_MAX_SAMPLERS
; ++i
) {
2920 state
->texture
[i
] &&
2921 --state
->texture
[i
]->bind_count
== 0)
2922 list_delinit(&state
->texture
[i
]->list
);
2923 nine_bind(&state
->texture
[i
], NULL
);
2928 nine_context_clear(struct NineDevice9
*device
)
2930 struct nine_context
*context
= &device
->context
;
2931 struct pipe_context
*pipe
= context
->pipe
;
2932 struct cso_context
*cso
= context
->cso
;
2935 /* Early device ctor failure. Nothing to do */
2939 pipe
->bind_vs_state(pipe
, NULL
);
2940 pipe
->bind_fs_state(pipe
, NULL
);
2942 /* Don't unbind constant buffers, they're device-private and
2943 * do not change on Reset.
2946 cso_set_samplers(cso
, PIPE_SHADER_VERTEX
, 0, NULL
);
2947 cso_set_samplers(cso
, PIPE_SHADER_FRAGMENT
, 0, NULL
);
2949 cso_set_sampler_views(cso
, PIPE_SHADER_VERTEX
, 0, NULL
);
2950 cso_set_sampler_views(cso
, PIPE_SHADER_FRAGMENT
, 0, NULL
);
2952 pipe
->set_vertex_buffers(pipe
, 0, device
->caps
.MaxStreams
, NULL
);
2953 pipe
->set_index_buffer(pipe
, NULL
);
2955 for (i
= 0; i
< ARRAY_SIZE(context
->rt
); ++i
)
2956 nine_bind(&context
->rt
[i
], NULL
);
2957 nine_bind(&context
->ds
, NULL
);
2958 nine_bind(&context
->vs
, NULL
);
2959 nine_bind(&context
->ps
, NULL
);
2960 nine_bind(&context
->vdecl
, NULL
);
2961 for (i
= 0; i
< PIPE_MAX_ATTRIBS
; ++i
)
2962 pipe_resource_reference(&context
->vtxbuf
[i
].buffer
, NULL
);
2963 pipe_resource_reference(&context
->idxbuf
.buffer
, NULL
);
2965 for (i
= 0; i
< NINE_MAX_SAMPLERS
; ++i
) {
2966 context
->texture
[i
].enabled
= FALSE
;
2967 pipe_resource_reference(&context
->texture
[i
].resource
,
2969 pipe_sampler_view_reference(&context
->texture
[i
].view
[0],
2971 pipe_sampler_view_reference(&context
->texture
[i
].view
[1],
2977 nine_state_init_sw(struct NineDevice9
*device
)
2979 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
2980 struct pipe_rasterizer_state rast
;
2981 struct pipe_blend_state blend
;
2982 struct pipe_depth_stencil_alpha_state dsa
;
2983 struct pipe_framebuffer_state fb
;
2985 /* Only used with Streamout */
2986 memset(&rast
, 0, sizeof(rast
));
2987 rast
.rasterizer_discard
= true;
2988 rast
.point_quad_rasterization
= 1; /* to make llvmpipe happy */
2989 cso_set_rasterizer(device
->cso_sw
, &rast
);
2991 /* dummy settings */
2992 memset(&blend
, 0, sizeof(blend
));
2993 memset(&dsa
, 0, sizeof(dsa
));
2994 memset(&fb
, 0, sizeof(fb
));
2995 cso_set_blend(device
->cso_sw
, &blend
);
2996 cso_set_depth_stencil_alpha(device
->cso_sw
, &dsa
);
2997 cso_set_framebuffer(device
->cso_sw
, &fb
);
2998 cso_set_viewport_dims(device
->cso_sw
, 1.0, 1.0, false);
2999 cso_set_fragment_shader_handle(device
->cso_sw
, util_make_empty_fragment_shader(pipe_sw
));
3002 /* There is duplication with update_vertex_elements.
3003 * TODO: Share the code */
3006 update_vertex_elements_sw(struct NineDevice9
*device
)
3008 struct nine_state
*state
= &device
->state
;
3009 const struct NineVertexDeclaration9
*vdecl
= device
->state
.vdecl
;
3010 const struct NineVertexShader9
*vs
;
3013 char vdecl_index_map
[16]; /* vs->num_inputs <= 16 */
3014 char used_streams
[device
->caps
.MaxStreams
];
3015 int dummy_vbo_stream
= -1;
3016 BOOL need_dummy_vbo
= FALSE
;
3017 struct pipe_vertex_element ve
[PIPE_MAX_ATTRIBS
];
3018 bool programmable_vs
= state
->vs
&& !(state
->vdecl
&& state
->vdecl
->position_t
);
3020 memset(vdecl_index_map
, -1, 16);
3021 memset(used_streams
, 0, device
->caps
.MaxStreams
);
3022 vs
= programmable_vs
? device
->state
.vs
: device
->ff
.vs
;
3025 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
3026 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
3027 n
, vs
->input_map
[n
].ndecl
, vdecl
);
3029 for (i
= 0; i
< vdecl
->nelems
; i
++) {
3030 if (vdecl
->usage_map
[i
] == vs
->input_map
[n
].ndecl
) {
3031 vdecl_index_map
[n
] = i
;
3032 used_streams
[vdecl
->elems
[i
].vertex_buffer_index
] = 1;
3036 if (vdecl_index_map
[n
] < 0)
3037 need_dummy_vbo
= TRUE
;
3040 /* No vertex declaration. Likely will never happen in practice,
3041 * but we need not crash on this */
3042 need_dummy_vbo
= TRUE
;
3045 if (need_dummy_vbo
) {
3046 for (i
= 0; i
< device
->caps
.MaxStreams
; i
++ ) {
3047 if (!used_streams
[i
]) {
3048 dummy_vbo_stream
= i
;
3053 /* TODO handle dummy_vbo */
3054 assert (!need_dummy_vbo
);
3056 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
3057 index
= vdecl_index_map
[n
];
3059 ve
[n
] = vdecl
->elems
[index
];
3060 b
= ve
[n
].vertex_buffer_index
;
3061 /* XXX wine just uses 1 here: */
3062 if (state
->stream_freq
[b
] & D3DSTREAMSOURCE_INSTANCEDATA
)
3063 ve
[n
].instance_divisor
= state
->stream_freq
[b
] & 0x7FFFFF;
3065 /* if the vertex declaration is incomplete compared to what the
3066 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
3067 * This is not precised by the spec, but is the behaviour
3069 ve
[n
].vertex_buffer_index
= dummy_vbo_stream
;
3070 ve
[n
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
3071 ve
[n
].src_offset
= 0;
3072 ve
[n
].instance_divisor
= 0;
3076 cso_set_vertex_elements(device
->cso_sw
, vs
->num_inputs
, ve
);
3080 update_vertex_buffers_sw(struct NineDevice9
*device
, int start_vertice
, int num_vertices
)
3082 struct pipe_context
*pipe
= NineDevice9_GetPipe(device
);
3083 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
3084 struct nine_state
*state
= &device
->state
;
3085 struct nine_state_sw_internal
*sw_internal
= &device
->state_sw_internal
;
3086 struct pipe_vertex_buffer vtxbuf
;
3087 uint32_t mask
= 0xf;
3090 DBG("mask=%x\n", mask
);
3092 /* TODO: handle dummy_vbo_bound_at */
3094 for (i
= 0; mask
; mask
>>= 1, ++i
) {
3096 if (state
->stream
[i
]) {
3097 struct pipe_resource
*buf
;
3098 struct pipe_box box
;
3100 vtxbuf
= state
->vtxbuf
[i
];
3101 vtxbuf
.buffer
= NineVertexBuffer9_GetResource(state
->stream
[i
]);
3103 DBG("Locking %p (offset %d, length %d)\n", vtxbuf
.buffer
,
3104 vtxbuf
.buffer_offset
, num_vertices
* vtxbuf
.stride
);
3106 u_box_1d(vtxbuf
.buffer_offset
+ start_vertice
* vtxbuf
.stride
,
3107 num_vertices
* vtxbuf
.stride
, &box
);
3108 buf
= vtxbuf
.buffer
;
3109 vtxbuf
.user_buffer
= pipe
->transfer_map(pipe
, buf
, 0, PIPE_TRANSFER_READ
, &box
,
3110 &(sw_internal
->transfers_so
[i
]));
3111 vtxbuf
.buffer
= NULL
;
3112 if (!device
->driver_caps
.user_sw_vbufs
) {
3113 u_upload_data(device
->vertex_sw_uploader
,
3118 &(vtxbuf
.buffer_offset
),
3120 u_upload_unmap(device
->vertex_sw_uploader
);
3121 vtxbuf
.user_buffer
= NULL
;
3123 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, &vtxbuf
);
3125 pipe_resource_reference(&vtxbuf
.buffer
, NULL
);
3127 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, NULL
);
3133 update_vs_constants_sw(struct NineDevice9
*device
)
3135 struct nine_state
*state
= &device
->state
;
3136 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
3141 struct pipe_constant_buffer cb
;
3145 cb
.buffer_offset
= 0;
3146 cb
.buffer_size
= 4096 * sizeof(float[4]);
3147 cb
.user_buffer
= state
->vs_const_f
;
3149 if (state
->vs
->lconstf
.ranges
) {
3150 const struct nine_lconstf
*lconstf
= &device
->state
.vs
->lconstf
;
3151 const struct nine_range
*r
= lconstf
->ranges
;
3153 float *dst
= device
->state
.vs_lconstf_temp
;
3154 float *src
= (float *)cb
.user_buffer
;
3155 memcpy(dst
, src
, 8192 * sizeof(float[4]));
3157 unsigned p
= r
->bgn
;
3158 unsigned c
= r
->end
- r
->bgn
;
3159 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
3163 cb
.user_buffer
= dst
;
3166 buf
= cb
.user_buffer
;
3167 if (!device
->driver_caps
.user_sw_cbufs
) {
3168 u_upload_data(device
->constbuf_sw_uploader
,
3173 &(cb
.buffer_offset
),
3175 u_upload_unmap(device
->constbuf_sw_uploader
);
3176 cb
.user_buffer
= NULL
;
3179 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 0, &cb
);
3181 pipe_resource_reference(&cb
.buffer
, NULL
);
3183 cb
.user_buffer
= (char *)buf
+ 4096 * sizeof(float[4]);
3184 if (!device
->driver_caps
.user_sw_cbufs
) {
3185 u_upload_data(device
->constbuf_sw_uploader
,
3190 &(cb
.buffer_offset
),
3192 u_upload_unmap(device
->constbuf_sw_uploader
);
3193 cb
.user_buffer
= NULL
;
3196 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 1, &cb
);
3198 pipe_resource_reference(&cb
.buffer
, NULL
);
3202 struct pipe_constant_buffer cb
;
3205 cb
.buffer_offset
= 0;
3206 cb
.buffer_size
= 2048 * sizeof(float[4]);
3207 cb
.user_buffer
= state
->vs_const_i
;
3209 if (!device
->driver_caps
.user_sw_cbufs
) {
3210 u_upload_data(device
->constbuf_sw_uploader
,
3215 &(cb
.buffer_offset
),
3217 u_upload_unmap(device
->constbuf_sw_uploader
);
3218 cb
.user_buffer
= NULL
;
3221 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 2, &cb
);
3223 pipe_resource_reference(&cb
.buffer
, NULL
);
3227 struct pipe_constant_buffer cb
;
3230 cb
.buffer_offset
= 0;
3231 cb
.buffer_size
= 512 * sizeof(float[4]);
3232 cb
.user_buffer
= state
->vs_const_b
;
3234 if (!device
->driver_caps
.user_sw_cbufs
) {
3235 u_upload_data(device
->constbuf_sw_uploader
,
3240 &(cb
.buffer_offset
),
3242 u_upload_unmap(device
->constbuf_sw_uploader
);
3243 cb
.user_buffer
= NULL
;
3246 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 3, &cb
);
3248 pipe_resource_reference(&cb
.buffer
, NULL
);
3252 struct pipe_constant_buffer cb
;
3253 const D3DVIEWPORT9
*vport
= &device
->state
.viewport
;
3254 float viewport_data
[8] = {(float)vport
->Width
* 0.5f
,
3255 (float)vport
->Height
* -0.5f
, vport
->MaxZ
- vport
->MinZ
, 0.f
,
3256 (float)vport
->Width
* 0.5f
+ (float)vport
->X
,
3257 (float)vport
->Height
* 0.5f
+ (float)vport
->Y
,
3261 cb
.buffer_offset
= 0;
3262 cb
.buffer_size
= 2 * sizeof(float[4]);
3263 cb
.user_buffer
= viewport_data
;
3266 u_upload_data(device
->constbuf_sw_uploader
,
3271 &(cb
.buffer_offset
),
3273 u_upload_unmap(device
->constbuf_sw_uploader
);
3274 cb
.user_buffer
= NULL
;
3277 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 4, &cb
);
3279 pipe_resource_reference(&cb
.buffer
, NULL
);
3285 nine_state_prepare_draw_sw(struct NineDevice9
*device
, struct NineVertexDeclaration9
*vdecl_out
,
3286 int start_vertice
, int num_vertices
, struct pipe_stream_output_info
*so
)
3288 struct nine_state
*state
= &device
->state
;
3289 bool programmable_vs
= state
->vs
&& !(state
->vdecl
&& state
->vdecl
->position_t
);
3290 struct NineVertexShader9
*vs
= programmable_vs
? device
->state
.vs
: device
->ff
.vs
;
3292 assert(programmable_vs
);
3294 DBG("Preparing draw\n");
3295 cso_set_vertex_shader_handle(device
->cso_sw
,
3296 NineVertexShader9_GetVariantProcessVertices(vs
, vdecl_out
, so
));
3297 update_vertex_elements_sw(device
);
3298 update_vertex_buffers_sw(device
, start_vertice
, num_vertices
);
3299 update_vs_constants_sw(device
);
3300 DBG("Preparation succeeded\n");
3304 nine_state_after_draw_sw(struct NineDevice9
*device
)
3306 struct nine_state_sw_internal
*sw_internal
= &device
->state_sw_internal
;
3307 struct pipe_context
*pipe
= NineDevice9_GetPipe(device
);
3308 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
3311 for (i
= 0; i
< 4; i
++) {
3312 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, NULL
);
3313 if (sw_internal
->transfers_so
[i
])
3314 pipe
->transfer_unmap(pipe
, sw_internal
->transfers_so
[i
]);
3315 sw_internal
->transfers_so
[i
] = NULL
;
3320 nine_state_destroy_sw(struct NineDevice9
*device
)
3323 /* Everything destroyed with cso */
3327 static const DWORD nine_render_states_pixel[] =
3329 D3DRS_ALPHABLENDENABLE,
3332 D3DRS_ALPHATESTENABLE,
3333 D3DRS_ANTIALIASEDLINEENABLE,
3337 D3DRS_CCW_STENCILFAIL,
3338 D3DRS_CCW_STENCILPASS,
3339 D3DRS_CCW_STENCILZFAIL,
3340 D3DRS_COLORWRITEENABLE,
3341 D3DRS_COLORWRITEENABLE1,
3342 D3DRS_COLORWRITEENABLE2,
3343 D3DRS_COLORWRITEENABLE3,
3346 D3DRS_DESTBLENDALPHA,
3353 D3DRS_SCISSORTESTENABLE,
3354 D3DRS_SEPARATEALPHABLENDENABLE,
3356 D3DRS_SLOPESCALEDEPTHBIAS,
3358 D3DRS_SRCBLENDALPHA,
3359 D3DRS_SRGBWRITEENABLE,
3360 D3DRS_STENCILENABLE,
3366 D3DRS_STENCILWRITEMASK,
3368 D3DRS_TEXTUREFACTOR,
3369 D3DRS_TWOSIDEDSTENCILMODE,
3391 const uint32_t nine_render_states_pixel
[(NINED3DRS_LAST
+ 31) / 32] =
3393 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000,
3394 0x000000ff, 0xde01c900, 0x0003ffcf
3398 static const DWORD nine_render_states_vertex[] =
3400 D3DRS_ADAPTIVETESS_W,
3401 D3DRS_ADAPTIVETESS_X,
3402 D3DRS_ADAPTIVETESS_Y,
3403 D3DRS_ADAPTIVETESS_Z,
3405 D3DRS_AMBIENTMATERIALSOURCE,
3407 D3DRS_CLIPPLANEENABLE,
3410 D3DRS_DIFFUSEMATERIALSOURCE,
3411 D3DRS_EMISSIVEMATERIALSOURCE,
3412 D3DRS_ENABLEADAPTIVETESSELLATION,
3419 D3DRS_FOGVERTEXMODE,
3420 D3DRS_INDEXEDVERTEXBLENDENABLE,
3423 D3DRS_MAXTESSELLATIONLEVEL,
3424 D3DRS_MINTESSELLATIONLEVEL,
3425 D3DRS_MULTISAMPLEANTIALIAS,
3426 D3DRS_MULTISAMPLEMASK,
3428 D3DRS_NORMALIZENORMALS,
3429 D3DRS_PATCHEDGESTYLE,
3433 D3DRS_POINTSCALEENABLE,
3435 D3DRS_POINTSIZE_MAX,
3436 D3DRS_POINTSIZE_MIN,
3437 D3DRS_POINTSPRITEENABLE,
3438 D3DRS_POSITIONDEGREE,
3439 D3DRS_RANGEFOGENABLE,
3441 D3DRS_SPECULARENABLE,
3442 D3DRS_SPECULARMATERIALSOURCE,
3447 const uint32_t nine_render_states_vertex
[(NINED3DRS_LAST
+ 31) / 32] =
3449 0x30400200, 0x0001007c, 0x00000000, 0x00000000,
3450 0xfd9efb00, 0x01fc34cf, 0x00000000
3453 /* TODO: put in the right values */
3454 const uint32_t nine_render_state_group
[NINED3DRS_LAST
+ 1] =
3456 [D3DRS_ZENABLE
] = NINE_STATE_DSA
| NINE_STATE_MULTISAMPLE
,
3457 [D3DRS_FILLMODE
] = NINE_STATE_RASTERIZER
,
3458 [D3DRS_SHADEMODE
] = NINE_STATE_RASTERIZER
,
3459 [D3DRS_ZWRITEENABLE
] = NINE_STATE_DSA
,
3460 [D3DRS_ALPHATESTENABLE
] = NINE_STATE_DSA
,
3461 [D3DRS_LASTPIXEL
] = NINE_STATE_RASTERIZER
,
3462 [D3DRS_SRCBLEND
] = NINE_STATE_BLEND
,
3463 [D3DRS_DESTBLEND
] = NINE_STATE_BLEND
,
3464 [D3DRS_CULLMODE
] = NINE_STATE_RASTERIZER
,
3465 [D3DRS_ZFUNC
] = NINE_STATE_DSA
,
3466 [D3DRS_ALPHAREF
] = NINE_STATE_DSA
,
3467 [D3DRS_ALPHAFUNC
] = NINE_STATE_DSA
,
3468 [D3DRS_DITHERENABLE
] = NINE_STATE_BLEND
,
3469 [D3DRS_ALPHABLENDENABLE
] = NINE_STATE_BLEND
,
3470 [D3DRS_FOGENABLE
] = NINE_STATE_FF_OTHER
| NINE_STATE_FOG_SHADER
| NINE_STATE_PS_CONST
,
3471 [D3DRS_SPECULARENABLE
] = NINE_STATE_FF_LIGHTING
,
3472 [D3DRS_FOGCOLOR
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
3473 [D3DRS_FOGTABLEMODE
] = NINE_STATE_FF_OTHER
| NINE_STATE_FOG_SHADER
| NINE_STATE_PS_CONST
,
3474 [D3DRS_FOGSTART
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
3475 [D3DRS_FOGEND
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
3476 [D3DRS_FOGDENSITY
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
3477 [D3DRS_RANGEFOGENABLE
] = NINE_STATE_FF_OTHER
,
3478 [D3DRS_STENCILENABLE
] = NINE_STATE_DSA
| NINE_STATE_MULTISAMPLE
,
3479 [D3DRS_STENCILFAIL
] = NINE_STATE_DSA
,
3480 [D3DRS_STENCILZFAIL
] = NINE_STATE_DSA
,
3481 [D3DRS_STENCILPASS
] = NINE_STATE_DSA
,
3482 [D3DRS_STENCILFUNC
] = NINE_STATE_DSA
,
3483 [D3DRS_STENCILREF
] = NINE_STATE_STENCIL_REF
,
3484 [D3DRS_STENCILMASK
] = NINE_STATE_DSA
,
3485 [D3DRS_STENCILWRITEMASK
] = NINE_STATE_DSA
,
3486 [D3DRS_TEXTUREFACTOR
] = NINE_STATE_FF_PSSTAGES
,
3487 [D3DRS_WRAP0
] = NINE_STATE_UNHANDLED
, /* cylindrical wrap is crazy */
3488 [D3DRS_WRAP1
] = NINE_STATE_UNHANDLED
,
3489 [D3DRS_WRAP2
] = NINE_STATE_UNHANDLED
,
3490 [D3DRS_WRAP3
] = NINE_STATE_UNHANDLED
,
3491 [D3DRS_WRAP4
] = NINE_STATE_UNHANDLED
,
3492 [D3DRS_WRAP5
] = NINE_STATE_UNHANDLED
,
3493 [D3DRS_WRAP6
] = NINE_STATE_UNHANDLED
,
3494 [D3DRS_WRAP7
] = NINE_STATE_UNHANDLED
,
3495 [D3DRS_CLIPPING
] = 0, /* software vertex processing only */
3496 [D3DRS_LIGHTING
] = NINE_STATE_FF_LIGHTING
,
3497 [D3DRS_AMBIENT
] = NINE_STATE_FF_LIGHTING
| NINE_STATE_FF_MATERIAL
,
3498 [D3DRS_FOGVERTEXMODE
] = NINE_STATE_FF_OTHER
,
3499 [D3DRS_COLORVERTEX
] = NINE_STATE_FF_LIGHTING
,
3500 [D3DRS_LOCALVIEWER
] = NINE_STATE_FF_LIGHTING
,
3501 [D3DRS_NORMALIZENORMALS
] = NINE_STATE_FF_OTHER
,
3502 [D3DRS_DIFFUSEMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3503 [D3DRS_SPECULARMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3504 [D3DRS_AMBIENTMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3505 [D3DRS_EMISSIVEMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
3506 [D3DRS_VERTEXBLEND
] = NINE_STATE_FF_OTHER
,
3507 [D3DRS_CLIPPLANEENABLE
] = NINE_STATE_RASTERIZER
,
3508 [D3DRS_POINTSIZE
] = NINE_STATE_RASTERIZER
,
3509 [D3DRS_POINTSIZE_MIN
] = NINE_STATE_RASTERIZER
| NINE_STATE_POINTSIZE_SHADER
,
3510 [D3DRS_POINTSPRITEENABLE
] = NINE_STATE_RASTERIZER
,
3511 [D3DRS_POINTSCALEENABLE
] = NINE_STATE_FF_OTHER
,
3512 [D3DRS_POINTSCALE_A
] = NINE_STATE_FF_OTHER
,
3513 [D3DRS_POINTSCALE_B
] = NINE_STATE_FF_OTHER
,
3514 [D3DRS_POINTSCALE_C
] = NINE_STATE_FF_OTHER
,
3515 [D3DRS_MULTISAMPLEANTIALIAS
] = NINE_STATE_MULTISAMPLE
,
3516 [D3DRS_MULTISAMPLEMASK
] = NINE_STATE_SAMPLE_MASK
,
3517 [D3DRS_PATCHEDGESTYLE
] = NINE_STATE_UNHANDLED
,
3518 [D3DRS_DEBUGMONITORTOKEN
] = NINE_STATE_UNHANDLED
,
3519 [D3DRS_POINTSIZE_MAX
] = NINE_STATE_RASTERIZER
| NINE_STATE_POINTSIZE_SHADER
,
3520 [D3DRS_INDEXEDVERTEXBLENDENABLE
] = NINE_STATE_FF_OTHER
,
3521 [D3DRS_COLORWRITEENABLE
] = NINE_STATE_BLEND
,
3522 [D3DRS_TWEENFACTOR
] = NINE_STATE_FF_OTHER
,
3523 [D3DRS_BLENDOP
] = NINE_STATE_BLEND
,
3524 [D3DRS_POSITIONDEGREE
] = NINE_STATE_UNHANDLED
,
3525 [D3DRS_NORMALDEGREE
] = NINE_STATE_UNHANDLED
,
3526 [D3DRS_SCISSORTESTENABLE
] = NINE_STATE_RASTERIZER
,
3527 [D3DRS_SLOPESCALEDEPTHBIAS
] = NINE_STATE_RASTERIZER
,
3528 [D3DRS_ANTIALIASEDLINEENABLE
] = NINE_STATE_RASTERIZER
,
3529 [D3DRS_MINTESSELLATIONLEVEL
] = NINE_STATE_UNHANDLED
,
3530 [D3DRS_MAXTESSELLATIONLEVEL
] = NINE_STATE_UNHANDLED
,
3531 [D3DRS_ADAPTIVETESS_X
] = NINE_STATE_UNHANDLED
,
3532 [D3DRS_ADAPTIVETESS_Y
] = NINE_STATE_UNHANDLED
,
3533 [D3DRS_ADAPTIVETESS_Z
] = NINE_STATE_UNHANDLED
,
3534 [D3DRS_ADAPTIVETESS_W
] = NINE_STATE_UNHANDLED
,
3535 [D3DRS_ENABLEADAPTIVETESSELLATION
] = NINE_STATE_UNHANDLED
,
3536 [D3DRS_TWOSIDEDSTENCILMODE
] = NINE_STATE_DSA
,
3537 [D3DRS_CCW_STENCILFAIL
] = NINE_STATE_DSA
,
3538 [D3DRS_CCW_STENCILZFAIL
] = NINE_STATE_DSA
,
3539 [D3DRS_CCW_STENCILPASS
] = NINE_STATE_DSA
,
3540 [D3DRS_CCW_STENCILFUNC
] = NINE_STATE_DSA
,
3541 [D3DRS_COLORWRITEENABLE1
] = NINE_STATE_BLEND
,
3542 [D3DRS_COLORWRITEENABLE2
] = NINE_STATE_BLEND
,
3543 [D3DRS_COLORWRITEENABLE3
] = NINE_STATE_BLEND
,
3544 [D3DRS_BLENDFACTOR
] = NINE_STATE_BLEND_COLOR
,
3545 [D3DRS_SRGBWRITEENABLE
] = NINE_STATE_FB
,
3546 [D3DRS_DEPTHBIAS
] = NINE_STATE_RASTERIZER
,
3547 [D3DRS_WRAP8
] = NINE_STATE_UNHANDLED
, /* cylwrap has to be done via GP */
3548 [D3DRS_WRAP9
] = NINE_STATE_UNHANDLED
,
3549 [D3DRS_WRAP10
] = NINE_STATE_UNHANDLED
,
3550 [D3DRS_WRAP11
] = NINE_STATE_UNHANDLED
,
3551 [D3DRS_WRAP12
] = NINE_STATE_UNHANDLED
,
3552 [D3DRS_WRAP13
] = NINE_STATE_UNHANDLED
,
3553 [D3DRS_WRAP14
] = NINE_STATE_UNHANDLED
,
3554 [D3DRS_WRAP15
] = NINE_STATE_UNHANDLED
,
3555 [D3DRS_SEPARATEALPHABLENDENABLE
] = NINE_STATE_BLEND
,
3556 [D3DRS_SRCBLENDALPHA
] = NINE_STATE_BLEND
,
3557 [D3DRS_DESTBLENDALPHA
] = NINE_STATE_BLEND
,
3558 [D3DRS_BLENDOPALPHA
] = NINE_STATE_BLEND
3564 nine_state_access_transform(struct nine_ff_state
*ff_state
, D3DTRANSFORMSTATETYPE t
,
3567 static D3DMATRIX Identity
= { .m
[0] = { 1, 0, 0, 0 },
3568 .m
[1] = { 0, 1, 0, 0 },
3569 .m
[2] = { 0, 0, 1, 0 },
3570 .m
[3] = { 0, 0, 0, 1 } };
3574 case D3DTS_VIEW
: index
= 0; break;
3575 case D3DTS_PROJECTION
: index
= 1; break;
3576 case D3DTS_TEXTURE0
: index
= 2; break;
3577 case D3DTS_TEXTURE1
: index
= 3; break;
3578 case D3DTS_TEXTURE2
: index
= 4; break;
3579 case D3DTS_TEXTURE3
: index
= 5; break;
3580 case D3DTS_TEXTURE4
: index
= 6; break;
3581 case D3DTS_TEXTURE5
: index
= 7; break;
3582 case D3DTS_TEXTURE6
: index
= 8; break;
3583 case D3DTS_TEXTURE7
: index
= 9; break;
3585 if (!(t
>= D3DTS_WORLDMATRIX(0) && t
<= D3DTS_WORLDMATRIX(255)))
3587 index
= 10 + (t
- D3DTS_WORLDMATRIX(0));
3591 if (index
>= ff_state
->num_transforms
) {
3592 unsigned N
= index
+ 1;
3593 unsigned n
= ff_state
->num_transforms
;
3597 ff_state
->transform
= REALLOC(ff_state
->transform
,
3598 n
* sizeof(D3DMATRIX
),
3599 N
* sizeof(D3DMATRIX
));
3601 ff_state
->transform
[n
] = Identity
;
3602 ff_state
->num_transforms
= N
;
3604 return &ff_state
->transform
[index
];
3608 nine_state_set_light(struct nine_ff_state
*ff_state
, DWORD Index
,
3609 const D3DLIGHT9
*pLight
)
3611 if (Index
>= ff_state
->num_lights
) {
3612 unsigned n
= ff_state
->num_lights
;
3613 unsigned N
= Index
+ 1;
3615 ff_state
->light
= REALLOC(ff_state
->light
, n
* sizeof(D3DLIGHT9
),
3616 N
* sizeof(D3DLIGHT9
));
3617 if (!ff_state
->light
)
3618 return E_OUTOFMEMORY
;
3619 ff_state
->num_lights
= N
;
3621 for (; n
< Index
; ++n
) {
3622 memset(&ff_state
->light
[n
], 0, sizeof(D3DLIGHT9
));
3623 ff_state
->light
[n
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
3626 ff_state
->light
[Index
] = *pLight
;
3628 if (pLight
->Type
== D3DLIGHT_SPOT
&& pLight
->Theta
>= pLight
->Phi
) {
3629 DBG("Warning: clamping D3DLIGHT9.Theta\n");
3630 ff_state
->light
[Index
].Theta
= ff_state
->light
[Index
].Phi
;
3636 nine_state_light_enable(struct nine_ff_state
*ff_state
, uint32_t *change_group
,
3637 DWORD Index
, BOOL Enable
)
3641 user_assert(Index
< ff_state
->num_lights
, D3DERR_INVALIDCALL
);
3643 for (i
= 0; i
< ff_state
->num_lights_active
; ++i
) {
3644 if (ff_state
->active_light
[i
] == Index
)
3649 if (i
< ff_state
->num_lights_active
)
3651 /* XXX wine thinks this should still succeed:
3653 user_assert(i
< NINE_MAX_LIGHTS_ACTIVE
, D3DERR_INVALIDCALL
);
3655 ff_state
->active_light
[i
] = Index
;
3656 ff_state
->num_lights_active
++;
3658 if (i
== ff_state
->num_lights_active
)
3660 --ff_state
->num_lights_active
;
3661 for (; i
< ff_state
->num_lights_active
; ++i
)
3662 ff_state
->active_light
[i
] = ff_state
->active_light
[i
+ 1];
3665 *change_group
|= NINE_STATE_FF_LIGHTING
;
3670 #define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n
3671 const char *nine_d3drs_to_string(DWORD State
)
3674 D3DRS_TO_STRING_CASE(ZENABLE
);
3675 D3DRS_TO_STRING_CASE(FILLMODE
);
3676 D3DRS_TO_STRING_CASE(SHADEMODE
);
3677 D3DRS_TO_STRING_CASE(ZWRITEENABLE
);
3678 D3DRS_TO_STRING_CASE(ALPHATESTENABLE
);
3679 D3DRS_TO_STRING_CASE(LASTPIXEL
);
3680 D3DRS_TO_STRING_CASE(SRCBLEND
);
3681 D3DRS_TO_STRING_CASE(DESTBLEND
);
3682 D3DRS_TO_STRING_CASE(CULLMODE
);
3683 D3DRS_TO_STRING_CASE(ZFUNC
);
3684 D3DRS_TO_STRING_CASE(ALPHAREF
);
3685 D3DRS_TO_STRING_CASE(ALPHAFUNC
);
3686 D3DRS_TO_STRING_CASE(DITHERENABLE
);
3687 D3DRS_TO_STRING_CASE(ALPHABLENDENABLE
);
3688 D3DRS_TO_STRING_CASE(FOGENABLE
);
3689 D3DRS_TO_STRING_CASE(SPECULARENABLE
);
3690 D3DRS_TO_STRING_CASE(FOGCOLOR
);
3691 D3DRS_TO_STRING_CASE(FOGTABLEMODE
);
3692 D3DRS_TO_STRING_CASE(FOGSTART
);
3693 D3DRS_TO_STRING_CASE(FOGEND
);
3694 D3DRS_TO_STRING_CASE(FOGDENSITY
);
3695 D3DRS_TO_STRING_CASE(RANGEFOGENABLE
);
3696 D3DRS_TO_STRING_CASE(STENCILENABLE
);
3697 D3DRS_TO_STRING_CASE(STENCILFAIL
);
3698 D3DRS_TO_STRING_CASE(STENCILZFAIL
);
3699 D3DRS_TO_STRING_CASE(STENCILPASS
);
3700 D3DRS_TO_STRING_CASE(STENCILFUNC
);
3701 D3DRS_TO_STRING_CASE(STENCILREF
);
3702 D3DRS_TO_STRING_CASE(STENCILMASK
);
3703 D3DRS_TO_STRING_CASE(STENCILWRITEMASK
);
3704 D3DRS_TO_STRING_CASE(TEXTUREFACTOR
);
3705 D3DRS_TO_STRING_CASE(WRAP0
);
3706 D3DRS_TO_STRING_CASE(WRAP1
);
3707 D3DRS_TO_STRING_CASE(WRAP2
);
3708 D3DRS_TO_STRING_CASE(WRAP3
);
3709 D3DRS_TO_STRING_CASE(WRAP4
);
3710 D3DRS_TO_STRING_CASE(WRAP5
);
3711 D3DRS_TO_STRING_CASE(WRAP6
);
3712 D3DRS_TO_STRING_CASE(WRAP7
);
3713 D3DRS_TO_STRING_CASE(CLIPPING
);
3714 D3DRS_TO_STRING_CASE(LIGHTING
);
3715 D3DRS_TO_STRING_CASE(AMBIENT
);
3716 D3DRS_TO_STRING_CASE(FOGVERTEXMODE
);
3717 D3DRS_TO_STRING_CASE(COLORVERTEX
);
3718 D3DRS_TO_STRING_CASE(LOCALVIEWER
);
3719 D3DRS_TO_STRING_CASE(NORMALIZENORMALS
);
3720 D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE
);
3721 D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE
);
3722 D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE
);
3723 D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE
);
3724 D3DRS_TO_STRING_CASE(VERTEXBLEND
);
3725 D3DRS_TO_STRING_CASE(CLIPPLANEENABLE
);
3726 D3DRS_TO_STRING_CASE(POINTSIZE
);
3727 D3DRS_TO_STRING_CASE(POINTSIZE_MIN
);
3728 D3DRS_TO_STRING_CASE(POINTSPRITEENABLE
);
3729 D3DRS_TO_STRING_CASE(POINTSCALEENABLE
);
3730 D3DRS_TO_STRING_CASE(POINTSCALE_A
);
3731 D3DRS_TO_STRING_CASE(POINTSCALE_B
);
3732 D3DRS_TO_STRING_CASE(POINTSCALE_C
);
3733 D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS
);
3734 D3DRS_TO_STRING_CASE(MULTISAMPLEMASK
);
3735 D3DRS_TO_STRING_CASE(PATCHEDGESTYLE
);
3736 D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN
);
3737 D3DRS_TO_STRING_CASE(POINTSIZE_MAX
);
3738 D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE
);
3739 D3DRS_TO_STRING_CASE(COLORWRITEENABLE
);
3740 D3DRS_TO_STRING_CASE(TWEENFACTOR
);
3741 D3DRS_TO_STRING_CASE(BLENDOP
);
3742 D3DRS_TO_STRING_CASE(POSITIONDEGREE
);
3743 D3DRS_TO_STRING_CASE(NORMALDEGREE
);
3744 D3DRS_TO_STRING_CASE(SCISSORTESTENABLE
);
3745 D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS
);
3746 D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE
);
3747 D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL
);
3748 D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL
);
3749 D3DRS_TO_STRING_CASE(ADAPTIVETESS_X
);
3750 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y
);
3751 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z
);
3752 D3DRS_TO_STRING_CASE(ADAPTIVETESS_W
);
3753 D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION
);
3754 D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE
);
3755 D3DRS_TO_STRING_CASE(CCW_STENCILFAIL
);
3756 D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL
);
3757 D3DRS_TO_STRING_CASE(CCW_STENCILPASS
);
3758 D3DRS_TO_STRING_CASE(CCW_STENCILFUNC
);
3759 D3DRS_TO_STRING_CASE(COLORWRITEENABLE1
);
3760 D3DRS_TO_STRING_CASE(COLORWRITEENABLE2
);
3761 D3DRS_TO_STRING_CASE(COLORWRITEENABLE3
);
3762 D3DRS_TO_STRING_CASE(BLENDFACTOR
);
3763 D3DRS_TO_STRING_CASE(SRGBWRITEENABLE
);
3764 D3DRS_TO_STRING_CASE(DEPTHBIAS
);
3765 D3DRS_TO_STRING_CASE(WRAP8
);
3766 D3DRS_TO_STRING_CASE(WRAP9
);
3767 D3DRS_TO_STRING_CASE(WRAP10
);
3768 D3DRS_TO_STRING_CASE(WRAP11
);
3769 D3DRS_TO_STRING_CASE(WRAP12
);
3770 D3DRS_TO_STRING_CASE(WRAP13
);
3771 D3DRS_TO_STRING_CASE(WRAP14
);
3772 D3DRS_TO_STRING_CASE(WRAP15
);
3773 D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE
);
3774 D3DRS_TO_STRING_CASE(SRCBLENDALPHA
);
3775 D3DRS_TO_STRING_CASE(DESTBLENDALPHA
);
3776 D3DRS_TO_STRING_CASE(BLENDOPALPHA
);