Home | History | Annotate | Download | only in nouveau
      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 
     36 static void
     37 nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref)
     38 {
     39 	context_dirty(ctx, ALPHA_FUNC);
     40 }
     41 
     42 static void
     43 nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4])
     44 {
     45 	context_dirty(ctx, BLEND_COLOR);
     46 }
     47 
     48 static void
     49 nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA)
     50 {
     51 	context_dirty(ctx, BLEND_EQUATION);
     52 }
     53 
     54 static void
     55 nouveau_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 
     61 static void
     62 nouveau_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 
     67 static void
     68 nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask,
     69 		   GLboolean bmask, GLboolean amask)
     70 {
     71 	context_dirty(ctx, COLOR_MASK);
     72 }
     73 
     74 static void
     75 nouveau_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 
     86 static void
     87 nouveau_cull_face(struct gl_context *ctx, GLenum mode)
     88 {
     89 	context_dirty(ctx, CULL_FACE);
     90 }
     91 
     92 static void
     93 nouveau_front_face(struct gl_context *ctx, GLenum mode)
     94 {
     95 	context_dirty(ctx, FRONT_FACE);
     96 }
     97 
     98 static void
     99 nouveau_depth_func(struct gl_context *ctx, GLenum func)
    100 {
    101 	context_dirty(ctx, DEPTH);
    102 }
    103 
    104 static void
    105 nouveau_depth_mask(struct gl_context *ctx, GLboolean flag)
    106 {
    107 	context_dirty(ctx, DEPTH);
    108 }
    109 
    110 static void
    111 nouveau_read_buffer(struct gl_context *ctx, GLenum buffer)
    112 {
    113 	nouveau_validate_framebuffer(ctx);
    114 }
    115 
    116 static void
    117 nouveau_draw_buffers(struct gl_context *ctx, GLsizei n, const GLenum *buffers)
    118 {
    119 	nouveau_validate_framebuffer(ctx);
    120 	context_dirty(ctx, FRAMEBUFFER);
    121 }
    122 
    123 static void
    124 nouveau_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 
    246 static void
    247 nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params)
    248 {
    249 	context_dirty(ctx, FOG);
    250 }
    251 
    252 static void
    253 nouveau_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 
    280 static void
    281 nouveau_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 
    287 static void
    288 nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern )
    289 {
    290 	context_dirty(ctx, LINE_STIPPLE);
    291 }
    292 
    293 static void
    294 nouveau_line_width(struct gl_context *ctx, GLfloat width)
    295 {
    296 	context_dirty(ctx, LINE_MODE);
    297 }
    298 
    299 static void
    300 nouveau_logic_opcode(struct gl_context *ctx, GLenum opcode)
    301 {
    302 	context_dirty(ctx, LOGIC_OPCODE);
    303 }
    304 
    305 static void
    306 nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params)
    307 {
    308 	context_dirty(ctx, POINT_PARAMETER);
    309 }
    310 
    311 static void
    312 nouveau_point_size(struct gl_context *ctx, GLfloat size)
    313 {
    314 	context_dirty(ctx, POINT_MODE);
    315 }
    316 
    317 static void
    318 nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode)
    319 {
    320 	context_dirty(ctx, POLYGON_MODE);
    321 }
    322 
    323 static void
    324 nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units, GLfloat clamp)
    325 {
    326 	context_dirty(ctx, POLYGON_OFFSET);
    327 }
    328 
    329 static void
    330 nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask)
    331 {
    332 	context_dirty(ctx, POLYGON_STIPPLE);
    333 }
    334 
    335 static void
    336 nouveau_render_mode(struct gl_context *ctx, GLenum mode)
    337 {
    338 	context_dirty(ctx, RENDER_MODE);
    339 }
    340 
    341 static void
    342 nouveau_shade_model(struct gl_context *ctx, GLenum mode)
    343 {
    344 	context_dirty(ctx, SHADE_MODEL);
    345 }
    346 
    347 static void
    348 nouveau_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 
    354 static void
    355 nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask)
    356 {
    357 	context_dirty(ctx, STENCIL_MASK);
    358 }
    359 
    360 static void
    361 nouveau_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 
    367 static void
    368 nouveau_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 
    382 static void
    383 nouveau_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 
    396 static void
    397 nouveau_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 
    421 void
    422 nouveau_emit_nothing(struct gl_context *ctx, int emit)
    423 {
    424 }
    425 
    426 int
    427 nouveau_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 
    438 void
    439 nouveau_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 
    453 static void
    454 nouveau_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 
    501 void
    502 nouveau_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