mesa: Use u_math.h from macros.h
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_state.c
1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_context.h"
29 #include "nouveau_texture.h"
30 #include "nouveau_util.h"
31
32 #include "swrast/swrast.h"
33 #include "tnl/tnl.h"
34
35 static void
36 nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref)
37 {
38 context_dirty(ctx, ALPHA_FUNC);
39 }
40
41 static void
42 nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4])
43 {
44 context_dirty(ctx, BLEND_COLOR);
45 }
46
47 static void
48 nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA)
49 {
50 context_dirty(ctx, BLEND_EQUATION);
51 }
52
53 static void
54 nouveau_blend_func_separate(struct gl_context *ctx, GLenum sfactorRGB,
55 GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA)
56 {
57 context_dirty(ctx, BLEND_FUNC);
58 }
59
60 static void
61 nouveau_clip_plane(struct gl_context *ctx, GLenum plane, const GLfloat *equation)
62 {
63 context_dirty_i(ctx, CLIP_PLANE, plane - GL_CLIP_PLANE0);
64 }
65
66 static void
67 nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask,
68 GLboolean bmask, GLboolean amask)
69 {
70 context_dirty(ctx, COLOR_MASK);
71 }
72
73 static void
74 nouveau_color_material(struct gl_context *ctx, GLenum face, GLenum mode)
75 {
76 context_dirty(ctx, COLOR_MATERIAL);
77 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
78 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
79 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
80 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
81 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
82 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
83 }
84
85 static void
86 nouveau_cull_face(struct gl_context *ctx, GLenum mode)
87 {
88 context_dirty(ctx, CULL_FACE);
89 }
90
91 static void
92 nouveau_front_face(struct gl_context *ctx, GLenum mode)
93 {
94 context_dirty(ctx, FRONT_FACE);
95 }
96
97 static void
98 nouveau_depth_func(struct gl_context *ctx, GLenum func)
99 {
100 context_dirty(ctx, DEPTH);
101 }
102
103 static void
104 nouveau_depth_mask(struct gl_context *ctx, GLboolean flag)
105 {
106 context_dirty(ctx, DEPTH);
107 }
108
109 static void
110 nouveau_read_buffer(struct gl_context *ctx, GLenum buffer)
111 {
112 nouveau_validate_framebuffer(ctx);
113 }
114
115 static void
116 nouveau_draw_buffers(struct gl_context *ctx, GLsizei n, const GLenum *buffers)
117 {
118 nouveau_validate_framebuffer(ctx);
119 context_dirty(ctx, FRAMEBUFFER);
120 }
121
122 static void
123 nouveau_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
124 {
125 int i;
126
127 switch (cap) {
128 case GL_ALPHA_TEST:
129 context_dirty(ctx, ALPHA_FUNC);
130 break;
131 case GL_BLEND:
132 context_dirty(ctx, BLEND_EQUATION);
133 break;
134 case GL_COLOR_LOGIC_OP:
135 context_dirty(ctx, LOGIC_OPCODE);
136 break;
137 case GL_COLOR_MATERIAL:
138 context_dirty(ctx, COLOR_MATERIAL);
139 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
140 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
141 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
142 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
143 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
144 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
145 break;
146 case GL_COLOR_SUM_EXT:
147 context_dirty(ctx, FRAG);
148 context_dirty(ctx, LIGHT_MODEL);
149 break;
150 case GL_CULL_FACE:
151 context_dirty(ctx, CULL_FACE);
152 break;
153 case GL_DEPTH_TEST:
154 context_dirty(ctx, DEPTH);
155 break;
156 case GL_DITHER:
157 context_dirty(ctx, DITHER);
158 break;
159 case GL_FOG:
160 context_dirty(ctx, FOG);
161 context_dirty(ctx, FRAG);
162 context_dirty(ctx, MODELVIEW);
163 break;
164 case GL_LIGHT0:
165 case GL_LIGHT1:
166 case GL_LIGHT2:
167 case GL_LIGHT3:
168 case GL_LIGHT4:
169 case GL_LIGHT5:
170 case GL_LIGHT6:
171 case GL_LIGHT7:
172 context_dirty(ctx, MODELVIEW);
173 context_dirty(ctx, LIGHT_ENABLE);
174 context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0);
175 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
176 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
177 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
178 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
179 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
180 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
181 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
182 context_dirty(ctx, MATERIAL_BACK_SHININESS);
183 break;
184 case GL_LIGHTING:
185 context_dirty(ctx, FRAG);
186 context_dirty(ctx, MODELVIEW);
187 context_dirty(ctx, LIGHT_MODEL);
188 context_dirty(ctx, LIGHT_ENABLE);
189
190 for (i = 0; i < MAX_LIGHTS; i++) {
191 if (ctx->Light.Light[i].Enabled)
192 context_dirty_i(ctx, LIGHT_SOURCE, i);
193 }
194
195 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
196 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
197 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
198 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
199 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
200 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
201 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
202 context_dirty(ctx, MATERIAL_BACK_SHININESS);
203 break;
204 case GL_LINE_SMOOTH:
205 context_dirty(ctx, LINE_MODE);
206 break;
207 case GL_NORMALIZE:
208 context_dirty(ctx, LIGHT_ENABLE);
209 break;
210 case GL_POINT_SMOOTH:
211 context_dirty(ctx, POINT_MODE);
212 break;
213 case GL_POLYGON_OFFSET_POINT:
214 case GL_POLYGON_OFFSET_LINE:
215 case GL_POLYGON_OFFSET_FILL:
216 context_dirty(ctx, POLYGON_OFFSET);
217 break;
218 case GL_POLYGON_SMOOTH:
219 context_dirty(ctx, POLYGON_MODE);
220 break;
221 case GL_SCISSOR_TEST:
222 context_dirty(ctx, SCISSOR);
223 break;
224 case GL_STENCIL_TEST:
225 context_dirty(ctx, STENCIL_FUNC);
226 break;
227 case GL_TEXTURE_1D:
228 case GL_TEXTURE_2D:
229 case GL_TEXTURE_3D:
230 case GL_TEXTURE_RECTANGLE:
231 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
232 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
233 break;
234 case GL_TEXTURE_GEN_S:
235 case GL_TEXTURE_GEN_T:
236 case GL_TEXTURE_GEN_R:
237 case GL_TEXTURE_GEN_Q:
238 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
239 context_dirty(ctx, MODELVIEW);
240 break;
241 }
242 }
243
244 static void
245 nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params)
246 {
247 context_dirty(ctx, FOG);
248 }
249
250 static void
251 nouveau_light(struct gl_context *ctx, GLenum light, GLenum pname, const GLfloat *params)
252 {
253 switch (pname) {
254 case GL_AMBIENT:
255 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
256 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
257 break;
258 case GL_DIFFUSE:
259 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
260 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
261 break;
262 case GL_SPECULAR:
263 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
264 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
265 break;
266 case GL_SPOT_CUTOFF:
267 case GL_POSITION:
268 context_dirty(ctx, MODELVIEW);
269 context_dirty(ctx, LIGHT_ENABLE);
270 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
271 break;
272 default:
273 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
274 break;
275 }
276 }
277
278 static void
279 nouveau_light_model(struct gl_context *ctx, GLenum pname, const GLfloat *params)
280 {
281 context_dirty(ctx, LIGHT_MODEL);
282 context_dirty(ctx, MODELVIEW);
283 }
284
285 static void
286 nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern )
287 {
288 context_dirty(ctx, LINE_STIPPLE);
289 }
290
291 static void
292 nouveau_line_width(struct gl_context *ctx, GLfloat width)
293 {
294 context_dirty(ctx, LINE_MODE);
295 }
296
297 static void
298 nouveau_logic_opcode(struct gl_context *ctx, GLenum opcode)
299 {
300 context_dirty(ctx, LOGIC_OPCODE);
301 }
302
303 static void
304 nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params)
305 {
306 context_dirty(ctx, POINT_PARAMETER);
307 }
308
309 static void
310 nouveau_point_size(struct gl_context *ctx, GLfloat size)
311 {
312 context_dirty(ctx, POINT_MODE);
313 }
314
315 static void
316 nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode)
317 {
318 context_dirty(ctx, POLYGON_MODE);
319 }
320
321 static void
322 nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units, GLfloat clamp)
323 {
324 context_dirty(ctx, POLYGON_OFFSET);
325 }
326
327 static void
328 nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask)
329 {
330 context_dirty(ctx, POLYGON_STIPPLE);
331 }
332
333 static void
334 nouveau_render_mode(struct gl_context *ctx, GLenum mode)
335 {
336 context_dirty(ctx, RENDER_MODE);
337 }
338
339 static void
340 nouveau_shade_model(struct gl_context *ctx, GLenum mode)
341 {
342 context_dirty(ctx, SHADE_MODEL);
343 }
344
345 static void
346 nouveau_stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func,
347 GLint ref, GLuint mask)
348 {
349 context_dirty(ctx, STENCIL_FUNC);
350 }
351
352 static void
353 nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask)
354 {
355 context_dirty(ctx, STENCIL_MASK);
356 }
357
358 static void
359 nouveau_stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum fail,
360 GLenum zfail, GLenum zpass)
361 {
362 context_dirty(ctx, STENCIL_OP);
363 }
364
365 static void
366 nouveau_tex_gen(struct gl_context *ctx, GLenum coord, GLenum pname,
367 const GLfloat *params)
368 {
369 switch (pname) {
370 case GL_TEXTURE_GEN_MODE:
371 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
372 context_dirty(ctx, MODELVIEW);
373 break;
374 default:
375 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
376 break;
377 }
378 }
379
380 static void
381 nouveau_tex_env(struct gl_context *ctx, GLenum target, GLenum pname,
382 const GLfloat *param)
383 {
384 switch (target) {
385 case GL_TEXTURE_FILTER_CONTROL_EXT:
386 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
387 break;
388 default:
389 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
390 break;
391 }
392 }
393
394 static void
395 nouveau_tex_parameter(struct gl_context *ctx,
396 struct gl_texture_object *t, GLenum pname,
397 const GLfloat *params)
398 {
399 switch (pname) {
400 case GL_TEXTURE_MAG_FILTER:
401 case GL_TEXTURE_WRAP_S:
402 case GL_TEXTURE_WRAP_T:
403 case GL_TEXTURE_WRAP_R:
404 case GL_TEXTURE_MIN_LOD:
405 case GL_TEXTURE_MAX_LOD:
406 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
407 case GL_TEXTURE_LOD_BIAS:
408 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
409 break;
410
411 case GL_TEXTURE_MIN_FILTER:
412 case GL_TEXTURE_BASE_LEVEL:
413 case GL_TEXTURE_MAX_LEVEL:
414 nouveau_texture_reallocate(ctx, t);
415 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
416 break;
417 }
418 }
419
420 void
421 nouveau_emit_nothing(struct gl_context *ctx, int emit)
422 {
423 }
424
425 int
426 nouveau_next_dirty_state(struct gl_context *ctx)
427 {
428 struct nouveau_context *nctx = to_nouveau_context(ctx);
429 int i = BITSET_FFS(nctx->dirty) - 1;
430
431 if (i < 0 || i >= context_drv(ctx)->num_emit)
432 return -1;
433
434 return i;
435 }
436
437 void
438 nouveau_state_emit(struct gl_context *ctx)
439 {
440 struct nouveau_context *nctx = to_nouveau_context(ctx);
441 const struct nouveau_driver *drv = context_drv(ctx);
442 int i;
443
444 while ((i = nouveau_next_dirty_state(ctx)) >= 0) {
445 BITSET_CLEAR(nctx->dirty, i);
446 drv->emit[i](ctx, i);
447 }
448
449 BITSET_ZERO(nctx->dirty);
450 }
451
452 static void
453 nouveau_update_state(struct gl_context *ctx, GLbitfield new_state)
454 {
455 int i;
456
457 if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW))
458 context_dirty(ctx, PROJECTION);
459
460 if (new_state & _NEW_MODELVIEW)
461 context_dirty(ctx, MODELVIEW);
462
463 if (new_state & _NEW_TEXTURE_MATRIX) {
464 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
465 context_dirty_i(ctx, TEX_MAT, i);
466 }
467
468 if (new_state & _NEW_SCISSOR)
469 context_dirty(ctx, SCISSOR);
470
471 if (new_state & _NEW_VIEWPORT)
472 context_dirty(ctx, VIEWPORT);
473
474 if (new_state & _NEW_CURRENT_ATTRIB &&
475 new_state & _NEW_LIGHT) {
476 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
477 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
478 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
479 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
480 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
481 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
482 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
483 context_dirty(ctx, MATERIAL_BACK_SHININESS);
484 }
485
486 if (new_state & _NEW_TEXTURE) {
487 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
488 if (ctx->Texture.Unit[i].Sampler)
489 context_dirty_i(ctx, TEX_OBJ, i);
490 }
491 }
492
493 _swrast_InvalidateState(ctx, new_state);
494 _tnl_InvalidateState(ctx, new_state);
495 _vbo_InvalidateState(ctx, new_state);
496
497 nouveau_state_emit(ctx);
498 }
499
500 void
501 nouveau_state_init(struct gl_context *ctx)
502 {
503 struct nouveau_context *nctx = to_nouveau_context(ctx);
504
505 ctx->Driver.AlphaFunc = nouveau_alpha_func;
506 ctx->Driver.BlendColor = nouveau_blend_color;
507 ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate;
508 ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate;
509 ctx->Driver.ClipPlane = nouveau_clip_plane;
510 ctx->Driver.ColorMask = nouveau_color_mask;
511 ctx->Driver.ColorMaterial = nouveau_color_material;
512 ctx->Driver.CullFace = nouveau_cull_face;
513 ctx->Driver.FrontFace = nouveau_front_face;
514 ctx->Driver.DepthFunc = nouveau_depth_func;
515 ctx->Driver.DepthMask = nouveau_depth_mask;
516 ctx->Driver.ReadBuffer = nouveau_read_buffer;
517 ctx->Driver.DrawBuffers = nouveau_draw_buffers;
518 ctx->Driver.Enable = nouveau_enable;
519 ctx->Driver.Fogfv = nouveau_fog;
520 ctx->Driver.Lightfv = nouveau_light;
521 ctx->Driver.LightModelfv = nouveau_light_model;
522 ctx->Driver.LineStipple = nouveau_line_stipple;
523 ctx->Driver.LineWidth = nouveau_line_width;
524 ctx->Driver.LogicOpcode = nouveau_logic_opcode;
525 ctx->Driver.PointParameterfv = nouveau_point_parameter;
526 ctx->Driver.PointSize = nouveau_point_size;
527 ctx->Driver.PolygonMode = nouveau_polygon_mode;
528 ctx->Driver.PolygonOffset = nouveau_polygon_offset;
529 ctx->Driver.PolygonStipple = nouveau_polygon_stipple;
530 ctx->Driver.RenderMode = nouveau_render_mode;
531 ctx->Driver.ShadeModel = nouveau_shade_model;
532 ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate;
533 ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate;
534 ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate;
535 ctx->Driver.TexGen = nouveau_tex_gen;
536 ctx->Driver.TexEnv = nouveau_tex_env;
537 ctx->Driver.TexParameter = nouveau_tex_parameter;
538
539 ctx->Driver.UpdateState = nouveau_update_state;
540
541 BITSET_ONES(nctx->dirty);
542 }