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