Merge branch '7.8'
[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(GLcontext *ctx, GLenum func, GLfloat ref)
37 {
38 context_dirty(ctx, ALPHA_FUNC);
39 }
40
41 static void
42 nouveau_blend_color(GLcontext *ctx, const GLfloat color[4])
43 {
44 context_dirty(ctx, BLEND_COLOR);
45 }
46
47 static void
48 nouveau_blend_equation_separate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
49 {
50 context_dirty(ctx, BLEND_EQUATION);
51 }
52
53 static void
54 nouveau_blend_func_separate(GLcontext *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(GLcontext *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(GLcontext *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(GLcontext *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(GLcontext *ctx, GLenum mode)
87 {
88 context_dirty(ctx, CULL_FACE);
89 }
90
91 static void
92 nouveau_front_face(GLcontext *ctx, GLenum mode)
93 {
94 context_dirty(ctx, FRONT_FACE);
95 }
96
97 static void
98 nouveau_depth_func(GLcontext *ctx, GLenum func)
99 {
100 context_dirty(ctx, DEPTH);
101 }
102
103 static void
104 nouveau_depth_mask(GLcontext *ctx, GLboolean flag)
105 {
106 context_dirty(ctx, DEPTH);
107 }
108
109 static void
110 nouveau_depth_range(GLcontext *ctx, GLclampd nearval, GLclampd farval)
111 {
112 context_dirty(ctx, VIEWPORT);
113 }
114
115 static void
116 nouveau_draw_buffer(GLcontext *ctx, GLenum buffer)
117 {
118 context_dirty(ctx, FRAMEBUFFER);
119 }
120
121 static void
122 nouveau_draw_buffers(GLcontext *ctx, GLsizei n, const GLenum *buffers)
123 {
124 context_dirty(ctx, FRAMEBUFFER);
125 }
126
127 static void
128 nouveau_enable(GLcontext *ctx, GLenum cap, GLboolean state)
129 {
130 int i;
131
132 switch (cap) {
133 case GL_ALPHA_TEST:
134 context_dirty(ctx, ALPHA_FUNC);
135 break;
136 case GL_BLEND:
137 context_dirty(ctx, BLEND_EQUATION);
138 break;
139 case GL_COLOR_LOGIC_OP:
140 context_dirty(ctx, LOGIC_OPCODE);
141 break;
142 case GL_COLOR_MATERIAL:
143 context_dirty(ctx, COLOR_MATERIAL);
144 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
145 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
146 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
147 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
148 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
149 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
150 break;
151 case GL_COLOR_SUM_EXT:
152 context_dirty(ctx, FRAG);
153 context_dirty(ctx, LIGHT_MODEL);
154 break;
155 case GL_CULL_FACE:
156 context_dirty(ctx, CULL_FACE);
157 break;
158 case GL_DEPTH_TEST:
159 context_dirty(ctx, DEPTH);
160 break;
161 case GL_DITHER:
162 context_dirty(ctx, DITHER);
163 break;
164 case GL_FOG:
165 context_dirty(ctx, FOG);
166 context_dirty(ctx, FRAG);
167 context_dirty(ctx, MODELVIEW);
168 break;
169 case GL_LIGHT0:
170 case GL_LIGHT1:
171 case GL_LIGHT2:
172 case GL_LIGHT3:
173 case GL_LIGHT4:
174 case GL_LIGHT5:
175 case GL_LIGHT6:
176 case GL_LIGHT7:
177 context_dirty(ctx, MODELVIEW);
178 context_dirty(ctx, LIGHT_ENABLE);
179 context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0);
180 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
181 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
182 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
183 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
184 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
185 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
186 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
187 context_dirty(ctx, MATERIAL_BACK_SHININESS);
188 break;
189 case GL_LIGHTING:
190 context_dirty(ctx, FRAG);
191 context_dirty(ctx, MODELVIEW);
192 context_dirty(ctx, LIGHT_ENABLE);
193
194 for (i = 0; i < MAX_LIGHTS; i++) {
195 if (ctx->Light.Light[i].Enabled)
196 context_dirty_i(ctx, LIGHT_SOURCE, i);
197 }
198
199 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
200 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
201 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
202 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
203 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
204 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
205 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
206 context_dirty(ctx, MATERIAL_BACK_SHININESS);
207 break;
208 case GL_LINE_SMOOTH:
209 context_dirty(ctx, LINE_MODE);
210 break;
211 case GL_NORMALIZE:
212 context_dirty(ctx, LIGHT_ENABLE);
213 break;
214 case GL_POINT_SMOOTH:
215 context_dirty(ctx, POINT_MODE);
216 break;
217 case GL_POLYGON_OFFSET_POINT:
218 case GL_POLYGON_OFFSET_LINE:
219 case GL_POLYGON_OFFSET_FILL:
220 context_dirty(ctx, POLYGON_OFFSET);
221 break;
222 case GL_POLYGON_SMOOTH:
223 context_dirty(ctx, POLYGON_MODE);
224 break;
225 case GL_SCISSOR_TEST:
226 context_dirty(ctx, SCISSOR);
227 break;
228 case GL_STENCIL_TEST:
229 context_dirty(ctx, STENCIL_FUNC);
230 break;
231 case GL_TEXTURE_1D:
232 case GL_TEXTURE_2D:
233 case GL_TEXTURE_3D:
234 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
235 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
236 break;
237 }
238 }
239
240 static void
241 nouveau_fog(GLcontext *ctx, GLenum pname, const GLfloat *params)
242 {
243 context_dirty(ctx, FOG);
244 }
245
246 static void
247 nouveau_light(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params)
248 {
249 switch (pname) {
250 case GL_AMBIENT:
251 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
252 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
253 break;
254 case GL_DIFFUSE:
255 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
256 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
257 break;
258 case GL_SPECULAR:
259 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
260 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
261 break;
262 case GL_SPOT_CUTOFF:
263 case GL_POSITION:
264 context_dirty(ctx, MODELVIEW);
265 context_dirty(ctx, LIGHT_ENABLE);
266 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
267 break;
268 default:
269 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
270 break;
271 }
272 }
273
274 static void
275 nouveau_light_model(GLcontext *ctx, GLenum pname, const GLfloat *params)
276 {
277 context_dirty(ctx, LIGHT_MODEL);
278 context_dirty(ctx, MODELVIEW);
279 }
280
281 static void
282 nouveau_line_stipple(GLcontext *ctx, GLint factor, GLushort pattern )
283 {
284 context_dirty(ctx, LINE_STIPPLE);
285 }
286
287 static void
288 nouveau_line_width(GLcontext *ctx, GLfloat width)
289 {
290 context_dirty(ctx, LINE_MODE);
291 }
292
293 static void
294 nouveau_logic_opcode(GLcontext *ctx, GLenum opcode)
295 {
296 context_dirty(ctx, LOGIC_OPCODE);
297 }
298
299 static void
300 nouveau_point_parameter(GLcontext *ctx, GLenum pname, const GLfloat *params)
301 {
302 context_dirty(ctx, POINT_PARAMETER);
303 }
304
305 static void
306 nouveau_point_size(GLcontext *ctx, GLfloat size)
307 {
308 context_dirty(ctx, POINT_MODE);
309 }
310
311 static void
312 nouveau_polygon_mode(GLcontext *ctx, GLenum face, GLenum mode)
313 {
314 context_dirty(ctx, POLYGON_MODE);
315 }
316
317 static void
318 nouveau_polygon_offset(GLcontext *ctx, GLfloat factor, GLfloat units)
319 {
320 context_dirty(ctx, POLYGON_OFFSET);
321 }
322
323 static void
324 nouveau_polygon_stipple(GLcontext *ctx, const GLubyte *mask)
325 {
326 context_dirty(ctx, POLYGON_STIPPLE);
327 }
328
329 static void
330 nouveau_render_mode(GLcontext *ctx, GLenum mode)
331 {
332 context_dirty(ctx, RENDER_MODE);
333 }
334
335 static void
336 nouveau_scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
337 {
338 context_dirty(ctx, SCISSOR);
339 }
340
341 static void
342 nouveau_shade_model(GLcontext *ctx, GLenum mode)
343 {
344 context_dirty(ctx, SHADE_MODEL);
345 }
346
347 static void
348 nouveau_stencil_func_separate(GLcontext *ctx, GLenum face, GLenum func,
349 GLint ref, GLuint mask)
350 {
351 context_dirty(ctx, STENCIL_FUNC);
352 }
353
354 static void
355 nouveau_stencil_mask_separate(GLcontext *ctx, GLenum face, GLuint mask)
356 {
357 context_dirty(ctx, STENCIL_MASK);
358 }
359
360 static void
361 nouveau_stencil_op_separate(GLcontext *ctx, GLenum face, GLenum fail,
362 GLenum zfail, GLenum zpass)
363 {
364 context_dirty(ctx, STENCIL_OP);
365 }
366
367 static void
368 nouveau_tex_gen(GLcontext *ctx, GLenum coord, GLenum pname,
369 const GLfloat *params)
370 {
371 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
372 }
373
374 static void
375 nouveau_tex_env(GLcontext *ctx, GLenum target, GLenum pname,
376 const GLfloat *param)
377 {
378 switch (target) {
379 case GL_TEXTURE_FILTER_CONTROL_EXT:
380 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
381 break;
382 default:
383 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
384 break;
385 }
386 }
387
388 static void
389 nouveau_tex_parameter(GLcontext *ctx, GLenum target,
390 struct gl_texture_object *t, GLenum pname,
391 const GLfloat *params)
392 {
393 switch (pname) {
394 case GL_TEXTURE_MAG_FILTER:
395 case GL_TEXTURE_WRAP_S:
396 case GL_TEXTURE_WRAP_T:
397 case GL_TEXTURE_WRAP_R:
398 case GL_TEXTURE_MIN_LOD:
399 case GL_TEXTURE_MAX_LOD:
400 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
401 case GL_TEXTURE_LOD_BIAS:
402 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
403 break;
404
405 case GL_TEXTURE_MIN_FILTER:
406 case GL_TEXTURE_BASE_LEVEL:
407 case GL_TEXTURE_MAX_LEVEL:
408 nouveau_texture_reallocate(ctx, t);
409 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
410 break;
411 }
412 }
413
414 static void
415 nouveau_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
416 {
417 context_dirty(ctx, VIEWPORT);
418 }
419
420 void
421 nouveau_emit_nothing(GLcontext *ctx, int emit)
422 {
423 }
424
425 int
426 nouveau_next_dirty_state(GLcontext *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(GLcontext *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 nouveau_bo_state_emit(ctx);
452 }
453
454 static void
455 nouveau_update_state(GLcontext *ctx, GLbitfield new_state)
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_CURRENT_ATTRIB &&
464 new_state & _NEW_LIGHT) {
465 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
466 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
467 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
468 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
469 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
470 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
471 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
472 context_dirty(ctx, MATERIAL_BACK_SHININESS);
473 }
474
475 _swrast_InvalidateState(ctx, new_state);
476 _tnl_InvalidateState(ctx, new_state);
477
478 nouveau_state_emit(ctx);
479 }
480
481 void
482 nouveau_state_init(GLcontext *ctx)
483 {
484 struct nouveau_context *nctx = to_nouveau_context(ctx);
485
486 ctx->Driver.AlphaFunc = nouveau_alpha_func;
487 ctx->Driver.BlendColor = nouveau_blend_color;
488 ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate;
489 ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate;
490 ctx->Driver.ClipPlane = nouveau_clip_plane;
491 ctx->Driver.ColorMask = nouveau_color_mask;
492 ctx->Driver.ColorMaterial = nouveau_color_material;
493 ctx->Driver.CullFace = nouveau_cull_face;
494 ctx->Driver.FrontFace = nouveau_front_face;
495 ctx->Driver.DepthFunc = nouveau_depth_func;
496 ctx->Driver.DepthMask = nouveau_depth_mask;
497 ctx->Driver.DepthRange = nouveau_depth_range;
498 ctx->Driver.DrawBuffer = nouveau_draw_buffer;
499 ctx->Driver.DrawBuffers = nouveau_draw_buffers;
500 ctx->Driver.Enable = nouveau_enable;
501 ctx->Driver.Fogfv = nouveau_fog;
502 ctx->Driver.Lightfv = nouveau_light;
503 ctx->Driver.LightModelfv = nouveau_light_model;
504 ctx->Driver.LineStipple = nouveau_line_stipple;
505 ctx->Driver.LineWidth = nouveau_line_width;
506 ctx->Driver.LogicOpcode = nouveau_logic_opcode;
507 ctx->Driver.PointParameterfv = nouveau_point_parameter;
508 ctx->Driver.PointSize = nouveau_point_size;
509 ctx->Driver.PolygonMode = nouveau_polygon_mode;
510 ctx->Driver.PolygonOffset = nouveau_polygon_offset;
511 ctx->Driver.PolygonStipple = nouveau_polygon_stipple;
512 ctx->Driver.RenderMode = nouveau_render_mode;
513 ctx->Driver.Scissor = nouveau_scissor;
514 ctx->Driver.ShadeModel = nouveau_shade_model;
515 ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate;
516 ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate;
517 ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate;
518 ctx->Driver.TexGen = nouveau_tex_gen;
519 ctx->Driver.TexEnv = nouveau_tex_env;
520 ctx->Driver.TexParameter = nouveau_tex_parameter;
521 ctx->Driver.Viewport = nouveau_viewport;
522
523 ctx->Driver.UpdateState = nouveau_update_state;
524
525 BITSET_ONES(nctx->dirty);
526 }