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#include "util/bitscan.h"
35#include "main/framebuffer.h"
36
37static void
38nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref)
39{
40	context_dirty(ctx, ALPHA_FUNC);
41}
42
43static void
44nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4])
45{
46	context_dirty(ctx, BLEND_COLOR);
47}
48
49static void
50nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA)
51{
52	context_dirty(ctx, BLEND_EQUATION);
53}
54
55static void
56nouveau_blend_func_separate(struct gl_context *ctx, GLenum sfactorRGB,
57			    GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA)
58{
59	context_dirty(ctx, BLEND_FUNC);
60}
61
62static void
63nouveau_clip_plane(struct gl_context *ctx, GLenum plane, const GLfloat *equation)
64{
65	context_dirty_i(ctx, CLIP_PLANE, plane - GL_CLIP_PLANE0);
66}
67
68static void
69nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask,
70		   GLboolean bmask, GLboolean amask)
71{
72	context_dirty(ctx, COLOR_MASK);
73}
74
75static void
76nouveau_color_material(struct gl_context *ctx, GLenum face, GLenum mode)
77{
78	context_dirty(ctx, COLOR_MATERIAL);
79	context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
80	context_dirty(ctx, MATERIAL_BACK_AMBIENT);
81	context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
82	context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
83	context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
84	context_dirty(ctx, MATERIAL_BACK_SPECULAR);
85}
86
87static void
88nouveau_cull_face(struct gl_context *ctx, GLenum mode)
89{
90	context_dirty(ctx, CULL_FACE);
91}
92
93static void
94nouveau_front_face(struct gl_context *ctx, GLenum mode)
95{
96	context_dirty(ctx, FRONT_FACE);
97}
98
99static void
100nouveau_depth_func(struct gl_context *ctx, GLenum func)
101{
102	context_dirty(ctx, DEPTH);
103}
104
105static void
106nouveau_depth_mask(struct gl_context *ctx, GLboolean flag)
107{
108	context_dirty(ctx, DEPTH);
109}
110
111static void
112nouveau_read_buffer(struct gl_context *ctx, GLenum buffer)
113{
114	nouveau_validate_framebuffer(ctx);
115}
116
117static void
118nouveau_draw_buffer(struct gl_context *ctx)
119{
120	nouveau_validate_framebuffer(ctx);
121	context_dirty(ctx, FRAMEBUFFER);
122}
123
124static void
125nouveau_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
126{
127	GLbitfield mask;
128
129	switch (cap) {
130	case GL_ALPHA_TEST:
131		context_dirty(ctx, ALPHA_FUNC);
132		break;
133	case GL_BLEND:
134		context_dirty(ctx, BLEND_EQUATION);
135		break;
136	case GL_COLOR_LOGIC_OP:
137		context_dirty(ctx, LOGIC_OPCODE);
138		break;
139	case GL_COLOR_MATERIAL:
140		context_dirty(ctx, COLOR_MATERIAL);
141		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
142		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
143		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
144		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
145		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
146		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
147		break;
148	case GL_COLOR_SUM_EXT:
149		context_dirty(ctx, FRAG);
150		context_dirty(ctx, LIGHT_MODEL);
151		break;
152	case GL_CULL_FACE:
153		context_dirty(ctx, CULL_FACE);
154		break;
155	case GL_DEPTH_TEST:
156		context_dirty(ctx, DEPTH);
157		break;
158	case GL_DITHER:
159		context_dirty(ctx, DITHER);
160		break;
161	case GL_FOG:
162		context_dirty(ctx, FOG);
163		context_dirty(ctx, FRAG);
164		context_dirty(ctx, MODELVIEW);
165		break;
166	case GL_LIGHT0:
167	case GL_LIGHT1:
168	case GL_LIGHT2:
169	case GL_LIGHT3:
170	case GL_LIGHT4:
171	case GL_LIGHT5:
172	case GL_LIGHT6:
173	case GL_LIGHT7:
174		context_dirty(ctx, MODELVIEW);
175		context_dirty(ctx, LIGHT_ENABLE);
176		context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0);
177		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
178		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
179		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
180		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
181		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
182		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
183		context_dirty(ctx, MATERIAL_FRONT_SHININESS);
184		context_dirty(ctx, MATERIAL_BACK_SHININESS);
185		break;
186	case GL_LIGHTING:
187		context_dirty(ctx, FRAG);
188		context_dirty(ctx, MODELVIEW);
189		context_dirty(ctx, LIGHT_MODEL);
190		context_dirty(ctx, LIGHT_ENABLE);
191
192		mask = ctx->Light._EnabledLights;
193		while (mask) {
194			const int i = u_bit_scan(&mask);
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	case GL_TEXTURE_RECTANGLE:
234		context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
235		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
236		break;
237	case GL_TEXTURE_GEN_S:
238	case GL_TEXTURE_GEN_T:
239	case GL_TEXTURE_GEN_R:
240	case GL_TEXTURE_GEN_Q:
241		context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
242		context_dirty(ctx, MODELVIEW);
243		break;
244	}
245}
246
247static void
248nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params)
249{
250	context_dirty(ctx, FOG);
251}
252
253static void
254nouveau_light(struct gl_context *ctx, GLenum light, GLenum pname, const GLfloat *params)
255{
256	switch (pname) {
257	case GL_AMBIENT:
258		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
259		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
260		break;
261	case GL_DIFFUSE:
262		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
263		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
264		break;
265	case GL_SPECULAR:
266		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
267		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
268		break;
269	case GL_SPOT_CUTOFF:
270	case GL_POSITION:
271		context_dirty(ctx, MODELVIEW);
272		context_dirty(ctx, LIGHT_ENABLE);
273		context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
274		break;
275	default:
276		context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0);
277		break;
278	}
279}
280
281static void
282nouveau_light_model(struct gl_context *ctx, GLenum pname, const GLfloat *params)
283{
284	context_dirty(ctx, LIGHT_MODEL);
285	context_dirty(ctx, MODELVIEW);
286}
287
288static void
289nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern )
290{
291	context_dirty(ctx, LINE_STIPPLE);
292}
293
294static void
295nouveau_line_width(struct gl_context *ctx, GLfloat width)
296{
297	context_dirty(ctx, LINE_MODE);
298}
299
300static void
301nouveau_logic_opcode(struct gl_context *ctx, UNUSED enum gl_logicop_mode opcode)
302{
303	context_dirty(ctx, LOGIC_OPCODE);
304}
305
306static void
307nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params)
308{
309	context_dirty(ctx, POINT_PARAMETER);
310}
311
312static void
313nouveau_point_size(struct gl_context *ctx, GLfloat size)
314{
315	context_dirty(ctx, POINT_MODE);
316}
317
318static void
319nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode)
320{
321	context_dirty(ctx, POLYGON_MODE);
322}
323
324static void
325nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units, GLfloat clamp)
326{
327	context_dirty(ctx, POLYGON_OFFSET);
328}
329
330static void
331nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask)
332{
333	context_dirty(ctx, POLYGON_STIPPLE);
334}
335
336static void
337nouveau_render_mode(struct gl_context *ctx, GLenum mode)
338{
339	context_dirty(ctx, RENDER_MODE);
340}
341
342static void
343nouveau_shade_model(struct gl_context *ctx, GLenum mode)
344{
345	context_dirty(ctx, SHADE_MODEL);
346}
347
348static void
349nouveau_stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func,
350			      GLint ref, GLuint mask)
351{
352	context_dirty(ctx, STENCIL_FUNC);
353}
354
355static void
356nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask)
357{
358	context_dirty(ctx, STENCIL_MASK);
359}
360
361static void
362nouveau_stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum fail,
363			    GLenum zfail, GLenum zpass)
364{
365	context_dirty(ctx, STENCIL_OP);
366}
367
368static void
369nouveau_tex_gen(struct gl_context *ctx, GLenum coord, GLenum pname,
370		const GLfloat *params)
371{
372	switch (pname) {
373	case GL_TEXTURE_GEN_MODE:
374		context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
375		context_dirty(ctx, MODELVIEW);
376		break;
377	default:
378		context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit);
379		break;
380	}
381}
382
383static void
384nouveau_tex_env(struct gl_context *ctx, GLenum target, GLenum pname,
385		const GLfloat *param)
386{
387	switch (target) {
388	case GL_TEXTURE_FILTER_CONTROL_EXT:
389		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
390		break;
391	default:
392		context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
393		break;
394	}
395}
396
397static void
398nouveau_tex_parameter(struct gl_context *ctx,
399		      struct gl_texture_object *t, GLenum pname)
400{
401	switch (pname) {
402	case GL_TEXTURE_MAG_FILTER:
403	case GL_TEXTURE_WRAP_S:
404	case GL_TEXTURE_WRAP_T:
405	case GL_TEXTURE_WRAP_R:
406	case GL_TEXTURE_MIN_LOD:
407	case GL_TEXTURE_MAX_LOD:
408	case GL_TEXTURE_MAX_ANISOTROPY_EXT:
409	case GL_TEXTURE_LOD_BIAS:
410		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
411		break;
412
413	case GL_TEXTURE_MIN_FILTER:
414	case GL_TEXTURE_BASE_LEVEL:
415	case GL_TEXTURE_MAX_LEVEL:
416		nouveau_texture_reallocate(ctx, t);
417		context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
418		break;
419	}
420}
421
422void
423nouveau_emit_nothing(struct gl_context *ctx, int emit)
424{
425}
426
427int
428nouveau_next_dirty_state(struct gl_context *ctx)
429{
430	struct nouveau_context *nctx = to_nouveau_context(ctx);
431	int i = BITSET_FFS(nctx->dirty) - 1;
432
433	if (i < 0 || i >= context_drv(ctx)->num_emit)
434		return -1;
435
436	return i;
437}
438
439void
440nouveau_state_emit(struct gl_context *ctx)
441{
442	struct nouveau_context *nctx = to_nouveau_context(ctx);
443	const struct nouveau_driver *drv = context_drv(ctx);
444	int i;
445
446	while ((i = nouveau_next_dirty_state(ctx)) >= 0) {
447		BITSET_CLEAR(nctx->dirty, i);
448		drv->emit[i](ctx, i);
449	}
450
451	BITSET_ZERO(nctx->dirty);
452}
453
454static void
455nouveau_update_state(struct gl_context *ctx)
456{
457	GLbitfield new_state = ctx->NewState;
458	int i;
459
460	if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
461		_mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
462
463	if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW))
464		context_dirty(ctx, PROJECTION);
465
466	if (new_state & _NEW_MODELVIEW)
467		context_dirty(ctx, MODELVIEW);
468
469	if (new_state & _NEW_TEXTURE_MATRIX) {
470		for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
471			context_dirty_i(ctx, TEX_MAT, i);
472	}
473
474	if (new_state & _NEW_SCISSOR)
475		context_dirty(ctx, SCISSOR);
476
477	if (new_state & _NEW_VIEWPORT)
478		context_dirty(ctx, VIEWPORT);
479
480	if (new_state & _NEW_CURRENT_ATTRIB &&
481	    new_state & _NEW_LIGHT) {
482		context_dirty(ctx, MATERIAL_FRONT_AMBIENT);
483		context_dirty(ctx, MATERIAL_BACK_AMBIENT);
484		context_dirty(ctx, MATERIAL_FRONT_DIFFUSE);
485		context_dirty(ctx, MATERIAL_BACK_DIFFUSE);
486		context_dirty(ctx, MATERIAL_FRONT_SPECULAR);
487		context_dirty(ctx, MATERIAL_BACK_SPECULAR);
488		context_dirty(ctx, MATERIAL_FRONT_SHININESS);
489		context_dirty(ctx, MATERIAL_BACK_SHININESS);
490	}
491
492	if (new_state & _NEW_TEXTURE) {
493		for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
494			if (ctx->Texture.Unit[i].Sampler)
495				context_dirty_i(ctx, TEX_OBJ, i);
496		}
497	}
498
499	_swrast_InvalidateState(ctx, new_state);
500	_tnl_InvalidateState(ctx, new_state);
501
502	nouveau_state_emit(ctx);
503}
504
505void
506nouveau_state_init(struct gl_context *ctx)
507{
508	struct nouveau_context *nctx = to_nouveau_context(ctx);
509
510	ctx->Driver.AlphaFunc = nouveau_alpha_func;
511	ctx->Driver.BlendColor = nouveau_blend_color;
512	ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate;
513	ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate;
514	ctx->Driver.ClipPlane = nouveau_clip_plane;
515	ctx->Driver.ColorMask = nouveau_color_mask;
516	ctx->Driver.ColorMaterial = nouveau_color_material;
517	ctx->Driver.CullFace = nouveau_cull_face;
518	ctx->Driver.FrontFace = nouveau_front_face;
519	ctx->Driver.DepthFunc = nouveau_depth_func;
520	ctx->Driver.DepthMask = nouveau_depth_mask;
521	ctx->Driver.ReadBuffer = nouveau_read_buffer;
522	ctx->Driver.DrawBuffer = nouveau_draw_buffer;
523	ctx->Driver.Enable = nouveau_enable;
524	ctx->Driver.Fogfv = nouveau_fog;
525	ctx->Driver.Lightfv = nouveau_light;
526	ctx->Driver.LightModelfv = nouveau_light_model;
527	ctx->Driver.LineStipple = nouveau_line_stipple;
528	ctx->Driver.LineWidth = nouveau_line_width;
529	ctx->Driver.LogicOpcode = nouveau_logic_opcode;
530	ctx->Driver.PointParameterfv = nouveau_point_parameter;
531	ctx->Driver.PointSize = nouveau_point_size;
532	ctx->Driver.PolygonMode = nouveau_polygon_mode;
533	ctx->Driver.PolygonOffset = nouveau_polygon_offset;
534	ctx->Driver.PolygonStipple = nouveau_polygon_stipple;
535	ctx->Driver.RenderMode = nouveau_render_mode;
536	ctx->Driver.ShadeModel = nouveau_shade_model;
537	ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate;
538	ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate;
539	ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate;
540	ctx->Driver.TexGen = nouveau_tex_gen;
541	ctx->Driver.TexEnv = nouveau_tex_env;
542	ctx->Driver.TexParameter = nouveau_tex_parameter;
543
544	ctx->Driver.UpdateState = nouveau_update_state;
545
546	BITSET_ONES(nctx->dirty);
547}
548