Merge remote branch 'origin/master' into nv50-compiler
[mesa.git] / src / gallium / drivers / nv50 / nv50_state.c
1 /*
2 * Copyright 2008 Ben Skeggs
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "pipe/p_state.h"
24 #include "pipe/p_defines.h"
25 #include "util/u_inlines.h"
26
27 #include "tgsi/tgsi_parse.h"
28
29 #include "nv50_context.h"
30 #include "nv50_texture.h"
31
32 #include "nouveau/nouveau_stateobj.h"
33
34 static INLINE uint32_t
35 nv50_colormask(unsigned mask)
36 {
37 uint32_t cmask = 0;
38
39 if (mask & PIPE_MASK_R)
40 cmask |= 0x0001;
41 if (mask & PIPE_MASK_G)
42 cmask |= 0x0010;
43 if (mask & PIPE_MASK_B)
44 cmask |= 0x0100;
45 if (mask & PIPE_MASK_A)
46 cmask |= 0x1000;
47
48 return cmask;
49 }
50
51 static INLINE uint32_t
52 nv50_blend_func(unsigned factor)
53 {
54 switch (factor) {
55 case PIPE_BLENDFACTOR_ZERO:
56 return NV50TCL_BLEND_FUNC_SRC_RGB_ZERO;
57 case PIPE_BLENDFACTOR_ONE:
58 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE;
59 case PIPE_BLENDFACTOR_SRC_COLOR:
60 return NV50TCL_BLEND_FUNC_SRC_RGB_SRC_COLOR;
61 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
62 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR;
63 case PIPE_BLENDFACTOR_SRC_ALPHA:
64 return NV50TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA;
65 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
66 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA;
67 case PIPE_BLENDFACTOR_DST_ALPHA:
68 return NV50TCL_BLEND_FUNC_SRC_RGB_DST_ALPHA;
69 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
70 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA;
71 case PIPE_BLENDFACTOR_DST_COLOR:
72 return NV50TCL_BLEND_FUNC_SRC_RGB_DST_COLOR;
73 case PIPE_BLENDFACTOR_INV_DST_COLOR:
74 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR;
75 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
76 return NV50TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE;
77 case PIPE_BLENDFACTOR_CONST_COLOR:
78 return NV50TCL_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR;
79 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
80 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR;
81 case PIPE_BLENDFACTOR_CONST_ALPHA:
82 return NV50TCL_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA;
83 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
84 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA;
85 case PIPE_BLENDFACTOR_SRC1_COLOR:
86 return NV50TCL_BLEND_FUNC_SRC_RGB_SRC1_COLOR;
87 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
88 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC1_COLOR;
89 case PIPE_BLENDFACTOR_SRC1_ALPHA:
90 return NV50TCL_BLEND_FUNC_SRC_RGB_SRC1_ALPHA;
91 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
92 return NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC1_ALPHA;
93 default:
94 return NV50TCL_BLEND_FUNC_SRC_RGB_ZERO;
95 }
96 }
97
98 static void *
99 nv50_blend_state_create(struct pipe_context *pipe,
100 const struct pipe_blend_state *cso)
101 {
102 struct nouveau_stateobj *so = so_new(5, 24, 0);
103 struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
104 struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj);
105 unsigned i, blend_enabled = 0;
106
107 /*XXX ignored:
108 * - dither
109 */
110
111 so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
112 if (cso->independent_blend_enable) {
113 for (i = 0; i < 8; ++i) {
114 so_data(so, cso->rt[i].blend_enable);
115 if (cso->rt[i].blend_enable)
116 blend_enabled = 1;
117 }
118 } else
119 if (cso->rt[0].blend_enable) {
120 blend_enabled = 1;
121 for (i = 0; i < 8; i++)
122 so_data(so, 1);
123 } else {
124 for (i = 0; i < 8; i++)
125 so_data(so, 0);
126 }
127 if (blend_enabled) {
128 so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
129 so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
130 so_data (so, nv50_blend_func(cso->rt[0].rgb_src_factor));
131 so_data (so, nv50_blend_func(cso->rt[0].rgb_dst_factor));
132 so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func));
133 so_data (so, nv50_blend_func(cso->rt[0].alpha_src_factor));
134 so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
135 so_data (so, nv50_blend_func(cso->rt[0].alpha_dst_factor));
136 }
137
138 if (cso->logicop_enable == 0 ) {
139 so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 1);
140 so_data (so, 0);
141 } else {
142 so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 2);
143 so_data (so, 1);
144 so_data (so, nvgl_logicop_func(cso->logicop_func));
145 }
146
147 so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8);
148 if (cso->independent_blend_enable)
149 for (i = 0; i < 8; ++i)
150 so_data(so, nv50_colormask(cso->rt[i].colormask));
151 else {
152 uint32_t cmask = nv50_colormask(cso->rt[0].colormask);
153 for (i = 0; i < 8; i++)
154 so_data(so, cmask);
155 }
156
157 bso->pipe = *cso;
158 so_ref(so, &bso->so);
159 so_ref(NULL, &so);
160 return (void *)bso;
161 }
162
163 static void
164 nv50_blend_state_bind(struct pipe_context *pipe, void *hwcso)
165 {
166 struct nv50_context *nv50 = nv50_context(pipe);
167
168 nv50->blend = hwcso;
169 nv50->dirty |= NV50_NEW_BLEND;
170 }
171
172 static void
173 nv50_blend_state_delete(struct pipe_context *pipe, void *hwcso)
174 {
175 struct nv50_blend_stateobj *bso = hwcso;
176
177 so_ref(NULL, &bso->so);
178 FREE(bso);
179 }
180
181 static INLINE unsigned
182 wrap_mode(unsigned wrap)
183 {
184 switch (wrap) {
185 case PIPE_TEX_WRAP_REPEAT:
186 return NV50TSC_1_0_WRAPS_REPEAT;
187 case PIPE_TEX_WRAP_MIRROR_REPEAT:
188 return NV50TSC_1_0_WRAPS_MIRROR_REPEAT;
189 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
190 return NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE;
191 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
192 return NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER;
193 case PIPE_TEX_WRAP_CLAMP:
194 return NV50TSC_1_0_WRAPS_CLAMP;
195 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
196 return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE;
197 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
198 return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER;
199 case PIPE_TEX_WRAP_MIRROR_CLAMP:
200 return NV50TSC_1_0_WRAPS_MIRROR_CLAMP;
201 default:
202 NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
203 return NV50TSC_1_0_WRAPS_REPEAT;
204 }
205 }
206 static void *
207 nv50_sampler_state_create(struct pipe_context *pipe,
208 const struct pipe_sampler_state *cso)
209 {
210 struct nv50_sampler_stateobj *sso = CALLOC(1, sizeof(*sso));
211 unsigned *tsc = sso->tsc;
212 float limit;
213
214 tsc[0] = (0x00026000 |
215 (wrap_mode(cso->wrap_s) << 0) |
216 (wrap_mode(cso->wrap_t) << 3) |
217 (wrap_mode(cso->wrap_r) << 6));
218
219 switch (cso->mag_img_filter) {
220 case PIPE_TEX_FILTER_LINEAR:
221 tsc[1] |= NV50TSC_1_1_MAGF_LINEAR;
222 break;
223 case PIPE_TEX_FILTER_NEAREST:
224 default:
225 tsc[1] |= NV50TSC_1_1_MAGF_NEAREST;
226 break;
227 }
228
229 switch (cso->min_img_filter) {
230 case PIPE_TEX_FILTER_LINEAR:
231 tsc[1] |= NV50TSC_1_1_MINF_LINEAR;
232 break;
233 case PIPE_TEX_FILTER_NEAREST:
234 default:
235 tsc[1] |= NV50TSC_1_1_MINF_NEAREST;
236 break;
237 }
238
239 switch (cso->min_mip_filter) {
240 case PIPE_TEX_MIPFILTER_LINEAR:
241 tsc[1] |= NV50TSC_1_1_MIPF_LINEAR;
242 break;
243 case PIPE_TEX_MIPFILTER_NEAREST:
244 tsc[1] |= NV50TSC_1_1_MIPF_NEAREST;
245 break;
246 case PIPE_TEX_MIPFILTER_NONE:
247 default:
248 tsc[1] |= NV50TSC_1_1_MIPF_NONE;
249 break;
250 }
251
252 if (cso->max_anisotropy >= 16)
253 tsc[0] |= (7 << 20);
254 else
255 if (cso->max_anisotropy >= 12)
256 tsc[0] |= (6 << 20);
257 else {
258 tsc[0] |= (cso->max_anisotropy >> 1) << 20;
259
260 if (cso->max_anisotropy >= 4)
261 tsc[1] |= NV50TSC_1_1_UNKN_ANISO_35;
262 else
263 if (cso->max_anisotropy >= 2)
264 tsc[1] |= NV50TSC_1_1_UNKN_ANISO_15;
265 }
266
267 if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
268 /* XXX: must be deactivated for non-shadow textures */
269 tsc[0] |= (1 << 9);
270 tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7) << 10;
271 }
272
273 limit = CLAMP(cso->lod_bias, -16.0, 15.0);
274 tsc[1] |= ((int)(limit * 256.0) & 0x1fff) << 12;
275
276 tsc[2] |= ((int)CLAMP(cso->max_lod, 0.0, 15.0) << 20) |
277 ((int)CLAMP(cso->min_lod, 0.0, 15.0) << 8);
278
279 tsc[4] = fui(cso->border_color[0]);
280 tsc[5] = fui(cso->border_color[1]);
281 tsc[6] = fui(cso->border_color[2]);
282 tsc[7] = fui(cso->border_color[3]);
283
284 sso->normalized = cso->normalized_coords;
285 return (void *)sso;
286 }
287
288 /* type == 0 for VPs, 1 for GPs, 2 for FPs, which is how the
289 * relevant tesla methods are indexed (NV50TCL_BIND_TSC etc.)
290 */
291 static INLINE void
292 nv50_sampler_state_bind(struct pipe_context *pipe, unsigned type,
293 unsigned nr, void **sampler)
294 {
295 struct nv50_context *nv50 = nv50_context(pipe);
296
297 memcpy(nv50->sampler[type], sampler, nr * sizeof(void *));
298
299 nv50->sampler_nr[type] = nr;
300 nv50->dirty |= NV50_NEW_SAMPLER;
301 }
302
303 static void
304 nv50_vp_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **s)
305 {
306 nv50_sampler_state_bind(pipe, 0, nr, s);
307 }
308
309 static void
310 nv50_fp_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **s)
311 {
312 nv50_sampler_state_bind(pipe, 2, nr, s);
313 }
314
315 static void
316 nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
317 {
318 FREE(hwcso);
319 }
320
321 static INLINE void
322 nv50_set_sampler_views(struct pipe_context *pipe, unsigned p,
323 unsigned nr,
324 struct pipe_sampler_view **views)
325 {
326 struct nv50_context *nv50 = nv50_context(pipe);
327 unsigned i;
328
329 for (i = 0; i < nr; i++)
330 pipe_sampler_view_reference(&nv50->sampler_views[p][i],
331 views[i]);
332
333 for (i = nr; i < nv50->sampler_view_nr[p]; i++)
334 pipe_sampler_view_reference(&nv50->sampler_views[p][i], NULL);
335
336 nv50->sampler_view_nr[p] = nr;
337 nv50->dirty |= NV50_NEW_TEXTURE;
338 }
339
340 static void
341 nv50_set_vp_sampler_views(struct pipe_context *pipe,
342 unsigned nr,
343 struct pipe_sampler_view **views)
344 {
345 nv50_set_sampler_views(pipe, 0, nr, views);
346 }
347
348 static void
349 nv50_set_fp_sampler_views(struct pipe_context *pipe,
350 unsigned nr,
351 struct pipe_sampler_view **views)
352 {
353 nv50_set_sampler_views(pipe, 2, nr, views);
354 }
355
356 static void
357 nv50_sampler_view_destroy(struct pipe_context *pipe,
358 struct pipe_sampler_view *view)
359 {
360 pipe_resource_reference(&view->texture, NULL);
361 FREE(nv50_sampler_view(view));
362 }
363
364 static struct pipe_sampler_view *
365 nv50_create_sampler_view(struct pipe_context *pipe,
366 struct pipe_resource *texture,
367 const struct pipe_sampler_view *templ)
368 {
369 struct nv50_sampler_view *view = CALLOC_STRUCT(nv50_sampler_view);
370
371 view->pipe = *templ;
372 view->pipe.reference.count = 1;
373 view->pipe.texture = NULL;
374 pipe_resource_reference(&view->pipe.texture, texture);
375 view->pipe.context = pipe;
376
377 if (!nv50_tex_construct(view)) {
378 nv50_sampler_view_destroy(pipe, &view->pipe);
379 return NULL;
380 }
381 return &view->pipe;
382 }
383
384
385 static void *
386 nv50_rasterizer_state_create(struct pipe_context *pipe,
387 const struct pipe_rasterizer_state *cso)
388 {
389 struct nouveau_stateobj *so = so_new(16, 22, 0);
390 struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
391 struct nv50_rasterizer_stateobj *rso =
392 CALLOC_STRUCT(nv50_rasterizer_stateobj);
393
394 /*XXX: ignored
395 * - light_twoside
396 * - point_smooth
397 * - multisample
398 * - point_sprite / sprite_coord_mode
399 */
400
401 so_method(so, tesla, NV50TCL_SCISSOR_ENABLE(0), 1);
402 so_data (so, cso->scissor);
403
404 so_method(so, tesla, NV50TCL_SHADE_MODEL, 1);
405 so_data (so, cso->flatshade ? NV50TCL_SHADE_MODEL_FLAT :
406 NV50TCL_SHADE_MODEL_SMOOTH);
407 so_method(so, tesla, NV50TCL_PROVOKING_VERTEX_LAST, 1);
408 so_data (so, cso->flatshade_first ? 0 : 1);
409
410 so_method(so, tesla, NV50TCL_VERTEX_TWO_SIDE_ENABLE, 1);
411 so_data (so, cso->light_twoside);
412
413 so_method(so, tesla, NV50TCL_LINE_WIDTH, 1);
414 so_data (so, fui(cso->line_width));
415 so_method(so, tesla, NV50TCL_LINE_SMOOTH_ENABLE, 1);
416 so_data (so, cso->line_smooth ? 1 : 0);
417 if (cso->line_stipple_enable) {
418 so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
419 so_data (so, 1);
420 so_method(so, tesla, NV50TCL_LINE_STIPPLE_PATTERN, 1);
421 so_data (so, (cso->line_stipple_pattern << 8) |
422 cso->line_stipple_factor);
423 } else {
424 so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
425 so_data (so, 0);
426 }
427
428 so_method(so, tesla, NV50TCL_POINT_SIZE, 1);
429 so_data (so, fui(cso->point_size));
430
431 so_method(so, tesla, NV50TCL_POINT_SPRITE_ENABLE, 1);
432 so_data (so, cso->point_quad_rasterization ? 1 : 0);
433
434 so_method(so, tesla, NV50TCL_POLYGON_MODE_FRONT, 3);
435 so_data(so, nvgl_polygon_mode(cso->fill_front));
436 so_data(so, nvgl_polygon_mode(cso->fill_back));
437 so_data(so, cso->poly_smooth ? 1 : 0);
438
439 so_method(so, tesla, NV50TCL_CULL_FACE_ENABLE, 3);
440 so_data (so, cso->cull_face != PIPE_FACE_NONE);
441 if (cso->front_ccw) {
442 so_data(so, NV50TCL_FRONT_FACE_CCW);
443 }
444 else {
445 so_data(so, NV50TCL_FRONT_FACE_CW);
446 }
447 switch (cso->cull_face) {
448 case PIPE_FACE_FRONT:
449 so_data(so, NV50TCL_CULL_FACE_FRONT);
450 break;
451 case PIPE_FACE_BACK:
452 so_data(so, NV50TCL_CULL_FACE_BACK);
453 break;
454 case PIPE_FACE_FRONT_AND_BACK:
455 so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK);
456 break;
457 default:
458 so_data(so, NV50TCL_CULL_FACE_BACK);
459 break;
460 }
461
462 so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_ENABLE, 1);
463 so_data (so, cso->poly_stipple_enable ? 1 : 0);
464
465 so_method(so, tesla, NV50TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
466 so_data(so, cso->offset_point);
467 so_data(so, cso->offset_line);
468 so_data(so, cso->offset_tri);
469
470 if (cso->offset_point ||
471 cso->offset_line ||
472 cso->offset_tri) {
473 so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1);
474 so_data (so, fui(cso->offset_scale));
475 so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1);
476 so_data (so, fui(cso->offset_units * 2.0f));
477 }
478
479 rso->pipe = *cso;
480 so_ref(so, &rso->so);
481 so_ref(NULL, &so);
482 return (void *)rso;
483 }
484
485 static void
486 nv50_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
487 {
488 struct nv50_context *nv50 = nv50_context(pipe);
489
490 nv50->rasterizer = hwcso;
491 nv50->dirty |= NV50_NEW_RASTERIZER;
492 }
493
494 static void
495 nv50_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
496 {
497 struct nv50_rasterizer_stateobj *rso = hwcso;
498
499 so_ref(NULL, &rso->so);
500 FREE(rso);
501 }
502
503 static void *
504 nv50_depth_stencil_alpha_state_create(struct pipe_context *pipe,
505 const struct pipe_depth_stencil_alpha_state *cso)
506 {
507 struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
508 struct nv50_zsa_stateobj *zsa = CALLOC_STRUCT(nv50_zsa_stateobj);
509 struct nouveau_stateobj *so = so_new(9, 21, 0);
510
511 so_method(so, tesla, NV50TCL_DEPTH_WRITE_ENABLE, 1);
512 so_data (so, cso->depth.writemask ? 1 : 0);
513 if (cso->depth.enabled) {
514 so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1);
515 so_data (so, 1);
516 so_method(so, tesla, NV50TCL_DEPTH_TEST_FUNC, 1);
517 so_data (so, nvgl_comparison_op(cso->depth.func));
518 } else {
519 so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1);
520 so_data (so, 0);
521 }
522
523 if (cso->stencil[0].enabled) {
524 so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 5);
525 so_data (so, 1);
526 so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op));
527 so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
528 so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
529 so_data (so, nvgl_comparison_op(cso->stencil[0].func));
530 so_method(so, tesla, NV50TCL_STENCIL_FRONT_MASK, 2);
531 so_data (so, cso->stencil[0].writemask);
532 so_data (so, cso->stencil[0].valuemask);
533 } else {
534 so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 1);
535 so_data (so, 0);
536 }
537
538 if (cso->stencil[1].enabled) {
539 so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 5);
540 so_data (so, 1);
541 so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op));
542 so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
543 so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
544 so_data (so, nvgl_comparison_op(cso->stencil[1].func));
545 so_method(so, tesla, NV50TCL_STENCIL_BACK_MASK, 2);
546 so_data (so, cso->stencil[1].writemask);
547 so_data (so, cso->stencil[1].valuemask);
548 } else {
549 so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 1);
550 so_data (so, 0);
551 }
552
553 if (cso->alpha.enabled) {
554 so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1);
555 so_data (so, 1);
556 so_method(so, tesla, NV50TCL_ALPHA_TEST_REF, 2);
557 so_data (so, fui(cso->alpha.ref_value));
558 so_data (so, nvgl_comparison_op(cso->alpha.func));
559 } else {
560 so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1);
561 so_data (so, 0);
562 }
563
564 zsa->pipe = *cso;
565 so_ref(so, &zsa->so);
566 so_ref(NULL, &so);
567 return (void *)zsa;
568 }
569
570 static void
571 nv50_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
572 {
573 struct nv50_context *nv50 = nv50_context(pipe);
574
575 nv50->zsa = hwcso;
576 nv50->dirty |= NV50_NEW_ZSA;
577 }
578
579 static void
580 nv50_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
581 {
582 struct nv50_zsa_stateobj *zsa = hwcso;
583
584 so_ref(NULL, &zsa->so);
585 FREE(zsa);
586 }
587
588 static void *
589 nv50_vp_state_create(struct pipe_context *pipe,
590 const struct pipe_shader_state *cso)
591 {
592 struct nv50_program *p = CALLOC_STRUCT(nv50_program);
593
594 p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
595 p->type = PIPE_SHADER_VERTEX;
596 return (void *)p;
597 }
598
599 static void
600 nv50_vp_state_bind(struct pipe_context *pipe, void *hwcso)
601 {
602 struct nv50_context *nv50 = nv50_context(pipe);
603
604 nv50->vertprog = hwcso;
605 nv50->dirty |= NV50_NEW_VERTPROG;
606 }
607
608 static void
609 nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso)
610 {
611 struct nv50_context *nv50 = nv50_context(pipe);
612 struct nv50_program *p = hwcso;
613
614 nv50_program_destroy(nv50, p);
615 FREE((void *)p->pipe.tokens);
616 FREE(p);
617 }
618
619 static void *
620 nv50_fp_state_create(struct pipe_context *pipe,
621 const struct pipe_shader_state *cso)
622 {
623 struct nv50_program *p = CALLOC_STRUCT(nv50_program);
624
625 p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
626 p->type = PIPE_SHADER_FRAGMENT;
627 return (void *)p;
628 }
629
630 static void
631 nv50_fp_state_bind(struct pipe_context *pipe, void *hwcso)
632 {
633 struct nv50_context *nv50 = nv50_context(pipe);
634
635 nv50->fragprog = hwcso;
636 nv50->dirty |= NV50_NEW_FRAGPROG;
637 }
638
639 static void
640 nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso)
641 {
642 struct nv50_context *nv50 = nv50_context(pipe);
643 struct nv50_program *p = hwcso;
644
645 nv50_program_destroy(nv50, p);
646 FREE((void *)p->pipe.tokens);
647 FREE(p);
648 }
649
650 static void *
651 nv50_gp_state_create(struct pipe_context *pipe,
652 const struct pipe_shader_state *cso)
653 {
654 struct nv50_program *p = CALLOC_STRUCT(nv50_program);
655
656 p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
657 p->type = PIPE_SHADER_GEOMETRY;
658 return (void *)p;
659 }
660
661 static void
662 nv50_gp_state_bind(struct pipe_context *pipe, void *hwcso)
663 {
664 struct nv50_context *nv50 = nv50_context(pipe);
665
666 nv50->fragprog = hwcso;
667 nv50->dirty |= NV50_NEW_GEOMPROG;
668 }
669
670 static void
671 nv50_gp_state_delete(struct pipe_context *pipe, void *hwcso)
672 {
673 struct nv50_context *nv50 = nv50_context(pipe);
674 struct nv50_program *p = hwcso;
675
676 nv50_program_destroy(nv50, p);
677 FREE((void *)p->pipe.tokens);
678 FREE(p);
679 }
680
681 static void
682 nv50_set_blend_color(struct pipe_context *pipe,
683 const struct pipe_blend_color *bcol)
684 {
685 struct nv50_context *nv50 = nv50_context(pipe);
686
687 nv50->blend_colour = *bcol;
688 nv50->dirty |= NV50_NEW_BLEND_COLOUR;
689 }
690
691 static void
692 nv50_set_stencil_ref(struct pipe_context *pipe,
693 const struct pipe_stencil_ref *sr)
694 {
695 struct nv50_context *nv50 = nv50_context(pipe);
696
697 nv50->stencil_ref = *sr;
698 nv50->dirty |= NV50_NEW_STENCIL_REF;
699 }
700
701 static void
702 nv50_set_clip_state(struct pipe_context *pipe,
703 const struct pipe_clip_state *clip)
704 {
705 struct nv50_context *nv50 = nv50_context(pipe);
706
707 nv50->clip.depth_clamp = clip->depth_clamp;
708 nv50->dirty |= NV50_NEW_CLIP;
709 }
710
711 static void
712 nv50_set_sample_mask(struct pipe_context *pipe,
713 unsigned sample_mask)
714 {
715 }
716
717 static void
718 nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
719 struct pipe_resource *buf )
720 {
721 struct nv50_context *nv50 = nv50_context(pipe);
722
723 if (shader == PIPE_SHADER_VERTEX) {
724 nv50->constbuf[PIPE_SHADER_VERTEX] = buf;
725 nv50->dirty |= NV50_NEW_VERTPROG_CB;
726 } else
727 if (shader == PIPE_SHADER_FRAGMENT) {
728 nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf;
729 nv50->dirty |= NV50_NEW_FRAGPROG_CB;
730 } else
731 if (shader == PIPE_SHADER_GEOMETRY) {
732 nv50->constbuf[PIPE_SHADER_GEOMETRY] = buf;
733 nv50->dirty |= NV50_NEW_GEOMPROG_CB;
734 }
735 }
736
737 static void
738 nv50_set_framebuffer_state(struct pipe_context *pipe,
739 const struct pipe_framebuffer_state *fb)
740 {
741 struct nv50_context *nv50 = nv50_context(pipe);
742
743 nv50->framebuffer = *fb;
744 nv50->dirty |= NV50_NEW_FRAMEBUFFER;
745 }
746
747 static void
748 nv50_set_polygon_stipple(struct pipe_context *pipe,
749 const struct pipe_poly_stipple *stipple)
750 {
751 struct nv50_context *nv50 = nv50_context(pipe);
752
753 nv50->stipple = *stipple;
754 nv50->dirty |= NV50_NEW_STIPPLE;
755 }
756
757 static void
758 nv50_set_scissor_state(struct pipe_context *pipe,
759 const struct pipe_scissor_state *s)
760 {
761 struct nv50_context *nv50 = nv50_context(pipe);
762
763 nv50->scissor = *s;
764 nv50->dirty |= NV50_NEW_SCISSOR;
765 }
766
767 static void
768 nv50_set_viewport_state(struct pipe_context *pipe,
769 const struct pipe_viewport_state *vpt)
770 {
771 struct nv50_context *nv50 = nv50_context(pipe);
772
773 nv50->viewport = *vpt;
774 nv50->dirty |= NV50_NEW_VIEWPORT;
775 }
776
777 static void
778 nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
779 const struct pipe_vertex_buffer *vb)
780 {
781 struct nv50_context *nv50 = nv50_context(pipe);
782
783 memcpy(nv50->vtxbuf, vb, sizeof(*vb) * count);
784 nv50->vtxbuf_nr = count;
785
786 nv50->dirty |= NV50_NEW_ARRAYS;
787 }
788
789 static void
790 nv50_set_index_buffer(struct pipe_context *pipe,
791 const struct pipe_index_buffer *ib)
792 {
793 struct nv50_context *nv50 = nv50_context(pipe);
794
795 if (ib)
796 memcpy(&nv50->idxbuf, ib, sizeof(nv50->idxbuf));
797 else
798 memset(&nv50->idxbuf, 0, sizeof(nv50->idxbuf));
799
800 /* TODO make this more like a state */
801 }
802
803 static void *
804 nv50_vtxelts_state_create(struct pipe_context *pipe,
805 unsigned num_elements,
806 const struct pipe_vertex_element *elements)
807 {
808 struct nv50_vtxelt_stateobj *cso = CALLOC_STRUCT(nv50_vtxelt_stateobj);
809
810 assert(num_elements < 16); /* not doing fallbacks yet */
811 cso->num_elements = num_elements;
812 memcpy(cso->pipe, elements, num_elements * sizeof(*elements));
813
814 nv50_vtxelt_construct(cso);
815
816 return (void *)cso;
817 }
818
819 static void
820 nv50_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso)
821 {
822 FREE(hwcso);
823 }
824
825 static void
826 nv50_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso)
827 {
828 struct nv50_context *nv50 = nv50_context(pipe);
829
830 nv50->vtxelt = hwcso;
831 nv50->dirty |= NV50_NEW_ARRAYS;
832 }
833
834 void
835 nv50_init_state_functions(struct nv50_context *nv50)
836 {
837 nv50->pipe.create_blend_state = nv50_blend_state_create;
838 nv50->pipe.bind_blend_state = nv50_blend_state_bind;
839 nv50->pipe.delete_blend_state = nv50_blend_state_delete;
840
841 nv50->pipe.create_sampler_state = nv50_sampler_state_create;
842 nv50->pipe.delete_sampler_state = nv50_sampler_state_delete;
843 nv50->pipe.bind_fragment_sampler_states = nv50_fp_sampler_state_bind;
844 nv50->pipe.bind_vertex_sampler_states = nv50_vp_sampler_state_bind;
845 nv50->pipe.set_fragment_sampler_views = nv50_set_fp_sampler_views;
846 nv50->pipe.set_vertex_sampler_views = nv50_set_vp_sampler_views;
847 nv50->pipe.create_sampler_view = nv50_create_sampler_view;
848 nv50->pipe.sampler_view_destroy = nv50_sampler_view_destroy;
849
850 nv50->pipe.create_rasterizer_state = nv50_rasterizer_state_create;
851 nv50->pipe.bind_rasterizer_state = nv50_rasterizer_state_bind;
852 nv50->pipe.delete_rasterizer_state = nv50_rasterizer_state_delete;
853
854 nv50->pipe.create_depth_stencil_alpha_state =
855 nv50_depth_stencil_alpha_state_create;
856 nv50->pipe.bind_depth_stencil_alpha_state =
857 nv50_depth_stencil_alpha_state_bind;
858 nv50->pipe.delete_depth_stencil_alpha_state =
859 nv50_depth_stencil_alpha_state_delete;
860
861 nv50->pipe.create_vs_state = nv50_vp_state_create;
862 nv50->pipe.bind_vs_state = nv50_vp_state_bind;
863 nv50->pipe.delete_vs_state = nv50_vp_state_delete;
864
865 nv50->pipe.create_fs_state = nv50_fp_state_create;
866 nv50->pipe.bind_fs_state = nv50_fp_state_bind;
867 nv50->pipe.delete_fs_state = nv50_fp_state_delete;
868
869 nv50->pipe.create_gs_state = nv50_gp_state_create;
870 nv50->pipe.bind_gs_state = nv50_gp_state_bind;
871 nv50->pipe.delete_gs_state = nv50_gp_state_delete;
872
873 nv50->pipe.set_blend_color = nv50_set_blend_color;
874 nv50->pipe.set_stencil_ref = nv50_set_stencil_ref;
875 nv50->pipe.set_clip_state = nv50_set_clip_state;
876 nv50->pipe.set_sample_mask = nv50_set_sample_mask;
877 nv50->pipe.set_constant_buffer = nv50_set_constant_buffer;
878 nv50->pipe.set_framebuffer_state = nv50_set_framebuffer_state;
879 nv50->pipe.set_polygon_stipple = nv50_set_polygon_stipple;
880 nv50->pipe.set_scissor_state = nv50_set_scissor_state;
881 nv50->pipe.set_viewport_state = nv50_set_viewport_state;
882
883 nv50->pipe.create_vertex_elements_state = nv50_vtxelts_state_create;
884 nv50->pipe.delete_vertex_elements_state = nv50_vtxelts_state_delete;
885 nv50->pipe.bind_vertex_elements_state = nv50_vtxelts_state_bind;
886
887 nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers;
888 nv50->pipe.set_index_buffer = nv50_set_index_buffer;
889 }
890