ac69b29616213eb604fc801d66973d886fc47c5c
[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_shader_tokens.h"
5 #include "pipe/p_inlines.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_value);
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_buffer *buf )
336 {
337 struct nv04_context *nv04 = nv04_context(pipe);
338 struct pipe_screen *pscreen = pipe->screen;
339
340 assert(shader < PIPE_SHADER_TYPES);
341 assert(index == 0);
342
343 if (buf) {
344 void *mapped;
345 if (buf && buf->size &&
346 (mapped = pipe_buffer_map(pscreen, buf, PIPE_BUFFER_USAGE_CPU_READ)))
347 {
348 memcpy(nv04->constbuf[shader], mapped, buf->size);
349 nv04->constbuf_nr[shader] =
350 buf->size / (4 * sizeof(float));
351 pipe_buffer_unmap(pscreen, buf);
352 }
353 }
354 }
355
356 static void
357 nv04_set_framebuffer_state(struct pipe_context *pipe,
358 const struct pipe_framebuffer_state *fb)
359 {
360 struct nv04_context *nv04 = nv04_context(pipe);
361
362 nv04->framebuffer = (struct pipe_framebuffer_state*)fb;
363
364 nv04->dirty |= NV04_NEW_FRAMEBUFFER;
365 }
366 static void
367 nv04_set_polygon_stipple(struct pipe_context *pipe,
368 const struct pipe_poly_stipple *stipple)
369 {
370 NOUVEAU_ERR("line stipple hahaha\n");
371 }
372
373 static void
374 nv04_set_scissor_state(struct pipe_context *pipe,
375 const struct pipe_scissor_state *s)
376 {
377 /* struct nv04_context *nv04 = nv04_context(pipe);
378
379 // XXX
380 BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_SCISSOR_HORIZ, 2);
381 OUT_RING (((s->maxx - s->minx) << 16) | s->minx);
382 OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/
383 }
384
385 static void
386 nv04_set_viewport_state(struct pipe_context *pipe,
387 const struct pipe_viewport_state *viewport)
388 {
389 struct nv04_context *nv04 = nv04_context(pipe);
390
391 nv04->viewport = *viewport;
392
393 draw_set_viewport_state(nv04->draw, &nv04->viewport);
394 }
395
396 static void
397 nv04_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
398 const struct pipe_vertex_buffer *buffers)
399 {
400 struct nv04_context *nv04 = nv04_context(pipe);
401
402 memcpy(nv04->vtxbuf, buffers, count * sizeof(buffers[0]));
403 nv04->dirty |= NV04_NEW_VTXARRAYS;
404
405 draw_set_vertex_buffers(nv04->draw, count, buffers);
406 }
407
408 static void
409 nv04_set_vertex_elements(struct pipe_context *pipe, unsigned count,
410 const struct pipe_vertex_element *elements)
411 {
412 struct nv04_context *nv04 = nv04_context(pipe);
413
414 memcpy(nv04->vtxelt, elements, sizeof(*elements) * count);
415 nv04->dirty |= NV04_NEW_VTXARRAYS;
416
417 draw_set_vertex_elements(nv04->draw, count, elements);
418 }
419
420 void
421 nv04_init_state_functions(struct nv04_context *nv04)
422 {
423 nv04->pipe.create_blend_state = nv04_blend_state_create;
424 nv04->pipe.bind_blend_state = nv04_blend_state_bind;
425 nv04->pipe.delete_blend_state = nv04_blend_state_delete;
426
427 nv04->pipe.create_sampler_state = nv04_sampler_state_create;
428 nv04->pipe.bind_fragment_sampler_states = nv04_sampler_state_bind;
429 nv04->pipe.delete_sampler_state = nv04_sampler_state_delete;
430 nv04->pipe.set_fragment_sampler_textures = nv04_set_sampler_texture;
431
432 nv04->pipe.create_rasterizer_state = nv04_rasterizer_state_create;
433 nv04->pipe.bind_rasterizer_state = nv04_rasterizer_state_bind;
434 nv04->pipe.delete_rasterizer_state = nv04_rasterizer_state_delete;
435
436 nv04->pipe.create_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_create;
437 nv04->pipe.bind_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_bind;
438 nv04->pipe.delete_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_delete;
439
440 nv04->pipe.create_vs_state = nv04_vp_state_create;
441 nv04->pipe.bind_vs_state = nv04_vp_state_bind;
442 nv04->pipe.delete_vs_state = nv04_vp_state_delete;
443
444 nv04->pipe.create_fs_state = nv04_fp_state_create;
445 nv04->pipe.bind_fs_state = nv04_fp_state_bind;
446 nv04->pipe.delete_fs_state = nv04_fp_state_delete;
447
448 nv04->pipe.set_blend_color = nv04_set_blend_color;
449 nv04->pipe.set_clip_state = nv04_set_clip_state;
450 nv04->pipe.set_constant_buffer = nv04_set_constant_buffer;
451 nv04->pipe.set_framebuffer_state = nv04_set_framebuffer_state;
452 nv04->pipe.set_polygon_stipple = nv04_set_polygon_stipple;
453 nv04->pipe.set_scissor_state = nv04_set_scissor_state;
454 nv04->pipe.set_viewport_state = nv04_set_viewport_state;
455
456 nv04->pipe.set_vertex_buffers = nv04_set_vertex_buffers;
457 nv04->pipe.set_vertex_elements = nv04_set_vertex_elements;
458 }
459