nv40: almost there..
[mesa.git] / src / gallium / drivers / nv40 / nv40_state.c
1 #include "pipe/p_state.h"
2 #include "pipe/p_defines.h"
3 #include "pipe/p_util.h"
4
5 #include "nv40_context.h"
6 #include "nv40_state.h"
7
8 static void *
9 nv40_blend_state_create(struct pipe_context *pipe,
10 const struct pipe_blend_state *cso)
11 {
12 struct nv40_context *nv40 = nv40_context(pipe);
13 struct nouveau_grobj *curie = nv40->hw->curie;
14 struct nv40_blend_state *bso = MALLOC(sizeof(*bso));
15 struct nouveau_stateobj *so = so_new(16, 0);
16
17 if (cso->blend_enable) {
18 so_method(so, curie, NV40TCL_BLEND_ENABLE, 3);
19 so_data (so, 1);
20 so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) |
21 nvgl_blend_func(cso->rgb_src_factor));
22 so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 |
23 nvgl_blend_func(cso->rgb_dst_factor));
24 so_method(so, curie, NV40TCL_BLEND_EQUATION, 1);
25 so_data (so, nvgl_blend_eqn(cso->alpha_func) << 16 |
26 nvgl_blend_eqn(cso->rgb_func));
27 } else {
28 so_method(so, curie, NV40TCL_BLEND_ENABLE, 1);
29 so_data (so, 0);
30 }
31
32 so_method(so, curie, NV40TCL_COLOR_MASK, 1);
33 so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
34 ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
35 ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) |
36 ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0)));
37
38 if (cso->logicop_enable) {
39 so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2);
40 so_data (so, 1);
41 so_data (so, nvgl_logicop_func(cso->logicop_func));
42 } else {
43 so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1);
44 so_data (so, 0);
45 }
46
47 so_method(so, curie, NV40TCL_DITHER_ENABLE, 1);
48 so_data (so, cso->dither ? 1 : 0);
49
50 bso->so = so;
51 bso->pipe = *cso;
52 return (void *)bso;
53 }
54
55 static void
56 nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso)
57 {
58 struct nv40_context *nv40 = nv40_context(pipe);
59
60 nv40->pipe_state.blend = hwcso;
61 nv40->dirty |= NV40_NEW_BLEND;
62 }
63
64 static void
65 nv40_blend_state_delete(struct pipe_context *pipe, void *hwcso)
66 {
67 struct nv40_blend_state *bso = hwcso;
68
69 so_ref(NULL, &bso->so);
70 FREE(bso);
71 }
72
73
74 static INLINE unsigned
75 wrap_mode(unsigned wrap) {
76 unsigned ret;
77
78 switch (wrap) {
79 case PIPE_TEX_WRAP_REPEAT:
80 ret = NV40TCL_TEX_WRAP_S_REPEAT;
81 break;
82 case PIPE_TEX_WRAP_MIRROR_REPEAT:
83 ret = NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT;
84 break;
85 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
86 ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE;
87 break;
88 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
89 ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER;
90 break;
91 case PIPE_TEX_WRAP_CLAMP:
92 ret = NV40TCL_TEX_WRAP_S_CLAMP;
93 break;
94 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
95 ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE;
96 break;
97 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
98 ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER;
99 break;
100 case PIPE_TEX_WRAP_MIRROR_CLAMP:
101 ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP;
102 break;
103 default:
104 NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
105 ret = NV40TCL_TEX_WRAP_S_REPEAT;
106 break;
107 }
108
109 return ret >> NV40TCL_TEX_WRAP_S_SHIFT;
110 }
111
112 static void *
113 nv40_sampler_state_create(struct pipe_context *pipe,
114 const struct pipe_sampler_state *cso)
115 {
116 struct nv40_sampler_state *ps;
117 uint32_t filter = 0;
118
119 ps = MALLOC(sizeof(struct nv40_sampler_state));
120
121 ps->fmt = 0;
122 if (!cso->normalized_coords)
123 ps->fmt |= NV40TCL_TEX_FORMAT_RECT;
124
125 ps->wrap = ((wrap_mode(cso->wrap_s) << NV40TCL_TEX_WRAP_S_SHIFT) |
126 (wrap_mode(cso->wrap_t) << NV40TCL_TEX_WRAP_T_SHIFT) |
127 (wrap_mode(cso->wrap_r) << NV40TCL_TEX_WRAP_R_SHIFT));
128
129 ps->en = 0;
130 if (cso->max_anisotropy >= 2.0) {
131 /* no idea, binary driver sets it, works without it.. meh.. */
132 ps->wrap |= (1 << 5);
133
134 if (cso->max_anisotropy >= 16.0) {
135 ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X;
136 } else
137 if (cso->max_anisotropy >= 12.0) {
138 ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X;
139 } else
140 if (cso->max_anisotropy >= 10.0) {
141 ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X;
142 } else
143 if (cso->max_anisotropy >= 8.0) {
144 ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X;
145 } else
146 if (cso->max_anisotropy >= 6.0) {
147 ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X;
148 } else
149 if (cso->max_anisotropy >= 4.0) {
150 ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X;
151 } else {
152 ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X;
153 }
154 }
155
156 switch (cso->mag_img_filter) {
157 case PIPE_TEX_FILTER_LINEAR:
158 filter |= NV40TCL_TEX_FILTER_MAG_LINEAR;
159 break;
160 case PIPE_TEX_FILTER_NEAREST:
161 default:
162 filter |= NV40TCL_TEX_FILTER_MAG_NEAREST;
163 break;
164 }
165
166 switch (cso->min_img_filter) {
167 case PIPE_TEX_FILTER_LINEAR:
168 switch (cso->min_mip_filter) {
169 case PIPE_TEX_MIPFILTER_NEAREST:
170 filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST;
171 break;
172 case PIPE_TEX_MIPFILTER_LINEAR:
173 filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR;
174 break;
175 case PIPE_TEX_MIPFILTER_NONE:
176 default:
177 filter |= NV40TCL_TEX_FILTER_MIN_LINEAR;
178 break;
179 }
180 break;
181 case PIPE_TEX_FILTER_NEAREST:
182 default:
183 switch (cso->min_mip_filter) {
184 case PIPE_TEX_MIPFILTER_NEAREST:
185 filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST;
186 break;
187 case PIPE_TEX_MIPFILTER_LINEAR:
188 filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR;
189 break;
190 case PIPE_TEX_MIPFILTER_NONE:
191 default:
192 filter |= NV40TCL_TEX_FILTER_MIN_NEAREST;
193 break;
194 }
195 break;
196 }
197
198 ps->filt = filter;
199
200 {
201 float limit;
202
203 limit = CLAMP(cso->lod_bias, -16.0, 15.0);
204 ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
205
206 limit = CLAMP(cso->max_lod, 0.0, 15.0);
207 ps->en |= (int)(limit * 256.0) << 7;
208
209 limit = CLAMP(cso->min_lod, 0.0, 15.0);
210 ps->en |= (int)(limit * 256.0) << 19;
211 }
212
213
214 if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
215 switch (cso->compare_func) {
216 case PIPE_FUNC_NEVER:
217 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NEVER;
218 break;
219 case PIPE_FUNC_GREATER:
220 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GREATER;
221 break;
222 case PIPE_FUNC_EQUAL:
223 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_EQUAL;
224 break;
225 case PIPE_FUNC_GEQUAL:
226 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GEQUAL;
227 break;
228 case PIPE_FUNC_LESS:
229 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LESS;
230 break;
231 case PIPE_FUNC_NOTEQUAL:
232 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL;
233 break;
234 case PIPE_FUNC_LEQUAL:
235 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LEQUAL;
236 break;
237 case PIPE_FUNC_ALWAYS:
238 ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_ALWAYS;
239 break;
240 default:
241 break;
242 }
243 }
244
245 ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
246 (float_to_ubyte(cso->border_color[0]) << 16) |
247 (float_to_ubyte(cso->border_color[1]) << 8) |
248 (float_to_ubyte(cso->border_color[2]) << 0));
249
250 return (void *)ps;
251 }
252
253 static void
254 nv40_sampler_state_bind(struct pipe_context *pipe, unsigned unit,
255 void *hwcso)
256 {
257 struct nv40_context *nv40 = nv40_context(pipe);
258 struct nv40_sampler_state *ps = hwcso;
259
260 nv40->tex_sampler[unit] = ps;
261 nv40->dirty_samplers |= (1 << unit);
262 }
263
264 static void
265 nv40_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
266 {
267 FREE(hwcso);
268 }
269
270 static void
271 nv40_set_sampler_texture(struct pipe_context *pipe, unsigned unit,
272 struct pipe_texture *miptree)
273 {
274 struct nv40_context *nv40 = nv40_context(pipe);
275
276 nv40->tex_miptree[unit] = (struct nv40_miptree *)miptree;
277 nv40->dirty_samplers |= (1 << unit);
278 }
279
280 static void *
281 nv40_rasterizer_state_create(struct pipe_context *pipe,
282 const struct pipe_rasterizer_state *cso)
283 {
284 struct nv40_context *nv40 = nv40_context(pipe);
285 struct nv40_rasterizer_state *rsso = MALLOC(sizeof(*rsso));
286 struct nouveau_stateobj *so = so_new(32, 0);
287 struct nouveau_grobj *curie = nv40->hw->curie;
288
289 /*XXX: ignored:
290 * light_twoside
291 * point_smooth -nohw
292 * multisample
293 */
294
295 so_method(so, curie, NV40TCL_SHADE_MODEL, 1);
296 so_data (so, cso->flatshade ? NV40TCL_SHADE_MODEL_FLAT :
297 NV40TCL_SHADE_MODEL_SMOOTH);
298
299 so_method(so, curie, NV40TCL_LINE_WIDTH, 2);
300 so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
301 so_data (so, cso->line_smooth ? 1 : 0);
302 so_method(so, curie, NV40TCL_LINE_STIPPLE_ENABLE, 2);
303 so_data (so, cso->line_stipple_enable ? 1 : 0);
304 so_data (so, (cso->line_stipple_pattern << 16) |
305 cso->line_stipple_factor);
306
307 so_method(so, curie, NV40TCL_POINT_SIZE, 1);
308 so_data (so, fui(cso->point_size));
309
310 so_method(so, curie, NV40TCL_POLYGON_MODE_FRONT, 6);
311 if (cso->front_winding == PIPE_WINDING_CCW) {
312 so_data(so, nvgl_polygon_mode(cso->fill_ccw));
313 so_data(so, nvgl_polygon_mode(cso->fill_cw));
314 switch (cso->cull_mode) {
315 case PIPE_WINDING_CCW:
316 so_data(so, NV40TCL_CULL_FACE_FRONT);
317 break;
318 case PIPE_WINDING_CW:
319 so_data(so, NV40TCL_CULL_FACE_BACK);
320 break;
321 case PIPE_WINDING_BOTH:
322 so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK);
323 break;
324 default:
325 so_data(so, 0);
326 break;
327 }
328 so_data(so, NV40TCL_FRONT_FACE_CCW);
329 } else {
330 so_data(so, nvgl_polygon_mode(cso->fill_cw));
331 so_data(so, nvgl_polygon_mode(cso->fill_ccw));
332 switch (cso->cull_mode) {
333 case PIPE_WINDING_CCW:
334 so_data(so, NV40TCL_CULL_FACE_BACK);
335 break;
336 case PIPE_WINDING_CW:
337 so_data(so, NV40TCL_CULL_FACE_FRONT);
338 break;
339 case PIPE_WINDING_BOTH:
340 so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK);
341 break;
342 default:
343 so_data(so, 0);
344 break;
345 }
346 so_data(so, NV40TCL_FRONT_FACE_CW);
347 }
348 so_data(so, cso->poly_smooth ? 1 : 0);
349 so_data(so, cso->cull_mode != PIPE_WINDING_NONE ? 1 : 0);
350
351 so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
352 so_data (so, cso->poly_stipple_enable ? 1 : 0);
353
354 so_method(so, curie, NV40TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
355 if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
356 (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
357 so_data(so, 1);
358 else
359 so_data(so, 0);
360 if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
361 (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
362 so_data(so, 1);
363 else
364 so_data(so, 0);
365 if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
366 (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
367 so_data(so, 1);
368 else
369 so_data(so, 0);
370 if (cso->offset_cw || cso->offset_ccw) {
371 so_method(so, curie, NV40TCL_POLYGON_OFFSET_FACTOR, 2);
372 so_data (so, fui(cso->offset_scale));
373 so_data (so, fui(cso->offset_units * 2));
374 }
375
376 so_method(so, curie, NV40TCL_POINT_SPRITE, 1);
377 if (cso->point_sprite) {
378 unsigned psctl = (1 << 0), i;
379
380 for (i = 0; i < 8; i++) {
381 if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
382 psctl |= (1 << (8 + i));
383 }
384
385 so_data(so, psctl);
386 } else {
387 so_data(so, 0);
388 }
389
390 rsso->so = so;
391 rsso->pipe = *cso;
392 return (void *)rsso;
393 }
394
395 static void
396 nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
397 {
398 struct nv40_context *nv40 = nv40_context(pipe);
399
400 nv40->pipe_state.rasterizer = hwcso;
401 nv40->dirty |= NV40_NEW_RAST;
402 }
403
404 static void
405 nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
406 {
407 struct nv40_rasterizer_state *rsso = hwcso;
408
409 so_ref(NULL, &rsso->so);
410 FREE(rsso);
411 }
412
413 static void *
414 nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe,
415 const struct pipe_depth_stencil_alpha_state *cso)
416 {
417 struct nv40_context *nv40 = nv40_context(pipe);
418 struct nv40_zsa_state *zsaso = MALLOC(sizeof(*zsaso));
419 struct nouveau_stateobj *so = so_new(32, 0);
420
421 so_method(so, nv40->hw->curie, NV40TCL_DEPTH_FUNC, 3);
422 so_data (so, nvgl_comparison_op(cso->depth.func));
423 so_data (so, cso->depth.writemask ? 1 : 0);
424 so_data (so, cso->depth.enabled ? 1 : 0);
425
426 so_method(so, nv40->hw->curie, NV40TCL_ALPHA_TEST_ENABLE, 3);
427 so_data (so, cso->alpha.enabled ? 1 : 0);
428 so_data (so, nvgl_comparison_op(cso->alpha.func));
429 so_data (so, float_to_ubyte(cso->alpha.ref));
430
431 if (cso->stencil[0].enabled) {
432 so_method(so, nv40->hw->curie, NV40TCL_STENCIL_FRONT_ENABLE, 8);
433 so_data (so, cso->stencil[0].enabled ? 1 : 0);
434 so_data (so, cso->stencil[0].write_mask);
435 so_data (so, nvgl_comparison_op(cso->stencil[0].func));
436 so_data (so, cso->stencil[0].ref_value);
437 so_data (so, cso->stencil[0].value_mask);
438 so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op));
439 so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
440 so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
441 } else {
442 so_method(so, nv40->hw->curie, NV40TCL_STENCIL_FRONT_ENABLE, 1);
443 so_data (so, 0);
444 }
445
446 if (cso->stencil[1].enabled) {
447 so_method(so, nv40->hw->curie, NV40TCL_STENCIL_BACK_ENABLE, 8);
448 so_data (so, cso->stencil[1].enabled ? 1 : 0);
449 so_data (so, cso->stencil[1].write_mask);
450 so_data (so, nvgl_comparison_op(cso->stencil[1].func));
451 so_data (so, cso->stencil[1].ref_value);
452 so_data (so, cso->stencil[1].value_mask);
453 so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op));
454 so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
455 so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
456 } else {
457 so_method(so, nv40->hw->curie, NV40TCL_STENCIL_BACK_ENABLE, 1);
458 so_data (so, 0);
459 }
460
461 zsaso->so = so;
462 zsaso->pipe = *cso;
463 return (void *)zsaso;
464 }
465
466 static void
467 nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
468 {
469 struct nv40_context *nv40 = nv40_context(pipe);
470
471 nv40->pipe_state.zsa = hwcso;
472 nv40->dirty |= NV40_NEW_ZSA;
473 }
474
475 static void
476 nv40_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
477 {
478 struct nv40_zsa_state *zsaso = hwcso;
479
480 so_ref(NULL, &zsaso->so);
481 FREE(zsaso);
482 }
483
484 static void *
485 nv40_vp_state_create(struct pipe_context *pipe,
486 const struct pipe_shader_state *cso)
487 {
488 struct nv40_vertex_program *vp;
489
490 vp = CALLOC(1, sizeof(struct nv40_vertex_program));
491 vp->pipe = cso;
492
493 return (void *)vp;
494 }
495
496 static void
497 nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso)
498 {
499 struct nv40_context *nv40 = nv40_context(pipe);
500
501 nv40->pipe_state.vertprog = hwcso;
502 nv40->dirty |= NV40_NEW_VERTPROG;
503 }
504
505 static void
506 nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso)
507 {
508 struct nv40_context *nv40 = nv40_context(pipe);
509 struct nv40_vertex_program *vp = hwcso;
510
511 nv40_vertprog_destroy(nv40, vp);
512 FREE(vp);
513 }
514
515 static void *
516 nv40_fp_state_create(struct pipe_context *pipe,
517 const struct pipe_shader_state *cso)
518 {
519 struct nv40_fragment_program *fp;
520
521 fp = CALLOC(1, sizeof(struct nv40_fragment_program));
522 fp->pipe = cso;
523
524 return (void *)fp;
525 }
526
527 static void
528 nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso)
529 {
530 struct nv40_context *nv40 = nv40_context(pipe);
531
532 nv40->pipe_state.fragprog = hwcso;
533 nv40->dirty |= NV40_NEW_FRAGPROG;
534 }
535
536 static void
537 nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso)
538 {
539 struct nv40_context *nv40 = nv40_context(pipe);
540 struct nv40_fragment_program *fp = hwcso;
541
542 nv40_fragprog_destroy(nv40, fp);
543 FREE(fp);
544 }
545
546 static void
547 nv40_set_blend_color(struct pipe_context *pipe,
548 const struct pipe_blend_color *bcol)
549 {
550 struct nv40_context *nv40 = nv40_context(pipe);
551
552 nv40->pipe_state.blend_colour = *bcol;
553 nv40->dirty |= NV40_NEW_BCOL;
554 }
555
556 static void
557 nv40_set_clip_state(struct pipe_context *pipe,
558 const struct pipe_clip_state *clip)
559 {
560 struct nv40_context *nv40 = nv40_context(pipe);
561
562 nv40->pipe_state.clip = *clip;
563 nv40->dirty |= NV40_NEW_UCP;
564 }
565
566 static void
567 nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
568 const struct pipe_constant_buffer *buf )
569 {
570 struct nv40_context *nv40 = nv40_context(pipe);
571
572 if (shader == PIPE_SHADER_VERTEX) {
573 nv40->pipe_state.constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
574 nv40->dirty |= NV40_NEW_VERTPROG;
575 } else
576 if (shader == PIPE_SHADER_FRAGMENT) {
577 nv40->pipe_state.constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
578 nv40->dirty |= NV40_NEW_FRAGPROG;
579 }
580 }
581
582 static void
583 nv40_set_framebuffer_state(struct pipe_context *pipe,
584 const struct pipe_framebuffer_state *fb)
585 {
586 struct nv40_context *nv40 = nv40_context(pipe);
587 struct pipe_surface *rt[4], *zeta;
588 uint32_t rt_enable, rt_format, w, h;
589 int i, colour_format = 0, zeta_format = 0;
590 struct nouveau_stateobj *so = so_new(64, 10);
591 unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
592
593 rt_enable = 0;
594 for (i = 0; i < 4; i++) {
595 if (!fb->cbufs[i])
596 continue;
597
598 if (colour_format) {
599 assert(w == fb->cbufs[i]->width);
600 assert(h == fb->cbufs[i]->height);
601 assert(colour_format == fb->cbufs[i]->format);
602 } else {
603 w = fb->cbufs[i]->width;
604 h = fb->cbufs[i]->height;
605 colour_format = fb->cbufs[i]->format;
606 rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i);
607 rt[i] = fb->cbufs[i];
608 }
609 }
610
611 if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 |
612 NV40TCL_RT_ENABLE_COLOR3))
613 rt_enable |= NV40TCL_RT_ENABLE_MRT;
614
615 if (fb->zsbuf) {
616 if (colour_format) {
617 assert(w == fb->zsbuf->width);
618 assert(h == fb->zsbuf->height);
619 } else {
620 w = fb->zsbuf->width;
621 h = fb->zsbuf->height;
622 }
623
624 zeta_format = fb->zsbuf->format;
625 zeta = fb->zsbuf;
626 }
627
628 rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR;
629
630 switch (colour_format) {
631 case PIPE_FORMAT_A8R8G8B8_UNORM:
632 case 0:
633 rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8;
634 break;
635 case PIPE_FORMAT_R5G6B5_UNORM:
636 rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5;
637 break;
638 default:
639 assert(0);
640 }
641
642 switch (zeta_format) {
643 case PIPE_FORMAT_Z16_UNORM:
644 rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16;
645 break;
646 case PIPE_FORMAT_Z24S8_UNORM:
647 case 0:
648 rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8;
649 break;
650 default:
651 assert(0);
652 }
653
654 if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) {
655 so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR0, 1);
656 so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
657 nv40->nvws->channel->vram->handle,
658 nv40->nvws->channel->gart->handle);
659 so_method(so, nv40->hw->curie, NV40TCL_COLOR0_PITCH, 2);
660 so_data (so, rt[0]->pitch * rt[0]->cpp);
661 so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags |
662 NOUVEAU_BO_LOW, 0, 0);
663 }
664
665 if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) {
666 so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR1, 1);
667 so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
668 nv40->nvws->channel->vram->handle,
669 nv40->nvws->channel->gart->handle);
670 so_method(so, nv40->hw->curie, NV40TCL_COLOR1_OFFSET, 2);
671 so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags |
672 NOUVEAU_BO_LOW, 0, 0);
673 so_data (so, rt[1]->pitch * rt[1]->cpp);
674 }
675
676 if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) {
677 so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR2, 1);
678 so_reloc (so, rt[2]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
679 nv40->nvws->channel->vram->handle,
680 nv40->nvws->channel->gart->handle);
681 so_method(so, nv40->hw->curie, NV40TCL_COLOR2_OFFSET, 1);
682 so_reloc (so, rt[2]->buffer, rt[2]->offset, rt_flags |
683 NOUVEAU_BO_LOW, 0, 0);
684 so_method(so, nv40->hw->curie, NV40TCL_COLOR2_PITCH, 1);
685 so_data (so, rt[2]->pitch * rt[2]->cpp);
686 }
687
688 if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) {
689 so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR3, 1);
690 so_reloc (so, rt[3]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
691 nv40->nvws->channel->vram->handle,
692 nv40->nvws->channel->gart->handle);
693 so_method(so, nv40->hw->curie, NV40TCL_COLOR3_OFFSET, 1);
694 so_reloc (so, rt[3]->buffer, rt[3]->offset, rt_flags |
695 NOUVEAU_BO_LOW, 0, 0);
696 so_method(so, nv40->hw->curie, NV40TCL_COLOR3_PITCH, 1);
697 so_data (so, rt[3]->pitch * rt[3]->cpp);
698 }
699
700 if (zeta_format) {
701 so_method(so, nv40->hw->curie, NV40TCL_DMA_ZETA, 1);
702 so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR,
703 nv40->nvws->channel->vram->handle,
704 nv40->nvws->channel->gart->handle);
705 so_method(so, nv40->hw->curie, NV40TCL_ZETA_OFFSET, 1);
706 so_reloc (so, zeta->buffer, zeta->offset, rt_flags |
707 NOUVEAU_BO_LOW, 0, 0);
708 so_method(so, nv40->hw->curie, NV40TCL_ZETA_PITCH, 1);
709 so_data (so, zeta->pitch * zeta->cpp);
710 }
711
712 so_method(so, nv40->hw->curie, NV40TCL_RT_ENABLE, 1);
713 so_data (so, rt_enable);
714 so_method(so, nv40->hw->curie, NV40TCL_RT_HORIZ, 3);
715 so_data (so, (w << 16) | 0);
716 so_data (so, (h << 16) | 0);
717 so_data (so, rt_format);
718 so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_HORIZ, 2);
719 so_data (so, (w << 16) | 0);
720 so_data (so, (h << 16) | 0);
721 so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
722 so_data (so, ((w - 1) << 16) | 0);
723 so_data (so, ((h - 1) << 16) | 0);
724
725 so_ref(so, &nv40->so_framebuffer);
726 so_ref(NULL, &so);
727 nv40->dirty |= NV40_NEW_FB;
728 }
729
730 static void
731 nv40_set_polygon_stipple(struct pipe_context *pipe,
732 const struct pipe_poly_stipple *stipple)
733 {
734 struct nv40_context *nv40 = nv40_context(pipe);
735
736 memcpy(nv40->pipe_state.stipple, stipple->stipple, 4 * 32);
737 nv40->dirty |= NV40_NEW_STIPPLE;
738 }
739
740 static void
741 nv40_set_scissor_state(struct pipe_context *pipe,
742 const struct pipe_scissor_state *s)
743 {
744 struct nv40_context *nv40 = nv40_context(pipe);
745
746 nv40->pipe_state.scissor = *s;
747 nv40->dirty |= NV40_NEW_SCISSOR;
748 }
749
750 static void
751 nv40_set_viewport_state(struct pipe_context *pipe,
752 const struct pipe_viewport_state *vpt)
753 {
754 struct nv40_context *nv40 = nv40_context(pipe);
755
756 nv40->pipe_state.viewport = *vpt;
757 nv40->dirty |= NV40_NEW_VIEWPORT;
758 }
759
760 static void
761 nv40_set_vertex_buffer(struct pipe_context *pipe, unsigned index,
762 const struct pipe_vertex_buffer *vb)
763 {
764 struct nv40_context *nv40 = nv40_context(pipe);
765
766 nv40->vtxbuf[index] = *vb;
767
768 nv40->dirty |= NV40_NEW_ARRAYS;
769 }
770
771 static void
772 nv40_set_vertex_element(struct pipe_context *pipe, unsigned index,
773 const struct pipe_vertex_element *ve)
774 {
775 struct nv40_context *nv40 = nv40_context(pipe);
776
777 nv40->vtxelt[index] = *ve;
778
779 nv40->dirty |= NV40_NEW_ARRAYS;
780 }
781
782 void
783 nv40_init_state_functions(struct nv40_context *nv40)
784 {
785 nv40->pipe.create_blend_state = nv40_blend_state_create;
786 nv40->pipe.bind_blend_state = nv40_blend_state_bind;
787 nv40->pipe.delete_blend_state = nv40_blend_state_delete;
788
789 nv40->pipe.create_sampler_state = nv40_sampler_state_create;
790 nv40->pipe.bind_sampler_state = nv40_sampler_state_bind;
791 nv40->pipe.delete_sampler_state = nv40_sampler_state_delete;
792 nv40->pipe.set_sampler_texture = nv40_set_sampler_texture;
793
794 nv40->pipe.create_rasterizer_state = nv40_rasterizer_state_create;
795 nv40->pipe.bind_rasterizer_state = nv40_rasterizer_state_bind;
796 nv40->pipe.delete_rasterizer_state = nv40_rasterizer_state_delete;
797
798 nv40->pipe.create_depth_stencil_alpha_state =
799 nv40_depth_stencil_alpha_state_create;
800 nv40->pipe.bind_depth_stencil_alpha_state =
801 nv40_depth_stencil_alpha_state_bind;
802 nv40->pipe.delete_depth_stencil_alpha_state =
803 nv40_depth_stencil_alpha_state_delete;
804
805 nv40->pipe.create_vs_state = nv40_vp_state_create;
806 nv40->pipe.bind_vs_state = nv40_vp_state_bind;
807 nv40->pipe.delete_vs_state = nv40_vp_state_delete;
808
809 nv40->pipe.create_fs_state = nv40_fp_state_create;
810 nv40->pipe.bind_fs_state = nv40_fp_state_bind;
811 nv40->pipe.delete_fs_state = nv40_fp_state_delete;
812
813 nv40->pipe.set_blend_color = nv40_set_blend_color;
814 nv40->pipe.set_clip_state = nv40_set_clip_state;
815 nv40->pipe.set_constant_buffer = nv40_set_constant_buffer;
816 nv40->pipe.set_framebuffer_state = nv40_set_framebuffer_state;
817 nv40->pipe.set_polygon_stipple = nv40_set_polygon_stipple;
818 nv40->pipe.set_scissor_state = nv40_set_scissor_state;
819 nv40->pipe.set_viewport_state = nv40_set_viewport_state;
820
821 nv40->pipe.set_vertex_buffer = nv40_set_vertex_buffer;
822 nv40->pipe.set_vertex_element = nv40_set_vertex_element;
823 }
824