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