668d875671fe3dd08b5ce88f2d91ea2d028a6e87
[mesa.git] / src / gallium / drivers / nv04 / nv04_state.c
1 #include "draw/draw_context.h"
2 #include "pipe/p_state.h"
3 #include "pipe/p_defines.h"
4 #include "pipe/p_util.h"
5 #include "pipe/p_shader_tokens.h"
6
7 #include "tgsi/tgsi_parse.h"
8
9 #include "nv04_context.h"
10 #include "nv04_state.h"
11
12 static void *
13 nv04_blend_state_create(struct pipe_context *pipe,
14 const struct pipe_blend_state *cso)
15 {
16 struct nv04_blend_state *cb;
17
18 cb = MALLOC(sizeof(struct nv04_blend_state));
19
20 cb->b_enable = cso->blend_enable ? 1 : 0;
21 cb->b_src = ((nvgl_blend_func(cso->alpha_src_factor)<<16) |
22 (nvgl_blend_func(cso->rgb_src_factor)));
23 cb->b_dst = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) |
24 (nvgl_blend_func(cso->rgb_dst_factor)));
25
26
27 return (void *)cb;
28 }
29
30 static void
31 nv04_blend_state_bind(struct pipe_context *pipe, void *blend)
32 {
33 struct nv04_context *nv04 = nv04_context(pipe);
34
35 nv04->blend = (struct nv04_blend_state*)blend;
36
37 nv04->dirty |= NV04_NEW_BLEND;
38 }
39
40 static void
41 nv04_blend_state_delete(struct pipe_context *pipe, void *hwcso)
42 {
43 free(hwcso);
44 }
45
46
47 static INLINE unsigned
48 wrap_mode(unsigned wrap) {
49 unsigned ret;
50
51 switch (wrap) {
52 case PIPE_TEX_WRAP_REPEAT:
53 ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT;
54 break;
55 case PIPE_TEX_WRAP_MIRROR_REPEAT:
56 ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT;
57 break;
58 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
59 ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE;
60 break;
61 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
62 ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER;
63 break;
64 case PIPE_TEX_WRAP_CLAMP:
65 ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP;
66 break;
67 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
68 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
69 case PIPE_TEX_WRAP_MIRROR_CLAMP:
70 default:
71 NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
72 ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP;
73 }
74 return ret >> NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT;
75 }
76
77 static void *
78 nv04_sampler_state_create(struct pipe_context *pipe,
79 const struct pipe_sampler_state *cso)
80 {
81
82 struct nv04_sampler_state *ss;
83 uint32_t filter = 0;
84
85 ss = MALLOC(sizeof(struct nv04_sampler_state));
86
87 ss->format = ((wrap_mode(cso->wrap_s) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT) |
88 (wrap_mode(cso->wrap_t) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_SHIFT));
89
90 if (cso->max_anisotropy > 1.0) {
91 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE | NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE;
92 }
93
94 switch (cso->mag_img_filter) {
95 case PIPE_TEX_FILTER_LINEAR:
96 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR;
97 break;
98 case PIPE_TEX_FILTER_NEAREST:
99 default:
100 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST;
101 break;
102 }
103
104 switch (cso->min_img_filter) {
105 case PIPE_TEX_FILTER_LINEAR:
106 switch (cso->min_mip_filter) {
107 case PIPE_TEX_MIPFILTER_NEAREST:
108 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
109 break;
110 case PIPE_TEX_MIPFILTER_LINEAR:
111 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
112 break;
113 case PIPE_TEX_MIPFILTER_NONE:
114 default:
115 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR;
116 break;
117 }
118 break;
119 case PIPE_TEX_FILTER_NEAREST:
120 default:
121 switch (cso->min_mip_filter) {
122 case PIPE_TEX_MIPFILTER_NEAREST:
123 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
124 break;
125 case PIPE_TEX_MIPFILTER_LINEAR:
126 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
127 break;
128 case PIPE_TEX_MIPFILTER_NONE:
129 default:
130 filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST;
131 break;
132 }
133 break;
134 }
135
136 ss->filter = filter;
137
138 return (void *)ss;
139 }
140
141 static void
142 nv04_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
143 {
144 struct nv04_context *nv04 = nv04_context(pipe);
145 unsigned unit;
146
147 for (unit = 0; unit < nr; unit++) {
148 nv04->sampler[unit] = sampler[unit];
149 nv04->dirty_samplers |= (1 << unit);
150 }
151 }
152
153 static void
154 nv04_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
155 {
156 free(hwcso);
157 }
158
159 static void
160 nv04_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
161 struct pipe_texture **miptree)
162 {
163 struct nv04_context *nv04 = nv04_context(pipe);
164 unsigned unit;
165
166 for (unit = 0; unit < nr; unit++) {
167 nv04->tex_miptree[unit] = (struct nv04_miptree *)miptree[unit];
168 nv04->dirty_samplers |= (1 << unit);
169 }
170 }
171
172 static void *
173 nv04_rasterizer_state_create(struct pipe_context *pipe,
174 const struct pipe_rasterizer_state *cso)
175 {
176 struct nv04_rasterizer_state *rs;
177
178 /*XXX: ignored:
179 * scissor
180 * points/lines (no hw support, emulated with tris in gallium)
181 */
182 rs = MALLOC(sizeof(struct nv04_rasterizer_state));
183
184 rs->blend = cso->flatshade ? NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT : NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
185
186 return (void *)rs;
187 }
188
189 static void
190 nv04_rasterizer_state_bind(struct pipe_context *pipe, void *rast)
191 {
192 struct nv04_context *nv04 = nv04_context(pipe);
193
194 nv04->rast = (struct nv04_rasterizer_state*)rast;
195
196 draw_set_rasterizer_state(nv04->draw, (nv04->rast ? nv04->rast->templ : NULL));
197
198 nv04->dirty |= NV04_NEW_RAST | NV04_NEW_BLEND;
199 }
200
201 static void
202 nv04_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
203 {
204 free(hwcso);
205 }
206
207 static INLINE uint32_t nv04_compare_func(uint32_t f)
208 {
209 switch ( f ) {
210 case PIPE_FUNC_NEVER: return 1;
211 case PIPE_FUNC_LESS: return 2;
212 case PIPE_FUNC_EQUAL: return 3;
213 case PIPE_FUNC_LEQUAL: return 4;
214 case PIPE_FUNC_GREATER: return 5;
215 case PIPE_FUNC_NOTEQUAL: return 6;
216 case PIPE_FUNC_GEQUAL: return 7;
217 case PIPE_FUNC_ALWAYS: return 8;
218 }
219 NOUVEAU_MSG("Unable to find the function\n");
220 return 0;
221 }
222
223 static void *
224 nv04_depth_stencil_alpha_state_create(struct pipe_context *pipe,
225 const struct pipe_depth_stencil_alpha_state *cso)
226 {
227 struct nv04_depth_stencil_alpha_state *hw;
228
229 hw = MALLOC(sizeof(struct nv04_depth_stencil_alpha_state));
230
231 hw->control = float_to_ubyte(cso->alpha.ref);
232 hw->control |= ( nv04_compare_func(cso->alpha.func) << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_SHIFT );
233 hw->control |= cso->alpha.enabled ? NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_TEST_ENABLE : 0;
234 hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ORIGIN;
235 hw->control |= cso->depth.enabled ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_SHIFT) : 0;
236 hw->control |= ( nv04_compare_func(cso->depth.func)<< NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_SHIFT );
237 hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_SHIFT; // no culling, handled by the draw module
238 hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE;
239 hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE;
240 hw->control |= cso->depth.writemask ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_SHIFT) : 0;
241 hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_SHIFT; // integer zbuffer format
242
243 return (void *)hw;
244 }
245
246 static void
247 nv04_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
248 {
249 struct nv04_context *nv04 = nv04_context(pipe);
250
251 nv04->dsa = hwcso;
252 nv04->dirty |= NV04_NEW_CONTROL;
253 }
254
255 static void
256 nv04_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
257 {
258 free(hwcso);
259 }
260
261 static void *
262 nv04_vp_state_create(struct pipe_context *pipe,
263 const struct pipe_shader_state *templ)
264 {
265 struct nv04_context *nv04 = nv04_context(pipe);
266
267 return draw_create_vertex_shader(nv04->draw, templ);
268 }
269
270 static void
271 nv04_vp_state_bind(struct pipe_context *pipe, void *shader)
272 {
273 struct nv04_context *nv04 = nv04_context(pipe);
274
275 draw_bind_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader);
276
277 nv04->dirty |= NV04_NEW_VERTPROG;
278 }
279
280 static void
281 nv04_vp_state_delete(struct pipe_context *pipe, void *shader)
282 {
283 struct nv04_context *nv04 = nv04_context(pipe);
284
285 draw_delete_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader);
286 }
287
288 static void *
289 nv04_fp_state_create(struct pipe_context *pipe,
290 const struct pipe_shader_state *cso)
291 {
292 struct nv04_fragment_program *fp;
293
294 fp = CALLOC(1, sizeof(struct nv04_fragment_program));
295 fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
296
297 return (void *)fp;
298 }
299
300 static void
301 nv04_fp_state_bind(struct pipe_context *pipe, void *hwcso)
302 {
303 struct nv04_context *nv04 = nv04_context(pipe);
304 struct nv04_fragment_program *fp = hwcso;
305
306 nv04->fragprog.current = fp;
307 nv04->dirty |= NV04_NEW_FRAGPROG;
308 }
309
310 static void
311 nv04_fp_state_delete(struct pipe_context *pipe, void *hwcso)
312 {
313 struct nv04_context *nv04 = nv04_context(pipe);
314 struct nv04_fragment_program *fp = hwcso;
315
316 nv04_fragprog_destroy(nv04, fp);
317 free((void*)fp->pipe.tokens);
318 free(fp);
319 }
320
321 static void
322 nv04_set_blend_color(struct pipe_context *pipe,
323 const struct pipe_blend_color *bcol)
324 {
325 }
326
327 static void
328 nv04_set_clip_state(struct pipe_context *pipe,
329 const struct pipe_clip_state *clip)
330 {
331 }
332
333 static void
334 nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
335 const struct pipe_constant_buffer *buf )
336 {
337 struct nv04_context *nv04 = nv04_context(pipe);
338
339 if (shader == PIPE_SHADER_VERTEX) {
340 nv04->vertprog.constant_buf = buf->buffer;
341 nv04->dirty |= NV04_NEW_VERTPROG;
342 } else
343 if (shader == PIPE_SHADER_FRAGMENT) {
344 nv04->fragprog.constant_buf = buf->buffer;
345 nv04->dirty |= NV04_NEW_FRAGPROG;
346 }
347 }
348
349 static void
350 nv04_set_framebuffer_state(struct pipe_context *pipe,
351 const struct pipe_framebuffer_state *fb)
352 {
353 struct nv04_context *nv04 = nv04_context(pipe);
354 struct pipe_surface *rt, *zeta;
355 uint32_t rt_format, w, h;
356 int colour_format = 0, zeta_format = 0;
357
358 w = fb->cbufs[0]->width;
359 h = fb->cbufs[0]->height;
360 colour_format = fb->cbufs[0]->format;
361 rt = fb->cbufs[0];
362
363 if (fb->zsbuf) {
364 if (colour_format) {
365 assert(w == fb->zsbuf->width);
366 assert(h == fb->zsbuf->height);
367 } else {
368 w = fb->zsbuf->width;
369 h = fb->zsbuf->height;
370 }
371
372 zeta_format = fb->zsbuf->format;
373 zeta = fb->zsbuf;
374 }
375
376 switch (colour_format) {
377 case PIPE_FORMAT_A8R8G8B8_UNORM:
378 case 0:
379 rt_format = 0x108;
380 break;
381 case PIPE_FORMAT_R5G6B5_UNORM:
382 rt_format = 0x103;
383 break;
384 default:
385 assert(0);
386 }
387
388 BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1);
389 OUT_RING(rt_format);
390
391 /* FIXME pitches have to be aligned ! */
392 BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
393 OUT_RING(rt->stride|(zeta->stride<<16));
394 OUT_RELOCl(rt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
395 if (fb->zsbuf) {
396 BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
397 OUT_RELOCl(zeta->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
398 }
399 }
400
401 static void
402 nv04_set_polygon_stipple(struct pipe_context *pipe,
403 const struct pipe_poly_stipple *stipple)
404 {
405 NOUVEAU_ERR("line stipple hahaha\n");
406 }
407
408 static void
409 nv04_set_scissor_state(struct pipe_context *pipe,
410 const struct pipe_scissor_state *s)
411 {
412 /* struct nv04_context *nv04 = nv04_context(pipe);
413
414 // XXX
415 BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_SCISSOR_HORIZ, 2);
416 OUT_RING (((s->maxx - s->minx) << 16) | s->minx);
417 OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/
418 }
419
420 static void
421 nv04_set_viewport_state(struct pipe_context *pipe,
422 const struct pipe_viewport_state *viewport)
423 {
424 struct nv04_context *nv04 = nv04_context(pipe);
425
426 nv04->viewport = *viewport;
427
428 draw_set_viewport_state(nv04->draw, &nv04->viewport);
429 }
430
431 static void
432 nv04_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
433 const struct pipe_vertex_buffer *buffers)
434 {
435 struct nv04_context *nv04 = nv04_context(pipe);
436
437 draw_flush(nv04->draw);
438
439 memcpy(nv04->vertex_buffer, buffers, count * sizeof(buffers[0]));
440 nv04->num_vertex_buffers = count;
441
442 draw_set_vertex_buffers(nv04->draw, count, buffers);
443 }
444
445 static void
446 nv04_set_vertex_elements(struct pipe_context *pipe, unsigned count,
447 const struct pipe_vertex_element *elements)
448 {
449 struct nv04_context *nv04 = nv04_context(pipe);
450
451 draw_flush(nv04->draw);
452
453 nv04->num_vertex_elements = count;
454 draw_set_vertex_elements(nv04->draw, count, elements);
455 }
456
457 void
458 nv04_init_state_functions(struct nv04_context *nv04)
459 {
460 nv04->pipe.create_blend_state = nv04_blend_state_create;
461 nv04->pipe.bind_blend_state = nv04_blend_state_bind;
462 nv04->pipe.delete_blend_state = nv04_blend_state_delete;
463
464 nv04->pipe.create_sampler_state = nv04_sampler_state_create;
465 nv04->pipe.bind_sampler_states = nv04_sampler_state_bind;
466 nv04->pipe.delete_sampler_state = nv04_sampler_state_delete;
467 nv04->pipe.set_sampler_textures = nv04_set_sampler_texture;
468
469 nv04->pipe.create_rasterizer_state = nv04_rasterizer_state_create;
470 nv04->pipe.bind_rasterizer_state = nv04_rasterizer_state_bind;
471 nv04->pipe.delete_rasterizer_state = nv04_rasterizer_state_delete;
472
473 nv04->pipe.create_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_create;
474 nv04->pipe.bind_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_bind;
475 nv04->pipe.delete_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_delete;
476
477 nv04->pipe.create_vs_state = nv04_vp_state_create;
478 nv04->pipe.bind_vs_state = nv04_vp_state_bind;
479 nv04->pipe.delete_vs_state = nv04_vp_state_delete;
480
481 nv04->pipe.create_fs_state = nv04_fp_state_create;
482 nv04->pipe.bind_fs_state = nv04_fp_state_bind;
483 nv04->pipe.delete_fs_state = nv04_fp_state_delete;
484
485 nv04->pipe.set_blend_color = nv04_set_blend_color;
486 nv04->pipe.set_clip_state = nv04_set_clip_state;
487 nv04->pipe.set_constant_buffer = nv04_set_constant_buffer;
488 nv04->pipe.set_framebuffer_state = nv04_set_framebuffer_state;
489 nv04->pipe.set_polygon_stipple = nv04_set_polygon_stipple;
490 nv04->pipe.set_scissor_state = nv04_set_scissor_state;
491 nv04->pipe.set_viewport_state = nv04_set_viewport_state;
492
493 nv04->pipe.set_vertex_buffers = nv04_set_vertex_buffers;
494 nv04->pipe.set_vertex_elements = nv04_set_vertex_elements;
495 }
496