nvfx: support both sprite coord origins
[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 * sprite_coord_origin
95 */
96
97 sb_method(sb, NV34TCL_SHADE_MODEL, 1);
98 sb_data(sb, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT :
99 NV34TCL_SHADE_MODEL_SMOOTH);
100
101 sb_method(sb, NV34TCL_VERTEX_TWO_SIDE_ENABLE, 1);
102 sb_data(sb, cso->light_twoside);
103
104 sb_method(sb, NV34TCL_LINE_WIDTH, 2);
105 sb_data(sb, (unsigned char)(cso->line_width * 8.0) & 0xff);
106 sb_data(sb, cso->line_smooth ? 1 : 0);
107 sb_method(sb, NV34TCL_LINE_STIPPLE_ENABLE, 2);
108 sb_data(sb, cso->line_stipple_enable ? 1 : 0);
109 sb_data(sb, (cso->line_stipple_pattern << 16) |
110 cso->line_stipple_factor);
111
112 sb_method(sb, NV34TCL_POINT_SIZE, 1);
113 sb_data(sb, fui(cso->point_size));
114
115 sb_method(sb, NV34TCL_POLYGON_MODE_FRONT, 6);
116 sb_data(sb, nvgl_polygon_mode(cso->fill_front));
117 sb_data(sb, nvgl_polygon_mode(cso->fill_back));
118 switch (cso->cull_face) {
119 case PIPE_FACE_FRONT:
120 sb_data(sb, NV34TCL_CULL_FACE_FRONT);
121 break;
122 case PIPE_FACE_BACK:
123 sb_data(sb, NV34TCL_CULL_FACE_BACK);
124 break;
125 case PIPE_FACE_FRONT_AND_BACK:
126 sb_data(sb, NV34TCL_CULL_FACE_FRONT_AND_BACK);
127 break;
128 default:
129 sb_data(sb, NV34TCL_CULL_FACE_BACK);
130 break;
131 }
132 if (cso->front_ccw) {
133 sb_data(sb, NV34TCL_FRONT_FACE_CCW);
134 } else {
135 sb_data(sb, NV34TCL_FRONT_FACE_CW);
136 }
137 sb_data(sb, cso->poly_smooth ? 1 : 0);
138 sb_data(sb, (cso->cull_face != PIPE_FACE_NONE) ? 1 : 0);
139
140 sb_method(sb, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
141 sb_data(sb, cso->poly_stipple_enable ? 1 : 0);
142
143 sb_method(sb, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
144 sb_data(sb, cso->offset_point);
145 sb_data(sb, cso->offset_line);
146 sb_data(sb, cso->offset_tri);
147
148 if (cso->offset_point || cso->offset_line || cso->offset_tri) {
149 sb_method(sb, NV34TCL_POLYGON_OFFSET_FACTOR, 2);
150 sb_data(sb, fui(cso->offset_scale));
151 sb_data(sb, fui(cso->offset_units * 2));
152 }
153
154 sb_method(sb, NV34TCL_FLATSHADE_FIRST, 1);
155 sb_data(sb, cso->flatshade_first);
156
157 rsso->pipe = *cso;
158 rsso->sb_len = sb_len(sb, rsso->sb);
159 return (void *)rsso;
160 }
161
162 static void
163 nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
164 {
165 struct nvfx_context *nvfx = nvfx_context(pipe);
166
167 if(nvfx->rasterizer && hwcso)
168 {
169 if(!nvfx->rasterizer || ((struct nvfx_rasterizer_state*)hwcso)->pipe.scissor
170 != nvfx->rasterizer->pipe.scissor)
171 {
172 nvfx->dirty |= NVFX_NEW_SCISSOR;
173 nvfx->draw_dirty |= NVFX_NEW_SCISSOR;
174 }
175
176 if(((struct nvfx_rasterizer_state*)hwcso)->pipe.point_quad_rasterization != nvfx->rasterizer->pipe.point_quad_rasterization
177 || ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_enable != nvfx->rasterizer->pipe.sprite_coord_enable
178 || ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_mode != nvfx->rasterizer->pipe.sprite_coord_mode)
179 {
180 nvfx->dirty |= NVFX_NEW_SPRITE;
181 }
182 }
183
184 nvfx->rasterizer = hwcso;
185 nvfx->dirty |= NVFX_NEW_RAST;
186 nvfx->draw_dirty |= NVFX_NEW_RAST;
187 }
188
189 static void
190 nvfx_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
191 {
192 struct nvfx_rasterizer_state *rsso = hwcso;
193
194 FREE(rsso);
195 }
196
197 static void *
198 nvfx_depth_stencil_alpha_state_create(struct pipe_context *pipe,
199 const struct pipe_depth_stencil_alpha_state *cso)
200 {
201 struct nvfx_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
202 struct nouveau_statebuf_builder sb = sb_init(zsaso->sb);
203
204 sb_method(sb, NV34TCL_DEPTH_FUNC, 1);
205 sb_data (sb, nvgl_comparison_op(cso->depth.func));
206
207 sb_method(sb, NV34TCL_ALPHA_FUNC_ENABLE, 3);
208 sb_data (sb, cso->alpha.enabled ? 1 : 0);
209 sb_data (sb, nvgl_comparison_op(cso->alpha.func));
210 sb_data (sb, float_to_ubyte(cso->alpha.ref_value));
211
212 if (cso->stencil[0].enabled) {
213 sb_method(sb, NV34TCL_STENCIL_FRONT_ENABLE, 3);
214 sb_data (sb, cso->stencil[0].enabled ? 1 : 0);
215 sb_data (sb, cso->stencil[0].writemask);
216 sb_data (sb, nvgl_comparison_op(cso->stencil[0].func));
217 sb_method(sb, NV34TCL_STENCIL_FRONT_FUNC_MASK, 4);
218 sb_data (sb, cso->stencil[0].valuemask);
219 sb_data (sb, nvgl_stencil_op(cso->stencil[0].fail_op));
220 sb_data (sb, nvgl_stencil_op(cso->stencil[0].zfail_op));
221 sb_data (sb, nvgl_stencil_op(cso->stencil[0].zpass_op));
222 } else {
223 sb_method(sb, NV34TCL_STENCIL_FRONT_ENABLE, 1);
224 sb_data (sb, 0);
225 }
226
227 if (cso->stencil[1].enabled) {
228 sb_method(sb, NV34TCL_STENCIL_BACK_ENABLE, 3);
229 sb_data (sb, cso->stencil[1].enabled ? 1 : 0);
230 sb_data (sb, cso->stencil[1].writemask);
231 sb_data (sb, nvgl_comparison_op(cso->stencil[1].func));
232 sb_method(sb, NV34TCL_STENCIL_BACK_FUNC_MASK, 4);
233 sb_data (sb, cso->stencil[1].valuemask);
234 sb_data (sb, nvgl_stencil_op(cso->stencil[1].fail_op));
235 sb_data (sb, nvgl_stencil_op(cso->stencil[1].zfail_op));
236 sb_data (sb, nvgl_stencil_op(cso->stencil[1].zpass_op));
237 } else {
238 sb_method(sb, NV34TCL_STENCIL_BACK_ENABLE, 1);
239 sb_data (sb, 0);
240 }
241
242 zsaso->pipe = *cso;
243 zsaso->sb_len = sb_len(sb, zsaso->sb);
244 return (void *)zsaso;
245 }
246
247 static void
248 nvfx_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
249 {
250 struct nvfx_context *nvfx = nvfx_context(pipe);
251
252 nvfx->zsa = hwcso;
253 nvfx->dirty |= NVFX_NEW_ZSA;
254 }
255
256 static void
257 nvfx_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
258 {
259 struct nvfx_zsa_state *zsaso = hwcso;
260
261 FREE(zsaso);
262 }
263
264 static void
265 nvfx_set_blend_color(struct pipe_context *pipe,
266 const struct pipe_blend_color *bcol)
267 {
268 struct nvfx_context *nvfx = nvfx_context(pipe);
269
270 nvfx->blend_colour = *bcol;
271 nvfx->dirty |= NVFX_NEW_BCOL;
272 }
273
274 static void
275 nvfx_set_stencil_ref(struct pipe_context *pipe,
276 const struct pipe_stencil_ref *sr)
277 {
278 struct nvfx_context *nvfx = nvfx_context(pipe);
279
280 nvfx->stencil_ref = *sr;
281 nvfx->dirty |= NVFX_NEW_SR;
282 }
283
284 static void
285 nvfx_set_clip_state(struct pipe_context *pipe,
286 const struct pipe_clip_state *clip)
287 {
288 struct nvfx_context *nvfx = nvfx_context(pipe);
289
290 nvfx->clip = *clip;
291 nvfx->dirty |= NVFX_NEW_UCP;
292 nvfx->draw_dirty |= NVFX_NEW_UCP;
293 }
294
295 static void
296 nvfx_set_sample_mask(struct pipe_context *pipe,
297 unsigned sample_mask)
298 {
299 }
300
301 static void
302 nvfx_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
303 struct pipe_resource *buf )
304 {
305 struct nvfx_context *nvfx = nvfx_context(pipe);
306
307 nvfx->constbuf[shader] = buf;
308 nvfx->constbuf_nr[shader] = buf->width0 / (4 * sizeof(float));
309
310 if (shader == PIPE_SHADER_VERTEX) {
311 nvfx->dirty |= NVFX_NEW_VERTCONST;
312 } else
313 if (shader == PIPE_SHADER_FRAGMENT) {
314 nvfx->dirty |= NVFX_NEW_FRAGCONST;
315 }
316 }
317
318 static void
319 nvfx_set_framebuffer_state(struct pipe_context *pipe,
320 const struct pipe_framebuffer_state *fb)
321 {
322 struct nvfx_context *nvfx = nvfx_context(pipe);
323
324 if(fb)
325 util_copy_framebuffer_state(&nvfx->framebuffer, fb);
326 else
327 util_unreference_framebuffer_state(&nvfx->framebuffer);
328 nvfx->dirty |= NVFX_NEW_FB;
329 }
330
331 static void
332 nvfx_set_polygon_stipple(struct pipe_context *pipe,
333 const struct pipe_poly_stipple *stipple)
334 {
335 struct nvfx_context *nvfx = nvfx_context(pipe);
336
337 memcpy(nvfx->stipple, stipple->stipple, 4 * 32);
338 nvfx->dirty |= NVFX_NEW_STIPPLE;
339 }
340
341 static void
342 nvfx_set_scissor_state(struct pipe_context *pipe,
343 const struct pipe_scissor_state *s)
344 {
345 struct nvfx_context *nvfx = nvfx_context(pipe);
346
347 nvfx->scissor = *s;
348 nvfx->dirty |= NVFX_NEW_SCISSOR;
349 }
350
351 static void
352 nvfx_set_viewport_state(struct pipe_context *pipe,
353 const struct pipe_viewport_state *vpt)
354 {
355 struct nvfx_context *nvfx = nvfx_context(pipe);
356
357 nvfx->viewport = *vpt;
358 nvfx->dirty |= NVFX_NEW_VIEWPORT;
359 nvfx->draw_dirty |= NVFX_NEW_VIEWPORT;
360 }
361
362 void
363 nvfx_init_state_functions(struct nvfx_context *nvfx)
364 {
365 nvfx->pipe.create_blend_state = nvfx_blend_state_create;
366 nvfx->pipe.bind_blend_state = nvfx_blend_state_bind;
367 nvfx->pipe.delete_blend_state = nvfx_blend_state_delete;
368
369 nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create;
370 nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind;
371 nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete;
372
373 nvfx->pipe.create_depth_stencil_alpha_state =
374 nvfx_depth_stencil_alpha_state_create;
375 nvfx->pipe.bind_depth_stencil_alpha_state =
376 nvfx_depth_stencil_alpha_state_bind;
377 nvfx->pipe.delete_depth_stencil_alpha_state =
378 nvfx_depth_stencil_alpha_state_delete;
379
380 nvfx->pipe.set_blend_color = nvfx_set_blend_color;
381 nvfx->pipe.set_stencil_ref = nvfx_set_stencil_ref;
382 nvfx->pipe.set_clip_state = nvfx_set_clip_state;
383 nvfx->pipe.set_sample_mask = nvfx_set_sample_mask;
384 nvfx->pipe.set_constant_buffer = nvfx_set_constant_buffer;
385 nvfx->pipe.set_framebuffer_state = nvfx_set_framebuffer_state;
386 nvfx->pipe.set_polygon_stipple = nvfx_set_polygon_stipple;
387 nvfx->pipe.set_scissor_state = nvfx_set_scissor_state;
388 nvfx->pipe.set_viewport_state = nvfx_set_viewport_state;
389 }