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