nvfx: rewrite draw code and buffer code
[mesa.git] / src / gallium / drivers / nvfx / nvfx_state.c
1 #include "pipe/p_state.h"
2 #include "pipe/p_defines.h"
3 #include "util/u_inlines.h"
4 #include "util/u_framebuffer.h"
5
6 #include "draw/draw_context.h"
7
8 #include "tgsi/tgsi_parse.h"
9
10 #include "nvfx_context.h"
11 #include "nvfx_state.h"
12 #include "nvfx_tex.h"
13
14 static void *
15 nvfx_blend_state_create(struct pipe_context *pipe,
16 const struct pipe_blend_state *cso)
17 {
18 struct nvfx_context *nvfx = nvfx_context(pipe);
19 struct nvfx_blend_state *bso = CALLOC(1, sizeof(*bso));
20 struct nouveau_statebuf_builder sb = sb_init(bso->sb);
21
22 if (cso->rt[0].blend_enable) {
23 sb_method(sb, NV34TCL_BLEND_FUNC_ENABLE, 3);
24 sb_data(sb, 1);
25 sb_data(sb, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) |
26 nvgl_blend_func(cso->rt[0].rgb_src_factor));
27 sb_data(sb, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 |
28 nvgl_blend_func(cso->rt[0].rgb_dst_factor));
29 if(nvfx->screen->base.device->chipset < 0x40) {
30 sb_method(sb, NV34TCL_BLEND_EQUATION, 1);
31 sb_data(sb, nvgl_blend_eqn(cso->rt[0].rgb_func));
32 } else {
33 sb_method(sb, NV40TCL_BLEND_EQUATION, 1);
34 sb_data(sb, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 |
35 nvgl_blend_eqn(cso->rt[0].rgb_func));
36 }
37 } else {
38 sb_method(sb, NV34TCL_BLEND_FUNC_ENABLE, 1);
39 sb_data(sb, 0);
40 }
41
42 sb_method(sb, NV34TCL_COLOR_MASK, 1);
43 sb_data(sb, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
44 ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
45 ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) |
46 ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0)));
47
48 /* TODO: add NV40 MRT color mask */
49
50 if (cso->logicop_enable) {
51 sb_method(sb, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2);
52 sb_data(sb, 1);
53 sb_data(sb, nvgl_logicop_func(cso->logicop_func));
54 } else {
55 sb_method(sb, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1);
56 sb_data(sb, 0);
57 }
58
59 sb_method(sb, NV34TCL_DITHER_ENABLE, 1);
60 sb_data(sb, cso->dither ? 1 : 0);
61
62 bso->sb_len = sb_len(sb, bso->sb);
63 bso->pipe = *cso;
64 return (void *)bso;
65 }
66
67 static void
68 nvfx_blend_state_bind(struct pipe_context *pipe, void *hwcso)
69 {
70 struct nvfx_context *nvfx = nvfx_context(pipe);
71
72 nvfx->blend = hwcso;
73 nvfx->dirty |= NVFX_NEW_BLEND;
74 }
75
76 static void
77 nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso)
78 {
79 struct nvfx_blend_state *bso = hwcso;
80
81 FREE(bso);
82 }
83
84 static void *
85 nvfx_rasterizer_state_create(struct pipe_context *pipe,
86 const struct pipe_rasterizer_state *cso)
87 {
88 struct nvfx_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
89 struct nouveau_statebuf_builder sb = sb_init(rsso->sb);
90
91 /*XXX: ignored:
92 * point_smooth -nohw
93 * multisample
94 */
95
96 sb_method(sb, NV34TCL_SHADE_MODEL, 1);
97 sb_data(sb, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT :
98 NV34TCL_SHADE_MODEL_SMOOTH);
99
100 sb_method(sb, NV34TCL_VERTEX_TWO_SIDE_ENABLE, 1);
101 sb_data(sb, cso->light_twoside);
102
103 sb_method(sb, NV34TCL_LINE_WIDTH, 2);
104 sb_data(sb, (unsigned char)(cso->line_width * 8.0) & 0xff);
105 sb_data(sb, cso->line_smooth ? 1 : 0);
106 sb_method(sb, NV34TCL_LINE_STIPPLE_ENABLE, 2);
107 sb_data(sb, cso->line_stipple_enable ? 1 : 0);
108 sb_data(sb, (cso->line_stipple_pattern << 16) |
109 cso->line_stipple_factor);
110
111 sb_method(sb, NV34TCL_POINT_SIZE, 1);
112 sb_data(sb, fui(cso->point_size));
113
114 sb_method(sb, NV34TCL_POLYGON_MODE_FRONT, 6);
115 sb_data(sb, nvgl_polygon_mode(cso->fill_front));
116 sb_data(sb, nvgl_polygon_mode(cso->fill_back));
117 switch (cso->cull_face) {
118 case PIPE_FACE_FRONT:
119 sb_data(sb, NV34TCL_CULL_FACE_FRONT);
120 break;
121 case PIPE_FACE_BACK:
122 sb_data(sb, NV34TCL_CULL_FACE_BACK);
123 break;
124 case PIPE_FACE_FRONT_AND_BACK:
125 sb_data(sb, NV34TCL_CULL_FACE_FRONT_AND_BACK);
126 break;
127 default:
128 sb_data(sb, NV34TCL_CULL_FACE_BACK);
129 break;
130 }
131 if (cso->front_ccw) {
132 sb_data(sb, NV34TCL_FRONT_FACE_CCW);
133 } else {
134 sb_data(sb, NV34TCL_FRONT_FACE_CW);
135 }
136 sb_data(sb, cso->poly_smooth ? 1 : 0);
137 sb_data(sb, (cso->cull_face != PIPE_FACE_NONE) ? 1 : 0);
138
139 sb_method(sb, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
140 sb_data(sb, cso->poly_stipple_enable ? 1 : 0);
141
142 sb_method(sb, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
143 sb_data(sb, cso->offset_point);
144 sb_data(sb, cso->offset_line);
145 sb_data(sb, cso->offset_tri);
146
147 if (cso->offset_point || cso->offset_line || cso->offset_tri) {
148 sb_method(sb, NV34TCL_POLYGON_OFFSET_FACTOR, 2);
149 sb_data(sb, fui(cso->offset_scale));
150 sb_data(sb, fui(cso->offset_units * 2));
151 }
152
153 sb_method(sb, NV34TCL_POINT_SPRITE, 1);
154 if (cso->point_quad_rasterization) {
155 unsigned psctl = (1 << 0), i;
156
157 for (i = 0; i < 8; i++) {
158 if ((cso->sprite_coord_enable >> i) & 1)
159 psctl |= (1 << (8 + i));
160 }
161
162 sb_data(sb, psctl);
163 } else {
164 sb_data(sb, 0);
165 }
166
167 rsso->pipe = *cso;
168 rsso->sb_len = sb_len(sb, rsso->sb);
169 return (void *)rsso;
170 }
171
172 static void
173 nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
174 {
175 struct nvfx_context *nvfx = nvfx_context(pipe);
176
177 if(nvfx->rasterizer && hwcso)
178 {
179 if(!nvfx->rasterizer || ((struct nvfx_rasterizer_state*)hwcso)->pipe.scissor
180 != nvfx->rasterizer->pipe.scissor)
181 {
182 nvfx->dirty |= NVFX_NEW_SCISSOR;
183 nvfx->draw_dirty |= NVFX_NEW_SCISSOR;
184 }
185
186 if(((struct nvfx_rasterizer_state*)hwcso)->pipe.poly_stipple_enable
187 != nvfx->rasterizer->pipe.poly_stipple_enable)
188 {
189 nvfx->dirty |= NVFX_NEW_STIPPLE;
190 nvfx->draw_dirty |= NVFX_NEW_STIPPLE;
191 }
192 }
193
194 nvfx->rasterizer = hwcso;
195 nvfx->dirty |= NVFX_NEW_RAST;
196 nvfx->draw_dirty |= NVFX_NEW_RAST;
197 }
198
199 static void
200 nvfx_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
201 {
202 struct nvfx_rasterizer_state *rsso = hwcso;
203
204 FREE(rsso);
205 }
206
207 static void *
208 nvfx_depth_stencil_alpha_state_create(struct pipe_context *pipe,
209 const struct pipe_depth_stencil_alpha_state *cso)
210 {
211 struct nvfx_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
212 struct nouveau_statebuf_builder sb = sb_init(zsaso->sb);
213
214 sb_method(sb, NV34TCL_DEPTH_FUNC, 3);
215 sb_data (sb, nvgl_comparison_op(cso->depth.func));
216 sb_data (sb, cso->depth.writemask ? 1 : 0);
217 sb_data (sb, cso->depth.enabled ? 1 : 0);
218
219 sb_method(sb, NV34TCL_ALPHA_FUNC_ENABLE, 3);
220 sb_data (sb, cso->alpha.enabled ? 1 : 0);
221 sb_data (sb, nvgl_comparison_op(cso->alpha.func));
222 sb_data (sb, float_to_ubyte(cso->alpha.ref_value));
223
224 if (cso->stencil[0].enabled) {
225 sb_method(sb, NV34TCL_STENCIL_FRONT_ENABLE, 3);
226 sb_data (sb, cso->stencil[0].enabled ? 1 : 0);
227 sb_data (sb, cso->stencil[0].writemask);
228 sb_data (sb, nvgl_comparison_op(cso->stencil[0].func));
229 sb_method(sb, NV34TCL_STENCIL_FRONT_FUNC_MASK, 4);
230 sb_data (sb, cso->stencil[0].valuemask);
231 sb_data (sb, nvgl_stencil_op(cso->stencil[0].fail_op));
232 sb_data (sb, nvgl_stencil_op(cso->stencil[0].zfail_op));
233 sb_data (sb, nvgl_stencil_op(cso->stencil[0].zpass_op));
234 } else {
235 sb_method(sb, NV34TCL_STENCIL_FRONT_ENABLE, 1);
236 sb_data (sb, 0);
237 }
238
239 if (cso->stencil[1].enabled) {
240 sb_method(sb, NV34TCL_STENCIL_BACK_ENABLE, 3);
241 sb_data (sb, cso->stencil[1].enabled ? 1 : 0);
242 sb_data (sb, cso->stencil[1].writemask);
243 sb_data (sb, nvgl_comparison_op(cso->stencil[1].func));
244 sb_method(sb, NV34TCL_STENCIL_BACK_FUNC_MASK, 4);
245 sb_data (sb, cso->stencil[1].valuemask);
246 sb_data (sb, nvgl_stencil_op(cso->stencil[1].fail_op));
247 sb_data (sb, nvgl_stencil_op(cso->stencil[1].zfail_op));
248 sb_data (sb, nvgl_stencil_op(cso->stencil[1].zpass_op));
249 } else {
250 sb_method(sb, NV34TCL_STENCIL_BACK_ENABLE, 1);
251 sb_data (sb, 0);
252 }
253
254 zsaso->pipe = *cso;
255 zsaso->sb_len = sb_len(sb, zsaso->sb);
256 return (void *)zsaso;
257 }
258
259 static void
260 nvfx_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
261 {
262 struct nvfx_context *nvfx = nvfx_context(pipe);
263
264 nvfx->zsa = hwcso;
265 nvfx->dirty |= NVFX_NEW_ZSA;
266 }
267
268 static void
269 nvfx_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
270 {
271 struct nvfx_zsa_state *zsaso = hwcso;
272
273 FREE(zsaso);
274 }
275
276 static void *
277 nvfx_vp_state_create(struct pipe_context *pipe,
278 const struct pipe_shader_state *cso)
279 {
280 struct nvfx_context *nvfx = nvfx_context(pipe);
281 struct nvfx_vertex_program *vp;
282
283 vp = CALLOC(1, sizeof(struct nvfx_vertex_program));
284 vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
285 vp->draw = draw_create_vertex_shader(nvfx->draw, &vp->pipe);
286
287 return (void *)vp;
288 }
289
290 static void
291 nvfx_vp_state_bind(struct pipe_context *pipe, void *hwcso)
292 {
293 struct nvfx_context *nvfx = nvfx_context(pipe);
294
295 nvfx->vertprog = hwcso;
296 nvfx->dirty |= NVFX_NEW_VERTPROG;
297 nvfx->draw_dirty |= NVFX_NEW_VERTPROG;
298 }
299
300 static void
301 nvfx_vp_state_delete(struct pipe_context *pipe, void *hwcso)
302 {
303 struct nvfx_context *nvfx = nvfx_context(pipe);
304 struct nvfx_vertex_program *vp = hwcso;
305
306 draw_delete_vertex_shader(nvfx->draw, vp->draw);
307 nvfx_vertprog_destroy(nvfx, vp);
308 FREE((void*)vp->pipe.tokens);
309 FREE(vp);
310 }
311
312 static void *
313 nvfx_fp_state_create(struct pipe_context *pipe,
314 const struct pipe_shader_state *cso)
315 {
316 struct nvfx_fragment_program *fp;
317
318 fp = CALLOC(1, sizeof(struct nvfx_fragment_program));
319 fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
320
321 tgsi_scan_shader(fp->pipe.tokens, &fp->info);
322
323 return (void *)fp;
324 }
325
326 static void
327 nvfx_fp_state_bind(struct pipe_context *pipe, void *hwcso)
328 {
329 struct nvfx_context *nvfx = nvfx_context(pipe);
330
331 nvfx->fragprog = hwcso;
332 nvfx->dirty |= NVFX_NEW_FRAGPROG;
333 }
334
335 static void
336 nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso)
337 {
338 struct nvfx_context *nvfx = nvfx_context(pipe);
339 struct nvfx_fragment_program *fp = hwcso;
340
341 nvfx_fragprog_destroy(nvfx, fp);
342 FREE((void*)fp->pipe.tokens);
343 FREE(fp);
344 }
345
346 static void
347 nvfx_set_blend_color(struct pipe_context *pipe,
348 const struct pipe_blend_color *bcol)
349 {
350 struct nvfx_context *nvfx = nvfx_context(pipe);
351
352 nvfx->blend_colour = *bcol;
353 nvfx->dirty |= NVFX_NEW_BCOL;
354 }
355
356 static void
357 nvfx_set_stencil_ref(struct pipe_context *pipe,
358 const struct pipe_stencil_ref *sr)
359 {
360 struct nvfx_context *nvfx = nvfx_context(pipe);
361
362 nvfx->stencil_ref = *sr;
363 nvfx->dirty |= NVFX_NEW_SR;
364 }
365
366 static void
367 nvfx_set_clip_state(struct pipe_context *pipe,
368 const struct pipe_clip_state *clip)
369 {
370 struct nvfx_context *nvfx = nvfx_context(pipe);
371
372 nvfx->clip = *clip;
373 nvfx->dirty |= NVFX_NEW_UCP;
374 nvfx->draw_dirty |= NVFX_NEW_UCP;
375 }
376
377 static void
378 nvfx_set_sample_mask(struct pipe_context *pipe,
379 unsigned sample_mask)
380 {
381 }
382
383 static void
384 nvfx_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
385 struct pipe_resource *buf )
386 {
387 struct nvfx_context *nvfx = nvfx_context(pipe);
388
389 nvfx->constbuf[shader] = buf;
390 nvfx->constbuf_nr[shader] = buf->width0 / (4 * sizeof(float));
391
392 if (shader == PIPE_SHADER_VERTEX) {
393 nvfx->dirty |= NVFX_NEW_VERTCONST;
394 } else
395 if (shader == PIPE_SHADER_FRAGMENT) {
396 nvfx->dirty |= NVFX_NEW_FRAGCONST;
397 }
398 }
399
400 static void
401 nvfx_set_framebuffer_state(struct pipe_context *pipe,
402 const struct pipe_framebuffer_state *fb)
403 {
404 struct nvfx_context *nvfx = nvfx_context(pipe);
405
406 if(fb)
407 util_copy_framebuffer_state(&nvfx->framebuffer, fb);
408 else
409 util_unreference_framebuffer_state(&nvfx->framebuffer);
410 nvfx->dirty |= NVFX_NEW_FB;
411 }
412
413 static void
414 nvfx_set_polygon_stipple(struct pipe_context *pipe,
415 const struct pipe_poly_stipple *stipple)
416 {
417 struct nvfx_context *nvfx = nvfx_context(pipe);
418
419 memcpy(nvfx->stipple, stipple->stipple, 4 * 32);
420 nvfx->dirty |= NVFX_NEW_STIPPLE;
421 }
422
423 static void
424 nvfx_set_scissor_state(struct pipe_context *pipe,
425 const struct pipe_scissor_state *s)
426 {
427 struct nvfx_context *nvfx = nvfx_context(pipe);
428
429 nvfx->scissor = *s;
430 nvfx->dirty |= NVFX_NEW_SCISSOR;
431 }
432
433 static void
434 nvfx_set_viewport_state(struct pipe_context *pipe,
435 const struct pipe_viewport_state *vpt)
436 {
437 struct nvfx_context *nvfx = nvfx_context(pipe);
438
439 nvfx->viewport = *vpt;
440 nvfx->dirty |= NVFX_NEW_VIEWPORT;
441 nvfx->draw_dirty |= NVFX_NEW_VIEWPORT;
442 }
443
444 void
445 nvfx_init_state_functions(struct nvfx_context *nvfx)
446 {
447 nvfx->pipe.create_blend_state = nvfx_blend_state_create;
448 nvfx->pipe.bind_blend_state = nvfx_blend_state_bind;
449 nvfx->pipe.delete_blend_state = nvfx_blend_state_delete;
450
451 nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create;
452 nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind;
453 nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete;
454
455 nvfx->pipe.create_depth_stencil_alpha_state =
456 nvfx_depth_stencil_alpha_state_create;
457 nvfx->pipe.bind_depth_stencil_alpha_state =
458 nvfx_depth_stencil_alpha_state_bind;
459 nvfx->pipe.delete_depth_stencil_alpha_state =
460 nvfx_depth_stencil_alpha_state_delete;
461
462 nvfx->pipe.create_vs_state = nvfx_vp_state_create;
463 nvfx->pipe.bind_vs_state = nvfx_vp_state_bind;
464 nvfx->pipe.delete_vs_state = nvfx_vp_state_delete;
465
466 nvfx->pipe.create_fs_state = nvfx_fp_state_create;
467 nvfx->pipe.bind_fs_state = nvfx_fp_state_bind;
468 nvfx->pipe.delete_fs_state = nvfx_fp_state_delete;
469
470 nvfx->pipe.set_blend_color = nvfx_set_blend_color;
471 nvfx->pipe.set_stencil_ref = nvfx_set_stencil_ref;
472 nvfx->pipe.set_clip_state = nvfx_set_clip_state;
473 nvfx->pipe.set_sample_mask = nvfx_set_sample_mask;
474 nvfx->pipe.set_constant_buffer = nvfx_set_constant_buffer;
475 nvfx->pipe.set_framebuffer_state = nvfx_set_framebuffer_state;
476 nvfx->pipe.set_polygon_stipple = nvfx_set_polygon_stipple;
477 nvfx->pipe.set_scissor_state = nvfx_set_scissor_state;
478 nvfx->pipe.set_viewport_state = nvfx_set_viewport_state;
479 }