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