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