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