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