dri/nouveau: Try to keep client buffers smaller than the scratch VBO length.
[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 break;
154 case GL_CULL_FACE:
155 context_dirty(ctx, CULL_FACE);
156 break;
157 case GL_DEPTH_TEST:
158 context_dirty(ctx, DEPTH);
159 break;
160 case GL_DITHER:
161 context_dirty(ctx, DITHER);
162 break;
163 case GL_FOG:
164 context_dirty(ctx, FOG);
165 context_dirty(ctx, FRAG);
166 context_dirty(ctx, MODELVIEW);
167 break;
168 case GL_LIGHT0:
169 case GL_LIGHT1:
170 case GL_LIGHT2:
171 case GL_LIGHT3:
172 case GL_LIGHT4:
173 case GL_LIGHT5:
174 case GL_LIGHT6:
175 case GL_LIGHT7:
176 context_dirty(ctx, MODELVIEW);
177 context_dirty(ctx, LIGHT_ENABLE);
178 context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0);
179 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
180 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
181 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
182 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
183 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
184 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
185 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
186 context_dirty(ctx, MATERIAL_BACK_SHININESS);
187 break;
188 case GL_LIGHTING:
189 context_dirty(ctx, FRAG);
190 context_dirty(ctx, MODELVIEW);
191 context_dirty(ctx, LIGHT_ENABLE);
192
193 for (i = 0; i < MAX_LIGHTS; i++) {
194 if (ctx->Light.Light[i].Enabled)
195 context_dirty_i(ctx, LIGHT_SOURCE, i);
196 }
197
198 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
199 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
200 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
201 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
202 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
203 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
204 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
205 context_dirty(ctx, MATERIAL_BACK_SHININESS);
206 break;
207 case GL_LINE_SMOOTH:
208 context_dirty(ctx, LINE_MODE);
209 break;
210 case GL_NORMALIZE:
211 context_dirty(ctx, LIGHT_ENABLE);
212 break;
213 case GL_POINT_SMOOTH:
214 context_dirty(ctx, POINT_MODE);
215 break;
216 case GL_POLYGON_OFFSET_POINT:
217 case GL_POLYGON_OFFSET_LINE:
218 case GL_POLYGON_OFFSET_FILL:
219 context_dirty(ctx, POLYGON_OFFSET);
220 break;
221 case GL_POLYGON_SMOOTH:
222 context_dirty(ctx, POLYGON_MODE);
223 break;
224 case GL_SCISSOR_TEST:
225 context_dirty(ctx, SCISSOR);
226 break;
227 case GL_STENCIL_TEST:
228 context_dirty(ctx, STENCIL_FUNC);
229 break;
230 case GL_TEXTURE_1D:
231 case GL_TEXTURE_2D:
232 case GL_TEXTURE_3D:
233 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
234 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
235 break;
236 }
237 }
238
239 static void
240 nouveau_fog(GLcontext *ctx, GLenum pname, const GLfloat *params)
241 {
242 context_dirty(ctx, FOG);
243 }
244
245 static void
246 nouveau_light(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params)
247 {
248 switch (pname) {
249 case GL_AMBIENT:
250 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
251 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
252 break;
253 case GL_DIFFUSE:
254 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
255 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
256 break;
257 case GL_SPECULAR:
258 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
259 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
260 break;
261 case GL_SPOT_CUTOFF:
262 case GL_POSITION:
263 context_dirty(ctx, MODELVIEW);
264 context_dirty(ctx, LIGHT_ENABLE);
265 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
266 break;
267 default:
268 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
269 break;
270 }
271 }
272
273 static void
274 nouveau_light_model(GLcontext *ctx, GLenum pname, const GLfloat *params)
275 {
276 context_dirty(ctx, LIGHT_MODEL);
277 context_dirty(ctx, MODELVIEW);
278 }
279
280 static void
281 nouveau_line_stipple(GLcontext *ctx, GLint factor, GLushort pattern )
282 {
283 context_dirty(ctx, LINE_STIPPLE);
284 }
285
286 static void
287 nouveau_line_width(GLcontext *ctx, GLfloat width)
288 {
289 context_dirty(ctx, LINE_MODE);
290 }
291
292 static void
293 nouveau_logic_opcode(GLcontext *ctx, GLenum opcode)
294 {
295 context_dirty(ctx, LOGIC_OPCODE);
296 }
297
298 static void
299 nouveau_point_parameter(GLcontext *ctx, GLenum pname, const GLfloat *params)
300 {
301 context_dirty(ctx, POINT_PARAMETER);
302 }
303
304 static void
305 nouveau_point_size(GLcontext *ctx, GLfloat size)
306 {
307 context_dirty(ctx, POINT_MODE);
308 }
309
310 static void
311 nouveau_polygon_mode(GLcontext *ctx, GLenum face, GLenum mode)
312 {
313 context_dirty(ctx, POLYGON_MODE);
314 }
315
316 static void
317 nouveau_polygon_offset(GLcontext *ctx, GLfloat factor, GLfloat units)
318 {
319 context_dirty(ctx, POLYGON_OFFSET);
320 }
321
322 static void
323 nouveau_polygon_stipple(GLcontext *ctx, const GLubyte *mask)
324 {
325 context_dirty(ctx, POLYGON_STIPPLE);
326 }
327
328 static void
329 nouveau_render_mode(GLcontext *ctx, GLenum mode)
330 {
331 context_dirty(ctx, RENDER_MODE);
332 }
333
334 static void
335 nouveau_scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
336 {
337 context_dirty(ctx, SCISSOR);
338 }
339
340 static void
341 nouveau_shade_model(GLcontext *ctx, GLenum mode)
342 {
343 context_dirty(ctx, SHADE_MODEL);
344 }
345
346 static void
347 nouveau_stencil_func_separate(GLcontext *ctx, GLenum face, GLenum func,
348 GLint ref, GLuint mask)
349 {
350 context_dirty(ctx, STENCIL_FUNC);
351 }
352
353 static void
354 nouveau_stencil_mask_separate(GLcontext *ctx, GLenum face, GLuint mask)
355 {
356 context_dirty(ctx, STENCIL_MASK);
357 }
358
359 static void
360 nouveau_stencil_op_separate(GLcontext *ctx, GLenum face, GLenum fail,
361 GLenum zfail, GLenum zpass)
362 {
363 context_dirty(ctx, STENCIL_OP);
364 }
365
366 static void
367 nouveau_tex_gen(GLcontext *ctx, GLenum coord, GLenum pname,
368 const GLfloat *params)
369 {
370 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
371 }
372
373 static void
374 nouveau_tex_env(GLcontext *ctx, GLenum target, GLenum pname,
375 const GLfloat *param)
376 {
377 switch (target) {
378 case GL_TEXTURE_FILTER_CONTROL_EXT:
379 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
380 break;
381 default:
382 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
383 break;
384 }
385 }
386
387 static void
388 nouveau_tex_parameter(GLcontext *ctx, GLenum target,
389 struct gl_texture_object *t, GLenum pname,
390 const GLfloat *params)
391 {
392 switch (pname) {
393 case GL_TEXTURE_MAG_FILTER:
394 case GL_TEXTURE_WRAP_S:
395 case GL_TEXTURE_WRAP_T:
396 case GL_TEXTURE_WRAP_R:
397 case GL_TEXTURE_MIN_LOD:
398 case GL_TEXTURE_MAX_LOD:
399 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
400 case GL_TEXTURE_LOD_BIAS:
401 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
402 break;
403
404 case GL_TEXTURE_MIN_FILTER:
405 case GL_TEXTURE_BASE_LEVEL:
406 case GL_TEXTURE_MAX_LEVEL:
407 nouveau_texture_reallocate(ctx, t);
408 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
409 break;
410 }
411 }
412
413 static void
414 nouveau_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
415 {
416 context_dirty(ctx, VIEWPORT);
417 }
418
419 void
420 nouveau_emit_nothing(GLcontext *ctx, int emit)
421 {
422 }
423
424 int
425 nouveau_next_dirty_state(GLcontext *ctx)
426 {
427 struct nouveau_context *nctx = to_nouveau_context(ctx);
428 int i = BITSET_FFS(nctx->dirty) - 1;
429
430 if (i < 0 || i >= context_drv(ctx)->num_emit)
431 return -1;
432
433 return i;
434 }
435
436 void
437 nouveau_state_emit(GLcontext *ctx)
438 {
439 struct nouveau_context *nctx = to_nouveau_context(ctx);
440 const struct nouveau_driver *drv = context_drv(ctx);
441 int i;
442
443 while ((i = nouveau_next_dirty_state(ctx)) >= 0) {
444 BITSET_CLEAR(nctx->dirty, i);
445 drv->emit[i](ctx, i);
446 }
447
448 BITSET_ZERO(nctx->dirty);
449
450 nouveau_bo_state_emit(ctx);
451 }
452
453 static void
454 nouveau_update_state(GLcontext *ctx, GLbitfield new_state)
455 {
456 if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW))
457 context_dirty(ctx, PROJECTION);
458
459 if (new_state & _NEW_MODELVIEW)
460 context_dirty(ctx, MODELVIEW);
461
462 if (new_state & _NEW_CURRENT_ATTRIB &&
463 new_state & _NEW_LIGHT) {
464 context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
465 context_dirty(ctx, MATERIAL_BACK_AMBIENT);
466 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
467 context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
468 context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
469 context_dirty(ctx, MATERIAL_BACK_SPECULAR);
470 context_dirty(ctx, MATERIAL_FRONT_SHININESS);
471 context_dirty(ctx, MATERIAL_BACK_SHININESS);
472 }
473
474 _swrast_InvalidateState(ctx, new_state);
475 _tnl_InvalidateState(ctx, new_state);
476
477 nouveau_state_emit(ctx);
478 }
479
480 void
481 nouveau_state_init(GLcontext *ctx)
482 {
483 struct nouveau_context *nctx = to_nouveau_context(ctx);
484
485 ctx->Driver.AlphaFunc = nouveau_alpha_func;
486 ctx->Driver.BlendColor = nouveau_blend_color;
487 ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate;
488 ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate;
489 ctx->Driver.ClipPlane = nouveau_clip_plane;
490 ctx->Driver.ColorMask = nouveau_color_mask;
491 ctx->Driver.ColorMaterial = nouveau_color_material;
492 ctx->Driver.CullFace = nouveau_cull_face;
493 ctx->Driver.FrontFace = nouveau_front_face;
494 ctx->Driver.DepthFunc = nouveau_depth_func;
495 ctx->Driver.DepthMask = nouveau_depth_mask;
496 ctx->Driver.DepthRange = nouveau_depth_range;
497 ctx->Driver.DrawBuffer = nouveau_draw_buffer;
498 ctx->Driver.DrawBuffers = nouveau_draw_buffers;
499 ctx->Driver.Enable = nouveau_enable;
500 ctx->Driver.Fogfv = nouveau_fog;
501 ctx->Driver.Lightfv = nouveau_light;
502 ctx->Driver.LightModelfv = nouveau_light_model;
503 ctx->Driver.LineStipple = nouveau_line_stipple;
504 ctx->Driver.LineWidth = nouveau_line_width;
505 ctx->Driver.LogicOpcode = nouveau_logic_opcode;
506 ctx->Driver.PointParameterfv = nouveau_point_parameter;
507 ctx->Driver.PointSize = nouveau_point_size;
508 ctx->Driver.PolygonMode = nouveau_polygon_mode;
509 ctx->Driver.PolygonOffset = nouveau_polygon_offset;
510 ctx->Driver.PolygonStipple = nouveau_polygon_stipple;
511 ctx->Driver.RenderMode = nouveau_render_mode;
512 ctx->Driver.Scissor = nouveau_scissor;
513 ctx->Driver.ShadeModel = nouveau_shade_model;
514 ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate;
515 ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate;
516 ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate;
517 ctx->Driver.TexGen = nouveau_tex_gen;
518 ctx->Driver.TexEnv = nouveau_tex_env;
519 ctx->Driver.TexParameter = nouveau_tex_parameter;
520 ctx->Driver.Viewport = nouveau_viewport;
521
522 ctx->Driver.UpdateState = nouveau_update_state;
523
524 BITSET_ONES(nctx->dirty);
525 }