Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright 2011 Joakim Sindholt |
||
3 | * Copyright 2013 Christoph Bumiller |
||
4 | * |
||
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
6 | * copy of this software and associated documentation files (the "Software"), |
||
7 | * to deal in the Software without restriction, including without limitation |
||
8 | * on the rights to use, copy, modify, merge, publish, distribute, sub |
||
9 | * license, and/or sell copies of the Software, and to permit persons to whom |
||
10 | * the Software is furnished to do so, subject to the following conditions: |
||
11 | * |
||
12 | * The above copyright notice and this permission notice (including the next |
||
13 | * paragraph) shall be included in all copies or substantial portions of the |
||
14 | * Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||
20 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
21 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
22 | * USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
||
23 | |||
24 | #include "device9.h" |
||
25 | #include "basetexture9.h" |
||
26 | #include "indexbuffer9.h" |
||
27 | #include "surface9.h" |
||
28 | #include "vertexdeclaration9.h" |
||
29 | #include "vertexshader9.h" |
||
30 | #include "pixelshader9.h" |
||
31 | #include "nine_pipe.h" |
||
32 | #include "nine_ff.h" |
||
33 | #include "pipe/p_context.h" |
||
34 | #include "pipe/p_state.h" |
||
35 | #include "cso_cache/cso_context.h" |
||
36 | #include "util/u_math.h" |
||
37 | |||
38 | #define DBG_CHANNEL DBG_DEVICE |
||
39 | |||
40 | static uint32_t |
||
41 | update_framebuffer(struct NineDevice9 *device) |
||
42 | { |
||
43 | struct pipe_context *pipe = device->pipe; |
||
44 | struct nine_state *state = &device->state; |
||
45 | struct pipe_framebuffer_state *fb = &device->state.fb; |
||
46 | unsigned i; |
||
47 | struct NineSurface9 *rt0 = state->rt[0]; |
||
48 | unsigned w = rt0->desc.Width; |
||
49 | unsigned h = rt0->desc.Height; |
||
50 | D3DMULTISAMPLE_TYPE nr_samples = rt0->desc.MultiSampleType; |
||
51 | unsigned mask = state->ps ? state->ps->rt_mask : 1; |
||
52 | const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; |
||
53 | |||
54 | DBG("\n"); |
||
55 | |||
56 | state->rt_mask = 0x0; |
||
57 | fb->nr_cbufs = 0; |
||
58 | |||
59 | /* all render targets must have the same size and the depth buffer must be |
||
60 | * bigger. Multisample has to match, according to spec. But some apps do |
||
61 | * things wrong there, and no error is returned. The behaviour they get |
||
62 | * apparently is that depth buffer is disabled if it doesn't match. |
||
63 | * Surely the same for render targets. */ |
||
64 | |||
65 | /* Special case: D3DFMT_NULL is used to bound no real render target, |
||
66 | * but render to depth buffer. We have to not take into account the render |
||
67 | * target info. TODO: know what should happen when there are several render targers |
||
68 | * and the first one is D3DFMT_NULL */ |
||
69 | if (rt0->desc.Format == D3DFMT_NULL && state->ds) { |
||
70 | w = state->ds->desc.Width; |
||
71 | h = state->ds->desc.Height; |
||
72 | nr_samples = state->ds->desc.MultiSampleType; |
||
73 | } |
||
74 | |||
75 | for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { |
||
76 | struct NineSurface9 *rt = state->rt[i]; |
||
77 | |||
78 | if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) && |
||
79 | rt->desc.Width == w && rt->desc.Height == h && |
||
80 | rt->desc.MultiSampleType == nr_samples) { |
||
81 | fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB); |
||
82 | state->rt_mask |= 1 << i; |
||
83 | fb->nr_cbufs = i + 1; |
||
84 | |||
85 | if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) { |
||
86 | assert(rt->texture == D3DRTYPE_TEXTURE || |
||
87 | rt->texture == D3DRTYPE_CUBETEXTURE); |
||
88 | NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE; |
||
89 | } |
||
90 | } else { |
||
91 | /* Color outputs must match RT slot, |
||
92 | * drivers will have to handle NULL entries for GL, too. |
||
93 | */ |
||
94 | fb->cbufs[i] = NULL; |
||
95 | } |
||
96 | } |
||
97 | |||
98 | if (state->ds && state->ds->desc.Width >= w && |
||
99 | state->ds->desc.Height >= h && |
||
100 | state->ds->desc.MultiSampleType == nr_samples) { |
||
101 | fb->zsbuf = NineSurface9_GetSurface(state->ds, 0); |
||
102 | } else { |
||
103 | fb->zsbuf = NULL; |
||
104 | } |
||
105 | |||
106 | fb->width = w; |
||
107 | fb->height = h; |
||
108 | |||
109 | pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */ |
||
110 | |||
111 | if (fb->zsbuf) { |
||
112 | DWORD scale; |
||
113 | switch (fb->zsbuf->format) { |
||
114 | case PIPE_FORMAT_Z32_FLOAT: |
||
115 | case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: |
||
116 | scale = fui(1.0f); |
||
117 | break; |
||
118 | case PIPE_FORMAT_Z16_UNORM: |
||
119 | scale = fui((float)(1 << 16)); |
||
120 | break; |
||
121 | default: |
||
122 | scale = fui((float)(1 << 24)); |
||
123 | break; |
||
124 | } |
||
125 | if (state->rs[NINED3DRS_ZBIASSCALE] != scale) { |
||
126 | state->rs[NINED3DRS_ZBIASSCALE] = scale; |
||
127 | state->changed.group |= NINE_STATE_RASTERIZER; |
||
128 | } |
||
129 | } |
||
130 | |||
131 | return state->changed.group; |
||
132 | } |
||
133 | |||
134 | static void |
||
135 | update_viewport(struct NineDevice9 *device) |
||
136 | { |
||
137 | struct pipe_context *pipe = device->pipe; |
||
138 | const D3DVIEWPORT9 *vport = &device->state.viewport; |
||
139 | struct pipe_viewport_state pvport; |
||
140 | |||
141 | /* D3D coordinates are: |
||
142 | * -1 .. +1 for X,Y and |
||
143 | * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz) |
||
144 | */ |
||
145 | pvport.scale[0] = (float)vport->Width * 0.5f; |
||
146 | pvport.scale[1] = (float)vport->Height * -0.5f; |
||
147 | pvport.scale[2] = vport->MaxZ - vport->MinZ; |
||
148 | pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X; |
||
149 | pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y; |
||
150 | pvport.translate[2] = vport->MinZ; |
||
151 | |||
152 | /* We found R600 and SI cards have some imprecision |
||
153 | * on the barycentric coordinates used for interpolation. |
||
154 | * Some shaders rely on having something precise. |
||
155 | * We found that the proprietary driver has the imprecision issue, |
||
156 | * except when the render target width and height are powers of two. |
||
157 | * It is using some sort of workaround for these cases |
||
158 | * which covers likely all the cases the applications rely |
||
159 | * on something precise. |
||
160 | * We haven't found the workaround, but it seems like it's better |
||
161 | * for applications if the imprecision is biased towards infinity |
||
162 | * instead of -infinity (which is what measured). So shift slightly |
||
163 | * the viewport: not enough to change rasterization result (in particular |
||
164 | * for multisampling), but enough to make the imprecision biased |
||
165 | * towards infinity. We do this shift only if render target width and |
||
166 | * height are powers of two. |
||
167 | * Solves 'red shadows' bug on UE3 games. |
||
168 | */ |
||
169 | if (device->driver_bugs.buggy_barycentrics && |
||
170 | ((vport->Width & (vport->Width-1)) == 0) && |
||
171 | ((vport->Height & (vport->Height-1)) == 0)) { |
||
172 | pvport.translate[0] -= 1.0f / 128.0f; |
||
173 | pvport.translate[1] -= 1.0f / 128.0f; |
||
174 | } |
||
175 | |||
176 | pipe->set_viewport_states(pipe, 0, 1, &pvport); |
||
177 | } |
||
178 | |||
179 | static INLINE void |
||
180 | update_scissor(struct NineDevice9 *device) |
||
181 | { |
||
182 | struct pipe_context *pipe = device->pipe; |
||
183 | |||
184 | pipe->set_scissor_states(pipe, 0, 1, &device->state.scissor); |
||
185 | } |
||
186 | |||
187 | static INLINE void |
||
188 | update_blend(struct NineDevice9 *device) |
||
189 | { |
||
190 | nine_convert_blend_state(device->cso, device->state.rs); |
||
191 | } |
||
192 | |||
193 | static INLINE void |
||
194 | update_dsa(struct NineDevice9 *device) |
||
195 | { |
||
196 | nine_convert_dsa_state(device->cso, device->state.rs); |
||
197 | } |
||
198 | |||
199 | static INLINE void |
||
200 | update_rasterizer(struct NineDevice9 *device) |
||
201 | { |
||
202 | nine_convert_rasterizer_state(device->cso, device->state.rs); |
||
203 | } |
||
204 | |||
205 | /* Loop through VS inputs and pick the vertex elements with the declared |
||
206 | * usage from the vertex declaration, then insert the instance divisor from |
||
207 | * the stream source frequency setting. |
||
208 | */ |
||
209 | static void |
||
210 | update_vertex_elements(struct NineDevice9 *device) |
||
211 | { |
||
212 | struct nine_state *state = &device->state; |
||
213 | const struct NineVertexDeclaration9 *vdecl = device->state.vdecl; |
||
214 | const struct NineVertexShader9 *vs; |
||
215 | unsigned n, b, i; |
||
216 | int index; |
||
217 | char vdecl_index_map[16]; /* vs->num_inputs <= 16 */ |
||
218 | char used_streams[device->caps.MaxStreams]; |
||
219 | int dummy_vbo_stream = -1; |
||
220 | BOOL need_dummy_vbo = FALSE; |
||
221 | struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS]; |
||
222 | |||
223 | state->stream_usage_mask = 0; |
||
224 | memset(vdecl_index_map, -1, 16); |
||
225 | memset(used_streams, 0, device->caps.MaxStreams); |
||
226 | vs = device->state.vs ? device->state.vs : device->ff.vs; |
||
227 | |||
228 | if (vdecl) { |
||
229 | for (n = 0; n < vs->num_inputs; ++n) { |
||
230 | DBG("looking up input %u (usage %u) from vdecl(%p)\n", |
||
231 | n, vs->input_map[n].ndecl, vdecl); |
||
232 | |||
233 | for (i = 0; i < vdecl->nelems; i++) { |
||
234 | if (vdecl->usage_map[i] == vs->input_map[n].ndecl) { |
||
235 | vdecl_index_map[n] = i; |
||
236 | used_streams[vdecl->elems[i].vertex_buffer_index] = 1; |
||
237 | break; |
||
238 | } |
||
239 | } |
||
240 | if (vdecl_index_map[n] < 0) |
||
241 | need_dummy_vbo = TRUE; |
||
242 | } |
||
243 | } else { |
||
244 | /* No vertex declaration. Likely will never happen in practice, |
||
245 | * but we need not crash on this */ |
||
246 | need_dummy_vbo = TRUE; |
||
247 | } |
||
248 | |||
249 | if (need_dummy_vbo) { |
||
250 | for (i = 0; i < device->caps.MaxStreams; i++ ) { |
||
251 | if (!used_streams[i]) { |
||
252 | dummy_vbo_stream = i; |
||
253 | break; |
||
254 | } |
||
255 | } |
||
256 | } |
||
257 | /* there are less vertex shader inputs than stream slots, |
||
258 | * so if we need a slot for the dummy vbo, we should have found one */ |
||
259 | assert (!need_dummy_vbo || dummy_vbo_stream != -1); |
||
260 | |||
261 | for (n = 0; n < vs->num_inputs; ++n) { |
||
262 | index = vdecl_index_map[n]; |
||
263 | if (index >= 0) { |
||
264 | ve[n] = vdecl->elems[index]; |
||
265 | b = ve[n].vertex_buffer_index; |
||
266 | state->stream_usage_mask |= 1 << b; |
||
267 | /* XXX wine just uses 1 here: */ |
||
268 | if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA) |
||
269 | ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF; |
||
270 | } else { |
||
271 | /* if the vertex declaration is incomplete compared to what the |
||
272 | * vertex shader needs, we bind a dummy vbo with 0 0 0 0. |
||
273 | * This is not precised by the spec, but is the behaviour |
||
274 | * tested on win */ |
||
275 | ve[n].vertex_buffer_index = dummy_vbo_stream; |
||
276 | ve[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; |
||
277 | ve[n].src_offset = 0; |
||
278 | ve[n].instance_divisor = 0; |
||
279 | } |
||
280 | } |
||
281 | |||
282 | if (state->dummy_vbo_bound_at != dummy_vbo_stream) { |
||
283 | if (state->dummy_vbo_bound_at >= 0) |
||
284 | state->changed.vtxbuf |= 1 << state->dummy_vbo_bound_at; |
||
285 | if (dummy_vbo_stream >= 0) { |
||
286 | state->changed.vtxbuf |= 1 << dummy_vbo_stream; |
||
287 | state->vbo_bound_done = FALSE; |
||
288 | } |
||
289 | state->dummy_vbo_bound_at = dummy_vbo_stream; |
||
290 | } |
||
291 | |||
292 | cso_set_vertex_elements(device->cso, vs->num_inputs, ve); |
||
293 | |||
294 | state->changed.stream_freq = 0; |
||
295 | } |
||
296 | |||
297 | static INLINE uint32_t |
||
298 | update_shader_variant_keys(struct NineDevice9 *device) |
||
299 | { |
||
300 | struct nine_state *state = &device->state; |
||
301 | uint32_t mask = 0; |
||
302 | uint32_t vs_key = state->samplers_shadow; |
||
303 | uint32_t ps_key = state->samplers_shadow; |
||
304 | |||
305 | vs_key = (vs_key & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0); |
||
306 | ps_key = (ps_key & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0); |
||
307 | |||
308 | if (state->vs) vs_key &= state->vs->sampler_mask; |
||
309 | if (state->ps) { |
||
310 | if (unlikely(state->ps->byte_code.version < 0x20)) { |
||
311 | /* no depth textures, but variable targets */ |
||
312 | uint32_t m = state->ps->sampler_mask; |
||
313 | ps_key = 0; |
||
314 | while (m) { |
||
315 | int s = ffs(m) - 1; |
||
316 | m &= ~(1 << s); |
||
317 | ps_key |= (state->texture[s] ? state->texture[s]->pstype : 1) << (s * 2); |
||
318 | } |
||
319 | } else { |
||
320 | ps_key &= state->ps->sampler_mask; |
||
321 | } |
||
322 | } |
||
323 | |||
324 | if (state->vs && state->vs_key != vs_key) { |
||
325 | state->vs_key = vs_key; |
||
326 | mask |= NINE_STATE_VS; |
||
327 | } |
||
328 | if (state->ps && state->ps_key != ps_key) { |
||
329 | state->ps_key = ps_key; |
||
330 | mask |= NINE_STATE_PS; |
||
331 | } |
||
332 | return mask; |
||
333 | } |
||
334 | |||
335 | static INLINE uint32_t |
||
336 | update_vs(struct NineDevice9 *device) |
||
337 | { |
||
338 | struct nine_state *state = &device->state; |
||
339 | struct NineVertexShader9 *vs = state->vs; |
||
340 | uint32_t changed_group = 0; |
||
341 | |||
342 | /* likely because we dislike FF */ |
||
343 | if (likely(vs)) { |
||
344 | state->cso.vs = NineVertexShader9_GetVariant(vs, state->vs_key); |
||
345 | } else { |
||
346 | vs = device->ff.vs; |
||
347 | state->cso.vs = vs->variant.cso; |
||
348 | } |
||
349 | device->pipe->bind_vs_state(device->pipe, state->cso.vs); |
||
350 | |||
351 | if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) { |
||
352 | state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size; |
||
353 | changed_group |= NINE_STATE_RASTERIZER; |
||
354 | } |
||
355 | |||
356 | if ((state->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask) |
||
357 | /* Bound dummy sampler. */ |
||
358 | changed_group |= NINE_STATE_SAMPLER; |
||
359 | return changed_group; |
||
360 | } |
||
361 | |||
362 | static INLINE uint32_t |
||
363 | update_ps(struct NineDevice9 *device) |
||
364 | { |
||
365 | struct nine_state *state = &device->state; |
||
366 | struct NinePixelShader9 *ps = state->ps; |
||
367 | uint32_t changed_group = 0; |
||
368 | |||
369 | if (likely(ps)) { |
||
370 | state->cso.ps = NinePixelShader9_GetVariant(ps, state->ps_key); |
||
371 | } else { |
||
372 | ps = device->ff.ps; |
||
373 | state->cso.ps = ps->variant.cso; |
||
374 | } |
||
375 | device->pipe->bind_fs_state(device->pipe, state->cso.ps); |
||
376 | |||
377 | if ((state->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask) |
||
378 | /* Bound dummy sampler. */ |
||
379 | changed_group |= NINE_STATE_SAMPLER; |
||
380 | return changed_group; |
||
381 | } |
||
382 | |||
383 | #define DO_UPLOAD_CONST_F(buf,p,c,d) \ |
||
384 | do { \ |
||
385 | DBG("upload ConstantF [%u .. %u]\n", x, (x) + (c) - 1); \ |
||
386 | box.x = (p) * 4 * sizeof(float); \ |
||
387 | box.width = (c) * 4 * sizeof(float); \ |
||
388 | pipe->transfer_inline_write(pipe, buf, 0, usage, &box, &((d)[p * 4]), \ |
||
389 | 0, 0); \ |
||
390 | } while(0) |
||
391 | |||
392 | /* OK, this is a bit ugly ... */ |
||
393 | static void |
||
394 | update_constants(struct NineDevice9 *device, unsigned shader_type) |
||
395 | { |
||
396 | struct pipe_context *pipe = device->pipe; |
||
397 | struct pipe_resource *buf; |
||
398 | struct pipe_box box; |
||
399 | const void *data; |
||
400 | const float *const_f; |
||
401 | const int *const_i; |
||
402 | const BOOL *const_b; |
||
403 | uint32_t data_b[NINE_MAX_CONST_B]; |
||
404 | uint16_t dirty_i; |
||
405 | uint16_t dirty_b; |
||
406 | const unsigned usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE; |
||
407 | unsigned x = 0; /* silence warning */ |
||
408 | unsigned i, c; |
||
409 | struct nine_range *r, *p, *lconstf_ranges; |
||
410 | float *lconstf_data; |
||
411 | |||
412 | box.y = 0; |
||
413 | box.z = 0; |
||
414 | box.height = 1; |
||
415 | box.depth = 1; |
||
416 | |||
417 | if (shader_type == PIPE_SHADER_VERTEX) { |
||
418 | DBG("VS\n"); |
||
419 | buf = device->constbuf_vs; |
||
420 | |||
421 | const_f = device->state.vs_const_f; |
||
422 | for (p = r = device->state.changed.vs_const_f; r; p = r, r = r->next) |
||
423 | DO_UPLOAD_CONST_F(buf, r->bgn, r->end - r->bgn, const_f); |
||
424 | if (p) { |
||
425 | nine_range_pool_put_chain(&device->range_pool, |
||
426 | device->state.changed.vs_const_f, p); |
||
427 | device->state.changed.vs_const_f = NULL; |
||
428 | } |
||
429 | |||
430 | dirty_i = device->state.changed.vs_const_i; |
||
431 | device->state.changed.vs_const_i = 0; |
||
432 | const_i = &device->state.vs_const_i[0][0]; |
||
433 | |||
434 | dirty_b = device->state.changed.vs_const_b; |
||
435 | device->state.changed.vs_const_b = 0; |
||
436 | const_b = device->state.vs_const_b; |
||
437 | |||
438 | lconstf_ranges = device->state.vs->lconstf.ranges; |
||
439 | lconstf_data = device->state.vs->lconstf.data; |
||
440 | |||
441 | device->state.ff.clobber.vs_const = TRUE; |
||
442 | device->state.changed.group &= ~NINE_STATE_VS_CONST; |
||
443 | } else { |
||
444 | DBG("PS\n"); |
||
445 | buf = device->constbuf_ps; |
||
446 | |||
447 | const_f = device->state.ps_const_f; |
||
448 | for (p = r = device->state.changed.ps_const_f; r; p = r, r = r->next) |
||
449 | DO_UPLOAD_CONST_F(buf, r->bgn, r->end - r->bgn, const_f); |
||
450 | if (p) { |
||
451 | nine_range_pool_put_chain(&device->range_pool, |
||
452 | device->state.changed.ps_const_f, p); |
||
453 | device->state.changed.ps_const_f = NULL; |
||
454 | } |
||
455 | |||
456 | dirty_i = device->state.changed.ps_const_i; |
||
457 | device->state.changed.ps_const_i = 0; |
||
458 | const_i = &device->state.ps_const_i[0][0]; |
||
459 | |||
460 | dirty_b = device->state.changed.ps_const_b; |
||
461 | device->state.changed.ps_const_b = 0; |
||
462 | const_b = device->state.ps_const_b; |
||
463 | |||
464 | lconstf_ranges = NULL; |
||
465 | lconstf_data = NULL; |
||
466 | |||
467 | device->state.ff.clobber.ps_const = TRUE; |
||
468 | device->state.changed.group &= ~NINE_STATE_PS_CONST; |
||
469 | } |
||
470 | |||
471 | /* write range from min to max changed, it's not much data */ |
||
472 | /* bool1 */ |
||
473 | if (dirty_b) { |
||
474 | c = util_last_bit(dirty_b); |
||
475 | i = ffs(dirty_b) - 1; |
||
476 | x = buf->width0 - (NINE_MAX_CONST_B - i) * 4; |
||
477 | c -= i; |
||
478 | memcpy(data_b, &(const_b[i]), c * sizeof(uint32_t)); |
||
479 | box.x = x; |
||
480 | box.width = c * 4; |
||
481 | DBG("upload ConstantB [%u .. %u]\n", x, x + c - 1); |
||
482 | pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data_b, 0, 0); |
||
483 | } |
||
484 | |||
485 | /* int4 */ |
||
486 | for (c = 0, i = 0; dirty_i; i++, dirty_i >>= 1) { |
||
487 | if (dirty_i & 1) { |
||
488 | if (!c) |
||
489 | x = i; |
||
490 | ++c; |
||
491 | } else |
||
492 | if (c) { |
||
493 | DBG("upload ConstantI [%u .. %u]\n", x, x + c - 1); |
||
494 | data = &const_i[x * 4]; |
||
495 | box.x = buf->width0 - (NINE_MAX_CONST_I * 4 + NINE_MAX_CONST_B) * 4; |
||
496 | box.x += x * 4 * sizeof(int); |
||
497 | box.width = c * 4 * sizeof(int); |
||
498 | c = 0; |
||
499 | pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0); |
||
500 | } |
||
501 | } |
||
502 | if (c) { |
||
503 | DBG("upload ConstantI [%u .. %u]\n", x, x + c - 1); |
||
504 | data = &const_i[x * 4]; |
||
505 | box.x = buf->width0 - (NINE_MAX_CONST_I * 4 + NINE_MAX_CONST_B) * 4; |
||
506 | box.x += x * 4 * sizeof(int); |
||
507 | box.width = c * 4 * sizeof(int); |
||
508 | pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0); |
||
509 | } |
||
510 | |||
511 | /* TODO: only upload these when shader itself changes */ |
||
512 | if (lconstf_ranges) { |
||
513 | unsigned n = 0; |
||
514 | struct nine_range *r = lconstf_ranges; |
||
515 | while (r) { |
||
516 | box.x = r->bgn * 4 * sizeof(float); |
||
517 | n += r->end - r->bgn; |
||
518 | box.width = (r->end - r->bgn) * 4 * sizeof(float); |
||
519 | data = &lconstf_data[4 * n]; |
||
520 | pipe->transfer_inline_write(pipe, buf, 0, usage, &box, data, 0, 0); |
||
521 | r = r->next; |
||
522 | } |
||
523 | } |
||
524 | } |
||
525 | |||
526 | static void |
||
527 | update_vs_constants_userbuf(struct NineDevice9 *device) |
||
528 | { |
||
529 | struct nine_state *state = &device->state; |
||
530 | struct pipe_context *pipe = device->pipe; |
||
531 | struct pipe_constant_buffer cb; |
||
532 | cb.buffer = NULL; |
||
533 | cb.buffer_offset = 0; |
||
534 | cb.buffer_size = device->state.vs->const_used_size; |
||
535 | cb.user_buffer = device->state.vs_const_f; |
||
536 | |||
537 | if (!cb.buffer_size) |
||
538 | return; |
||
539 | |||
540 | if (state->changed.vs_const_i) { |
||
541 | int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f]; |
||
542 | memcpy(idst, state->vs_const_i, sizeof(state->vs_const_i)); |
||
543 | state->changed.vs_const_i = 0; |
||
544 | } |
||
545 | if (state->changed.vs_const_b) { |
||
546 | int *idst = (int *)&state->vs_const_f[4 * device->max_vs_const_f]; |
||
547 | uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; |
||
548 | memcpy(bdst, state->vs_const_b, sizeof(state->vs_const_b)); |
||
549 | state->changed.vs_const_b = 0; |
||
550 | } |
||
551 | |||
552 | if (device->state.vs->lconstf.ranges) { |
||
553 | /* TODO: Can we make it so that we don't have to copy everything ? */ |
||
554 | const struct nine_lconstf *lconstf = &device->state.vs->lconstf; |
||
555 | const struct nine_range *r = lconstf->ranges; |
||
556 | unsigned n = 0; |
||
557 | float *dst = device->state.vs_lconstf_temp; |
||
558 | float *src = (float *)cb.user_buffer; |
||
559 | memcpy(dst, src, cb.buffer_size); |
||
560 | while (r) { |
||
561 | unsigned p = r->bgn; |
||
562 | unsigned c = r->end - r->bgn; |
||
563 | memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); |
||
564 | n += c; |
||
565 | r = r->next; |
||
566 | } |
||
567 | cb.user_buffer = dst; |
||
568 | } |
||
569 | |||
570 | pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb); |
||
571 | |||
572 | if (device->state.changed.vs_const_f) { |
||
573 | struct nine_range *r = device->state.changed.vs_const_f; |
||
574 | struct nine_range *p = r; |
||
575 | while (p->next) |
||
576 | p = p->next; |
||
577 | nine_range_pool_put_chain(&device->range_pool, r, p); |
||
578 | device->state.changed.vs_const_f = NULL; |
||
579 | } |
||
580 | state->changed.group &= ~NINE_STATE_VS_CONST; |
||
581 | } |
||
582 | |||
583 | static void |
||
584 | update_ps_constants_userbuf(struct NineDevice9 *device) |
||
585 | { |
||
586 | struct nine_state *state = &device->state; |
||
587 | struct pipe_context *pipe = device->pipe; |
||
588 | struct pipe_constant_buffer cb; |
||
589 | cb.buffer = NULL; |
||
590 | cb.buffer_offset = 0; |
||
591 | cb.buffer_size = device->state.ps->const_used_size; |
||
592 | cb.user_buffer = device->state.ps_const_f; |
||
593 | |||
594 | if (!cb.buffer_size) |
||
595 | return; |
||
596 | |||
597 | if (state->changed.ps_const_i) { |
||
598 | int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f]; |
||
599 | memcpy(idst, state->ps_const_i, sizeof(state->ps_const_i)); |
||
600 | state->changed.ps_const_i = 0; |
||
601 | } |
||
602 | if (state->changed.ps_const_b) { |
||
603 | int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f]; |
||
604 | uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; |
||
605 | memcpy(bdst, state->ps_const_b, sizeof(state->ps_const_b)); |
||
606 | state->changed.ps_const_b = 0; |
||
607 | } |
||
608 | |||
609 | pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb); |
||
610 | |||
611 | if (device->state.changed.ps_const_f) { |
||
612 | struct nine_range *r = device->state.changed.ps_const_f; |
||
613 | struct nine_range *p = r; |
||
614 | while (p->next) |
||
615 | p = p->next; |
||
616 | nine_range_pool_put_chain(&device->range_pool, r, p); |
||
617 | device->state.changed.ps_const_f = NULL; |
||
618 | } |
||
619 | state->changed.group &= ~NINE_STATE_PS_CONST; |
||
620 | } |
||
621 | |||
622 | static void |
||
623 | update_vertex_buffers(struct NineDevice9 *device) |
||
624 | { |
||
625 | struct pipe_context *pipe = device->pipe; |
||
626 | struct nine_state *state = &device->state; |
||
627 | struct pipe_vertex_buffer dummy_vtxbuf; |
||
628 | uint32_t mask = state->changed.vtxbuf; |
||
629 | unsigned i; |
||
630 | unsigned start; |
||
631 | |||
632 | DBG("mask=%x\n", mask); |
||
633 | |||
634 | if (state->dummy_vbo_bound_at >= 0) { |
||
635 | if (!state->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, state->dummy_vbo_bound_at, |
||
641 | 1, &dummy_vtxbuf); |
||
642 | state->vbo_bound_done = TRUE; |
||
643 | } |
||
644 | mask &= ~(1 << state->dummy_vbo_bound_at); |
||
645 | } |
||
646 | |||
647 | for (i = 0; mask; mask >>= 1, ++i) { |
||
648 | if (mask & 1) { |
||
649 | if (state->vtxbuf[i].buffer) |
||
650 | pipe->set_vertex_buffers(pipe, i, 1, &state->vtxbuf[i]); |
||
651 | else |
||
652 | pipe->set_vertex_buffers(pipe, i, 1, NULL); |
||
653 | } |
||
654 | } |
||
655 | |||
656 | state->changed.vtxbuf = 0; |
||
657 | } |
||
658 | |||
659 | static INLINE void |
||
660 | update_index_buffer(struct NineDevice9 *device) |
||
661 | { |
||
662 | struct pipe_context *pipe = device->pipe; |
||
663 | if (device->state.idxbuf) |
||
664 | pipe->set_index_buffer(pipe, &device->state.idxbuf->buffer); |
||
665 | else |
||
666 | pipe->set_index_buffer(pipe, NULL); |
||
667 | } |
||
668 | |||
669 | /* TODO: only go through dirty textures */ |
||
670 | static void |
||
671 | validate_textures(struct NineDevice9 *device) |
||
672 | { |
||
673 | struct NineBaseTexture9 *tex, *ptr; |
||
674 | LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) { |
||
675 | list_delinit(&tex->list); |
||
676 | NineBaseTexture9_Validate(tex); |
||
677 | } |
||
678 | } |
||
679 | |||
680 | static INLINE boolean |
||
681 | update_sampler_derived(struct nine_state *state, unsigned s) |
||
682 | { |
||
683 | boolean changed = FALSE; |
||
684 | |||
685 | if (state->samp[s][NINED3DSAMP_SHADOW] != state->texture[s]->shadow) { |
||
686 | changed = TRUE; |
||
687 | state->samp[s][NINED3DSAMP_SHADOW] = state->texture[s]->shadow; |
||
688 | } |
||
689 | |||
690 | if (state->samp[s][D3DSAMP_MIPFILTER] != D3DTEXF_NONE) { |
||
691 | int lod = state->samp[s][D3DSAMP_MAXMIPLEVEL] - state->texture[s]->managed.lod; |
||
692 | if (lod < 0) |
||
693 | lod = 0; |
||
694 | if (state->samp[s][NINED3DSAMP_MINLOD] != lod) { |
||
695 | changed = TRUE; |
||
696 | state->samp[s][NINED3DSAMP_MINLOD] = lod; |
||
697 | } |
||
698 | } else { |
||
699 | state->changed.sampler[s] &= ~0x300; /* lod changes irrelevant */ |
||
700 | } |
||
701 | |||
702 | return changed; |
||
703 | } |
||
704 | |||
705 | /* TODO: add sRGB override to pipe_sampler_state ? */ |
||
706 | static void |
||
707 | update_textures_and_samplers(struct NineDevice9 *device) |
||
708 | { |
||
709 | struct pipe_context *pipe = device->pipe; |
||
710 | struct nine_state *state = &device->state; |
||
711 | struct pipe_sampler_view *view[NINE_MAX_SAMPLERS]; |
||
712 | struct pipe_sampler_state samp; |
||
713 | unsigned num_textures; |
||
714 | unsigned i; |
||
715 | boolean commit_views; |
||
716 | boolean commit_samplers; |
||
717 | uint16_t sampler_mask = state->ps ? state->ps->sampler_mask : |
||
718 | device->ff.ps->sampler_mask; |
||
719 | |||
720 | /* TODO: Can we reduce iterations here ? */ |
||
721 | |||
722 | commit_views = FALSE; |
||
723 | commit_samplers = FALSE; |
||
724 | state->bound_samplers_mask_ps = 0; |
||
725 | for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) { |
||
726 | const unsigned s = NINE_SAMPLER_PS(i); |
||
727 | int sRGB; |
||
728 | |||
729 | if (!state->texture[s] && !(sampler_mask & (1 << i))) { |
||
730 | view[i] = NULL; |
||
731 | continue; |
||
732 | } |
||
733 | |||
734 | if (state->texture[s]) { |
||
735 | sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; |
||
736 | |||
737 | view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB); |
||
738 | num_textures = i + 1; |
||
739 | |||
740 | if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) { |
||
741 | state->changed.sampler[s] = 0; |
||
742 | commit_samplers = TRUE; |
||
743 | nine_convert_sampler_state(device->cso, s, state->samp[s]); |
||
744 | } |
||
745 | } else { |
||
746 | /* Bind dummy sampler. We do not bind dummy sampler when |
||
747 | * it is not needed because it could add overhead. The |
||
748 | * dummy sampler should have r=g=b=0 and a=1. We do not |
||
749 | * unbind dummy sampler directly when they are not needed |
||
750 | * anymore, but they're going to be removed as long as texture |
||
751 | * or sampler states are changed. */ |
||
752 | view[i] = device->dummy_sampler; |
||
753 | num_textures = i + 1; |
||
754 | |||
755 | memset(&samp, 0, sizeof(samp)); |
||
756 | samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
||
757 | samp.max_lod = 15.0f; |
||
758 | samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
||
759 | samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
||
760 | samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
||
761 | samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
||
762 | samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
||
763 | samp.compare_mode = PIPE_TEX_COMPARE_NONE; |
||
764 | samp.compare_func = PIPE_FUNC_LEQUAL; |
||
765 | samp.normalized_coords = 1; |
||
766 | samp.seamless_cube_map = 1; |
||
767 | |||
768 | cso_single_sampler(device->cso, PIPE_SHADER_FRAGMENT, |
||
769 | s - NINE_SAMPLER_PS(0), &samp); |
||
770 | |||
771 | commit_views = TRUE; |
||
772 | commit_samplers = TRUE; |
||
773 | state->changed.sampler[s] = ~0; |
||
774 | } |
||
775 | |||
776 | state->bound_samplers_mask_ps |= (1 << s); |
||
777 | } |
||
778 | |||
779 | commit_views |= (state->changed.texture & NINE_PS_SAMPLERS_MASK) != 0; |
||
780 | commit_views |= state->changed.srgb; |
||
781 | if (commit_views) |
||
782 | pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, |
||
783 | num_textures, view); |
||
784 | |||
785 | if (commit_samplers) |
||
786 | cso_single_sampler_done(device->cso, PIPE_SHADER_FRAGMENT); |
||
787 | |||
788 | commit_views = FALSE; |
||
789 | commit_samplers = FALSE; |
||
790 | sampler_mask = state->vs ? state->vs->sampler_mask : 0; |
||
791 | state->bound_samplers_mask_vs = 0; |
||
792 | for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_VS; ++i) { |
||
793 | const unsigned s = NINE_SAMPLER_VS(i); |
||
794 | int sRGB; |
||
795 | |||
796 | if (!state->texture[s] && !(sampler_mask & (1 << i))) { |
||
797 | view[i] = NULL; |
||
798 | continue; |
||
799 | } |
||
800 | |||
801 | if (state->texture[s]) { |
||
802 | sRGB = state->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; |
||
803 | |||
804 | view[i] = NineBaseTexture9_GetSamplerView(state->texture[s], sRGB); |
||
805 | num_textures = i + 1; |
||
806 | |||
807 | if (update_sampler_derived(state, s) || (state->changed.sampler[s] & 0x05fe)) { |
||
808 | state->changed.sampler[s] = 0; |
||
809 | commit_samplers = TRUE; |
||
810 | nine_convert_sampler_state(device->cso, s, state->samp[s]); |
||
811 | } |
||
812 | } else { |
||
813 | /* Bind dummy sampler. We do not bind dummy sampler when |
||
814 | * it is not needed because it could add overhead. The |
||
815 | * dummy sampler should have r=g=b=0 and a=1. We do not |
||
816 | * unbind dummy sampler directly when they are not needed |
||
817 | * anymore, but they're going to be removed as long as texture |
||
818 | * or sampler states are changed. */ |
||
819 | view[i] = device->dummy_sampler; |
||
820 | num_textures = i + 1; |
||
821 | |||
822 | memset(&samp, 0, sizeof(samp)); |
||
823 | samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
||
824 | samp.max_lod = 15.0f; |
||
825 | samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
||
826 | samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
||
827 | samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
||
828 | samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
||
829 | samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
||
830 | samp.compare_mode = PIPE_TEX_COMPARE_NONE; |
||
831 | samp.compare_func = PIPE_FUNC_LEQUAL; |
||
832 | samp.normalized_coords = 1; |
||
833 | samp.seamless_cube_map = 1; |
||
834 | |||
835 | cso_single_sampler(device->cso, PIPE_SHADER_VERTEX, |
||
836 | s - NINE_SAMPLER_VS(0), &samp); |
||
837 | |||
838 | commit_views = TRUE; |
||
839 | commit_samplers = TRUE; |
||
840 | state->changed.sampler[s] = ~0; |
||
841 | } |
||
842 | |||
843 | state->bound_samplers_mask_vs |= (1 << s); |
||
844 | } |
||
845 | commit_views |= (state->changed.texture & NINE_VS_SAMPLERS_MASK) != 0; |
||
846 | commit_views |= state->changed.srgb; |
||
847 | if (commit_views) |
||
848 | pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, |
||
849 | num_textures, view); |
||
850 | |||
851 | if (commit_samplers) |
||
852 | cso_single_sampler_done(device->cso, PIPE_SHADER_VERTEX); |
||
853 | |||
854 | state->changed.srgb = FALSE; |
||
855 | state->changed.texture = 0; |
||
856 | } |
||
857 | |||
858 | |||
859 | #define NINE_STATE_FREQ_GROUP_0 \ |
||
860 | (NINE_STATE_FB | \ |
||
861 | NINE_STATE_VIEWPORT | \ |
||
862 | NINE_STATE_SCISSOR | \ |
||
863 | NINE_STATE_BLEND | \ |
||
864 | NINE_STATE_DSA | \ |
||
865 | NINE_STATE_RASTERIZER | \ |
||
866 | NINE_STATE_VS | \ |
||
867 | NINE_STATE_PS | \ |
||
868 | NINE_STATE_BLEND_COLOR | \ |
||
869 | NINE_STATE_STENCIL_REF | \ |
||
870 | NINE_STATE_SAMPLE_MASK) |
||
871 | |||
872 | #define NINE_STATE_FREQ_GROUP_1 ~NINE_STATE_FREQ_GROUP_0 |
||
873 | |||
874 | #define NINE_STATE_SHADER_VARIANT_GROUP \ |
||
875 | (NINE_STATE_TEXTURE | \ |
||
876 | NINE_STATE_VS | \ |
||
877 | NINE_STATE_PS) |
||
878 | |||
879 | boolean |
||
880 | nine_update_state(struct NineDevice9 *device, uint32_t mask) |
||
881 | { |
||
882 | struct pipe_context *pipe = device->pipe; |
||
883 | struct nine_state *state = &device->state; |
||
884 | uint32_t group; |
||
885 | |||
886 | DBG("changed state groups: %x | %x\n", |
||
887 | state->changed.group & NINE_STATE_FREQ_GROUP_0, |
||
888 | state->changed.group & NINE_STATE_FREQ_GROUP_1); |
||
889 | |||
890 | /* NOTE: We may want to use the cso cache for everything, or let |
||
891 | * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't |
||
892 | * have to care about state being clobbered here and could merge this back |
||
893 | * into update_textures. Except, we also need to re-validate textures that |
||
894 | * may be dirty anyway, even if no texture bindings changed. |
||
895 | */ |
||
896 | validate_textures(device); /* may clobber state */ |
||
897 | |||
898 | /* ff_update may change VS/PS dirty bits */ |
||
899 | if ((mask & NINE_STATE_FF) && unlikely(!state->vs || !state->ps)) |
||
900 | nine_ff_update(device); |
||
901 | group = state->changed.group & mask; |
||
902 | |||
903 | if (group & NINE_STATE_SHADER_VARIANT_GROUP) |
||
904 | group |= update_shader_variant_keys(device); |
||
905 | |||
906 | if (group & NINE_STATE_FREQ_GROUP_0) { |
||
907 | if (group & NINE_STATE_FB) |
||
908 | group = update_framebuffer(device) & mask; |
||
909 | if (group & NINE_STATE_VIEWPORT) |
||
910 | update_viewport(device); |
||
911 | if (group & NINE_STATE_SCISSOR) |
||
912 | update_scissor(device); |
||
913 | |||
914 | if (group & NINE_STATE_DSA) |
||
915 | update_dsa(device); |
||
916 | if (group & NINE_STATE_BLEND) |
||
917 | update_blend(device); |
||
918 | |||
919 | if (group & NINE_STATE_VS) |
||
920 | group |= update_vs(device); |
||
921 | |||
922 | if (group & NINE_STATE_RASTERIZER) |
||
923 | update_rasterizer(device); |
||
924 | |||
925 | if (group & NINE_STATE_PS) |
||
926 | group |= update_ps(device); |
||
927 | |||
928 | if (group & NINE_STATE_BLEND_COLOR) { |
||
929 | struct pipe_blend_color color; |
||
930 | d3dcolor_to_rgba(&color.color[0], state->rs[D3DRS_BLENDFACTOR]); |
||
931 | pipe->set_blend_color(pipe, &color); |
||
932 | } |
||
933 | if (group & NINE_STATE_SAMPLE_MASK) { |
||
934 | pipe->set_sample_mask(pipe, state->rs[D3DRS_MULTISAMPLEMASK]); |
||
935 | } |
||
936 | if (group & NINE_STATE_STENCIL_REF) { |
||
937 | struct pipe_stencil_ref ref; |
||
938 | ref.ref_value[0] = state->rs[D3DRS_STENCILREF]; |
||
939 | ref.ref_value[1] = ref.ref_value[0]; |
||
940 | pipe->set_stencil_ref(pipe, &ref); |
||
941 | } |
||
942 | } |
||
943 | |||
944 | if (state->changed.ucp) { |
||
945 | pipe->set_clip_state(pipe, &state->clip); |
||
946 | state->changed.ucp = 0; |
||
947 | } |
||
948 | |||
949 | if (group & (NINE_STATE_FREQ_GROUP_1 | NINE_STATE_VS)) { |
||
950 | if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER)) |
||
951 | update_textures_and_samplers(device); |
||
952 | |||
953 | if (group & NINE_STATE_IDXBUF) |
||
954 | update_index_buffer(device); |
||
955 | |||
956 | if ((group & (NINE_STATE_VDECL | NINE_STATE_VS)) || |
||
957 | state->changed.stream_freq & ~1) |
||
958 | update_vertex_elements(device); |
||
959 | |||
960 | if (device->prefer_user_constbuf) { |
||
961 | if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS)) && state->vs) |
||
962 | update_vs_constants_userbuf(device); |
||
963 | if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && state->ps) |
||
964 | update_ps_constants_userbuf(device); |
||
965 | } else { |
||
966 | if ((group & NINE_STATE_VS_CONST) && state->vs) |
||
967 | update_constants(device, PIPE_SHADER_VERTEX); |
||
968 | if ((group & NINE_STATE_PS_CONST) && state->ps) |
||
969 | update_constants(device, PIPE_SHADER_FRAGMENT); |
||
970 | } |
||
971 | } |
||
972 | if (state->changed.vtxbuf) |
||
973 | update_vertex_buffers(device); |
||
974 | |||
975 | device->state.changed.group &= ~mask | |
||
976 | (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST); |
||
977 | |||
978 | DBG("finished\n"); |
||
979 | |||
980 | return TRUE; |
||
981 | } |
||
982 | |||
983 | |||
984 | static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] = |
||
985 | { |
||
986 | /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */ |
||
987 | [D3DRS_ZENABLE] = D3DZB_FALSE, |
||
988 | [D3DRS_FILLMODE] = D3DFILL_SOLID, |
||
989 | [D3DRS_SHADEMODE] = D3DSHADE_GOURAUD, |
||
990 | /* [D3DRS_LINEPATTERN] = 0x00000000, */ |
||
991 | [D3DRS_ZWRITEENABLE] = TRUE, |
||
992 | [D3DRS_ALPHATESTENABLE] = FALSE, |
||
993 | [D3DRS_LASTPIXEL] = TRUE, |
||
994 | [D3DRS_SRCBLEND] = D3DBLEND_ONE, |
||
995 | [D3DRS_DESTBLEND] = D3DBLEND_ZERO, |
||
996 | [D3DRS_CULLMODE] = D3DCULL_CCW, |
||
997 | [D3DRS_ZFUNC] = D3DCMP_LESSEQUAL, |
||
998 | [D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS, |
||
999 | [D3DRS_ALPHAREF] = 0, |
||
1000 | [D3DRS_DITHERENABLE] = FALSE, |
||
1001 | [D3DRS_ALPHABLENDENABLE] = FALSE, |
||
1002 | [D3DRS_FOGENABLE] = FALSE, |
||
1003 | [D3DRS_SPECULARENABLE] = FALSE, |
||
1004 | /* [D3DRS_ZVISIBLE] = 0, */ |
||
1005 | [D3DRS_FOGCOLOR] = 0, |
||
1006 | [D3DRS_FOGTABLEMODE] = D3DFOG_NONE, |
||
1007 | [D3DRS_FOGSTART] = 0x00000000, |
||
1008 | [D3DRS_FOGEND] = 0x3F800000, |
||
1009 | [D3DRS_FOGDENSITY] = 0x3F800000, |
||
1010 | /* [D3DRS_EDGEANTIALIAS] = FALSE, */ |
||
1011 | [D3DRS_RANGEFOGENABLE] = FALSE, |
||
1012 | [D3DRS_STENCILENABLE] = FALSE, |
||
1013 | [D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP, |
||
1014 | [D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP, |
||
1015 | [D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP, |
||
1016 | [D3DRS_STENCILREF] = 0, |
||
1017 | [D3DRS_STENCILMASK] = 0xFFFFFFFF, |
||
1018 | [D3DRS_STENCILFUNC] = D3DCMP_ALWAYS, |
||
1019 | [D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF, |
||
1020 | [D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF, |
||
1021 | [D3DRS_WRAP0] = 0, |
||
1022 | [D3DRS_WRAP1] = 0, |
||
1023 | [D3DRS_WRAP2] = 0, |
||
1024 | [D3DRS_WRAP3] = 0, |
||
1025 | [D3DRS_WRAP4] = 0, |
||
1026 | [D3DRS_WRAP5] = 0, |
||
1027 | [D3DRS_WRAP6] = 0, |
||
1028 | [D3DRS_WRAP7] = 0, |
||
1029 | [D3DRS_CLIPPING] = TRUE, |
||
1030 | [D3DRS_LIGHTING] = TRUE, |
||
1031 | [D3DRS_AMBIENT] = 0, |
||
1032 | [D3DRS_FOGVERTEXMODE] = D3DFOG_NONE, |
||
1033 | [D3DRS_COLORVERTEX] = TRUE, |
||
1034 | [D3DRS_LOCALVIEWER] = TRUE, |
||
1035 | [D3DRS_NORMALIZENORMALS] = FALSE, |
||
1036 | [D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1, |
||
1037 | [D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2, |
||
1038 | [D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL, |
||
1039 | [D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL, |
||
1040 | [D3DRS_VERTEXBLEND] = D3DVBF_DISABLE, |
||
1041 | [D3DRS_CLIPPLANEENABLE] = 0, |
||
1042 | /* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */ |
||
1043 | [D3DRS_POINTSIZE] = 0x3F800000, |
||
1044 | [D3DRS_POINTSIZE_MIN] = 0x3F800000, |
||
1045 | [D3DRS_POINTSPRITEENABLE] = FALSE, |
||
1046 | [D3DRS_POINTSCALEENABLE] = FALSE, |
||
1047 | [D3DRS_POINTSCALE_A] = 0x3F800000, |
||
1048 | [D3DRS_POINTSCALE_B] = 0x00000000, |
||
1049 | [D3DRS_POINTSCALE_C] = 0x00000000, |
||
1050 | [D3DRS_MULTISAMPLEANTIALIAS] = TRUE, |
||
1051 | [D3DRS_MULTISAMPLEMASK] = 0xFFFFFFFF, |
||
1052 | [D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE, |
||
1053 | /* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */ |
||
1054 | [D3DRS_DEBUGMONITORTOKEN] = 0xDEADCAFE, |
||
1055 | [D3DRS_POINTSIZE_MAX] = 0x3F800000, /* depends on cap */ |
||
1056 | [D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE, |
||
1057 | [D3DRS_COLORWRITEENABLE] = 0x0000000f, |
||
1058 | [D3DRS_TWEENFACTOR] = 0x00000000, |
||
1059 | [D3DRS_BLENDOP] = D3DBLENDOP_ADD, |
||
1060 | [D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC, |
||
1061 | [D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR, |
||
1062 | [D3DRS_SCISSORTESTENABLE] = FALSE, |
||
1063 | [D3DRS_SLOPESCALEDEPTHBIAS] = 0, |
||
1064 | [D3DRS_MINTESSELLATIONLEVEL] = 0x3F800000, |
||
1065 | [D3DRS_MAXTESSELLATIONLEVEL] = 0x3F800000, |
||
1066 | [D3DRS_ANTIALIASEDLINEENABLE] = FALSE, |
||
1067 | [D3DRS_ADAPTIVETESS_X] = 0x00000000, |
||
1068 | [D3DRS_ADAPTIVETESS_Y] = 0x00000000, |
||
1069 | [D3DRS_ADAPTIVETESS_Z] = 0x3F800000, |
||
1070 | [D3DRS_ADAPTIVETESS_W] = 0x00000000, |
||
1071 | [D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE, |
||
1072 | [D3DRS_TWOSIDEDSTENCILMODE] = FALSE, |
||
1073 | [D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP, |
||
1074 | [D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP, |
||
1075 | [D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP, |
||
1076 | [D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS, |
||
1077 | [D3DRS_COLORWRITEENABLE1] = 0x0000000F, |
||
1078 | [D3DRS_COLORWRITEENABLE2] = 0x0000000F, |
||
1079 | [D3DRS_COLORWRITEENABLE3] = 0x0000000F, |
||
1080 | [D3DRS_BLENDFACTOR] = 0xFFFFFFFF, |
||
1081 | [D3DRS_SRGBWRITEENABLE] = 0, |
||
1082 | [D3DRS_DEPTHBIAS] = 0, |
||
1083 | [D3DRS_WRAP8] = 0, |
||
1084 | [D3DRS_WRAP9] = 0, |
||
1085 | [D3DRS_WRAP10] = 0, |
||
1086 | [D3DRS_WRAP11] = 0, |
||
1087 | [D3DRS_WRAP12] = 0, |
||
1088 | [D3DRS_WRAP13] = 0, |
||
1089 | [D3DRS_WRAP14] = 0, |
||
1090 | [D3DRS_WRAP15] = 0, |
||
1091 | [D3DRS_SEPARATEALPHABLENDENABLE] = FALSE, |
||
1092 | [D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE, |
||
1093 | [D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO, |
||
1094 | [D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD, |
||
1095 | [NINED3DRS_VSPOINTSIZE] = FALSE, |
||
1096 | [NINED3DRS_RTMASK] = 0xf, |
||
1097 | [NINED3DRS_ALPHACOVERAGE] = FALSE |
||
1098 | }; |
||
1099 | static const DWORD nine_tex_stage_state_defaults[NINED3DTSS_LAST + 1] = |
||
1100 | { |
||
1101 | [D3DTSS_COLOROP] = D3DTOP_DISABLE, |
||
1102 | [D3DTSS_ALPHAOP] = D3DTOP_DISABLE, |
||
1103 | [D3DTSS_COLORARG1] = D3DTA_TEXTURE, |
||
1104 | [D3DTSS_COLORARG2] = D3DTA_CURRENT, |
||
1105 | [D3DTSS_COLORARG0] = D3DTA_CURRENT, |
||
1106 | [D3DTSS_ALPHAARG1] = D3DTA_TEXTURE, |
||
1107 | [D3DTSS_ALPHAARG2] = D3DTA_CURRENT, |
||
1108 | [D3DTSS_ALPHAARG0] = D3DTA_CURRENT, |
||
1109 | [D3DTSS_RESULTARG] = D3DTA_CURRENT, |
||
1110 | [D3DTSS_BUMPENVMAT00] = 0, |
||
1111 | [D3DTSS_BUMPENVMAT01] = 0, |
||
1112 | [D3DTSS_BUMPENVMAT10] = 0, |
||
1113 | [D3DTSS_BUMPENVMAT11] = 0, |
||
1114 | [D3DTSS_BUMPENVLSCALE] = 0, |
||
1115 | [D3DTSS_BUMPENVLOFFSET] = 0, |
||
1116 | [D3DTSS_TEXCOORDINDEX] = 0, |
||
1117 | [D3DTSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE, |
||
1118 | }; |
||
1119 | static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] = |
||
1120 | { |
||
1121 | [D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP, |
||
1122 | [D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP, |
||
1123 | [D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP, |
||
1124 | [D3DSAMP_BORDERCOLOR] = 0, |
||
1125 | [D3DSAMP_MAGFILTER] = D3DTEXF_POINT, |
||
1126 | [D3DSAMP_MINFILTER] = D3DTEXF_POINT, |
||
1127 | [D3DSAMP_MIPFILTER] = D3DTEXF_NONE, |
||
1128 | [D3DSAMP_MIPMAPLODBIAS] = 0, |
||
1129 | [D3DSAMP_MAXMIPLEVEL] = 0, |
||
1130 | [D3DSAMP_MAXANISOTROPY] = 1, |
||
1131 | [D3DSAMP_SRGBTEXTURE] = 0, |
||
1132 | [D3DSAMP_ELEMENTINDEX] = 0, |
||
1133 | [D3DSAMP_DMAPOFFSET] = 0, |
||
1134 | [NINED3DSAMP_MINLOD] = 0, |
||
1135 | [NINED3DSAMP_SHADOW] = 0 |
||
1136 | }; |
||
1137 | void |
||
1138 | nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps, |
||
1139 | boolean is_reset) |
||
1140 | { |
||
1141 | struct nine_state *state = &device->state; |
||
1142 | unsigned s; |
||
1143 | |||
1144 | /* Initialize defaults. |
||
1145 | */ |
||
1146 | memcpy(state->rs, nine_render_state_defaults, sizeof(state->rs)); |
||
1147 | |||
1148 | for (s = 0; s < Elements(state->ff.tex_stage); ++s) { |
||
1149 | memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults, |
||
1150 | sizeof(state->ff.tex_stage[s])); |
||
1151 | state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] = s; |
||
1152 | } |
||
1153 | state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE; |
||
1154 | state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1; |
||
1155 | |||
1156 | for (s = 0; s < Elements(state->samp); ++s) { |
||
1157 | memcpy(&state->samp[s], nine_samp_state_defaults, |
||
1158 | sizeof(state->samp[s])); |
||
1159 | } |
||
1160 | |||
1161 | if (state->vs_const_f) |
||
1162 | memset(state->vs_const_f, 0, device->vs_const_size); |
||
1163 | if (state->ps_const_f) |
||
1164 | memset(state->ps_const_f, 0, device->ps_const_size); |
||
1165 | |||
1166 | /* Cap dependent initial state: |
||
1167 | */ |
||
1168 | state->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize); |
||
1169 | |||
1170 | /* Set changed flags to initialize driver. |
||
1171 | */ |
||
1172 | state->changed.group = NINE_STATE_ALL; |
||
1173 | |||
1174 | state->ff.changed.transform[0] = ~0; |
||
1175 | state->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); |
||
1176 | |||
1177 | if (!is_reset) { |
||
1178 | state->viewport.MinZ = 0.0f; |
||
1179 | state->viewport.MaxZ = 1.0f; |
||
1180 | } |
||
1181 | |||
1182 | for (s = 0; s < Elements(state->changed.sampler); ++s) |
||
1183 | state->changed.sampler[s] = ~0; |
||
1184 | |||
1185 | if (!is_reset) { |
||
1186 | state->dummy_vbo_bound_at = -1; |
||
1187 | state->vbo_bound_done = FALSE; |
||
1188 | } |
||
1189 | } |
||
1190 | |||
1191 | void |
||
1192 | nine_state_clear(struct nine_state *state, const boolean device) |
||
1193 | { |
||
1194 | unsigned i; |
||
1195 | |||
1196 | for (i = 0; i < Elements(state->rt); ++i) |
||
1197 | nine_bind(&state->rt[i], NULL); |
||
1198 | nine_bind(&state->ds, NULL); |
||
1199 | nine_bind(&state->vs, NULL); |
||
1200 | nine_bind(&state->ps, NULL); |
||
1201 | nine_bind(&state->vdecl, NULL); |
||
1202 | for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) |
||
1203 | nine_bind(&state->stream[i], NULL); |
||
1204 | nine_bind(&state->idxbuf, NULL); |
||
1205 | for (i = 0; i < NINE_MAX_SAMPLERS; ++i) { |
||
1206 | if (device && |
||
1207 | state->texture[i] && |
||
1208 | --state->texture[i]->bind_count == 0) |
||
1209 | list_delinit(&state->texture[i]->list); |
||
1210 | nine_bind(&state->texture[i], NULL); |
||
1211 | } |
||
1212 | } |
||
1213 | |||
1214 | /* |
||
1215 | static const DWORD nine_render_states_pixel[] = |
||
1216 | { |
||
1217 | D3DRS_ALPHABLENDENABLE, |
||
1218 | D3DRS_ALPHAFUNC, |
||
1219 | D3DRS_ALPHAREF, |
||
1220 | D3DRS_ALPHATESTENABLE, |
||
1221 | D3DRS_ANTIALIASEDLINEENABLE, |
||
1222 | D3DRS_BLENDFACTOR, |
||
1223 | D3DRS_BLENDOP, |
||
1224 | D3DRS_BLENDOPALPHA, |
||
1225 | D3DRS_CCW_STENCILFAIL, |
||
1226 | D3DRS_CCW_STENCILPASS, |
||
1227 | D3DRS_CCW_STENCILZFAIL, |
||
1228 | D3DRS_COLORWRITEENABLE, |
||
1229 | D3DRS_COLORWRITEENABLE1, |
||
1230 | D3DRS_COLORWRITEENABLE2, |
||
1231 | D3DRS_COLORWRITEENABLE3, |
||
1232 | D3DRS_DEPTHBIAS, |
||
1233 | D3DRS_DESTBLEND, |
||
1234 | D3DRS_DESTBLENDALPHA, |
||
1235 | D3DRS_DITHERENABLE, |
||
1236 | D3DRS_FILLMODE, |
||
1237 | D3DRS_FOGDENSITY, |
||
1238 | D3DRS_FOGEND, |
||
1239 | D3DRS_FOGSTART, |
||
1240 | D3DRS_LASTPIXEL, |
||
1241 | D3DRS_SCISSORTESTENABLE, |
||
1242 | D3DRS_SEPARATEALPHABLENDENABLE, |
||
1243 | D3DRS_SHADEMODE, |
||
1244 | D3DRS_SLOPESCALEDEPTHBIAS, |
||
1245 | D3DRS_SRCBLEND, |
||
1246 | D3DRS_SRCBLENDALPHA, |
||
1247 | D3DRS_SRGBWRITEENABLE, |
||
1248 | D3DRS_STENCILENABLE, |
||
1249 | D3DRS_STENCILFAIL, |
||
1250 | D3DRS_STENCILFUNC, |
||
1251 | D3DRS_STENCILMASK, |
||
1252 | D3DRS_STENCILPASS, |
||
1253 | D3DRS_STENCILREF, |
||
1254 | D3DRS_STENCILWRITEMASK, |
||
1255 | D3DRS_STENCILZFAIL, |
||
1256 | D3DRS_TEXTUREFACTOR, |
||
1257 | D3DRS_TWOSIDEDSTENCILMODE, |
||
1258 | D3DRS_WRAP0, |
||
1259 | D3DRS_WRAP1, |
||
1260 | D3DRS_WRAP10, |
||
1261 | D3DRS_WRAP11, |
||
1262 | D3DRS_WRAP12, |
||
1263 | D3DRS_WRAP13, |
||
1264 | D3DRS_WRAP14, |
||
1265 | D3DRS_WRAP15, |
||
1266 | D3DRS_WRAP2, |
||
1267 | D3DRS_WRAP3, |
||
1268 | D3DRS_WRAP4, |
||
1269 | D3DRS_WRAP5, |
||
1270 | D3DRS_WRAP6, |
||
1271 | D3DRS_WRAP7, |
||
1272 | D3DRS_WRAP8, |
||
1273 | D3DRS_WRAP9, |
||
1274 | D3DRS_ZENABLE, |
||
1275 | D3DRS_ZFUNC, |
||
1276 | D3DRS_ZWRITEENABLE |
||
1277 | }; |
||
1278 | */ |
||
1279 | const uint32_t nine_render_states_pixel[(NINED3DRS_LAST + 31) / 32] = |
||
1280 | { |
||
1281 | 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000, |
||
1282 | 0x000000ff, 0xde01c900, 0x0003ffcf |
||
1283 | }; |
||
1284 | |||
1285 | /* |
||
1286 | static const DWORD nine_render_states_vertex[] = |
||
1287 | { |
||
1288 | D3DRS_ADAPTIVETESS_W, |
||
1289 | D3DRS_ADAPTIVETESS_X, |
||
1290 | D3DRS_ADAPTIVETESS_Y, |
||
1291 | D3DRS_ADAPTIVETESS_Z, |
||
1292 | D3DRS_AMBIENT, |
||
1293 | D3DRS_AMBIENTMATERIALSOURCE, |
||
1294 | D3DRS_CLIPPING, |
||
1295 | D3DRS_CLIPPLANEENABLE, |
||
1296 | D3DRS_COLORVERTEX, |
||
1297 | D3DRS_CULLMODE, |
||
1298 | D3DRS_DIFFUSEMATERIALSOURCE, |
||
1299 | D3DRS_EMISSIVEMATERIALSOURCE, |
||
1300 | D3DRS_ENABLEADAPTIVETESSELLATION, |
||
1301 | D3DRS_FOGCOLOR, |
||
1302 | D3DRS_FOGDENSITY, |
||
1303 | D3DRS_FOGENABLE, |
||
1304 | D3DRS_FOGEND, |
||
1305 | D3DRS_FOGSTART, |
||
1306 | D3DRS_FOGTABLEMODE, |
||
1307 | D3DRS_FOGVERTEXMODE, |
||
1308 | D3DRS_INDEXEDVERTEXBLENDENABLE, |
||
1309 | D3DRS_LIGHTING, |
||
1310 | D3DRS_LOCALVIEWER, |
||
1311 | D3DRS_MAXTESSELLATIONLEVEL, |
||
1312 | D3DRS_MINTESSELLATIONLEVEL, |
||
1313 | D3DRS_MULTISAMPLEANTIALIAS, |
||
1314 | D3DRS_MULTISAMPLEMASK, |
||
1315 | D3DRS_NORMALDEGREE, |
||
1316 | D3DRS_NORMALIZENORMALS, |
||
1317 | D3DRS_PATCHEDGESTYLE, |
||
1318 | D3DRS_POINTSCALE_A, |
||
1319 | D3DRS_POINTSCALE_B, |
||
1320 | D3DRS_POINTSCALE_C, |
||
1321 | D3DRS_POINTSCALEENABLE, |
||
1322 | D3DRS_POINTSIZE, |
||
1323 | D3DRS_POINTSIZE_MAX, |
||
1324 | D3DRS_POINTSIZE_MIN, |
||
1325 | D3DRS_POINTSPRITEENABLE, |
||
1326 | D3DRS_POSITIONDEGREE, |
||
1327 | D3DRS_RANGEFOGENABLE, |
||
1328 | D3DRS_SHADEMODE, |
||
1329 | D3DRS_SPECULARENABLE, |
||
1330 | D3DRS_SPECULARMATERIALSOURCE, |
||
1331 | D3DRS_TWEENFACTOR, |
||
1332 | D3DRS_VERTEXBLEND |
||
1333 | }; |
||
1334 | */ |
||
1335 | const uint32_t nine_render_states_vertex[(NINED3DRS_LAST + 31) / 32] = |
||
1336 | { |
||
1337 | 0x30400200, 0x0001007c, 0x00000000, 0x00000000, |
||
1338 | 0xfd9efb00, 0x01fc34cf, 0x00000000 |
||
1339 | }; |
||
1340 | |||
1341 | /* TODO: put in the right values */ |
||
1342 | const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] = |
||
1343 | { |
||
1344 | [D3DRS_ZENABLE] = NINE_STATE_DSA, |
||
1345 | [D3DRS_FILLMODE] = NINE_STATE_RASTERIZER, |
||
1346 | [D3DRS_SHADEMODE] = NINE_STATE_RASTERIZER, |
||
1347 | [D3DRS_ZWRITEENABLE] = NINE_STATE_DSA, |
||
1348 | [D3DRS_ALPHATESTENABLE] = NINE_STATE_DSA, |
||
1349 | [D3DRS_LASTPIXEL] = NINE_STATE_RASTERIZER, |
||
1350 | [D3DRS_SRCBLEND] = NINE_STATE_BLEND, |
||
1351 | [D3DRS_DESTBLEND] = NINE_STATE_BLEND, |
||
1352 | [D3DRS_CULLMODE] = NINE_STATE_RASTERIZER, |
||
1353 | [D3DRS_ZFUNC] = NINE_STATE_DSA, |
||
1354 | [D3DRS_ALPHAREF] = NINE_STATE_DSA, |
||
1355 | [D3DRS_ALPHAFUNC] = NINE_STATE_DSA, |
||
1356 | [D3DRS_DITHERENABLE] = NINE_STATE_RASTERIZER, |
||
1357 | [D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND, |
||
1358 | [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER, |
||
1359 | [D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING, |
||
1360 | [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER, |
||
1361 | [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER, |
||
1362 | [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER, |
||
1363 | [D3DRS_FOGEND] = NINE_STATE_FF_OTHER, |
||
1364 | [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER, |
||
1365 | [D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_OTHER, |
||
1366 | [D3DRS_STENCILENABLE] = NINE_STATE_DSA, |
||
1367 | [D3DRS_STENCILFAIL] = NINE_STATE_DSA, |
||
1368 | [D3DRS_STENCILZFAIL] = NINE_STATE_DSA, |
||
1369 | [D3DRS_STENCILPASS] = NINE_STATE_DSA, |
||
1370 | [D3DRS_STENCILFUNC] = NINE_STATE_DSA, |
||
1371 | [D3DRS_STENCILREF] = NINE_STATE_STENCIL_REF, |
||
1372 | [D3DRS_STENCILMASK] = NINE_STATE_DSA, |
||
1373 | [D3DRS_STENCILWRITEMASK] = NINE_STATE_DSA, |
||
1374 | [D3DRS_TEXTUREFACTOR] = NINE_STATE_FF_PSSTAGES, |
||
1375 | [D3DRS_WRAP0] = NINE_STATE_UNHANDLED, /* cylindrical wrap is crazy */ |
||
1376 | [D3DRS_WRAP1] = NINE_STATE_UNHANDLED, |
||
1377 | [D3DRS_WRAP2] = NINE_STATE_UNHANDLED, |
||
1378 | [D3DRS_WRAP3] = NINE_STATE_UNHANDLED, |
||
1379 | [D3DRS_WRAP4] = NINE_STATE_UNHANDLED, |
||
1380 | [D3DRS_WRAP5] = NINE_STATE_UNHANDLED, |
||
1381 | [D3DRS_WRAP6] = NINE_STATE_UNHANDLED, |
||
1382 | [D3DRS_WRAP7] = NINE_STATE_UNHANDLED, |
||
1383 | [D3DRS_CLIPPING] = 0, /* software vertex processing only */ |
||
1384 | [D3DRS_LIGHTING] = NINE_STATE_FF_LIGHTING, |
||
1385 | [D3DRS_AMBIENT] = NINE_STATE_FF_LIGHTING | NINE_STATE_FF_MATERIAL, |
||
1386 | [D3DRS_FOGVERTEXMODE] = NINE_STATE_FF_OTHER, |
||
1387 | [D3DRS_COLORVERTEX] = NINE_STATE_FF_LIGHTING, |
||
1388 | [D3DRS_LOCALVIEWER] = NINE_STATE_FF_LIGHTING, |
||
1389 | [D3DRS_NORMALIZENORMALS] = NINE_STATE_FF_OTHER, |
||
1390 | [D3DRS_DIFFUSEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, |
||
1391 | [D3DRS_SPECULARMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, |
||
1392 | [D3DRS_AMBIENTMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, |
||
1393 | [D3DRS_EMISSIVEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, |
||
1394 | [D3DRS_VERTEXBLEND] = NINE_STATE_FF_OTHER, |
||
1395 | [D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER, |
||
1396 | [D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER, |
||
1397 | [D3DRS_POINTSIZE_MIN] = NINE_STATE_MISC_CONST, |
||
1398 | [D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER, |
||
1399 | [D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_OTHER, |
||
1400 | [D3DRS_POINTSCALE_A] = NINE_STATE_FF_OTHER, |
||
1401 | [D3DRS_POINTSCALE_B] = NINE_STATE_FF_OTHER, |
||
1402 | [D3DRS_POINTSCALE_C] = NINE_STATE_FF_OTHER, |
||
1403 | [D3DRS_MULTISAMPLEANTIALIAS] = NINE_STATE_RASTERIZER, |
||
1404 | [D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK, |
||
1405 | [D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED, |
||
1406 | [D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED, |
||
1407 | [D3DRS_POINTSIZE_MAX] = NINE_STATE_MISC_CONST, |
||
1408 | [D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_OTHER, |
||
1409 | [D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND, |
||
1410 | [D3DRS_TWEENFACTOR] = NINE_STATE_FF_OTHER, |
||
1411 | [D3DRS_BLENDOP] = NINE_STATE_BLEND, |
||
1412 | [D3DRS_POSITIONDEGREE] = NINE_STATE_UNHANDLED, |
||
1413 | [D3DRS_NORMALDEGREE] = NINE_STATE_UNHANDLED, |
||
1414 | [D3DRS_SCISSORTESTENABLE] = NINE_STATE_RASTERIZER, |
||
1415 | [D3DRS_SLOPESCALEDEPTHBIAS] = NINE_STATE_RASTERIZER, |
||
1416 | [D3DRS_ANTIALIASEDLINEENABLE] = NINE_STATE_RASTERIZER, |
||
1417 | [D3DRS_MINTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, |
||
1418 | [D3DRS_MAXTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, |
||
1419 | [D3DRS_ADAPTIVETESS_X] = NINE_STATE_UNHANDLED, |
||
1420 | [D3DRS_ADAPTIVETESS_Y] = NINE_STATE_UNHANDLED, |
||
1421 | [D3DRS_ADAPTIVETESS_Z] = NINE_STATE_UNHANDLED, |
||
1422 | [D3DRS_ADAPTIVETESS_W] = NINE_STATE_UNHANDLED, |
||
1423 | [D3DRS_ENABLEADAPTIVETESSELLATION] = NINE_STATE_UNHANDLED, |
||
1424 | [D3DRS_TWOSIDEDSTENCILMODE] = NINE_STATE_DSA, |
||
1425 | [D3DRS_CCW_STENCILFAIL] = NINE_STATE_DSA, |
||
1426 | [D3DRS_CCW_STENCILZFAIL] = NINE_STATE_DSA, |
||
1427 | [D3DRS_CCW_STENCILPASS] = NINE_STATE_DSA, |
||
1428 | [D3DRS_CCW_STENCILFUNC] = NINE_STATE_DSA, |
||
1429 | [D3DRS_COLORWRITEENABLE1] = NINE_STATE_BLEND, |
||
1430 | [D3DRS_COLORWRITEENABLE2] = NINE_STATE_BLEND, |
||
1431 | [D3DRS_COLORWRITEENABLE3] = NINE_STATE_BLEND, |
||
1432 | [D3DRS_BLENDFACTOR] = NINE_STATE_BLEND_COLOR, |
||
1433 | [D3DRS_SRGBWRITEENABLE] = NINE_STATE_FB, |
||
1434 | [D3DRS_DEPTHBIAS] = NINE_STATE_RASTERIZER, |
||
1435 | [D3DRS_WRAP8] = NINE_STATE_UNHANDLED, /* cylwrap has to be done via GP */ |
||
1436 | [D3DRS_WRAP9] = NINE_STATE_UNHANDLED, |
||
1437 | [D3DRS_WRAP10] = NINE_STATE_UNHANDLED, |
||
1438 | [D3DRS_WRAP11] = NINE_STATE_UNHANDLED, |
||
1439 | [D3DRS_WRAP12] = NINE_STATE_UNHANDLED, |
||
1440 | [D3DRS_WRAP13] = NINE_STATE_UNHANDLED, |
||
1441 | [D3DRS_WRAP14] = NINE_STATE_UNHANDLED, |
||
1442 | [D3DRS_WRAP15] = NINE_STATE_UNHANDLED, |
||
1443 | [D3DRS_SEPARATEALPHABLENDENABLE] = NINE_STATE_BLEND, |
||
1444 | [D3DRS_SRCBLENDALPHA] = NINE_STATE_BLEND, |
||
1445 | [D3DRS_DESTBLENDALPHA] = NINE_STATE_BLEND, |
||
1446 | [D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND |
||
1447 | }; |
||
1448 | |||
1449 | D3DMATRIX * |
||
1450 | nine_state_access_transform(struct nine_state *state, D3DTRANSFORMSTATETYPE t, |
||
1451 | boolean alloc) |
||
1452 | { |
||
1453 | static D3DMATRIX Identity = { .m[0] = { 1, 0, 0, 0 }, |
||
1454 | .m[1] = { 0, 1, 0, 0 }, |
||
1455 | .m[2] = { 0, 0, 1, 0 }, |
||
1456 | .m[3] = { 0, 0, 0, 1 } }; |
||
1457 | unsigned index; |
||
1458 | |||
1459 | switch (t) { |
||
1460 | case D3DTS_VIEW: index = 0; break; |
||
1461 | case D3DTS_PROJECTION: index = 1; break; |
||
1462 | case D3DTS_TEXTURE0: index = 2; break; |
||
1463 | case D3DTS_TEXTURE1: index = 3; break; |
||
1464 | case D3DTS_TEXTURE2: index = 4; break; |
||
1465 | case D3DTS_TEXTURE3: index = 5; break; |
||
1466 | case D3DTS_TEXTURE4: index = 6; break; |
||
1467 | case D3DTS_TEXTURE5: index = 7; break; |
||
1468 | case D3DTS_TEXTURE6: index = 8; break; |
||
1469 | case D3DTS_TEXTURE7: index = 9; break; |
||
1470 | default: |
||
1471 | if (!(t >= D3DTS_WORLDMATRIX(0) && t <= D3DTS_WORLDMATRIX(255))) |
||
1472 | return NULL; |
||
1473 | index = 10 + (t - D3DTS_WORLDMATRIX(0)); |
||
1474 | break; |
||
1475 | } |
||
1476 | |||
1477 | if (index >= state->ff.num_transforms) { |
||
1478 | unsigned N = index + 1; |
||
1479 | unsigned n = state->ff.num_transforms; |
||
1480 | |||
1481 | if (!alloc) |
||
1482 | return &Identity; |
||
1483 | state->ff.transform = REALLOC(state->ff.transform, |
||
1484 | n * sizeof(D3DMATRIX), |
||
1485 | N * sizeof(D3DMATRIX)); |
||
1486 | for (; n < N; ++n) |
||
1487 | state->ff.transform[n] = Identity; |
||
1488 | state->ff.num_transforms = N; |
||
1489 | } |
||
1490 | return &state->ff.transform[index]; |
||
1491 | } |
||
1492 | |||
1493 | #define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n |
||
1494 | const char *nine_d3drs_to_string(DWORD State) |
||
1495 | { |
||
1496 | switch (State) { |
||
1497 | D3DRS_TO_STRING_CASE(ZENABLE); |
||
1498 | D3DRS_TO_STRING_CASE(FILLMODE); |
||
1499 | D3DRS_TO_STRING_CASE(SHADEMODE); |
||
1500 | D3DRS_TO_STRING_CASE(ZWRITEENABLE); |
||
1501 | D3DRS_TO_STRING_CASE(ALPHATESTENABLE); |
||
1502 | D3DRS_TO_STRING_CASE(LASTPIXEL); |
||
1503 | D3DRS_TO_STRING_CASE(SRCBLEND); |
||
1504 | D3DRS_TO_STRING_CASE(DESTBLEND); |
||
1505 | D3DRS_TO_STRING_CASE(CULLMODE); |
||
1506 | D3DRS_TO_STRING_CASE(ZFUNC); |
||
1507 | D3DRS_TO_STRING_CASE(ALPHAREF); |
||
1508 | D3DRS_TO_STRING_CASE(ALPHAFUNC); |
||
1509 | D3DRS_TO_STRING_CASE(DITHERENABLE); |
||
1510 | D3DRS_TO_STRING_CASE(ALPHABLENDENABLE); |
||
1511 | D3DRS_TO_STRING_CASE(FOGENABLE); |
||
1512 | D3DRS_TO_STRING_CASE(SPECULARENABLE); |
||
1513 | D3DRS_TO_STRING_CASE(FOGCOLOR); |
||
1514 | D3DRS_TO_STRING_CASE(FOGTABLEMODE); |
||
1515 | D3DRS_TO_STRING_CASE(FOGSTART); |
||
1516 | D3DRS_TO_STRING_CASE(FOGEND); |
||
1517 | D3DRS_TO_STRING_CASE(FOGDENSITY); |
||
1518 | D3DRS_TO_STRING_CASE(RANGEFOGENABLE); |
||
1519 | D3DRS_TO_STRING_CASE(STENCILENABLE); |
||
1520 | D3DRS_TO_STRING_CASE(STENCILFAIL); |
||
1521 | D3DRS_TO_STRING_CASE(STENCILZFAIL); |
||
1522 | D3DRS_TO_STRING_CASE(STENCILPASS); |
||
1523 | D3DRS_TO_STRING_CASE(STENCILFUNC); |
||
1524 | D3DRS_TO_STRING_CASE(STENCILREF); |
||
1525 | D3DRS_TO_STRING_CASE(STENCILMASK); |
||
1526 | D3DRS_TO_STRING_CASE(STENCILWRITEMASK); |
||
1527 | D3DRS_TO_STRING_CASE(TEXTUREFACTOR); |
||
1528 | D3DRS_TO_STRING_CASE(WRAP0); |
||
1529 | D3DRS_TO_STRING_CASE(WRAP1); |
||
1530 | D3DRS_TO_STRING_CASE(WRAP2); |
||
1531 | D3DRS_TO_STRING_CASE(WRAP3); |
||
1532 | D3DRS_TO_STRING_CASE(WRAP4); |
||
1533 | D3DRS_TO_STRING_CASE(WRAP5); |
||
1534 | D3DRS_TO_STRING_CASE(WRAP6); |
||
1535 | D3DRS_TO_STRING_CASE(WRAP7); |
||
1536 | D3DRS_TO_STRING_CASE(CLIPPING); |
||
1537 | D3DRS_TO_STRING_CASE(LIGHTING); |
||
1538 | D3DRS_TO_STRING_CASE(AMBIENT); |
||
1539 | D3DRS_TO_STRING_CASE(FOGVERTEXMODE); |
||
1540 | D3DRS_TO_STRING_CASE(COLORVERTEX); |
||
1541 | D3DRS_TO_STRING_CASE(LOCALVIEWER); |
||
1542 | D3DRS_TO_STRING_CASE(NORMALIZENORMALS); |
||
1543 | D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE); |
||
1544 | D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE); |
||
1545 | D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE); |
||
1546 | D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE); |
||
1547 | D3DRS_TO_STRING_CASE(VERTEXBLEND); |
||
1548 | D3DRS_TO_STRING_CASE(CLIPPLANEENABLE); |
||
1549 | D3DRS_TO_STRING_CASE(POINTSIZE); |
||
1550 | D3DRS_TO_STRING_CASE(POINTSIZE_MIN); |
||
1551 | D3DRS_TO_STRING_CASE(POINTSPRITEENABLE); |
||
1552 | D3DRS_TO_STRING_CASE(POINTSCALEENABLE); |
||
1553 | D3DRS_TO_STRING_CASE(POINTSCALE_A); |
||
1554 | D3DRS_TO_STRING_CASE(POINTSCALE_B); |
||
1555 | D3DRS_TO_STRING_CASE(POINTSCALE_C); |
||
1556 | D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS); |
||
1557 | D3DRS_TO_STRING_CASE(MULTISAMPLEMASK); |
||
1558 | D3DRS_TO_STRING_CASE(PATCHEDGESTYLE); |
||
1559 | D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN); |
||
1560 | D3DRS_TO_STRING_CASE(POINTSIZE_MAX); |
||
1561 | D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE); |
||
1562 | D3DRS_TO_STRING_CASE(COLORWRITEENABLE); |
||
1563 | D3DRS_TO_STRING_CASE(TWEENFACTOR); |
||
1564 | D3DRS_TO_STRING_CASE(BLENDOP); |
||
1565 | D3DRS_TO_STRING_CASE(POSITIONDEGREE); |
||
1566 | D3DRS_TO_STRING_CASE(NORMALDEGREE); |
||
1567 | D3DRS_TO_STRING_CASE(SCISSORTESTENABLE); |
||
1568 | D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS); |
||
1569 | D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE); |
||
1570 | D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL); |
||
1571 | D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL); |
||
1572 | D3DRS_TO_STRING_CASE(ADAPTIVETESS_X); |
||
1573 | D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y); |
||
1574 | D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z); |
||
1575 | D3DRS_TO_STRING_CASE(ADAPTIVETESS_W); |
||
1576 | D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION); |
||
1577 | D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE); |
||
1578 | D3DRS_TO_STRING_CASE(CCW_STENCILFAIL); |
||
1579 | D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL); |
||
1580 | D3DRS_TO_STRING_CASE(CCW_STENCILPASS); |
||
1581 | D3DRS_TO_STRING_CASE(CCW_STENCILFUNC); |
||
1582 | D3DRS_TO_STRING_CASE(COLORWRITEENABLE1); |
||
1583 | D3DRS_TO_STRING_CASE(COLORWRITEENABLE2); |
||
1584 | D3DRS_TO_STRING_CASE(COLORWRITEENABLE3); |
||
1585 | D3DRS_TO_STRING_CASE(BLENDFACTOR); |
||
1586 | D3DRS_TO_STRING_CASE(SRGBWRITEENABLE); |
||
1587 | D3DRS_TO_STRING_CASE(DEPTHBIAS); |
||
1588 | D3DRS_TO_STRING_CASE(WRAP8); |
||
1589 | D3DRS_TO_STRING_CASE(WRAP9); |
||
1590 | D3DRS_TO_STRING_CASE(WRAP10); |
||
1591 | D3DRS_TO_STRING_CASE(WRAP11); |
||
1592 | D3DRS_TO_STRING_CASE(WRAP12); |
||
1593 | D3DRS_TO_STRING_CASE(WRAP13); |
||
1594 | D3DRS_TO_STRING_CASE(WRAP14); |
||
1595 | D3DRS_TO_STRING_CASE(WRAP15); |
||
1596 | D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE); |
||
1597 | D3DRS_TO_STRING_CASE(SRCBLENDALPHA); |
||
1598 | D3DRS_TO_STRING_CASE(DESTBLENDALPHA); |
||
1599 | D3DRS_TO_STRING_CASE(BLENDOPALPHA); |
||
1600 | default: |
||
1601 | return "(invalid)"; |
||
1602 | } |
||
1603 | }>=>>>>>><>>>><>><>>><>><>>>><>><>><>>><>><>><>>>>>>=>><>><>><>><>> |
||
1604 |