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. */
25 #include "basetexture9.h"
27 #include "indexbuffer9.h"
29 #include "vertexbuffer9.h"
30 #include "vertexdeclaration9.h"
31 #include "vertexshader9.h"
32 #include "pixelshader9.h"
33 #include "nine_pipe.h"
35 #include "nine_limits.h"
36 #include "pipe/p_context.h"
37 #include "pipe/p_state.h"
38 #include "cso_cache/cso_context.h"
39 #include "util/u_upload_mgr.h"
40 #include "util/u_math.h"
41 #include "util/u_box.h"
42 #include "util/u_simple_shaders.h"
44 #define DBG_CHANNEL DBG_DEVICE
46 /* Check if some states need to be set dirty */
49 check_multisample(struct NineDevice9
*device
)
51 DWORD
*rs
= device
->context
.rs
;
52 DWORD new_value
= (rs
[D3DRS_ZENABLE
] || rs
[D3DRS_STENCILENABLE
]) &&
53 device
->context
.rt
[0]->desc
.MultiSampleType
>= 1 &&
54 rs
[D3DRS_MULTISAMPLEANTIALIAS
];
55 if (rs
[NINED3DRS_MULTISAMPLE
] != new_value
) {
56 rs
[NINED3DRS_MULTISAMPLE
] = new_value
;
57 return NINE_STATE_RASTERIZER
;
62 /* State preparation only */
65 prepare_blend(struct NineDevice9
*device
)
67 nine_convert_blend_state(&device
->context
.pipe_data
.blend
, device
->context
.rs
);
68 device
->context
.commit
|= NINE_STATE_COMMIT_BLEND
;
72 prepare_dsa(struct NineDevice9
*device
)
74 nine_convert_dsa_state(&device
->context
.pipe_data
.dsa
, device
->context
.rs
);
75 device
->context
.commit
|= NINE_STATE_COMMIT_DSA
;
79 prepare_rasterizer(struct NineDevice9
*device
)
81 nine_convert_rasterizer_state(device
, &device
->context
.pipe_data
.rast
, device
->context
.rs
);
82 device
->context
.commit
|= NINE_STATE_COMMIT_RASTERIZER
;
86 prepare_vs_constants_userbuf_swvp(struct NineDevice9
*device
)
88 struct nine_context
*context
= &device
->context
;
90 if (context
->changed
.vs_const_f
|| context
->changed
.group
& NINE_STATE_SWVP
) {
91 struct pipe_constant_buffer cb
;
94 cb
.buffer_size
= 4096 * sizeof(float[4]);
95 cb
.user_buffer
= context
->vs_const_f_swvp
;
97 if (context
->vs
->lconstf
.ranges
) {
98 const struct nine_lconstf
*lconstf
= &(context
->vs
->lconstf
);
99 const struct nine_range
*r
= lconstf
->ranges
;
101 float *dst
= context
->vs_lconstf_temp
;
102 float *src
= (float *)cb
.user_buffer
;
103 memcpy(dst
, src
, cb
.buffer_size
);
106 unsigned c
= r
->end
- r
->bgn
;
107 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
111 cb
.user_buffer
= dst
;
114 /* Do not erase the buffer field.
115 * It is either NULL (user_cbufs), or a resource.
116 * u_upload_data will do the proper refcount */
117 context
->pipe_data
.cb0_swvp
.buffer_offset
= cb
.buffer_offset
;
118 context
->pipe_data
.cb0_swvp
.buffer_size
= cb
.buffer_size
;
119 context
->pipe_data
.cb0_swvp
.user_buffer
= cb
.user_buffer
;
121 cb
.user_buffer
= (char *)cb
.user_buffer
+ 4096 * sizeof(float[4]);
122 context
->pipe_data
.cb1_swvp
.buffer_offset
= cb
.buffer_offset
;
123 context
->pipe_data
.cb1_swvp
.buffer_size
= cb
.buffer_size
;
124 context
->pipe_data
.cb1_swvp
.user_buffer
= cb
.user_buffer
;
126 context
->changed
.vs_const_f
= 0;
129 if (context
->changed
.vs_const_i
|| context
->changed
.group
& NINE_STATE_SWVP
) {
130 struct pipe_constant_buffer cb
;
132 cb
.buffer_offset
= 0;
133 cb
.buffer_size
= 2048 * sizeof(float[4]);
134 cb
.user_buffer
= context
->vs_const_i
;
136 context
->pipe_data
.cb2_swvp
.buffer_offset
= cb
.buffer_offset
;
137 context
->pipe_data
.cb2_swvp
.buffer_size
= cb
.buffer_size
;
138 context
->pipe_data
.cb2_swvp
.user_buffer
= cb
.user_buffer
;
139 context
->changed
.vs_const_i
= 0;
142 if (context
->changed
.vs_const_b
|| context
->changed
.group
& NINE_STATE_SWVP
) {
143 struct pipe_constant_buffer cb
;
145 cb
.buffer_offset
= 0;
146 cb
.buffer_size
= 512 * sizeof(float[4]);
147 cb
.user_buffer
= context
->vs_const_b
;
149 context
->pipe_data
.cb3_swvp
.buffer_offset
= cb
.buffer_offset
;
150 context
->pipe_data
.cb3_swvp
.buffer_size
= cb
.buffer_size
;
151 context
->pipe_data
.cb3_swvp
.user_buffer
= cb
.user_buffer
;
152 context
->changed
.vs_const_b
= 0;
155 if (!device
->driver_caps
.user_cbufs
) {
156 struct pipe_constant_buffer
*cb
= &(context
->pipe_data
.cb0_swvp
);
157 u_upload_data(device
->constbuf_uploader
,
160 device
->constbuf_alignment
,
162 &(cb
->buffer_offset
),
164 u_upload_unmap(device
->constbuf_uploader
);
165 cb
->user_buffer
= NULL
;
167 cb
= &(context
->pipe_data
.cb1_swvp
);
168 u_upload_data(device
->constbuf_uploader
,
171 device
->constbuf_alignment
,
173 &(cb
->buffer_offset
),
175 u_upload_unmap(device
->constbuf_uploader
);
176 cb
->user_buffer
= NULL
;
178 cb
= &(context
->pipe_data
.cb2_swvp
);
179 u_upload_data(device
->constbuf_uploader
,
182 device
->constbuf_alignment
,
184 &(cb
->buffer_offset
),
186 u_upload_unmap(device
->constbuf_uploader
);
187 cb
->user_buffer
= NULL
;
189 cb
= &(context
->pipe_data
.cb3_swvp
);
190 u_upload_data(device
->constbuf_uploader
,
193 device
->constbuf_alignment
,
195 &(cb
->buffer_offset
),
197 u_upload_unmap(device
->constbuf_uploader
);
198 cb
->user_buffer
= NULL
;
201 context
->changed
.group
&= ~NINE_STATE_VS_CONST
;
202 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
206 prepare_vs_constants_userbuf(struct NineDevice9
*device
)
208 struct nine_context
*context
= &device
->context
;
209 struct pipe_constant_buffer cb
;
211 cb
.buffer_offset
= 0;
212 cb
.buffer_size
= context
->vs
->const_used_size
;
213 cb
.user_buffer
= context
->vs_const_f
;
216 prepare_vs_constants_userbuf_swvp(device
);
220 if (context
->changed
.vs_const_i
|| context
->changed
.group
& NINE_STATE_SWVP
) {
221 int *idst
= (int *)&context
->vs_const_f
[4 * device
->max_vs_const_f
];
222 memcpy(idst
, context
->vs_const_i
, NINE_MAX_CONST_I
* sizeof(int[4]));
223 context
->changed
.vs_const_i
= 0;
226 if (context
->changed
.vs_const_b
|| context
->changed
.group
& NINE_STATE_SWVP
) {
227 int *idst
= (int *)&context
->vs_const_f
[4 * device
->max_vs_const_f
];
228 uint32_t *bdst
= (uint32_t *)&idst
[4 * NINE_MAX_CONST_I
];
229 memcpy(bdst
, context
->vs_const_b
, NINE_MAX_CONST_B
* sizeof(BOOL
));
230 context
->changed
.vs_const_b
= 0;
236 if (context
->vs
->lconstf
.ranges
) {
237 /* TODO: Can we make it so that we don't have to copy everything ? */
238 const struct nine_lconstf
*lconstf
= &(context
->vs
->lconstf
);
239 const struct nine_range
*r
= lconstf
->ranges
;
241 float *dst
= context
->vs_lconstf_temp
;
242 float *src
= (float *)cb
.user_buffer
;
243 memcpy(dst
, src
, cb
.buffer_size
);
246 unsigned c
= r
->end
- r
->bgn
;
247 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
251 cb
.user_buffer
= dst
;
254 if (!device
->driver_caps
.user_cbufs
) {
255 context
->pipe_data
.cb_vs
.buffer_size
= cb
.buffer_size
;
256 u_upload_data(device
->constbuf_uploader
,
259 device
->constbuf_alignment
,
261 &context
->pipe_data
.cb_vs
.buffer_offset
,
262 &context
->pipe_data
.cb_vs
.buffer
);
263 u_upload_unmap(device
->constbuf_uploader
);
264 context
->pipe_data
.cb_vs
.user_buffer
= NULL
;
266 context
->pipe_data
.cb_vs
= cb
;
268 context
->changed
.vs_const_f
= 0;
270 context
->changed
.group
&= ~NINE_STATE_VS_CONST
;
271 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
275 prepare_ps_constants_userbuf(struct NineDevice9
*device
)
277 struct nine_context
*context
= &device
->context
;
278 struct pipe_constant_buffer cb
;
280 cb
.buffer_offset
= 0;
281 cb
.buffer_size
= context
->ps
->const_used_size
;
282 cb
.user_buffer
= context
->ps_const_f
;
284 if (context
->changed
.ps_const_i
) {
285 int *idst
= (int *)&context
->ps_const_f
[4 * device
->max_ps_const_f
];
286 memcpy(idst
, context
->ps_const_i
, sizeof(context
->ps_const_i
));
287 context
->changed
.ps_const_i
= 0;
289 if (context
->changed
.ps_const_b
) {
290 int *idst
= (int *)&context
->ps_const_f
[4 * device
->max_ps_const_f
];
291 uint32_t *bdst
= (uint32_t *)&idst
[4 * NINE_MAX_CONST_I
];
292 memcpy(bdst
, context
->ps_const_b
, sizeof(context
->ps_const_b
));
293 context
->changed
.ps_const_b
= 0;
296 /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */
297 if (context
->ps
->bumpenvmat_needed
) {
298 memcpy(context
->ps_lconstf_temp
, cb
.user_buffer
, cb
.buffer_size
);
299 memcpy(&context
->ps_lconstf_temp
[4 * 8], &device
->context
.bumpmap_vars
, sizeof(device
->context
.bumpmap_vars
));
301 cb
.user_buffer
= context
->ps_lconstf_temp
;
304 if (context
->ps
->byte_code
.version
< 0x30 &&
305 context
->rs
[D3DRS_FOGENABLE
]) {
306 float *dst
= &context
->ps_lconstf_temp
[4 * 32];
307 if (cb
.user_buffer
!= context
->ps_lconstf_temp
) {
308 memcpy(context
->ps_lconstf_temp
, cb
.user_buffer
, cb
.buffer_size
);
309 cb
.user_buffer
= context
->ps_lconstf_temp
;
312 d3dcolor_to_rgba(dst
, context
->rs
[D3DRS_FOGCOLOR
]);
313 if (context
->rs
[D3DRS_FOGTABLEMODE
] == D3DFOG_LINEAR
) {
314 dst
[4] = asfloat(context
->rs
[D3DRS_FOGEND
]);
315 dst
[5] = 1.0f
/ (asfloat(context
->rs
[D3DRS_FOGEND
]) - asfloat(context
->rs
[D3DRS_FOGSTART
]));
316 } else if (context
->rs
[D3DRS_FOGTABLEMODE
] != D3DFOG_NONE
) {
317 dst
[4] = asfloat(context
->rs
[D3DRS_FOGDENSITY
]);
319 cb
.buffer_size
= 4 * 4 * 34;
325 if (!device
->driver_caps
.user_cbufs
) {
326 context
->pipe_data
.cb_ps
.buffer_size
= cb
.buffer_size
;
327 u_upload_data(device
->constbuf_uploader
,
330 device
->constbuf_alignment
,
332 &context
->pipe_data
.cb_ps
.buffer_offset
,
333 &context
->pipe_data
.cb_ps
.buffer
);
334 u_upload_unmap(device
->constbuf_uploader
);
335 context
->pipe_data
.cb_ps
.user_buffer
= NULL
;
337 context
->pipe_data
.cb_ps
= cb
;
339 context
->changed
.ps_const_f
= 0;
341 context
->changed
.group
&= ~NINE_STATE_PS_CONST
;
342 context
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
345 static inline uint32_t
346 prepare_vs(struct NineDevice9
*device
, uint8_t shader_changed
)
348 struct nine_context
*context
= &device
->context
;
349 struct NineVertexShader9
*vs
= context
->vs
;
350 uint32_t changed_group
= 0;
351 int has_key_changed
= 0;
353 if (likely(context
->programmable_vs
))
354 has_key_changed
= NineVertexShader9_UpdateKey(vs
, device
);
356 if (!shader_changed
&& !has_key_changed
)
359 /* likely because we dislike FF */
360 if (likely(context
->programmable_vs
)) {
361 context
->cso_shader
.vs
= NineVertexShader9_GetVariant(vs
);
364 context
->cso_shader
.vs
= vs
->ff_cso
;
367 if (context
->rs
[NINED3DRS_VSPOINTSIZE
] != vs
->point_size
) {
368 context
->rs
[NINED3DRS_VSPOINTSIZE
] = vs
->point_size
;
369 changed_group
|= NINE_STATE_RASTERIZER
;
372 if ((context
->bound_samplers_mask_vs
& vs
->sampler_mask
) != vs
->sampler_mask
)
373 /* Bound dummy sampler. */
374 changed_group
|= NINE_STATE_SAMPLER
;
376 context
->commit
|= NINE_STATE_COMMIT_VS
;
377 return changed_group
;
380 static inline uint32_t
381 prepare_ps(struct NineDevice9
*device
, uint8_t shader_changed
)
383 struct nine_context
*context
= &device
->context
;
384 struct NinePixelShader9
*ps
= context
->ps
;
385 uint32_t changed_group
= 0;
386 int has_key_changed
= 0;
389 has_key_changed
= NinePixelShader9_UpdateKey(ps
, context
);
391 if (!shader_changed
&& !has_key_changed
)
395 context
->cso_shader
.ps
= NinePixelShader9_GetVariant(ps
);
398 context
->cso_shader
.ps
= ps
->ff_cso
;
401 if ((context
->bound_samplers_mask_ps
& ps
->sampler_mask
) != ps
->sampler_mask
)
402 /* Bound dummy sampler. */
403 changed_group
|= NINE_STATE_SAMPLER
;
405 context
->commit
|= NINE_STATE_COMMIT_PS
;
406 return changed_group
;
409 /* State preparation incremental */
411 /* State preparation + State commit */
414 update_framebuffer(struct NineDevice9
*device
, bool is_clear
)
416 struct pipe_context
*pipe
= device
->pipe
;
417 struct nine_context
*context
= &device
->context
;
418 struct pipe_framebuffer_state
*fb
= &context
->pipe_data
.fb
;
420 struct NineSurface9
*rt0
= context
->rt
[0];
421 unsigned w
= rt0
->desc
.Width
;
422 unsigned h
= rt0
->desc
.Height
;
423 unsigned nr_samples
= rt0
->base
.info
.nr_samples
;
424 unsigned ps_mask
= context
->ps
? context
->ps
->rt_mask
: 1;
425 unsigned mask
= is_clear
? 0xf : ps_mask
;
426 const int sRGB
= context
->rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
430 context
->rt_mask
= 0x0;
433 /* all render targets must have the same size and the depth buffer must be
434 * bigger. Multisample has to match, according to spec. But some apps do
435 * things wrong there, and no error is returned. The behaviour they get
436 * apparently is that depth buffer is disabled if it doesn't match.
437 * Surely the same for render targets. */
439 /* Special case: D3DFMT_NULL is used to bound no real render target,
440 * but render to depth buffer. We have to not take into account the render
441 * target info. TODO: know what should happen when there are several render targers
442 * and the first one is D3DFMT_NULL */
443 if (rt0
->desc
.Format
== D3DFMT_NULL
&& context
->ds
) {
444 w
= context
->ds
->desc
.Width
;
445 h
= context
->ds
->desc
.Height
;
446 nr_samples
= context
->ds
->base
.info
.nr_samples
;
449 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
450 struct NineSurface9
*rt
= context
->rt
[i
];
452 if (rt
&& rt
->desc
.Format
!= D3DFMT_NULL
&& (mask
& (1 << i
)) &&
453 rt
->desc
.Width
== w
&& rt
->desc
.Height
== h
&&
454 rt
->base
.info
.nr_samples
== nr_samples
) {
455 fb
->cbufs
[i
] = NineSurface9_GetSurface(rt
, sRGB
);
456 context
->rt_mask
|= 1 << i
;
457 fb
->nr_cbufs
= i
+ 1;
459 if (unlikely(rt
->desc
.Usage
& D3DUSAGE_AUTOGENMIPMAP
)) {
460 assert(rt
->texture
== D3DRTYPE_TEXTURE
||
461 rt
->texture
== D3DRTYPE_CUBETEXTURE
);
462 NineBaseTexture9(rt
->base
.base
.container
)->dirty_mip
= TRUE
;
465 /* Color outputs must match RT slot,
466 * drivers will have to handle NULL entries for GL, too.
472 if (context
->ds
&& context
->ds
->desc
.Width
>= w
&&
473 context
->ds
->desc
.Height
>= h
&&
474 context
->ds
->base
.info
.nr_samples
== nr_samples
) {
475 fb
->zsbuf
= NineSurface9_GetSurface(context
->ds
, 0);
483 pipe
->set_framebuffer_state(pipe
, fb
); /* XXX: cso ? */
485 if (is_clear
&& context
->rt_mask
== ps_mask
)
486 context
->changed
.group
&= ~NINE_STATE_FB
;
490 update_viewport(struct NineDevice9
*device
)
492 const D3DVIEWPORT9
*vport
= &device
->context
.viewport
;
493 struct pipe_viewport_state pvport
;
495 /* D3D coordinates are:
496 * -1 .. +1 for X,Y and
497 * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz)
499 pvport
.scale
[0] = (float)vport
->Width
* 0.5f
;
500 pvport
.scale
[1] = (float)vport
->Height
* -0.5f
;
501 pvport
.scale
[2] = vport
->MaxZ
- vport
->MinZ
;
502 pvport
.translate
[0] = (float)vport
->Width
* 0.5f
+ (float)vport
->X
;
503 pvport
.translate
[1] = (float)vport
->Height
* 0.5f
+ (float)vport
->Y
;
504 pvport
.translate
[2] = vport
->MinZ
;
506 /* We found R600 and SI cards have some imprecision
507 * on the barycentric coordinates used for interpolation.
508 * Some shaders rely on having something precise.
509 * We found that the proprietary driver has the imprecision issue,
510 * except when the render target width and height are powers of two.
511 * It is using some sort of workaround for these cases
512 * which covers likely all the cases the applications rely
513 * on something precise.
514 * We haven't found the workaround, but it seems like it's better
515 * for applications if the imprecision is biased towards infinity
516 * instead of -infinity (which is what measured). So shift slightly
517 * the viewport: not enough to change rasterization result (in particular
518 * for multisampling), but enough to make the imprecision biased
519 * towards infinity. We do this shift only if render target width and
520 * height are powers of two.
521 * Solves 'red shadows' bug on UE3 games.
523 if (device
->driver_bugs
.buggy_barycentrics
&&
524 ((vport
->Width
& (vport
->Width
-1)) == 0) &&
525 ((vport
->Height
& (vport
->Height
-1)) == 0)) {
526 pvport
.translate
[0] -= 1.0f
/ 128.0f
;
527 pvport
.translate
[1] -= 1.0f
/ 128.0f
;
530 cso_set_viewport(device
->cso
, &pvport
);
533 /* Loop through VS inputs and pick the vertex elements with the declared
534 * usage from the vertex declaration, then insert the instance divisor from
535 * the stream source frequency setting.
538 update_vertex_elements(struct NineDevice9
*device
)
540 struct nine_context
*context
= &device
->context
;
541 const struct NineVertexDeclaration9
*vdecl
= device
->context
.vdecl
;
542 const struct NineVertexShader9
*vs
;
545 char vdecl_index_map
[16]; /* vs->num_inputs <= 16 */
546 char used_streams
[device
->caps
.MaxStreams
];
547 int dummy_vbo_stream
= -1;
548 BOOL need_dummy_vbo
= FALSE
;
549 struct pipe_vertex_element ve
[PIPE_MAX_ATTRIBS
];
551 context
->stream_usage_mask
= 0;
552 memset(vdecl_index_map
, -1, 16);
553 memset(used_streams
, 0, device
->caps
.MaxStreams
);
554 vs
= context
->programmable_vs
? context
->vs
: device
->ff
.vs
;
557 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
558 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
559 n
, vs
->input_map
[n
].ndecl
, vdecl
);
561 for (i
= 0; i
< vdecl
->nelems
; i
++) {
562 if (vdecl
->usage_map
[i
] == vs
->input_map
[n
].ndecl
) {
563 vdecl_index_map
[n
] = i
;
564 used_streams
[vdecl
->elems
[i
].vertex_buffer_index
] = 1;
568 if (vdecl_index_map
[n
] < 0)
569 need_dummy_vbo
= TRUE
;
572 /* No vertex declaration. Likely will never happen in practice,
573 * but we need not crash on this */
574 need_dummy_vbo
= TRUE
;
577 if (need_dummy_vbo
) {
578 for (i
= 0; i
< device
->caps
.MaxStreams
; i
++ ) {
579 if (!used_streams
[i
]) {
580 dummy_vbo_stream
= i
;
585 /* there are less vertex shader inputs than stream slots,
586 * so if we need a slot for the dummy vbo, we should have found one */
587 assert (!need_dummy_vbo
|| dummy_vbo_stream
!= -1);
589 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
590 index
= vdecl_index_map
[n
];
592 ve
[n
] = vdecl
->elems
[index
];
593 b
= ve
[n
].vertex_buffer_index
;
594 context
->stream_usage_mask
|= 1 << b
;
595 /* XXX wine just uses 1 here: */
596 if (context
->stream_freq
[b
] & D3DSTREAMSOURCE_INSTANCEDATA
)
597 ve
[n
].instance_divisor
= context
->stream_freq
[b
] & 0x7FFFFF;
599 /* if the vertex declaration is incomplete compared to what the
600 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
601 * This is not precised by the spec, but is the behaviour
603 ve
[n
].vertex_buffer_index
= dummy_vbo_stream
;
604 ve
[n
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
605 ve
[n
].src_offset
= 0;
606 ve
[n
].instance_divisor
= 0;
610 if (context
->dummy_vbo_bound_at
!= dummy_vbo_stream
) {
611 if (context
->dummy_vbo_bound_at
>= 0)
612 context
->changed
.vtxbuf
|= 1 << context
->dummy_vbo_bound_at
;
613 if (dummy_vbo_stream
>= 0) {
614 context
->changed
.vtxbuf
|= 1 << dummy_vbo_stream
;
615 context
->vbo_bound_done
= FALSE
;
617 context
->dummy_vbo_bound_at
= dummy_vbo_stream
;
620 cso_set_vertex_elements(device
->cso
, vs
->num_inputs
, ve
);
624 update_vertex_buffers(struct NineDevice9
*device
)
626 struct pipe_context
*pipe
= device
->pipe
;
627 struct nine_context
*context
= &device
->context
;
628 struct pipe_vertex_buffer dummy_vtxbuf
;
629 uint32_t mask
= context
->changed
.vtxbuf
;
632 DBG("mask=%x\n", mask
);
634 if (context
->dummy_vbo_bound_at
>= 0) {
635 if (!context
->vbo_bound_done
) {
636 dummy_vtxbuf
.buffer
= device
->dummy_vbo
;
637 dummy_vtxbuf
.stride
= 0;
638 dummy_vtxbuf
.user_buffer
= NULL
;
639 dummy_vtxbuf
.buffer_offset
= 0;
640 pipe
->set_vertex_buffers(pipe
, context
->dummy_vbo_bound_at
,
642 context
->vbo_bound_done
= TRUE
;
644 mask
&= ~(1 << context
->dummy_vbo_bound_at
);
647 for (i
= 0; mask
; mask
>>= 1, ++i
) {
649 if (context
->vtxbuf
[i
].buffer
)
650 pipe
->set_vertex_buffers(pipe
, i
, 1, &context
->vtxbuf
[i
]);
652 pipe
->set_vertex_buffers(pipe
, i
, 1, NULL
);
656 context
->changed
.vtxbuf
= 0;
659 static inline boolean
660 update_sampler_derived(struct nine_context
*context
, unsigned s
)
662 boolean changed
= FALSE
;
664 if (context
->samp
[s
][NINED3DSAMP_SHADOW
] != context
->texture
[s
]->shadow
) {
666 context
->samp
[s
][NINED3DSAMP_SHADOW
] = context
->texture
[s
]->shadow
;
669 if (context
->samp
[s
][NINED3DSAMP_CUBETEX
] !=
670 (NineResource9(context
->texture
[s
])->type
== D3DRTYPE_CUBETEXTURE
)) {
672 context
->samp
[s
][NINED3DSAMP_CUBETEX
] =
673 NineResource9(context
->texture
[s
])->type
== D3DRTYPE_CUBETEXTURE
;
676 if (context
->samp
[s
][D3DSAMP_MIPFILTER
] != D3DTEXF_NONE
) {
677 int lod
= context
->samp
[s
][D3DSAMP_MAXMIPLEVEL
] - context
->texture
[s
]->managed
.lod
;
680 if (context
->samp
[s
][NINED3DSAMP_MINLOD
] != lod
) {
682 context
->samp
[s
][NINED3DSAMP_MINLOD
] = lod
;
685 context
->changed
.sampler
[s
] &= ~0x300; /* lod changes irrelevant */
691 /* TODO: add sRGB override to pipe_sampler_state ? */
693 update_textures_and_samplers(struct NineDevice9
*device
)
695 struct nine_context
*context
= &device
->context
;
696 struct pipe_sampler_view
*view
[NINE_MAX_SAMPLERS
];
697 unsigned num_textures
;
699 boolean commit_samplers
;
700 uint16_t sampler_mask
= context
->ps
? context
->ps
->sampler_mask
:
701 device
->ff
.ps
->sampler_mask
;
703 /* TODO: Can we reduce iterations here ? */
705 commit_samplers
= FALSE
;
706 context
->bound_samplers_mask_ps
= 0;
707 for (num_textures
= 0, i
= 0; i
< NINE_MAX_SAMPLERS_PS
; ++i
) {
708 const unsigned s
= NINE_SAMPLER_PS(i
);
711 if (!context
->texture
[s
] && !(sampler_mask
& (1 << i
))) {
716 if (context
->texture
[s
]) {
717 sRGB
= context
->samp
[s
][D3DSAMP_SRGBTEXTURE
] ? 1 : 0;
719 view
[i
] = NineBaseTexture9_GetSamplerView(context
->texture
[s
], sRGB
);
720 num_textures
= i
+ 1;
722 if (update_sampler_derived(context
, s
) || (context
->changed
.sampler
[s
] & 0x05fe)) {
723 context
->changed
.sampler
[s
] = 0;
724 commit_samplers
= TRUE
;
725 nine_convert_sampler_state(device
->cso
, s
, context
->samp
[s
]);
728 /* Bind dummy sampler. We do not bind dummy sampler when
729 * it is not needed because it could add overhead. The
730 * dummy sampler should have r=g=b=0 and a=1. We do not
731 * unbind dummy sampler directly when they are not needed
732 * anymore, but they're going to be removed as long as texture
733 * or sampler states are changed. */
734 view
[i
] = device
->dummy_sampler_view
;
735 num_textures
= i
+ 1;
737 cso_single_sampler(device
->cso
, PIPE_SHADER_FRAGMENT
,
738 s
- NINE_SAMPLER_PS(0), &device
->dummy_sampler_state
);
740 commit_samplers
= TRUE
;
741 context
->changed
.sampler
[s
] = ~0;
744 context
->bound_samplers_mask_ps
|= (1 << s
);
747 cso_set_sampler_views(device
->cso
, PIPE_SHADER_FRAGMENT
, num_textures
, view
);
750 cso_single_sampler_done(device
->cso
, PIPE_SHADER_FRAGMENT
);
752 commit_samplers
= FALSE
;
753 sampler_mask
= context
->programmable_vs
? context
->vs
->sampler_mask
: 0;
754 context
->bound_samplers_mask_vs
= 0;
755 for (num_textures
= 0, i
= 0; i
< NINE_MAX_SAMPLERS_VS
; ++i
) {
756 const unsigned s
= NINE_SAMPLER_VS(i
);
759 if (!context
->texture
[s
] && !(sampler_mask
& (1 << i
))) {
764 if (context
->texture
[s
]) {
765 sRGB
= context
->samp
[s
][D3DSAMP_SRGBTEXTURE
] ? 1 : 0;
767 view
[i
] = NineBaseTexture9_GetSamplerView(context
->texture
[s
], sRGB
);
768 num_textures
= i
+ 1;
770 if (update_sampler_derived(context
, s
) || (context
->changed
.sampler
[s
] & 0x05fe)) {
771 context
->changed
.sampler
[s
] = 0;
772 commit_samplers
= TRUE
;
773 nine_convert_sampler_state(device
->cso
, s
, context
->samp
[s
]);
776 /* Bind dummy sampler. We do not bind dummy sampler when
777 * it is not needed because it could add overhead. The
778 * dummy sampler should have r=g=b=0 and a=1. We do not
779 * unbind dummy sampler directly when they are not needed
780 * anymore, but they're going to be removed as long as texture
781 * or sampler states are changed. */
782 view
[i
] = device
->dummy_sampler_view
;
783 num_textures
= i
+ 1;
785 cso_single_sampler(device
->cso
, PIPE_SHADER_VERTEX
,
786 s
- NINE_SAMPLER_VS(0), &device
->dummy_sampler_state
);
788 commit_samplers
= TRUE
;
789 context
->changed
.sampler
[s
] = ~0;
792 context
->bound_samplers_mask_vs
|= (1 << s
);
795 cso_set_sampler_views(device
->cso
, PIPE_SHADER_VERTEX
, num_textures
, view
);
798 cso_single_sampler_done(device
->cso
, PIPE_SHADER_VERTEX
);
801 /* State commit only */
804 commit_blend(struct NineDevice9
*device
)
806 cso_set_blend(device
->cso
, &device
->context
.pipe_data
.blend
);
810 commit_dsa(struct NineDevice9
*device
)
812 cso_set_depth_stencil_alpha(device
->cso
, &device
->context
.pipe_data
.dsa
);
816 commit_scissor(struct NineDevice9
*device
)
818 struct pipe_context
*pipe
= device
->pipe
;
820 pipe
->set_scissor_states(pipe
, 0, 1, &device
->context
.scissor
);
824 commit_rasterizer(struct NineDevice9
*device
)
826 cso_set_rasterizer(device
->cso
, &device
->context
.pipe_data
.rast
);
830 commit_index_buffer(struct NineDevice9
*device
)
832 struct pipe_context
*pipe
= device
->pipe
;
833 if (device
->context
.idxbuf
.buffer
)
834 pipe
->set_index_buffer(pipe
, &device
->context
.idxbuf
);
836 pipe
->set_index_buffer(pipe
, NULL
);
840 commit_vs_constants(struct NineDevice9
*device
)
842 struct pipe_context
*pipe
= device
->pipe
;
844 if (unlikely(!device
->context
.programmable_vs
))
845 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &device
->context
.pipe_data
.cb_vs_ff
);
848 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &device
->context
.pipe_data
.cb0_swvp
);
849 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 1, &device
->context
.pipe_data
.cb1_swvp
);
850 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 2, &device
->context
.pipe_data
.cb2_swvp
);
851 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 3, &device
->context
.pipe_data
.cb3_swvp
);
853 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_VERTEX
, 0, &device
->context
.pipe_data
.cb_vs
);
859 commit_ps_constants(struct NineDevice9
*device
)
861 struct pipe_context
*pipe
= device
->pipe
;
863 if (unlikely(!device
->context
.ps
))
864 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &device
->context
.pipe_data
.cb_ps_ff
);
866 pipe
->set_constant_buffer(pipe
, PIPE_SHADER_FRAGMENT
, 0, &device
->context
.pipe_data
.cb_ps
);
870 commit_vs(struct NineDevice9
*device
)
872 struct nine_context
*context
= &device
->context
;
874 device
->pipe
->bind_vs_state(device
->pipe
, context
->cso_shader
.vs
);
879 commit_ps(struct NineDevice9
*device
)
881 struct nine_context
*context
= &device
->context
;
883 device
->pipe
->bind_fs_state(device
->pipe
, context
->cso_shader
.ps
);
887 #define NINE_STATE_SHADER_CHANGE_VS \
889 NINE_STATE_TEXTURE | \
890 NINE_STATE_FOG_SHADER | \
891 NINE_STATE_POINTSIZE_SHADER | \
894 #define NINE_STATE_SHADER_CHANGE_PS \
896 NINE_STATE_TEXTURE | \
897 NINE_STATE_FOG_SHADER | \
898 NINE_STATE_PS1X_SHADER)
900 #define NINE_STATE_FREQUENT \
901 (NINE_STATE_RASTERIZER | \
902 NINE_STATE_TEXTURE | \
903 NINE_STATE_SAMPLER | \
904 NINE_STATE_VS_CONST | \
905 NINE_STATE_PS_CONST | \
906 NINE_STATE_MULTISAMPLE)
908 #define NINE_STATE_COMMON \
912 NINE_STATE_VIEWPORT | \
914 NINE_STATE_IDXBUF | \
915 NINE_STATE_STREAMFREQ)
917 #define NINE_STATE_RARE \
918 (NINE_STATE_SCISSOR | \
919 NINE_STATE_BLEND_COLOR | \
920 NINE_STATE_STENCIL_REF | \
921 NINE_STATE_SAMPLE_MASK)
924 /* TODO: only go through dirty textures */
926 validate_textures(struct NineDevice9
*device
)
928 struct NineBaseTexture9
*tex
, *ptr
;
929 LIST_FOR_EACH_ENTRY_SAFE(tex
, ptr
, &device
->update_textures
, list
) {
930 list_delinit(&tex
->list
);
931 NineBaseTexture9_Validate(tex
);
936 update_managed_buffers(struct NineDevice9
*device
)
938 struct NineBuffer9
*buf
, *ptr
;
939 LIST_FOR_EACH_ENTRY_SAFE(buf
, ptr
, &device
->update_buffers
, managed
.list
) {
940 list_delinit(&buf
->managed
.list
);
941 NineBuffer9_Upload(buf
);
946 nine_update_state(struct NineDevice9
*device
)
948 struct pipe_context
*pipe
= device
->pipe
;
949 struct nine_context
*context
= &device
->context
;
952 DBG("changed state groups: %x\n", context
->changed
.group
);
954 /* NOTE: We may want to use the cso cache for everything, or let
955 * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't
956 * have to care about state being clobbered here and could merge this back
957 * into update_textures. Except, we also need to re-validate textures that
958 * may be dirty anyway, even if no texture bindings changed.
960 validate_textures(device
); /* may clobber state */
961 update_managed_buffers(device
);
963 /* ff_update may change VS/PS dirty bits */
964 if (unlikely(!context
->programmable_vs
|| !context
->ps
))
965 nine_ff_update(device
);
966 group
= context
->changed
.group
;
968 if (group
& (NINE_STATE_SHADER_CHANGE_VS
| NINE_STATE_SHADER_CHANGE_PS
)) {
969 if (group
& NINE_STATE_SHADER_CHANGE_VS
)
970 group
|= prepare_vs(device
, (group
& NINE_STATE_VS
) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/
971 if (group
& NINE_STATE_SHADER_CHANGE_PS
)
972 group
|= prepare_ps(device
, (group
& NINE_STATE_PS
) != 0);
975 if (group
& (NINE_STATE_COMMON
| NINE_STATE_VS
)) {
976 if (group
& NINE_STATE_FB
)
977 update_framebuffer(device
, FALSE
);
978 if (group
& NINE_STATE_BLEND
)
979 prepare_blend(device
);
980 if (group
& NINE_STATE_DSA
)
982 if (group
& NINE_STATE_VIEWPORT
)
983 update_viewport(device
);
984 if (group
& (NINE_STATE_VDECL
| NINE_STATE_VS
| NINE_STATE_STREAMFREQ
))
985 update_vertex_elements(device
);
986 if (group
& NINE_STATE_IDXBUF
)
987 commit_index_buffer(device
);
990 if (likely(group
& (NINE_STATE_FREQUENT
| NINE_STATE_VS
| NINE_STATE_PS
| NINE_STATE_SWVP
))) {
991 if (group
& NINE_STATE_MULTISAMPLE
)
992 group
|= check_multisample(device
);
993 if (group
& NINE_STATE_RASTERIZER
)
994 prepare_rasterizer(device
);
995 if (group
& (NINE_STATE_TEXTURE
| NINE_STATE_SAMPLER
))
996 update_textures_and_samplers(device
);
997 if ((group
& (NINE_STATE_VS_CONST
| NINE_STATE_VS
| NINE_STATE_SWVP
)) && context
->programmable_vs
)
998 prepare_vs_constants_userbuf(device
);
999 if ((group
& (NINE_STATE_PS_CONST
| NINE_STATE_PS
)) && context
->ps
)
1000 prepare_ps_constants_userbuf(device
);
1003 if (context
->changed
.vtxbuf
)
1004 update_vertex_buffers(device
);
1006 if (context
->commit
& NINE_STATE_COMMIT_BLEND
)
1007 commit_blend(device
);
1008 if (context
->commit
& NINE_STATE_COMMIT_DSA
)
1010 if (context
->commit
& NINE_STATE_COMMIT_RASTERIZER
)
1011 commit_rasterizer(device
);
1012 if (context
->commit
& NINE_STATE_COMMIT_CONST_VS
)
1013 commit_vs_constants(device
);
1014 if (context
->commit
& NINE_STATE_COMMIT_CONST_PS
)
1015 commit_ps_constants(device
);
1016 if (context
->commit
& NINE_STATE_COMMIT_VS
)
1018 if (context
->commit
& NINE_STATE_COMMIT_PS
)
1021 context
->commit
= 0;
1023 if (unlikely(context
->changed
.ucp
)) {
1024 pipe
->set_clip_state(pipe
, &context
->clip
);
1025 context
->changed
.ucp
= FALSE
;
1028 if (unlikely(group
& NINE_STATE_RARE
)) {
1029 if (group
& NINE_STATE_SCISSOR
)
1030 commit_scissor(device
);
1031 if (group
& NINE_STATE_BLEND_COLOR
) {
1032 struct pipe_blend_color color
;
1033 d3dcolor_to_rgba(&color
.color
[0], context
->rs
[D3DRS_BLENDFACTOR
]);
1034 pipe
->set_blend_color(pipe
, &color
);
1036 if (group
& NINE_STATE_SAMPLE_MASK
) {
1037 if (context
->rt
[0]->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
) {
1038 pipe
->set_sample_mask(pipe
, ~0);
1040 pipe
->set_sample_mask(pipe
, context
->rs
[D3DRS_MULTISAMPLEMASK
]);
1043 if (group
& NINE_STATE_STENCIL_REF
) {
1044 struct pipe_stencil_ref ref
;
1045 ref
.ref_value
[0] = context
->rs
[D3DRS_STENCILREF
];
1046 ref
.ref_value
[1] = ref
.ref_value
[0];
1047 pipe
->set_stencil_ref(pipe
, &ref
);
1051 context
->changed
.group
&=
1052 (NINE_STATE_FF
| NINE_STATE_VS_CONST
| NINE_STATE_PS_CONST
);
1057 #define RESZ_CODE 0x7fa05000
1060 NineDevice9_ResolveZ( struct NineDevice9
*device
)
1062 struct nine_context
*context
= &device
->context
;
1063 const struct util_format_description
*desc
;
1064 struct NineSurface9
*source
= context
->ds
;
1065 struct NineBaseTexture9
*destination
= context
->texture
[0];
1066 struct pipe_resource
*src
, *dst
;
1067 struct pipe_blit_info blit
;
1069 DBG("RESZ resolve\n");
1071 if (!source
|| !destination
||
1072 destination
->base
.type
!= D3DRTYPE_TEXTURE
)
1075 src
= source
->base
.resource
;
1076 dst
= destination
->base
.resource
;
1081 /* check dst is depth format. we know already for src */
1082 desc
= util_format_description(dst
->format
);
1083 if (desc
->colorspace
!= UTIL_FORMAT_COLORSPACE_ZS
)
1086 memset(&blit
, 0, sizeof(blit
));
1087 blit
.src
.resource
= src
;
1089 blit
.src
.format
= src
->format
;
1091 blit
.src
.box
.depth
= 1;
1094 blit
.src
.box
.width
= src
->width0
;
1095 blit
.src
.box
.height
= src
->height0
;
1097 blit
.dst
.resource
= dst
;
1099 blit
.dst
.format
= dst
->format
;
1101 blit
.dst
.box
.depth
= 1;
1104 blit
.dst
.box
.width
= dst
->width0
;
1105 blit
.dst
.box
.height
= dst
->height0
;
1107 blit
.mask
= PIPE_MASK_ZS
;
1108 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
1109 blit
.scissor_enable
= FALSE
;
1111 device
->pipe
->blit(device
->pipe
, &blit
);
1114 #define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1')
1115 #define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0')
1119 nine_context_set_render_state(struct NineDevice9
*device
,
1120 D3DRENDERSTATETYPE State
,
1123 struct nine_context
*context
= &device
->context
;
1125 /* Amd hacks (equivalent to GL extensions) */
1126 if (unlikely(State
== D3DRS_POINTSIZE
)) {
1127 if (Value
== RESZ_CODE
) {
1128 NineDevice9_ResolveZ(device
);
1132 if (Value
== ALPHA_TO_COVERAGE_ENABLE
||
1133 Value
== ALPHA_TO_COVERAGE_DISABLE
) {
1134 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== ALPHA_TO_COVERAGE_ENABLE
);
1135 context
->changed
.group
|= NINE_STATE_BLEND
;
1141 if (unlikely(State
== D3DRS_ADAPTIVETESS_Y
)) {
1142 if (Value
== D3DFMT_ATOC
|| (Value
== D3DFMT_UNKNOWN
&& context
->rs
[NINED3DRS_ALPHACOVERAGE
])) {
1143 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
== D3DFMT_ATOC
) ? 3 : 0;
1144 context
->rs
[NINED3DRS_ALPHACOVERAGE
] &= context
->rs
[D3DRS_ALPHATESTENABLE
] ? 3 : 2;
1145 context
->changed
.group
|= NINE_STATE_BLEND
;
1149 if (unlikely(State
== D3DRS_ALPHATESTENABLE
&& (context
->rs
[NINED3DRS_ALPHACOVERAGE
] & 2))) {
1150 DWORD alphacoverage_prev
= context
->rs
[NINED3DRS_ALPHACOVERAGE
];
1151 context
->rs
[NINED3DRS_ALPHACOVERAGE
] = (Value
? 3 : 2);
1152 if (context
->rs
[NINED3DRS_ALPHACOVERAGE
] != alphacoverage_prev
)
1153 context
->changed
.group
|= NINE_STATE_BLEND
;
1156 context
->rs
[State
] = nine_fix_render_state_value(State
, Value
);
1157 context
->changed
.group
|= nine_render_state_group
[State
];
1161 nine_context_set_texture(struct NineDevice9
*device
,
1163 struct NineBaseTexture9
*tex
)
1165 struct nine_context
*context
= &device
->context
;
1167 context
->samplers_shadow
&= ~(1 << Stage
);
1169 context
->samplers_shadow
|= tex
->shadow
<< Stage
;
1171 nine_bind(&context
->texture
[Stage
], tex
);
1173 context
->changed
.group
|= NINE_STATE_TEXTURE
;
1177 nine_context_set_sampler_state(struct NineDevice9
*device
,
1179 D3DSAMPLERSTATETYPE Type
,
1182 struct nine_context
*context
= &device
->context
;
1184 if (unlikely(!nine_check_sampler_state_value(Type
, Value
)))
1187 context
->samp
[Sampler
][Type
] = Value
;
1188 context
->changed
.group
|= NINE_STATE_SAMPLER
;
1189 context
->changed
.sampler
[Sampler
] |= 1 << Type
;
1193 nine_context_set_stream_source(struct NineDevice9
*device
,
1195 struct NineVertexBuffer9
*pVBuf9
,
1199 struct nine_context
*context
= &device
->context
;
1200 const unsigned i
= StreamNumber
;
1202 context
->changed
.vtxbuf
|= 1 << StreamNumber
;
1205 context
->vtxbuf
[i
].stride
= Stride
;
1206 context
->vtxbuf
[i
].buffer_offset
= OffsetInBytes
;
1208 pipe_resource_reference(&context
->vtxbuf
[i
].buffer
,
1209 pVBuf9
? NineVertexBuffer9_GetResource(pVBuf9
) : NULL
);
1213 nine_context_set_stream_source_freq(struct NineDevice9
*device
,
1217 struct nine_context
*context
= &device
->context
;
1219 context
->stream_freq
[StreamNumber
] = Setting
;
1221 if (Setting
& D3DSTREAMSOURCE_INSTANCEDATA
)
1222 context
->stream_instancedata_mask
|= 1 << StreamNumber
;
1224 context
->stream_instancedata_mask
&= ~(1 << StreamNumber
);
1226 if (StreamNumber
!= 0)
1227 context
->changed
.group
|= NINE_STATE_STREAMFREQ
;
1231 nine_context_set_indices(struct NineDevice9
*device
,
1232 struct NineIndexBuffer9
*idxbuf
)
1234 struct nine_context
*context
= &device
->context
;
1235 const struct pipe_index_buffer
*pipe_idxbuf
;
1238 pipe_idxbuf
= NineIndexBuffer9_GetBuffer(idxbuf
);
1239 context
->idxbuf
.index_size
= pipe_idxbuf
->index_size
;
1240 pipe_resource_reference(&context
->idxbuf
.buffer
, pipe_idxbuf
->buffer
);
1241 context
->idxbuf
.offset
= pipe_idxbuf
->offset
;
1242 context
->idxbuf
.user_buffer
= NULL
;
1244 pipe_resource_reference(&context
->idxbuf
.buffer
, NULL
);
1246 context
->changed
.group
|= NINE_STATE_IDXBUF
;
1250 nine_context_set_vertex_declaration(struct NineDevice9
*device
,
1251 struct NineVertexDeclaration9
*vdecl
)
1253 struct nine_context
*context
= &device
->context
;
1254 BOOL was_programmable_vs
= context
->programmable_vs
;
1256 nine_bind(&context
->vdecl
, vdecl
);
1258 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
1259 if (was_programmable_vs
!= context
->programmable_vs
) {
1260 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
1261 context
->changed
.group
|= NINE_STATE_VS
;
1264 context
->changed
.group
|= NINE_STATE_VDECL
;
1268 nine_context_set_vertex_shader(struct NineDevice9
*device
,
1269 struct NineVertexShader9
*pShader
)
1271 struct nine_context
*context
= &device
->context
;
1272 BOOL was_programmable_vs
= context
->programmable_vs
;
1274 nine_bind(&context
->vs
, pShader
);
1276 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
1278 /* ff -> non-ff: commit back non-ff constants */
1279 if (!was_programmable_vs
&& context
->programmable_vs
)
1280 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
;
1282 context
->changed
.group
|= NINE_STATE_VS
;
1286 nine_context_set_vertex_shader_constant_f(struct NineDevice9
*device
,
1288 const float *pConstantData
,
1291 struct nine_context
*context
= &device
->context
;
1292 float *vs_const_f
= device
->may_swvp
? context
->vs_const_f_swvp
: context
->vs_const_f
;
1294 memcpy(&vs_const_f
[StartRegister
* 4],
1296 Vector4fCount
* 4 * sizeof(context
->vs_const_f
[0]));
1298 if (device
->may_swvp
) {
1299 Vector4fCount
= MIN2(StartRegister
+ Vector4fCount
, NINE_MAX_CONST_F
) - StartRegister
;
1300 if (StartRegister
< NINE_MAX_CONST_F
)
1301 memcpy(&context
->vs_const_f
[StartRegister
* 4],
1303 Vector4fCount
* 4 * sizeof(context
->vs_const_f
[0]));
1306 context
->changed
.vs_const_f
= TRUE
;
1307 context
->changed
.group
|= NINE_STATE_VS_CONST
;
1312 nine_context_set_vertex_shader_constant_i(struct NineDevice9
*device
,
1314 const int *pConstantData
,
1317 struct nine_context
*context
= &device
->context
;
1320 if (device
->driver_caps
.vs_integer
) {
1321 memcpy(&context
->vs_const_i
[4 * StartRegister
],
1323 Vector4iCount
* sizeof(int[4]));
1325 for (i
= 0; i
< Vector4iCount
; i
++) {
1326 context
->vs_const_i
[4 * (StartRegister
+ i
)] = fui((float)(pConstantData
[4 * i
]));
1327 context
->vs_const_i
[4 * (StartRegister
+ i
) + 1] = fui((float)(pConstantData
[4 * i
+ 1]));
1328 context
->vs_const_i
[4 * (StartRegister
+ i
) + 2] = fui((float)(pConstantData
[4 * i
+ 2]));
1329 context
->vs_const_i
[4 * (StartRegister
+ i
) + 3] = fui((float)(pConstantData
[4 * i
+ 3]));
1333 context
->changed
.vs_const_i
= TRUE
;
1334 context
->changed
.group
|= NINE_STATE_VS_CONST
;
1338 nine_context_set_vertex_shader_constant_b(struct NineDevice9
*device
,
1340 const BOOL
*pConstantData
,
1343 struct nine_context
*context
= &device
->context
;
1345 uint32_t bool_true
= device
->driver_caps
.vs_integer
? 0xFFFFFFFF : fui(1.0f
);
1347 for (i
= 0; i
< BoolCount
; i
++)
1348 context
->vs_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
1350 context
->changed
.vs_const_b
= TRUE
;
1351 context
->changed
.group
|= NINE_STATE_VS_CONST
;
1355 nine_context_set_pixel_shader(struct NineDevice9
*device
,
1356 struct NinePixelShader9
* ps
)
1358 struct nine_context
*context
= &device
->context
;
1359 unsigned old_mask
= context
->ps
? context
->ps
->rt_mask
: 1;
1362 /* ff -> non-ff: commit back non-ff constants */
1363 if (!context
->ps
&& ps
)
1364 context
->commit
|= NINE_STATE_COMMIT_CONST_PS
;
1366 nine_bind(&context
->ps
, ps
);
1368 context
->changed
.group
|= NINE_STATE_PS
;
1370 mask
= context
->ps
? context
->ps
->rt_mask
: 1;
1371 /* We need to update cbufs if the pixel shader would
1372 * write to different render targets */
1373 if (mask
!= old_mask
)
1374 context
->changed
.group
|= NINE_STATE_FB
;
1378 nine_context_set_pixel_shader_constant_f(struct NineDevice9
*device
,
1380 const float *pConstantData
,
1383 struct nine_context
*context
= &device
->context
;
1385 memcpy(&context
->ps_const_f
[StartRegister
* 4],
1387 Vector4fCount
* 4 * sizeof(context
->ps_const_f
[0]));
1389 context
->changed
.ps_const_f
= TRUE
;
1390 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1394 nine_context_set_pixel_shader_constant_i(struct NineDevice9
*device
,
1396 const int *pConstantData
,
1399 struct nine_context
*context
= &device
->context
;
1402 if (device
->driver_caps
.ps_integer
) {
1403 memcpy(&context
->ps_const_i
[StartRegister
][0],
1405 Vector4iCount
* sizeof(context
->ps_const_i
[0]));
1407 for (i
= 0; i
< Vector4iCount
; i
++) {
1408 context
->ps_const_i
[StartRegister
+i
][0] = fui((float)(pConstantData
[4*i
]));
1409 context
->ps_const_i
[StartRegister
+i
][1] = fui((float)(pConstantData
[4*i
+1]));
1410 context
->ps_const_i
[StartRegister
+i
][2] = fui((float)(pConstantData
[4*i
+2]));
1411 context
->ps_const_i
[StartRegister
+i
][3] = fui((float)(pConstantData
[4*i
+3]));
1414 context
->changed
.ps_const_i
= TRUE
;
1415 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1419 nine_context_set_pixel_shader_constant_b(struct NineDevice9
*device
,
1421 const BOOL
*pConstantData
,
1424 struct nine_context
*context
= &device
->context
;
1426 uint32_t bool_true
= device
->driver_caps
.ps_integer
? 0xFFFFFFFF : fui(1.0f
);
1428 for (i
= 0; i
< BoolCount
; i
++)
1429 context
->ps_const_b
[StartRegister
+ i
] = pConstantData
[i
] ? bool_true
: 0;
1431 context
->changed
.ps_const_b
= TRUE
;
1432 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1436 nine_context_set_render_target(struct NineDevice9
*device
,
1437 DWORD RenderTargetIndex
,
1438 struct NineSurface9
*rt
)
1440 struct nine_context
*context
= &device
->context
;
1441 const unsigned i
= RenderTargetIndex
;
1444 context
->viewport
.X
= 0;
1445 context
->viewport
.Y
= 0;
1446 context
->viewport
.Width
= rt
->desc
.Width
;
1447 context
->viewport
.Height
= rt
->desc
.Height
;
1448 context
->viewport
.MinZ
= 0.0f
;
1449 context
->viewport
.MaxZ
= 1.0f
;
1451 context
->scissor
.minx
= 0;
1452 context
->scissor
.miny
= 0;
1453 context
->scissor
.maxx
= rt
->desc
.Width
;
1454 context
->scissor
.maxy
= rt
->desc
.Height
;
1456 context
->changed
.group
|= NINE_STATE_VIEWPORT
| NINE_STATE_SCISSOR
| NINE_STATE_MULTISAMPLE
;
1458 if (context
->rt
[0] &&
1459 (context
->rt
[0]->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
) !=
1460 (rt
->desc
.MultiSampleType
<= D3DMULTISAMPLE_NONMASKABLE
))
1461 context
->changed
.group
|= NINE_STATE_SAMPLE_MASK
;
1464 if (context
->rt
[i
] != rt
) {
1465 nine_bind(&context
->rt
[i
], rt
);
1466 context
->changed
.group
|= NINE_STATE_FB
;
1471 nine_context_set_depth_stencil(struct NineDevice9
*device
,
1472 struct NineSurface9
*ds
)
1474 struct nine_context
*context
= &device
->context
;
1476 nine_bind(&context
->ds
, ds
);
1477 context
->changed
.group
|= NINE_STATE_FB
;
1481 nine_context_set_viewport(struct NineDevice9
*device
,
1482 const D3DVIEWPORT9
*viewport
)
1484 struct nine_context
*context
= &device
->context
;
1486 context
->viewport
= *viewport
;
1487 context
->changed
.group
|= NINE_STATE_VIEWPORT
;
1491 nine_context_set_scissor(struct NineDevice9
*device
,
1492 const struct pipe_scissor_state
*scissor
)
1494 struct nine_context
*context
= &device
->context
;
1496 context
->scissor
= *scissor
;
1497 context
->changed
.group
|= NINE_STATE_SCISSOR
;
1501 nine_context_set_transform(struct NineDevice9
*device
,
1502 D3DTRANSFORMSTATETYPE State
,
1503 const D3DMATRIX
*pMatrix
)
1505 struct nine_context
*context
= &device
->context
;
1506 D3DMATRIX
*M
= nine_state_access_transform(&context
->ff
, State
, TRUE
);
1509 context
->ff
.changed
.transform
[State
/ 32] |= 1 << (State
% 32);
1510 context
->changed
.group
|= NINE_STATE_FF
;
1514 nine_context_set_material(struct NineDevice9
*device
,
1515 const D3DMATERIAL9
*pMaterial
)
1517 struct nine_context
*context
= &device
->context
;
1519 context
->ff
.material
= *pMaterial
;
1520 context
->changed
.group
|= NINE_STATE_FF_MATERIAL
;
1524 nine_context_set_light(struct NineDevice9
*device
,
1526 const D3DLIGHT9
*pLight
)
1528 struct nine_context
*context
= &device
->context
;
1530 (void)nine_state_set_light(&context
->ff
, Index
, pLight
);
1531 context
->changed
.group
|= NINE_STATE_FF_LIGHTING
;
1535 nine_context_light_enable(struct NineDevice9
*device
,
1539 struct nine_context
*context
= &device
->context
;
1541 nine_state_light_enable(&context
->ff
, &context
->changed
.group
, Index
, Enable
);
1545 nine_context_set_texture_stage_state(struct NineDevice9
*device
,
1547 D3DTEXTURESTAGESTATETYPE Type
,
1550 struct nine_context
*context
= &device
->context
;
1551 int bumpmap_index
= -1;
1553 context
->ff
.tex_stage
[Stage
][Type
] = Value
;
1555 case D3DTSS_BUMPENVMAT00
:
1556 bumpmap_index
= 4 * Stage
;
1558 case D3DTSS_BUMPENVMAT01
:
1559 bumpmap_index
= 4 * Stage
+ 1;
1561 case D3DTSS_BUMPENVMAT10
:
1562 bumpmap_index
= 4 * Stage
+ 2;
1564 case D3DTSS_BUMPENVMAT11
:
1565 bumpmap_index
= 4 * Stage
+ 3;
1567 case D3DTSS_BUMPENVLSCALE
:
1568 bumpmap_index
= 4 * 8 + 2 * Stage
;
1570 case D3DTSS_BUMPENVLOFFSET
:
1571 bumpmap_index
= 4 * 8 + 2 * Stage
+ 1;
1573 case D3DTSS_TEXTURETRANSFORMFLAGS
:
1574 context
->changed
.group
|= NINE_STATE_PS1X_SHADER
;
1580 if (bumpmap_index
>= 0) {
1581 context
->bumpmap_vars
[bumpmap_index
] = Value
;
1582 context
->changed
.group
|= NINE_STATE_PS_CONST
;
1585 context
->changed
.group
|= NINE_STATE_FF_PSSTAGES
;
1586 context
->ff
.changed
.tex_stage
[Stage
][Type
/ 32] |= 1 << (Type
% 32);
1590 nine_context_set_clip_plane(struct NineDevice9
*device
,
1592 const float *pPlane
)
1594 struct nine_context
*context
= &device
->context
;
1596 memcpy(&context
->clip
.ucp
[Index
][0], pPlane
, sizeof(context
->clip
.ucp
[0]));
1597 context
->changed
.ucp
= TRUE
;
1601 nine_context_apply_stateblock(struct NineDevice9
*device
,
1602 const struct nine_state
*src
)
1604 struct nine_context
*context
= &device
->context
;
1607 context
->changed
.group
|= src
->changed
.group
;
1609 for (i
= 0; i
< ARRAY_SIZE(src
->changed
.rs
); ++i
) {
1610 uint32_t m
= src
->changed
.rs
[i
];
1612 const int r
= ffs(m
) - 1;
1614 context
->rs
[i
* 32 + r
] = nine_fix_render_state_value(i
* 32 + r
, src
->rs_advertised
[i
* 32 + r
]);
1619 if (src
->changed
.texture
) {
1620 uint32_t m
= src
->changed
.texture
;
1623 context
->samplers_shadow
&= ~m
;
1625 for (s
= 0; m
; ++s
, m
>>= 1) {
1626 struct NineBaseTexture9
*tex
= src
->texture
[s
];
1630 context
->samplers_shadow
|= tex
->shadow
<< s
;
1631 nine_bind(&context
->texture
[s
], src
->texture
[s
]);
1636 if (src
->changed
.group
& NINE_STATE_SAMPLER
) {
1639 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
1640 uint32_t m
= src
->changed
.sampler
[s
];
1642 const int i
= ffs(m
) - 1;
1644 if (nine_check_sampler_state_value(i
, src
->samp_advertised
[s
][i
]))
1645 context
->samp
[s
][i
] = src
->samp_advertised
[s
][i
];
1647 context
->changed
.sampler
[s
] |= src
->changed
.sampler
[s
];
1651 /* Vertex buffers */
1652 if (src
->changed
.vtxbuf
| src
->changed
.stream_freq
) {
1653 uint32_t m
= src
->changed
.vtxbuf
| src
->changed
.stream_freq
;
1654 for (i
= 0; m
; ++i
, m
>>= 1) {
1655 if (src
->changed
.vtxbuf
& (1 << i
)) {
1656 if (src
->stream
[i
]) {
1657 context
->vtxbuf
[i
].buffer_offset
= src
->vtxbuf
[i
].buffer_offset
;
1658 pipe_resource_reference(&context
->vtxbuf
[i
].buffer
,
1659 src
->stream
[i
] ? NineVertexBuffer9_GetResource(src
->stream
[i
]) : NULL
);
1660 context
->vtxbuf
[i
].stride
= src
->vtxbuf
[i
].stride
;
1663 if (src
->changed
.stream_freq
& (1 << i
)) {
1664 context
->stream_freq
[i
] = src
->stream_freq
[i
];
1665 if (src
->stream_freq
[i
] & D3DSTREAMSOURCE_INSTANCEDATA
)
1666 context
->stream_instancedata_mask
|= 1 << i
;
1668 context
->stream_instancedata_mask
&= ~(1 << i
);
1671 context
->changed
.vtxbuf
|= src
->changed
.vtxbuf
;
1675 if (src
->changed
.group
& NINE_STATE_IDXBUF
)
1676 nine_context_set_indices(device
, src
->idxbuf
);
1678 /* Vertex declaration */
1679 if ((src
->changed
.group
& NINE_STATE_VDECL
) && src
->vdecl
)
1680 nine_context_set_vertex_declaration(device
, src
->vdecl
);
1683 if (src
->changed
.group
& NINE_STATE_VS
)
1684 nine_bind(&context
->vs
, src
->vs
);
1686 context
->programmable_vs
= context
->vs
&& !(context
->vdecl
&& context
->vdecl
->position_t
);
1689 if (src
->changed
.group
& NINE_STATE_PS
)
1690 nine_bind(&context
->ps
, src
->ps
);
1692 /* Vertex constants */
1693 if (src
->changed
.group
& NINE_STATE_VS_CONST
) {
1694 struct nine_range
*r
;
1695 if (device
->may_swvp
) {
1696 for (r
= src
->changed
.vs_const_f
; r
; r
= r
->next
) {
1699 memcpy(&context
->vs_const_f_swvp
[bgn
* 4],
1700 &src
->vs_const_f
[bgn
* 4],
1701 (end
- bgn
) * 4 * sizeof(float));
1702 if (bgn
< device
->max_vs_const_f
) {
1703 end
= MIN2(end
, device
->max_vs_const_f
);
1704 memcpy(&context
->vs_const_f
[bgn
* 4],
1705 &src
->vs_const_f
[bgn
* 4],
1706 (end
- bgn
) * 4 * sizeof(float));
1710 for (r
= src
->changed
.vs_const_f
; r
; r
= r
->next
) {
1711 memcpy(&context
->vs_const_f
[r
->bgn
* 4],
1712 &src
->vs_const_f
[r
->bgn
* 4],
1713 (r
->end
- r
->bgn
) * 4 * sizeof(float));
1716 for (r
= src
->changed
.vs_const_i
; r
; r
= r
->next
) {
1717 memcpy(&context
->vs_const_i
[r
->bgn
* 4],
1718 &src
->vs_const_i
[r
->bgn
* 4],
1719 (r
->end
- r
->bgn
) * 4 * sizeof(int));
1721 for (r
= src
->changed
.vs_const_b
; r
; r
= r
->next
) {
1722 memcpy(&context
->vs_const_b
[r
->bgn
],
1723 &src
->vs_const_b
[r
->bgn
],
1724 (r
->end
- r
->bgn
) * sizeof(int));
1726 context
->changed
.vs_const_f
= !!src
->changed
.vs_const_f
;
1727 context
->changed
.vs_const_i
= !!src
->changed
.vs_const_i
;
1728 context
->changed
.vs_const_b
= !!src
->changed
.vs_const_b
;
1731 /* Pixel constants */
1732 if (src
->changed
.group
& NINE_STATE_PS_CONST
) {
1733 struct nine_range
*r
;
1734 for (r
= src
->changed
.ps_const_f
; r
; r
= r
->next
) {
1735 memcpy(&context
->ps_const_f
[r
->bgn
* 4],
1736 &src
->ps_const_f
[r
->bgn
* 4],
1737 (r
->end
- r
->bgn
) * 4 * sizeof(float));
1739 if (src
->changed
.ps_const_i
) {
1740 uint16_t m
= src
->changed
.ps_const_i
;
1741 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
1743 memcpy(context
->ps_const_i
[i
], src
->ps_const_i
[i
], 4 * sizeof(int));
1745 if (src
->changed
.ps_const_b
) {
1746 uint16_t m
= src
->changed
.ps_const_b
;
1747 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
1749 context
->ps_const_b
[i
] = src
->ps_const_b
[i
];
1751 context
->changed
.ps_const_f
= !!src
->changed
.ps_const_f
;
1752 context
->changed
.ps_const_i
= !!src
->changed
.ps_const_i
;
1753 context
->changed
.ps_const_b
= !!src
->changed
.ps_const_b
;
1757 if (src
->changed
.group
& NINE_STATE_VIEWPORT
)
1758 context
->viewport
= src
->viewport
;
1761 if (src
->changed
.group
& NINE_STATE_SCISSOR
)
1762 context
->scissor
= src
->scissor
;
1764 /* User Clip Planes */
1765 if (src
->changed
.ucp
) {
1766 for (i
= 0; i
< PIPE_MAX_CLIP_PLANES
; ++i
)
1767 if (src
->changed
.ucp
& (1 << i
))
1768 memcpy(context
->clip
.ucp
[i
],
1769 src
->clip
.ucp
[i
], sizeof(src
->clip
.ucp
[0]));
1770 context
->changed
.ucp
= TRUE
;
1773 if (!(src
->changed
.group
& NINE_STATE_FF
))
1776 /* Fixed function state. */
1778 if (src
->changed
.group
& NINE_STATE_FF_MATERIAL
)
1779 context
->ff
.material
= src
->ff
.material
;
1781 if (src
->changed
.group
& NINE_STATE_FF_PSSTAGES
) {
1783 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
1784 for (i
= 0; i
< NINED3DTSS_COUNT
; ++i
)
1785 if (src
->ff
.changed
.tex_stage
[s
][i
/ 32] & (1 << (i
% 32)))
1786 context
->ff
.tex_stage
[s
][i
] = src
->ff
.tex_stage
[s
][i
];
1789 if (src
->changed
.group
& NINE_STATE_FF_LIGHTING
) {
1790 unsigned num_lights
= MAX2(context
->ff
.num_lights
, src
->ff
.num_lights
);
1791 /* Can happen if the stateblock had recorded the creation of
1793 if (context
->ff
.num_lights
< num_lights
) {
1794 context
->ff
.light
= REALLOC(context
->ff
.light
,
1795 context
->ff
.num_lights
* sizeof(D3DLIGHT9
),
1796 num_lights
* sizeof(D3DLIGHT9
));
1797 memset(&context
->ff
.light
[context
->ff
.num_lights
], 0, (num_lights
- context
->ff
.num_lights
) * sizeof(D3DLIGHT9
));
1798 for (i
= context
->ff
.num_lights
; i
< num_lights
; ++i
)
1799 context
->ff
.light
[i
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
1800 context
->ff
.num_lights
= num_lights
;
1802 /* src->ff.num_lights < num_lights has been handled before */
1803 assert (src
->ff
.num_lights
== num_lights
);
1805 for (i
= 0; i
< num_lights
; ++i
)
1806 if (src
->ff
.light
[i
].Type
!= NINED3DLIGHT_INVALID
)
1807 context
->ff
.light
[i
] = src
->ff
.light
[i
];
1809 memcpy(context
->ff
.active_light
, src
->ff
.active_light
, sizeof(src
->ff
.active_light
) );
1810 context
->ff
.num_lights_active
= src
->ff
.num_lights_active
;
1812 if (src
->changed
.group
& NINE_STATE_FF_VSTRANSF
) {
1813 for (i
= 0; i
< ARRAY_SIZE(src
->ff
.changed
.transform
); ++i
) {
1815 if (!src
->ff
.changed
.transform
[i
])
1817 for (s
= i
* 32; s
< (i
* 32 + 32); ++s
) {
1818 if (!(src
->ff
.changed
.transform
[i
] & (1 << (s
% 32))))
1820 *nine_state_access_transform(&context
->ff
, s
, TRUE
) =
1821 *nine_state_access_transform( /* const because !alloc */
1822 (struct nine_ff_state
*)&src
->ff
, s
, FALSE
);
1824 context
->ff
.changed
.transform
[i
] |= src
->ff
.changed
.transform
[i
];
1830 nine_update_state_framebuffer_clear(struct NineDevice9
*device
)
1832 struct nine_context
*context
= &device
->context
;
1834 validate_textures(device
);
1836 if (context
->changed
.group
& NINE_STATE_FB
)
1837 update_framebuffer(device
, TRUE
);
1840 /* Checks were already done before the call */
1842 nine_context_clear_fb(struct NineDevice9
*device
,
1844 const D3DRECT
*pRects
,
1850 struct nine_context
*context
= &device
->context
;
1851 const int sRGB
= context
->rs
[D3DRS_SRGBWRITEENABLE
] ? 1 : 0;
1852 struct pipe_surface
*cbuf
, *zsbuf
;
1853 struct pipe_context
*pipe
= device
->pipe
;
1854 struct NineSurface9
*zsbuf_surf
= context
->ds
;
1855 struct NineSurface9
*rt
;
1858 union pipe_color_union rgba
;
1859 unsigned rt_mask
= 0;
1862 nine_update_state_framebuffer_clear(device
);
1864 if (Flags
& D3DCLEAR_TARGET
) bufs
|= PIPE_CLEAR_COLOR
;
1865 /* Ignore Z buffer if not bound */
1866 if (context
->pipe_data
.fb
.zsbuf
!= NULL
) {
1867 if (Flags
& D3DCLEAR_ZBUFFER
) bufs
|= PIPE_CLEAR_DEPTH
;
1868 if (Flags
& D3DCLEAR_STENCIL
) bufs
|= PIPE_CLEAR_STENCIL
;
1872 d3dcolor_to_pipe_color_union(&rgba
, Color
);
1874 rect
.x1
= context
->viewport
.X
;
1875 rect
.y1
= context
->viewport
.Y
;
1876 rect
.x2
= context
->viewport
.Width
+ rect
.x1
;
1877 rect
.y2
= context
->viewport
.Height
+ rect
.y1
;
1879 /* Both rectangles apply, which is weird, but that's D3D9. */
1880 if (context
->rs
[D3DRS_SCISSORTESTENABLE
]) {
1881 rect
.x1
= MAX2(rect
.x1
, context
->scissor
.minx
);
1882 rect
.y1
= MAX2(rect
.y1
, context
->scissor
.miny
);
1883 rect
.x2
= MIN2(rect
.x2
, context
->scissor
.maxx
);
1884 rect
.y2
= MIN2(rect
.y2
, context
->scissor
.maxy
);
1888 /* Maybe apps like to specify a large rect ? */
1889 if (pRects
[0].x1
<= rect
.x1
&& pRects
[0].x2
>= rect
.x2
&&
1890 pRects
[0].y1
<= rect
.y1
&& pRects
[0].y2
>= rect
.y2
) {
1891 DBG("First rect covers viewport.\n");
1897 if (rect
.x1
>= context
->pipe_data
.fb
.width
|| rect
.y1
>= context
->pipe_data
.fb
.height
)
1900 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
1901 if (context
->rt
[i
] && context
->rt
[i
]->desc
.Format
!= D3DFMT_NULL
)
1905 /* fast path, clears everything at once */
1907 (!(bufs
& PIPE_CLEAR_COLOR
) || (rt_mask
== context
->rt_mask
)) &&
1908 rect
.x1
== 0 && rect
.y1
== 0 &&
1909 /* Case we clear only render target. Check clear region vs rt. */
1910 ((!(bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
1911 rect
.x2
>= context
->pipe_data
.fb
.width
&&
1912 rect
.y2
>= context
->pipe_data
.fb
.height
) ||
1913 /* Case we clear depth buffer (and eventually rt too).
1914 * depth buffer size is always >= rt size. Compare to clear region */
1915 ((bufs
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)) &&
1916 rect
.x2
>= zsbuf_surf
->desc
.Width
&&
1917 rect
.y2
>= zsbuf_surf
->desc
.Height
))) {
1918 DBG("Clear fast path\n");
1919 pipe
->clear(pipe
, bufs
, &rgba
, Z
, Stencil
);
1928 for (i
= 0; i
< device
->caps
.NumSimultaneousRTs
; ++i
) {
1929 rt
= context
->rt
[i
];
1930 if (!rt
|| rt
->desc
.Format
== D3DFMT_NULL
||
1931 !(bufs
& PIPE_CLEAR_COLOR
))
1932 continue; /* save space, compiler should hoist this */
1933 cbuf
= NineSurface9_GetSurface(rt
, sRGB
);
1934 for (r
= 0; r
< Count
; ++r
) {
1935 /* Don't trust users to pass these in the right order. */
1936 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
1937 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
1938 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
1939 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
1941 /* Drop negative rectangles (like wine expects). */
1942 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
1943 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
1946 x1
= MAX2(x1
, rect
.x1
);
1947 y1
= MAX2(y1
, rect
.y1
);
1948 x2
= MIN3(x2
, rect
.x2
, rt
->desc
.Width
);
1949 y2
= MIN3(y2
, rect
.y2
, rt
->desc
.Height
);
1951 DBG("Clearing (%u..%u)x(%u..%u)\n", x1
, x2
, y1
, y2
);
1952 pipe
->clear_render_target(pipe
, cbuf
, &rgba
,
1953 x1
, y1
, x2
- x1
, y2
- y1
, false);
1956 if (!(bufs
& PIPE_CLEAR_DEPTHSTENCIL
))
1959 bufs
&= PIPE_CLEAR_DEPTHSTENCIL
;
1961 for (r
= 0; r
< Count
; ++r
) {
1962 unsigned x1
= MIN2(pRects
[r
].x1
, pRects
[r
].x2
);
1963 unsigned y1
= MIN2(pRects
[r
].y1
, pRects
[r
].y2
);
1964 unsigned x2
= MAX2(pRects
[r
].x1
, pRects
[r
].x2
);
1965 unsigned y2
= MAX2(pRects
[r
].y1
, pRects
[r
].y2
);
1967 /* Drop negative rectangles. */
1968 if (pRects
[r
].x1
> pRects
[r
].x2
) continue;
1969 if (pRects
[r
].y1
> pRects
[r
].y2
) continue;
1972 x1
= MIN2(x1
, rect
.x1
);
1973 y1
= MIN2(y1
, rect
.y1
);
1974 x2
= MIN3(x2
, rect
.x2
, zsbuf_surf
->desc
.Width
);
1975 y2
= MIN3(y2
, rect
.y2
, zsbuf_surf
->desc
.Height
);
1977 zsbuf
= NineSurface9_GetSurface(zsbuf_surf
, 0);
1979 pipe
->clear_depth_stencil(pipe
, zsbuf
, bufs
, Z
, Stencil
,
1980 x1
, y1
, x2
- x1
, y2
- y1
, false);
1987 init_draw_info(struct pipe_draw_info
*info
,
1988 struct NineDevice9
*dev
, D3DPRIMITIVETYPE type
, UINT count
)
1990 info
->mode
= d3dprimitivetype_to_pipe_prim(type
);
1991 info
->count
= prim_count_to_vertex_count(type
, count
);
1992 info
->start_instance
= 0;
1993 info
->instance_count
= 1;
1994 if (dev
->context
.stream_instancedata_mask
& dev
->context
.stream_usage_mask
)
1995 info
->instance_count
= MAX2(dev
->context
.stream_freq
[0] & 0x7FFFFF, 1);
1996 info
->primitive_restart
= FALSE
;
1997 info
->restart_index
= 0;
1998 info
->count_from_stream_output
= NULL
;
1999 info
->indirect
= NULL
;
2000 info
->indirect_params
= NULL
;
2004 nine_context_draw_primitive(struct NineDevice9
*device
,
2005 D3DPRIMITIVETYPE PrimitiveType
,
2007 UINT PrimitiveCount
)
2009 struct pipe_draw_info info
;
2011 nine_update_state(device
);
2013 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2014 info
.indexed
= FALSE
;
2015 info
.start
= StartVertex
;
2016 info
.index_bias
= 0;
2017 info
.min_index
= info
.start
;
2018 info
.max_index
= info
.count
- 1;
2020 device
->pipe
->draw_vbo(device
->pipe
, &info
);
2024 nine_context_draw_indexed_primitive(struct NineDevice9
*device
,
2025 D3DPRIMITIVETYPE PrimitiveType
,
2026 INT BaseVertexIndex
,
2027 UINT MinVertexIndex
,
2030 UINT PrimitiveCount
)
2032 struct pipe_draw_info info
;
2034 nine_update_state(device
);
2036 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2037 info
.indexed
= TRUE
;
2038 info
.start
= StartIndex
;
2039 info
.index_bias
= BaseVertexIndex
;
2040 /* These don't include index bias: */
2041 info
.min_index
= MinVertexIndex
;
2042 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2044 device
->pipe
->draw_vbo(device
->pipe
, &info
);
2048 nine_context_draw_primitive_from_vtxbuf(struct NineDevice9
*device
,
2049 D3DPRIMITIVETYPE PrimitiveType
,
2050 UINT PrimitiveCount
,
2051 struct pipe_vertex_buffer
*vtxbuf
)
2053 struct pipe_draw_info info
;
2055 nine_update_state(device
);
2057 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2058 info
.indexed
= FALSE
;
2060 info
.index_bias
= 0;
2062 info
.max_index
= info
.count
- 1;
2064 device
->pipe
->set_vertex_buffers(device
->pipe
, 0, 1, vtxbuf
);
2066 device
->pipe
->draw_vbo(device
->pipe
, &info
);
2070 nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(struct NineDevice9
*device
,
2071 D3DPRIMITIVETYPE PrimitiveType
,
2072 UINT MinVertexIndex
,
2074 UINT PrimitiveCount
,
2075 struct pipe_vertex_buffer
*vbuf
,
2076 struct pipe_index_buffer
*ibuf
)
2078 struct pipe_draw_info info
;
2080 nine_update_state(device
);
2082 init_draw_info(&info
, device
, PrimitiveType
, PrimitiveCount
);
2083 info
.indexed
= TRUE
;
2085 info
.index_bias
= 0;
2086 info
.min_index
= MinVertexIndex
;
2087 info
.max_index
= MinVertexIndex
+ NumVertices
- 1;
2088 device
->pipe
->set_vertex_buffers(device
->pipe
, 0, 1, vbuf
);
2089 device
->pipe
->set_index_buffer(device
->pipe
, ibuf
);
2091 device
->pipe
->draw_vbo(device
->pipe
, &info
);
2095 nine_context_create_query(struct NineDevice9
*device
, unsigned query_type
)
2097 return device
->pipe
->create_query(device
->pipe
, query_type
, 0);
2101 nine_context_destroy_query(struct NineDevice9
*device
, struct pipe_query
*query
)
2103 device
->pipe
->destroy_query(device
->pipe
, query
);
2107 nine_context_begin_query(struct NineDevice9
*device
, struct pipe_query
*query
)
2109 (void) device
->pipe
->begin_query(device
->pipe
, query
);
2113 nine_context_end_query(struct NineDevice9
*device
, struct pipe_query
*query
)
2115 (void) device
->pipe
->end_query(device
->pipe
, query
);
2119 nine_context_get_query_result(struct NineDevice9
*device
, struct pipe_query
*query
,
2120 boolean flush
, boolean wait
,
2121 union pipe_query_result
*result
)
2124 return device
->pipe
->get_query_result(device
->pipe
, query
, wait
, result
);
2127 /* State defaults */
2129 static const DWORD nine_render_state_defaults
[NINED3DRS_LAST
+ 1] =
2131 /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */
2132 [D3DRS_ZENABLE
] = D3DZB_FALSE
,
2133 [D3DRS_FILLMODE
] = D3DFILL_SOLID
,
2134 [D3DRS_SHADEMODE
] = D3DSHADE_GOURAUD
,
2135 /* [D3DRS_LINEPATTERN] = 0x00000000, */
2136 [D3DRS_ZWRITEENABLE
] = TRUE
,
2137 [D3DRS_ALPHATESTENABLE
] = FALSE
,
2138 [D3DRS_LASTPIXEL
] = TRUE
,
2139 [D3DRS_SRCBLEND
] = D3DBLEND_ONE
,
2140 [D3DRS_DESTBLEND
] = D3DBLEND_ZERO
,
2141 [D3DRS_CULLMODE
] = D3DCULL_CCW
,
2142 [D3DRS_ZFUNC
] = D3DCMP_LESSEQUAL
,
2143 [D3DRS_ALPHAFUNC
] = D3DCMP_ALWAYS
,
2144 [D3DRS_ALPHAREF
] = 0,
2145 [D3DRS_DITHERENABLE
] = FALSE
,
2146 [D3DRS_ALPHABLENDENABLE
] = FALSE
,
2147 [D3DRS_FOGENABLE
] = FALSE
,
2148 [D3DRS_SPECULARENABLE
] = FALSE
,
2149 /* [D3DRS_ZVISIBLE] = 0, */
2150 [D3DRS_FOGCOLOR
] = 0,
2151 [D3DRS_FOGTABLEMODE
] = D3DFOG_NONE
,
2152 [D3DRS_FOGSTART
] = 0x00000000,
2153 [D3DRS_FOGEND
] = 0x3F800000,
2154 [D3DRS_FOGDENSITY
] = 0x3F800000,
2155 /* [D3DRS_EDGEANTIALIAS] = FALSE, */
2156 [D3DRS_RANGEFOGENABLE
] = FALSE
,
2157 [D3DRS_STENCILENABLE
] = FALSE
,
2158 [D3DRS_STENCILFAIL
] = D3DSTENCILOP_KEEP
,
2159 [D3DRS_STENCILZFAIL
] = D3DSTENCILOP_KEEP
,
2160 [D3DRS_STENCILPASS
] = D3DSTENCILOP_KEEP
,
2161 [D3DRS_STENCILREF
] = 0,
2162 [D3DRS_STENCILMASK
] = 0xFFFFFFFF,
2163 [D3DRS_STENCILFUNC
] = D3DCMP_ALWAYS
,
2164 [D3DRS_STENCILWRITEMASK
] = 0xFFFFFFFF,
2165 [D3DRS_TEXTUREFACTOR
] = 0xFFFFFFFF,
2174 [D3DRS_CLIPPING
] = TRUE
,
2175 [D3DRS_LIGHTING
] = TRUE
,
2176 [D3DRS_AMBIENT
] = 0,
2177 [D3DRS_FOGVERTEXMODE
] = D3DFOG_NONE
,
2178 [D3DRS_COLORVERTEX
] = TRUE
,
2179 [D3DRS_LOCALVIEWER
] = TRUE
,
2180 [D3DRS_NORMALIZENORMALS
] = FALSE
,
2181 [D3DRS_DIFFUSEMATERIALSOURCE
] = D3DMCS_COLOR1
,
2182 [D3DRS_SPECULARMATERIALSOURCE
] = D3DMCS_COLOR2
,
2183 [D3DRS_AMBIENTMATERIALSOURCE
] = D3DMCS_MATERIAL
,
2184 [D3DRS_EMISSIVEMATERIALSOURCE
] = D3DMCS_MATERIAL
,
2185 [D3DRS_VERTEXBLEND
] = D3DVBF_DISABLE
,
2186 [D3DRS_CLIPPLANEENABLE
] = 0,
2187 /* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */
2188 [D3DRS_POINTSIZE
] = 0x3F800000,
2189 [D3DRS_POINTSIZE_MIN
] = 0x3F800000,
2190 [D3DRS_POINTSPRITEENABLE
] = FALSE
,
2191 [D3DRS_POINTSCALEENABLE
] = FALSE
,
2192 [D3DRS_POINTSCALE_A
] = 0x3F800000,
2193 [D3DRS_POINTSCALE_B
] = 0x00000000,
2194 [D3DRS_POINTSCALE_C
] = 0x00000000,
2195 [D3DRS_MULTISAMPLEANTIALIAS
] = TRUE
,
2196 [D3DRS_MULTISAMPLEMASK
] = 0xFFFFFFFF,
2197 [D3DRS_PATCHEDGESTYLE
] = D3DPATCHEDGE_DISCRETE
,
2198 /* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */
2199 [D3DRS_DEBUGMONITORTOKEN
] = 0xDEADCAFE,
2200 [D3DRS_POINTSIZE_MAX
] = 0x3F800000, /* depends on cap */
2201 [D3DRS_INDEXEDVERTEXBLENDENABLE
] = FALSE
,
2202 [D3DRS_COLORWRITEENABLE
] = 0x0000000f,
2203 [D3DRS_TWEENFACTOR
] = 0x00000000,
2204 [D3DRS_BLENDOP
] = D3DBLENDOP_ADD
,
2205 [D3DRS_POSITIONDEGREE
] = D3DDEGREE_CUBIC
,
2206 [D3DRS_NORMALDEGREE
] = D3DDEGREE_LINEAR
,
2207 [D3DRS_SCISSORTESTENABLE
] = FALSE
,
2208 [D3DRS_SLOPESCALEDEPTHBIAS
] = 0,
2209 [D3DRS_MINTESSELLATIONLEVEL
] = 0x3F800000,
2210 [D3DRS_MAXTESSELLATIONLEVEL
] = 0x3F800000,
2211 [D3DRS_ANTIALIASEDLINEENABLE
] = FALSE
,
2212 [D3DRS_ADAPTIVETESS_X
] = 0x00000000,
2213 [D3DRS_ADAPTIVETESS_Y
] = 0x00000000,
2214 [D3DRS_ADAPTIVETESS_Z
] = 0x3F800000,
2215 [D3DRS_ADAPTIVETESS_W
] = 0x00000000,
2216 [D3DRS_ENABLEADAPTIVETESSELLATION
] = FALSE
,
2217 [D3DRS_TWOSIDEDSTENCILMODE
] = FALSE
,
2218 [D3DRS_CCW_STENCILFAIL
] = D3DSTENCILOP_KEEP
,
2219 [D3DRS_CCW_STENCILZFAIL
] = D3DSTENCILOP_KEEP
,
2220 [D3DRS_CCW_STENCILPASS
] = D3DSTENCILOP_KEEP
,
2221 [D3DRS_CCW_STENCILFUNC
] = D3DCMP_ALWAYS
,
2222 [D3DRS_COLORWRITEENABLE1
] = 0x0000000F,
2223 [D3DRS_COLORWRITEENABLE2
] = 0x0000000F,
2224 [D3DRS_COLORWRITEENABLE3
] = 0x0000000F,
2225 [D3DRS_BLENDFACTOR
] = 0xFFFFFFFF,
2226 [D3DRS_SRGBWRITEENABLE
] = 0,
2227 [D3DRS_DEPTHBIAS
] = 0,
2236 [D3DRS_SEPARATEALPHABLENDENABLE
] = FALSE
,
2237 [D3DRS_SRCBLENDALPHA
] = D3DBLEND_ONE
,
2238 [D3DRS_DESTBLENDALPHA
] = D3DBLEND_ZERO
,
2239 [D3DRS_BLENDOPALPHA
] = D3DBLENDOP_ADD
,
2240 [NINED3DRS_VSPOINTSIZE
] = FALSE
,
2241 [NINED3DRS_RTMASK
] = 0xf,
2242 [NINED3DRS_ALPHACOVERAGE
] = FALSE
,
2243 [NINED3DRS_MULTISAMPLE
] = FALSE
2245 static const DWORD nine_tex_stage_state_defaults
[NINED3DTSS_LAST
+ 1] =
2247 [D3DTSS_COLOROP
] = D3DTOP_DISABLE
,
2248 [D3DTSS_ALPHAOP
] = D3DTOP_DISABLE
,
2249 [D3DTSS_COLORARG1
] = D3DTA_TEXTURE
,
2250 [D3DTSS_COLORARG2
] = D3DTA_CURRENT
,
2251 [D3DTSS_COLORARG0
] = D3DTA_CURRENT
,
2252 [D3DTSS_ALPHAARG1
] = D3DTA_TEXTURE
,
2253 [D3DTSS_ALPHAARG2
] = D3DTA_CURRENT
,
2254 [D3DTSS_ALPHAARG0
] = D3DTA_CURRENT
,
2255 [D3DTSS_RESULTARG
] = D3DTA_CURRENT
,
2256 [D3DTSS_BUMPENVMAT00
] = 0,
2257 [D3DTSS_BUMPENVMAT01
] = 0,
2258 [D3DTSS_BUMPENVMAT10
] = 0,
2259 [D3DTSS_BUMPENVMAT11
] = 0,
2260 [D3DTSS_BUMPENVLSCALE
] = 0,
2261 [D3DTSS_BUMPENVLOFFSET
] = 0,
2262 [D3DTSS_TEXCOORDINDEX
] = 0,
2263 [D3DTSS_TEXTURETRANSFORMFLAGS
] = D3DTTFF_DISABLE
,
2265 static const DWORD nine_samp_state_defaults
[NINED3DSAMP_LAST
+ 1] =
2267 [D3DSAMP_ADDRESSU
] = D3DTADDRESS_WRAP
,
2268 [D3DSAMP_ADDRESSV
] = D3DTADDRESS_WRAP
,
2269 [D3DSAMP_ADDRESSW
] = D3DTADDRESS_WRAP
,
2270 [D3DSAMP_BORDERCOLOR
] = 0,
2271 [D3DSAMP_MAGFILTER
] = D3DTEXF_POINT
,
2272 [D3DSAMP_MINFILTER
] = D3DTEXF_POINT
,
2273 [D3DSAMP_MIPFILTER
] = D3DTEXF_NONE
,
2274 [D3DSAMP_MIPMAPLODBIAS
] = 0,
2275 [D3DSAMP_MAXMIPLEVEL
] = 0,
2276 [D3DSAMP_MAXANISOTROPY
] = 1,
2277 [D3DSAMP_SRGBTEXTURE
] = 0,
2278 [D3DSAMP_ELEMENTINDEX
] = 0,
2279 [D3DSAMP_DMAPOFFSET
] = 0,
2280 [NINED3DSAMP_MINLOD
] = 0,
2281 [NINED3DSAMP_SHADOW
] = 0,
2282 [NINED3DSAMP_CUBETEX
] = 0
2285 void nine_state_restore_non_cso(struct NineDevice9
*device
)
2287 struct nine_context
*context
= &device
->context
;
2289 context
->changed
.group
= NINE_STATE_ALL
;
2290 context
->changed
.vtxbuf
= (1ULL << device
->caps
.MaxStreams
) - 1;
2291 context
->changed
.ucp
= TRUE
;
2292 context
->commit
|= NINE_STATE_COMMIT_CONST_VS
| NINE_STATE_COMMIT_CONST_PS
;
2296 nine_state_set_defaults(struct NineDevice9
*device
, const D3DCAPS9
*caps
,
2299 struct nine_state
*state
= &device
->state
;
2300 struct nine_context
*context
= &device
->context
;
2303 /* Initialize defaults.
2305 memcpy(context
->rs
, nine_render_state_defaults
, sizeof(context
->rs
));
2307 for (s
= 0; s
< ARRAY_SIZE(state
->ff
.tex_stage
); ++s
) {
2308 memcpy(&state
->ff
.tex_stage
[s
], nine_tex_stage_state_defaults
,
2309 sizeof(state
->ff
.tex_stage
[s
]));
2310 state
->ff
.tex_stage
[s
][D3DTSS_TEXCOORDINDEX
] = s
;
2312 state
->ff
.tex_stage
[0][D3DTSS_COLOROP
] = D3DTOP_MODULATE
;
2313 state
->ff
.tex_stage
[0][D3DTSS_ALPHAOP
] = D3DTOP_SELECTARG1
;
2315 for (s
= 0; s
< ARRAY_SIZE(state
->ff
.tex_stage
); ++s
)
2316 memcpy(&context
->ff
.tex_stage
[s
], state
->ff
.tex_stage
[s
],
2317 sizeof(state
->ff
.tex_stage
[s
]));
2319 memset(&context
->bumpmap_vars
, 0, sizeof(context
->bumpmap_vars
));
2321 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
2322 memcpy(&context
->samp
[s
], nine_samp_state_defaults
,
2323 sizeof(context
->samp
[s
]));
2324 memcpy(&state
->samp_advertised
[s
], nine_samp_state_defaults
,
2325 sizeof(state
->samp_advertised
[s
]));
2328 memset(state
->vs_const_f
, 0, VS_CONST_F_SIZE(device
));
2329 memset(context
->vs_const_f
, 0, device
->vs_const_size
);
2330 if (context
->vs_const_f_swvp
)
2331 memset(context
->vs_const_f_swvp
, 0, NINE_MAX_CONST_F_SWVP
* sizeof(float[4]));
2332 memset(state
->vs_const_i
, 0, VS_CONST_I_SIZE(device
));
2333 memset(context
->vs_const_i
, 0, VS_CONST_I_SIZE(device
));
2334 memset(state
->vs_const_b
, 0, VS_CONST_B_SIZE(device
));
2335 memset(context
->vs_const_b
, 0, VS_CONST_B_SIZE(device
));
2336 memset(state
->ps_const_f
, 0, device
->ps_const_size
);
2337 memset(context
->ps_const_f
, 0, device
->ps_const_size
);
2338 memset(state
->ps_const_i
, 0, sizeof(state
->ps_const_i
));
2339 memset(context
->ps_const_i
, 0, sizeof(context
->ps_const_i
));
2340 memset(state
->ps_const_b
, 0, sizeof(state
->ps_const_b
));
2341 memset(context
->ps_const_b
, 0, sizeof(context
->ps_const_b
));
2343 /* Cap dependent initial state:
2345 context
->rs
[D3DRS_POINTSIZE_MAX
] = fui(caps
->MaxPointSize
);
2347 memcpy(state
->rs_advertised
, context
->rs
, sizeof(context
->rs
));
2349 /* Set changed flags to initialize driver.
2351 context
->changed
.group
= NINE_STATE_ALL
;
2352 context
->changed
.vtxbuf
= (1ULL << device
->caps
.MaxStreams
) - 1;
2353 context
->changed
.ucp
= TRUE
;
2355 context
->ff
.changed
.transform
[0] = ~0;
2356 context
->ff
.changed
.transform
[D3DTS_WORLD
/ 32] |= 1 << (D3DTS_WORLD
% 32);
2359 state
->viewport
.MinZ
= context
->viewport
.MinZ
= 0.0f
;
2360 state
->viewport
.MaxZ
= context
->viewport
.MaxZ
= 1.0f
;
2363 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
)
2364 context
->changed
.sampler
[s
] = ~0;
2367 context
->dummy_vbo_bound_at
= -1;
2368 context
->vbo_bound_done
= FALSE
;
2373 nine_state_clear(struct nine_state
*state
, const boolean device
)
2377 for (i
= 0; i
< ARRAY_SIZE(state
->rt
); ++i
)
2378 nine_bind(&state
->rt
[i
], NULL
);
2379 nine_bind(&state
->ds
, NULL
);
2380 nine_bind(&state
->vs
, NULL
);
2381 nine_bind(&state
->ps
, NULL
);
2382 nine_bind(&state
->vdecl
, NULL
);
2383 for (i
= 0; i
< PIPE_MAX_ATTRIBS
; ++i
)
2384 nine_bind(&state
->stream
[i
], NULL
);
2386 nine_bind(&state
->idxbuf
, NULL
);
2387 for (i
= 0; i
< NINE_MAX_SAMPLERS
; ++i
) {
2389 state
->texture
[i
] &&
2390 --state
->texture
[i
]->bind_count
== 0)
2391 list_delinit(&state
->texture
[i
]->list
);
2392 nine_bind(&state
->texture
[i
], NULL
);
2397 nine_context_clear(struct nine_context
*context
)
2401 for (i
= 0; i
< ARRAY_SIZE(context
->rt
); ++i
)
2402 nine_bind(&context
->rt
[i
], NULL
);
2403 nine_bind(&context
->ds
, NULL
);
2404 nine_bind(&context
->vs
, NULL
);
2405 nine_bind(&context
->ps
, NULL
);
2406 nine_bind(&context
->vdecl
, NULL
);
2407 for (i
= 0; i
< PIPE_MAX_ATTRIBS
; ++i
)
2408 pipe_resource_reference(&context
->vtxbuf
[i
].buffer
, NULL
);
2409 pipe_resource_reference(&context
->idxbuf
.buffer
, NULL
);
2411 for (i
= 0; i
< NINE_MAX_SAMPLERS
; ++i
)
2412 nine_bind(&context
->texture
[i
], NULL
);
2416 nine_state_init_sw(struct NineDevice9
*device
)
2418 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
2419 struct pipe_rasterizer_state rast
;
2420 struct pipe_blend_state blend
;
2421 struct pipe_depth_stencil_alpha_state dsa
;
2422 struct pipe_framebuffer_state fb
;
2424 /* Only used with Streamout */
2425 memset(&rast
, 0, sizeof(rast
));
2426 rast
.rasterizer_discard
= true;
2427 rast
.point_quad_rasterization
= 1; /* to make llvmpipe happy */
2428 cso_set_rasterizer(device
->cso_sw
, &rast
);
2430 /* dummy settings */
2431 memset(&blend
, 0, sizeof(blend
));
2432 memset(&dsa
, 0, sizeof(dsa
));
2433 memset(&fb
, 0, sizeof(fb
));
2434 cso_set_blend(device
->cso_sw
, &blend
);
2435 cso_set_depth_stencil_alpha(device
->cso_sw
, &dsa
);
2436 cso_set_framebuffer(device
->cso_sw
, &fb
);
2437 cso_set_viewport_dims(device
->cso_sw
, 1.0, 1.0, false);
2438 cso_set_fragment_shader_handle(device
->cso_sw
, util_make_empty_fragment_shader(pipe_sw
));
2441 /* There is duplication with update_vertex_elements.
2442 * TODO: Share the code */
2445 update_vertex_elements_sw(struct NineDevice9
*device
)
2447 struct nine_state
*state
= &device
->state
;
2448 const struct NineVertexDeclaration9
*vdecl
= device
->state
.vdecl
;
2449 const struct NineVertexShader9
*vs
;
2452 char vdecl_index_map
[16]; /* vs->num_inputs <= 16 */
2453 char used_streams
[device
->caps
.MaxStreams
];
2454 int dummy_vbo_stream
= -1;
2455 BOOL need_dummy_vbo
= FALSE
;
2456 struct pipe_vertex_element ve
[PIPE_MAX_ATTRIBS
];
2457 bool programmable_vs
= state
->vs
&& !(state
->vdecl
&& state
->vdecl
->position_t
);
2459 memset(vdecl_index_map
, -1, 16);
2460 memset(used_streams
, 0, device
->caps
.MaxStreams
);
2461 vs
= programmable_vs
? device
->state
.vs
: device
->ff
.vs
;
2464 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
2465 DBG("looking up input %u (usage %u) from vdecl(%p)\n",
2466 n
, vs
->input_map
[n
].ndecl
, vdecl
);
2468 for (i
= 0; i
< vdecl
->nelems
; i
++) {
2469 if (vdecl
->usage_map
[i
] == vs
->input_map
[n
].ndecl
) {
2470 vdecl_index_map
[n
] = i
;
2471 used_streams
[vdecl
->elems
[i
].vertex_buffer_index
] = 1;
2475 if (vdecl_index_map
[n
] < 0)
2476 need_dummy_vbo
= TRUE
;
2479 /* No vertex declaration. Likely will never happen in practice,
2480 * but we need not crash on this */
2481 need_dummy_vbo
= TRUE
;
2484 if (need_dummy_vbo
) {
2485 for (i
= 0; i
< device
->caps
.MaxStreams
; i
++ ) {
2486 if (!used_streams
[i
]) {
2487 dummy_vbo_stream
= i
;
2492 /* TODO handle dummy_vbo */
2493 assert (!need_dummy_vbo
);
2495 for (n
= 0; n
< vs
->num_inputs
; ++n
) {
2496 index
= vdecl_index_map
[n
];
2498 ve
[n
] = vdecl
->elems
[index
];
2499 b
= ve
[n
].vertex_buffer_index
;
2500 /* XXX wine just uses 1 here: */
2501 if (state
->stream_freq
[b
] & D3DSTREAMSOURCE_INSTANCEDATA
)
2502 ve
[n
].instance_divisor
= state
->stream_freq
[b
] & 0x7FFFFF;
2504 /* if the vertex declaration is incomplete compared to what the
2505 * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
2506 * This is not precised by the spec, but is the behaviour
2508 ve
[n
].vertex_buffer_index
= dummy_vbo_stream
;
2509 ve
[n
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
2510 ve
[n
].src_offset
= 0;
2511 ve
[n
].instance_divisor
= 0;
2515 cso_set_vertex_elements(device
->cso_sw
, vs
->num_inputs
, ve
);
2519 update_vertex_buffers_sw(struct NineDevice9
*device
, int start_vertice
, int num_vertices
)
2521 struct pipe_context
*pipe
= device
->pipe
;
2522 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
2523 struct nine_state
*state
= &device
->state
;
2524 struct nine_state_sw_internal
*sw_internal
= &device
->state_sw_internal
;
2525 struct pipe_vertex_buffer vtxbuf
;
2526 uint32_t mask
= 0xf;
2529 DBG("mask=%x\n", mask
);
2531 /* TODO: handle dummy_vbo_bound_at */
2533 for (i
= 0; mask
; mask
>>= 1, ++i
) {
2535 if (state
->stream
[i
]) {
2536 struct pipe_resource
*buf
;
2537 struct pipe_box box
;
2539 vtxbuf
= state
->vtxbuf
[i
];
2540 vtxbuf
.buffer
= NineVertexBuffer9_GetResource(state
->stream
[i
]);
2542 DBG("Locking %p (offset %d, length %d)\n", vtxbuf
.buffer
,
2543 vtxbuf
.buffer_offset
, num_vertices
* vtxbuf
.stride
);
2545 u_box_1d(vtxbuf
.buffer_offset
+ start_vertice
* vtxbuf
.stride
,
2546 num_vertices
* vtxbuf
.stride
, &box
);
2547 buf
= vtxbuf
.buffer
;
2548 vtxbuf
.user_buffer
= pipe
->transfer_map(pipe
, buf
, 0, PIPE_TRANSFER_READ
, &box
,
2549 &(sw_internal
->transfers_so
[i
]));
2550 vtxbuf
.buffer
= NULL
;
2551 if (!device
->driver_caps
.user_sw_vbufs
) {
2552 u_upload_data(device
->vertex_sw_uploader
,
2557 &(vtxbuf
.buffer_offset
),
2559 u_upload_unmap(device
->vertex_sw_uploader
);
2560 vtxbuf
.user_buffer
= NULL
;
2562 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, &vtxbuf
);
2564 pipe_resource_reference(&vtxbuf
.buffer
, NULL
);
2566 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, NULL
);
2572 update_vs_constants_sw(struct NineDevice9
*device
)
2574 struct nine_state
*state
= &device
->state
;
2575 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
2580 struct pipe_constant_buffer cb
;
2584 cb
.buffer_offset
= 0;
2585 cb
.buffer_size
= 4096 * sizeof(float[4]);
2586 cb
.user_buffer
= state
->vs_const_f
;
2588 if (state
->vs
->lconstf
.ranges
) {
2589 const struct nine_lconstf
*lconstf
= &device
->state
.vs
->lconstf
;
2590 const struct nine_range
*r
= lconstf
->ranges
;
2592 float *dst
= device
->state
.vs_lconstf_temp
;
2593 float *src
= (float *)cb
.user_buffer
;
2594 memcpy(dst
, src
, 8192 * sizeof(float[4]));
2596 unsigned p
= r
->bgn
;
2597 unsigned c
= r
->end
- r
->bgn
;
2598 memcpy(&dst
[p
* 4], &lconstf
->data
[n
* 4], c
* 4 * sizeof(float));
2602 cb
.user_buffer
= dst
;
2605 buf
= cb
.user_buffer
;
2606 if (!device
->driver_caps
.user_sw_cbufs
) {
2607 u_upload_data(device
->constbuf_sw_uploader
,
2612 &(cb
.buffer_offset
),
2614 u_upload_unmap(device
->constbuf_sw_uploader
);
2615 cb
.user_buffer
= NULL
;
2618 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 0, &cb
);
2620 pipe_resource_reference(&cb
.buffer
, NULL
);
2622 cb
.user_buffer
= (char *)buf
+ 4096 * sizeof(float[4]);
2623 if (!device
->driver_caps
.user_sw_cbufs
) {
2624 u_upload_data(device
->constbuf_sw_uploader
,
2629 &(cb
.buffer_offset
),
2631 u_upload_unmap(device
->constbuf_sw_uploader
);
2632 cb
.user_buffer
= NULL
;
2635 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 1, &cb
);
2637 pipe_resource_reference(&cb
.buffer
, NULL
);
2641 struct pipe_constant_buffer cb
;
2644 cb
.buffer_offset
= 0;
2645 cb
.buffer_size
= 2048 * sizeof(float[4]);
2646 cb
.user_buffer
= state
->vs_const_i
;
2648 if (!device
->driver_caps
.user_sw_cbufs
) {
2649 u_upload_data(device
->constbuf_sw_uploader
,
2654 &(cb
.buffer_offset
),
2656 u_upload_unmap(device
->constbuf_sw_uploader
);
2657 cb
.user_buffer
= NULL
;
2660 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 2, &cb
);
2662 pipe_resource_reference(&cb
.buffer
, NULL
);
2666 struct pipe_constant_buffer cb
;
2669 cb
.buffer_offset
= 0;
2670 cb
.buffer_size
= 512 * sizeof(float[4]);
2671 cb
.user_buffer
= state
->vs_const_b
;
2673 if (!device
->driver_caps
.user_sw_cbufs
) {
2674 u_upload_data(device
->constbuf_sw_uploader
,
2679 &(cb
.buffer_offset
),
2681 u_upload_unmap(device
->constbuf_sw_uploader
);
2682 cb
.user_buffer
= NULL
;
2685 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 3, &cb
);
2687 pipe_resource_reference(&cb
.buffer
, NULL
);
2691 struct pipe_constant_buffer cb
;
2692 const D3DVIEWPORT9
*vport
= &device
->state
.viewport
;
2693 float viewport_data
[8] = {(float)vport
->Width
* 0.5f
,
2694 (float)vport
->Height
* -0.5f
, vport
->MaxZ
- vport
->MinZ
, 0.f
,
2695 (float)vport
->Width
* 0.5f
+ (float)vport
->X
,
2696 (float)vport
->Height
* 0.5f
+ (float)vport
->Y
,
2700 cb
.buffer_offset
= 0;
2701 cb
.buffer_size
= 2 * sizeof(float[4]);
2702 cb
.user_buffer
= viewport_data
;
2705 u_upload_data(device
->constbuf_sw_uploader
,
2710 &(cb
.buffer_offset
),
2712 u_upload_unmap(device
->constbuf_sw_uploader
);
2713 cb
.user_buffer
= NULL
;
2716 pipe_sw
->set_constant_buffer(pipe_sw
, PIPE_SHADER_VERTEX
, 4, &cb
);
2718 pipe_resource_reference(&cb
.buffer
, NULL
);
2724 nine_state_prepare_draw_sw(struct NineDevice9
*device
, struct NineVertexDeclaration9
*vdecl_out
,
2725 int start_vertice
, int num_vertices
, struct pipe_stream_output_info
*so
)
2727 struct nine_state
*state
= &device
->state
;
2728 bool programmable_vs
= state
->vs
&& !(state
->vdecl
&& state
->vdecl
->position_t
);
2729 struct NineVertexShader9
*vs
= programmable_vs
? device
->state
.vs
: device
->ff
.vs
;
2731 assert(programmable_vs
);
2733 DBG("Preparing draw\n");
2734 cso_set_vertex_shader_handle(device
->cso_sw
,
2735 NineVertexShader9_GetVariantProcessVertices(vs
, vdecl_out
, so
));
2736 update_vertex_elements_sw(device
);
2737 update_vertex_buffers_sw(device
, start_vertice
, num_vertices
);
2738 update_vs_constants_sw(device
);
2739 DBG("Preparation succeeded\n");
2743 nine_state_after_draw_sw(struct NineDevice9
*device
)
2745 struct nine_state_sw_internal
*sw_internal
= &device
->state_sw_internal
;
2746 struct pipe_context
*pipe
= device
->pipe
;
2747 struct pipe_context
*pipe_sw
= device
->pipe_sw
;
2750 for (i
= 0; i
< 4; i
++) {
2751 pipe_sw
->set_vertex_buffers(pipe_sw
, i
, 1, NULL
);
2752 if (sw_internal
->transfers_so
[i
])
2753 pipe
->transfer_unmap(pipe
, sw_internal
->transfers_so
[i
]);
2754 sw_internal
->transfers_so
[i
] = NULL
;
2759 nine_state_destroy_sw(struct NineDevice9
*device
)
2762 /* Everything destroyed with cso */
2766 static const DWORD nine_render_states_pixel[] =
2768 D3DRS_ALPHABLENDENABLE,
2771 D3DRS_ALPHATESTENABLE,
2772 D3DRS_ANTIALIASEDLINEENABLE,
2776 D3DRS_CCW_STENCILFAIL,
2777 D3DRS_CCW_STENCILPASS,
2778 D3DRS_CCW_STENCILZFAIL,
2779 D3DRS_COLORWRITEENABLE,
2780 D3DRS_COLORWRITEENABLE1,
2781 D3DRS_COLORWRITEENABLE2,
2782 D3DRS_COLORWRITEENABLE3,
2785 D3DRS_DESTBLENDALPHA,
2792 D3DRS_SCISSORTESTENABLE,
2793 D3DRS_SEPARATEALPHABLENDENABLE,
2795 D3DRS_SLOPESCALEDEPTHBIAS,
2797 D3DRS_SRCBLENDALPHA,
2798 D3DRS_SRGBWRITEENABLE,
2799 D3DRS_STENCILENABLE,
2805 D3DRS_STENCILWRITEMASK,
2807 D3DRS_TEXTUREFACTOR,
2808 D3DRS_TWOSIDEDSTENCILMODE,
2830 const uint32_t nine_render_states_pixel
[(NINED3DRS_LAST
+ 31) / 32] =
2832 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000,
2833 0x000000ff, 0xde01c900, 0x0003ffcf
2837 static const DWORD nine_render_states_vertex[] =
2839 D3DRS_ADAPTIVETESS_W,
2840 D3DRS_ADAPTIVETESS_X,
2841 D3DRS_ADAPTIVETESS_Y,
2842 D3DRS_ADAPTIVETESS_Z,
2844 D3DRS_AMBIENTMATERIALSOURCE,
2846 D3DRS_CLIPPLANEENABLE,
2849 D3DRS_DIFFUSEMATERIALSOURCE,
2850 D3DRS_EMISSIVEMATERIALSOURCE,
2851 D3DRS_ENABLEADAPTIVETESSELLATION,
2858 D3DRS_FOGVERTEXMODE,
2859 D3DRS_INDEXEDVERTEXBLENDENABLE,
2862 D3DRS_MAXTESSELLATIONLEVEL,
2863 D3DRS_MINTESSELLATIONLEVEL,
2864 D3DRS_MULTISAMPLEANTIALIAS,
2865 D3DRS_MULTISAMPLEMASK,
2867 D3DRS_NORMALIZENORMALS,
2868 D3DRS_PATCHEDGESTYLE,
2872 D3DRS_POINTSCALEENABLE,
2874 D3DRS_POINTSIZE_MAX,
2875 D3DRS_POINTSIZE_MIN,
2876 D3DRS_POINTSPRITEENABLE,
2877 D3DRS_POSITIONDEGREE,
2878 D3DRS_RANGEFOGENABLE,
2880 D3DRS_SPECULARENABLE,
2881 D3DRS_SPECULARMATERIALSOURCE,
2886 const uint32_t nine_render_states_vertex
[(NINED3DRS_LAST
+ 31) / 32] =
2888 0x30400200, 0x0001007c, 0x00000000, 0x00000000,
2889 0xfd9efb00, 0x01fc34cf, 0x00000000
2892 /* TODO: put in the right values */
2893 const uint32_t nine_render_state_group
[NINED3DRS_LAST
+ 1] =
2895 [D3DRS_ZENABLE
] = NINE_STATE_DSA
| NINE_STATE_MULTISAMPLE
,
2896 [D3DRS_FILLMODE
] = NINE_STATE_RASTERIZER
,
2897 [D3DRS_SHADEMODE
] = NINE_STATE_RASTERIZER
,
2898 [D3DRS_ZWRITEENABLE
] = NINE_STATE_DSA
,
2899 [D3DRS_ALPHATESTENABLE
] = NINE_STATE_DSA
,
2900 [D3DRS_LASTPIXEL
] = NINE_STATE_RASTERIZER
,
2901 [D3DRS_SRCBLEND
] = NINE_STATE_BLEND
,
2902 [D3DRS_DESTBLEND
] = NINE_STATE_BLEND
,
2903 [D3DRS_CULLMODE
] = NINE_STATE_RASTERIZER
,
2904 [D3DRS_ZFUNC
] = NINE_STATE_DSA
,
2905 [D3DRS_ALPHAREF
] = NINE_STATE_DSA
,
2906 [D3DRS_ALPHAFUNC
] = NINE_STATE_DSA
,
2907 [D3DRS_DITHERENABLE
] = NINE_STATE_BLEND
,
2908 [D3DRS_ALPHABLENDENABLE
] = NINE_STATE_BLEND
,
2909 [D3DRS_FOGENABLE
] = NINE_STATE_FF_OTHER
| NINE_STATE_FOG_SHADER
| NINE_STATE_PS_CONST
,
2910 [D3DRS_SPECULARENABLE
] = NINE_STATE_FF_LIGHTING
,
2911 [D3DRS_FOGCOLOR
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
2912 [D3DRS_FOGTABLEMODE
] = NINE_STATE_FF_OTHER
| NINE_STATE_FOG_SHADER
| NINE_STATE_PS_CONST
,
2913 [D3DRS_FOGSTART
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
2914 [D3DRS_FOGEND
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
2915 [D3DRS_FOGDENSITY
] = NINE_STATE_FF_OTHER
| NINE_STATE_PS_CONST
,
2916 [D3DRS_RANGEFOGENABLE
] = NINE_STATE_FF_OTHER
,
2917 [D3DRS_STENCILENABLE
] = NINE_STATE_DSA
| NINE_STATE_MULTISAMPLE
,
2918 [D3DRS_STENCILFAIL
] = NINE_STATE_DSA
,
2919 [D3DRS_STENCILZFAIL
] = NINE_STATE_DSA
,
2920 [D3DRS_STENCILPASS
] = NINE_STATE_DSA
,
2921 [D3DRS_STENCILFUNC
] = NINE_STATE_DSA
,
2922 [D3DRS_STENCILREF
] = NINE_STATE_STENCIL_REF
,
2923 [D3DRS_STENCILMASK
] = NINE_STATE_DSA
,
2924 [D3DRS_STENCILWRITEMASK
] = NINE_STATE_DSA
,
2925 [D3DRS_TEXTUREFACTOR
] = NINE_STATE_FF_PSSTAGES
,
2926 [D3DRS_WRAP0
] = NINE_STATE_UNHANDLED
, /* cylindrical wrap is crazy */
2927 [D3DRS_WRAP1
] = NINE_STATE_UNHANDLED
,
2928 [D3DRS_WRAP2
] = NINE_STATE_UNHANDLED
,
2929 [D3DRS_WRAP3
] = NINE_STATE_UNHANDLED
,
2930 [D3DRS_WRAP4
] = NINE_STATE_UNHANDLED
,
2931 [D3DRS_WRAP5
] = NINE_STATE_UNHANDLED
,
2932 [D3DRS_WRAP6
] = NINE_STATE_UNHANDLED
,
2933 [D3DRS_WRAP7
] = NINE_STATE_UNHANDLED
,
2934 [D3DRS_CLIPPING
] = 0, /* software vertex processing only */
2935 [D3DRS_LIGHTING
] = NINE_STATE_FF_LIGHTING
,
2936 [D3DRS_AMBIENT
] = NINE_STATE_FF_LIGHTING
| NINE_STATE_FF_MATERIAL
,
2937 [D3DRS_FOGVERTEXMODE
] = NINE_STATE_FF_OTHER
,
2938 [D3DRS_COLORVERTEX
] = NINE_STATE_FF_LIGHTING
,
2939 [D3DRS_LOCALVIEWER
] = NINE_STATE_FF_LIGHTING
,
2940 [D3DRS_NORMALIZENORMALS
] = NINE_STATE_FF_OTHER
,
2941 [D3DRS_DIFFUSEMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
2942 [D3DRS_SPECULARMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
2943 [D3DRS_AMBIENTMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
2944 [D3DRS_EMISSIVEMATERIALSOURCE
] = NINE_STATE_FF_LIGHTING
,
2945 [D3DRS_VERTEXBLEND
] = NINE_STATE_FF_OTHER
,
2946 [D3DRS_CLIPPLANEENABLE
] = NINE_STATE_RASTERIZER
,
2947 [D3DRS_POINTSIZE
] = NINE_STATE_RASTERIZER
,
2948 [D3DRS_POINTSIZE_MIN
] = NINE_STATE_RASTERIZER
| NINE_STATE_POINTSIZE_SHADER
,
2949 [D3DRS_POINTSPRITEENABLE
] = NINE_STATE_RASTERIZER
,
2950 [D3DRS_POINTSCALEENABLE
] = NINE_STATE_FF_OTHER
,
2951 [D3DRS_POINTSCALE_A
] = NINE_STATE_FF_OTHER
,
2952 [D3DRS_POINTSCALE_B
] = NINE_STATE_FF_OTHER
,
2953 [D3DRS_POINTSCALE_C
] = NINE_STATE_FF_OTHER
,
2954 [D3DRS_MULTISAMPLEANTIALIAS
] = NINE_STATE_MULTISAMPLE
,
2955 [D3DRS_MULTISAMPLEMASK
] = NINE_STATE_SAMPLE_MASK
,
2956 [D3DRS_PATCHEDGESTYLE
] = NINE_STATE_UNHANDLED
,
2957 [D3DRS_DEBUGMONITORTOKEN
] = NINE_STATE_UNHANDLED
,
2958 [D3DRS_POINTSIZE_MAX
] = NINE_STATE_RASTERIZER
| NINE_STATE_POINTSIZE_SHADER
,
2959 [D3DRS_INDEXEDVERTEXBLENDENABLE
] = NINE_STATE_FF_OTHER
,
2960 [D3DRS_COLORWRITEENABLE
] = NINE_STATE_BLEND
,
2961 [D3DRS_TWEENFACTOR
] = NINE_STATE_FF_OTHER
,
2962 [D3DRS_BLENDOP
] = NINE_STATE_BLEND
,
2963 [D3DRS_POSITIONDEGREE
] = NINE_STATE_UNHANDLED
,
2964 [D3DRS_NORMALDEGREE
] = NINE_STATE_UNHANDLED
,
2965 [D3DRS_SCISSORTESTENABLE
] = NINE_STATE_RASTERIZER
,
2966 [D3DRS_SLOPESCALEDEPTHBIAS
] = NINE_STATE_RASTERIZER
,
2967 [D3DRS_ANTIALIASEDLINEENABLE
] = NINE_STATE_RASTERIZER
,
2968 [D3DRS_MINTESSELLATIONLEVEL
] = NINE_STATE_UNHANDLED
,
2969 [D3DRS_MAXTESSELLATIONLEVEL
] = NINE_STATE_UNHANDLED
,
2970 [D3DRS_ADAPTIVETESS_X
] = NINE_STATE_UNHANDLED
,
2971 [D3DRS_ADAPTIVETESS_Y
] = NINE_STATE_UNHANDLED
,
2972 [D3DRS_ADAPTIVETESS_Z
] = NINE_STATE_UNHANDLED
,
2973 [D3DRS_ADAPTIVETESS_W
] = NINE_STATE_UNHANDLED
,
2974 [D3DRS_ENABLEADAPTIVETESSELLATION
] = NINE_STATE_UNHANDLED
,
2975 [D3DRS_TWOSIDEDSTENCILMODE
] = NINE_STATE_DSA
,
2976 [D3DRS_CCW_STENCILFAIL
] = NINE_STATE_DSA
,
2977 [D3DRS_CCW_STENCILZFAIL
] = NINE_STATE_DSA
,
2978 [D3DRS_CCW_STENCILPASS
] = NINE_STATE_DSA
,
2979 [D3DRS_CCW_STENCILFUNC
] = NINE_STATE_DSA
,
2980 [D3DRS_COLORWRITEENABLE1
] = NINE_STATE_BLEND
,
2981 [D3DRS_COLORWRITEENABLE2
] = NINE_STATE_BLEND
,
2982 [D3DRS_COLORWRITEENABLE3
] = NINE_STATE_BLEND
,
2983 [D3DRS_BLENDFACTOR
] = NINE_STATE_BLEND_COLOR
,
2984 [D3DRS_SRGBWRITEENABLE
] = NINE_STATE_FB
,
2985 [D3DRS_DEPTHBIAS
] = NINE_STATE_RASTERIZER
,
2986 [D3DRS_WRAP8
] = NINE_STATE_UNHANDLED
, /* cylwrap has to be done via GP */
2987 [D3DRS_WRAP9
] = NINE_STATE_UNHANDLED
,
2988 [D3DRS_WRAP10
] = NINE_STATE_UNHANDLED
,
2989 [D3DRS_WRAP11
] = NINE_STATE_UNHANDLED
,
2990 [D3DRS_WRAP12
] = NINE_STATE_UNHANDLED
,
2991 [D3DRS_WRAP13
] = NINE_STATE_UNHANDLED
,
2992 [D3DRS_WRAP14
] = NINE_STATE_UNHANDLED
,
2993 [D3DRS_WRAP15
] = NINE_STATE_UNHANDLED
,
2994 [D3DRS_SEPARATEALPHABLENDENABLE
] = NINE_STATE_BLEND
,
2995 [D3DRS_SRCBLENDALPHA
] = NINE_STATE_BLEND
,
2996 [D3DRS_DESTBLENDALPHA
] = NINE_STATE_BLEND
,
2997 [D3DRS_BLENDOPALPHA
] = NINE_STATE_BLEND
3003 nine_state_access_transform(struct nine_ff_state
*ff_state
, D3DTRANSFORMSTATETYPE t
,
3006 static D3DMATRIX Identity
= { .m
[0] = { 1, 0, 0, 0 },
3007 .m
[1] = { 0, 1, 0, 0 },
3008 .m
[2] = { 0, 0, 1, 0 },
3009 .m
[3] = { 0, 0, 0, 1 } };
3013 case D3DTS_VIEW
: index
= 0; break;
3014 case D3DTS_PROJECTION
: index
= 1; break;
3015 case D3DTS_TEXTURE0
: index
= 2; break;
3016 case D3DTS_TEXTURE1
: index
= 3; break;
3017 case D3DTS_TEXTURE2
: index
= 4; break;
3018 case D3DTS_TEXTURE3
: index
= 5; break;
3019 case D3DTS_TEXTURE4
: index
= 6; break;
3020 case D3DTS_TEXTURE5
: index
= 7; break;
3021 case D3DTS_TEXTURE6
: index
= 8; break;
3022 case D3DTS_TEXTURE7
: index
= 9; break;
3024 if (!(t
>= D3DTS_WORLDMATRIX(0) && t
<= D3DTS_WORLDMATRIX(255)))
3026 index
= 10 + (t
- D3DTS_WORLDMATRIX(0));
3030 if (index
>= ff_state
->num_transforms
) {
3031 unsigned N
= index
+ 1;
3032 unsigned n
= ff_state
->num_transforms
;
3036 ff_state
->transform
= REALLOC(ff_state
->transform
,
3037 n
* sizeof(D3DMATRIX
),
3038 N
* sizeof(D3DMATRIX
));
3040 ff_state
->transform
[n
] = Identity
;
3041 ff_state
->num_transforms
= N
;
3043 return &ff_state
->transform
[index
];
3047 nine_state_set_light(struct nine_ff_state
*ff_state
, DWORD Index
,
3048 const D3DLIGHT9
*pLight
)
3050 if (Index
>= ff_state
->num_lights
) {
3051 unsigned n
= ff_state
->num_lights
;
3052 unsigned N
= Index
+ 1;
3054 ff_state
->light
= REALLOC(ff_state
->light
, n
* sizeof(D3DLIGHT9
),
3055 N
* sizeof(D3DLIGHT9
));
3056 if (!ff_state
->light
)
3057 return E_OUTOFMEMORY
;
3058 ff_state
->num_lights
= N
;
3060 for (; n
< Index
; ++n
) {
3061 memset(&ff_state
->light
[n
], 0, sizeof(D3DLIGHT9
));
3062 ff_state
->light
[n
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
3065 ff_state
->light
[Index
] = *pLight
;
3067 if (pLight
->Type
== D3DLIGHT_SPOT
&& pLight
->Theta
>= pLight
->Phi
) {
3068 DBG("Warning: clamping D3DLIGHT9.Theta\n");
3069 ff_state
->light
[Index
].Theta
= ff_state
->light
[Index
].Phi
;
3075 nine_state_light_enable(struct nine_ff_state
*ff_state
, uint32_t *change_group
,
3076 DWORD Index
, BOOL Enable
)
3080 user_assert(Index
< ff_state
->num_lights
, D3DERR_INVALIDCALL
);
3082 for (i
= 0; i
< ff_state
->num_lights_active
; ++i
) {
3083 if (ff_state
->active_light
[i
] == Index
)
3088 if (i
< ff_state
->num_lights_active
)
3090 /* XXX wine thinks this should still succeed:
3092 user_assert(i
< NINE_MAX_LIGHTS_ACTIVE
, D3DERR_INVALIDCALL
);
3094 ff_state
->active_light
[i
] = Index
;
3095 ff_state
->num_lights_active
++;
3097 if (i
== ff_state
->num_lights_active
)
3099 --ff_state
->num_lights_active
;
3100 for (; i
< ff_state
->num_lights_active
; ++i
)
3101 ff_state
->active_light
[i
] = ff_state
->active_light
[i
+ 1];
3104 *change_group
|= NINE_STATE_FF_LIGHTING
;
3109 #define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n
3110 const char *nine_d3drs_to_string(DWORD State
)
3113 D3DRS_TO_STRING_CASE(ZENABLE
);
3114 D3DRS_TO_STRING_CASE(FILLMODE
);
3115 D3DRS_TO_STRING_CASE(SHADEMODE
);
3116 D3DRS_TO_STRING_CASE(ZWRITEENABLE
);
3117 D3DRS_TO_STRING_CASE(ALPHATESTENABLE
);
3118 D3DRS_TO_STRING_CASE(LASTPIXEL
);
3119 D3DRS_TO_STRING_CASE(SRCBLEND
);
3120 D3DRS_TO_STRING_CASE(DESTBLEND
);
3121 D3DRS_TO_STRING_CASE(CULLMODE
);
3122 D3DRS_TO_STRING_CASE(ZFUNC
);
3123 D3DRS_TO_STRING_CASE(ALPHAREF
);
3124 D3DRS_TO_STRING_CASE(ALPHAFUNC
);
3125 D3DRS_TO_STRING_CASE(DITHERENABLE
);
3126 D3DRS_TO_STRING_CASE(ALPHABLENDENABLE
);
3127 D3DRS_TO_STRING_CASE(FOGENABLE
);
3128 D3DRS_TO_STRING_CASE(SPECULARENABLE
);
3129 D3DRS_TO_STRING_CASE(FOGCOLOR
);
3130 D3DRS_TO_STRING_CASE(FOGTABLEMODE
);
3131 D3DRS_TO_STRING_CASE(FOGSTART
);
3132 D3DRS_TO_STRING_CASE(FOGEND
);
3133 D3DRS_TO_STRING_CASE(FOGDENSITY
);
3134 D3DRS_TO_STRING_CASE(RANGEFOGENABLE
);
3135 D3DRS_TO_STRING_CASE(STENCILENABLE
);
3136 D3DRS_TO_STRING_CASE(STENCILFAIL
);
3137 D3DRS_TO_STRING_CASE(STENCILZFAIL
);
3138 D3DRS_TO_STRING_CASE(STENCILPASS
);
3139 D3DRS_TO_STRING_CASE(STENCILFUNC
);
3140 D3DRS_TO_STRING_CASE(STENCILREF
);
3141 D3DRS_TO_STRING_CASE(STENCILMASK
);
3142 D3DRS_TO_STRING_CASE(STENCILWRITEMASK
);
3143 D3DRS_TO_STRING_CASE(TEXTUREFACTOR
);
3144 D3DRS_TO_STRING_CASE(WRAP0
);
3145 D3DRS_TO_STRING_CASE(WRAP1
);
3146 D3DRS_TO_STRING_CASE(WRAP2
);
3147 D3DRS_TO_STRING_CASE(WRAP3
);
3148 D3DRS_TO_STRING_CASE(WRAP4
);
3149 D3DRS_TO_STRING_CASE(WRAP5
);
3150 D3DRS_TO_STRING_CASE(WRAP6
);
3151 D3DRS_TO_STRING_CASE(WRAP7
);
3152 D3DRS_TO_STRING_CASE(CLIPPING
);
3153 D3DRS_TO_STRING_CASE(LIGHTING
);
3154 D3DRS_TO_STRING_CASE(AMBIENT
);
3155 D3DRS_TO_STRING_CASE(FOGVERTEXMODE
);
3156 D3DRS_TO_STRING_CASE(COLORVERTEX
);
3157 D3DRS_TO_STRING_CASE(LOCALVIEWER
);
3158 D3DRS_TO_STRING_CASE(NORMALIZENORMALS
);
3159 D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE
);
3160 D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE
);
3161 D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE
);
3162 D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE
);
3163 D3DRS_TO_STRING_CASE(VERTEXBLEND
);
3164 D3DRS_TO_STRING_CASE(CLIPPLANEENABLE
);
3165 D3DRS_TO_STRING_CASE(POINTSIZE
);
3166 D3DRS_TO_STRING_CASE(POINTSIZE_MIN
);
3167 D3DRS_TO_STRING_CASE(POINTSPRITEENABLE
);
3168 D3DRS_TO_STRING_CASE(POINTSCALEENABLE
);
3169 D3DRS_TO_STRING_CASE(POINTSCALE_A
);
3170 D3DRS_TO_STRING_CASE(POINTSCALE_B
);
3171 D3DRS_TO_STRING_CASE(POINTSCALE_C
);
3172 D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS
);
3173 D3DRS_TO_STRING_CASE(MULTISAMPLEMASK
);
3174 D3DRS_TO_STRING_CASE(PATCHEDGESTYLE
);
3175 D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN
);
3176 D3DRS_TO_STRING_CASE(POINTSIZE_MAX
);
3177 D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE
);
3178 D3DRS_TO_STRING_CASE(COLORWRITEENABLE
);
3179 D3DRS_TO_STRING_CASE(TWEENFACTOR
);
3180 D3DRS_TO_STRING_CASE(BLENDOP
);
3181 D3DRS_TO_STRING_CASE(POSITIONDEGREE
);
3182 D3DRS_TO_STRING_CASE(NORMALDEGREE
);
3183 D3DRS_TO_STRING_CASE(SCISSORTESTENABLE
);
3184 D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS
);
3185 D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE
);
3186 D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL
);
3187 D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL
);
3188 D3DRS_TO_STRING_CASE(ADAPTIVETESS_X
);
3189 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y
);
3190 D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z
);
3191 D3DRS_TO_STRING_CASE(ADAPTIVETESS_W
);
3192 D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION
);
3193 D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE
);
3194 D3DRS_TO_STRING_CASE(CCW_STENCILFAIL
);
3195 D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL
);
3196 D3DRS_TO_STRING_CASE(CCW_STENCILPASS
);
3197 D3DRS_TO_STRING_CASE(CCW_STENCILFUNC
);
3198 D3DRS_TO_STRING_CASE(COLORWRITEENABLE1
);
3199 D3DRS_TO_STRING_CASE(COLORWRITEENABLE2
);
3200 D3DRS_TO_STRING_CASE(COLORWRITEENABLE3
);
3201 D3DRS_TO_STRING_CASE(BLENDFACTOR
);
3202 D3DRS_TO_STRING_CASE(SRGBWRITEENABLE
);
3203 D3DRS_TO_STRING_CASE(DEPTHBIAS
);
3204 D3DRS_TO_STRING_CASE(WRAP8
);
3205 D3DRS_TO_STRING_CASE(WRAP9
);
3206 D3DRS_TO_STRING_CASE(WRAP10
);
3207 D3DRS_TO_STRING_CASE(WRAP11
);
3208 D3DRS_TO_STRING_CASE(WRAP12
);
3209 D3DRS_TO_STRING_CASE(WRAP13
);
3210 D3DRS_TO_STRING_CASE(WRAP14
);
3211 D3DRS_TO_STRING_CASE(WRAP15
);
3212 D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE
);
3213 D3DRS_TO_STRING_CASE(SRCBLENDALPHA
);
3214 D3DRS_TO_STRING_CASE(DESTBLENDALPHA
);
3215 D3DRS_TO_STRING_CASE(BLENDOPALPHA
);