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 35 static void 36 nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref) 37 { 38 context_dirty(ctx, ALPHA_FUNC); 39 } 40 41 static void 42 nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4]) 43 { 44 context_dirty(ctx, BLEND_COLOR); 45 } 46 47 static void 48 nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA) 49 { 50 context_dirty(ctx, BLEND_EQUATION); 51 } 52 53 static void 54 nouveau_blend_func_separate(struct gl_context *ctx, GLenum sfactorRGB, 55 GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA) 56 { 57 context_dirty(ctx, BLEND_FUNC); 58 } 59 60 static void 61 nouveau_clip_plane(struct gl_context *ctx, GLenum plane, const GLfloat *equation) 62 { 63 context_dirty_i(ctx, CLIP_PLANE, plane - GL_CLIP_PLANE0); 64 } 65 66 static void 67 nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask, 68 GLboolean bmask, GLboolean amask) 69 { 70 context_dirty(ctx, COLOR_MASK); 71 } 72 73 static void 74 nouveau_color_material(struct gl_context *ctx, GLenum face, GLenum mode) 75 { 76 context_dirty(ctx, COLOR_MATERIAL); 77 context_dirty(ctx, MATERIAL_FRONT_AMBIENT); 78 context_dirty(ctx, MATERIAL_BACK_AMBIENT); 79 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); 80 context_dirty(ctx, MATERIAL_BACK_DIFFUSE); 81 context_dirty(ctx, MATERIAL_FRONT_SPECULAR); 82 context_dirty(ctx, MATERIAL_BACK_SPECULAR); 83 } 84 85 static void 86 nouveau_cull_face(struct gl_context *ctx, GLenum mode) 87 { 88 context_dirty(ctx, CULL_FACE); 89 } 90 91 static void 92 nouveau_front_face(struct gl_context *ctx, GLenum mode) 93 { 94 context_dirty(ctx, FRONT_FACE); 95 } 96 97 static void 98 nouveau_depth_func(struct gl_context *ctx, GLenum func) 99 { 100 context_dirty(ctx, DEPTH); 101 } 102 103 static void 104 nouveau_depth_mask(struct gl_context *ctx, GLboolean flag) 105 { 106 context_dirty(ctx, DEPTH); 107 } 108 109 static void 110 nouveau_depth_range(struct gl_context *ctx, GLclampd nearval, GLclampd farval) 111 { 112 context_dirty(ctx, VIEWPORT); 113 } 114 115 static void 116 nouveau_read_buffer(struct gl_context *ctx, GLenum buffer) 117 { 118 nouveau_validate_framebuffer(ctx); 119 } 120 121 static void 122 nouveau_draw_buffers(struct gl_context *ctx, GLsizei n, const GLenum *buffers) 123 { 124 nouveau_validate_framebuffer(ctx); 125 context_dirty(ctx, FRAMEBUFFER); 126 } 127 128 static void 129 nouveau_enable(struct gl_context *ctx, GLenum cap, GLboolean state) 130 { 131 int i; 132 133 switch (cap) { 134 case GL_ALPHA_TEST: 135 context_dirty(ctx, ALPHA_FUNC); 136 break; 137 case GL_BLEND: 138 context_dirty(ctx, BLEND_EQUATION); 139 break; 140 case GL_COLOR_LOGIC_OP: 141 context_dirty(ctx, LOGIC_OPCODE); 142 break; 143 case GL_COLOR_MATERIAL: 144 context_dirty(ctx, COLOR_MATERIAL); 145 context_dirty(ctx, MATERIAL_FRONT_AMBIENT); 146 context_dirty(ctx, MATERIAL_BACK_AMBIENT); 147 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); 148 context_dirty(ctx, MATERIAL_BACK_DIFFUSE); 149 context_dirty(ctx, MATERIAL_FRONT_SPECULAR); 150 context_dirty(ctx, MATERIAL_BACK_SPECULAR); 151 break; 152 case GL_COLOR_SUM_EXT: 153 context_dirty(ctx, FRAG); 154 context_dirty(ctx, LIGHT_MODEL); 155 break; 156 case GL_CULL_FACE: 157 context_dirty(ctx, CULL_FACE); 158 break; 159 case GL_DEPTH_TEST: 160 context_dirty(ctx, DEPTH); 161 break; 162 case GL_DITHER: 163 context_dirty(ctx, DITHER); 164 break; 165 case GL_FOG: 166 context_dirty(ctx, FOG); 167 context_dirty(ctx, FRAG); 168 context_dirty(ctx, MODELVIEW); 169 break; 170 case GL_LIGHT0: 171 case GL_LIGHT1: 172 case GL_LIGHT2: 173 case GL_LIGHT3: 174 case GL_LIGHT4: 175 case GL_LIGHT5: 176 case GL_LIGHT6: 177 case GL_LIGHT7: 178 context_dirty(ctx, MODELVIEW); 179 context_dirty(ctx, LIGHT_ENABLE); 180 context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0); 181 context_dirty(ctx, MATERIAL_FRONT_AMBIENT); 182 context_dirty(ctx, MATERIAL_BACK_AMBIENT); 183 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); 184 context_dirty(ctx, MATERIAL_BACK_DIFFUSE); 185 context_dirty(ctx, MATERIAL_FRONT_SPECULAR); 186 context_dirty(ctx, MATERIAL_BACK_SPECULAR); 187 context_dirty(ctx, MATERIAL_FRONT_SHININESS); 188 context_dirty(ctx, MATERIAL_BACK_SHININESS); 189 break; 190 case GL_LIGHTING: 191 context_dirty(ctx, FRAG); 192 context_dirty(ctx, MODELVIEW); 193 context_dirty(ctx, LIGHT_MODEL); 194 context_dirty(ctx, LIGHT_ENABLE); 195 196 for (i = 0; i < MAX_LIGHTS; i++) { 197 if (ctx->Light.Light[i].Enabled) 198 context_dirty_i(ctx, LIGHT_SOURCE, i); 199 } 200 201 context_dirty(ctx, MATERIAL_FRONT_AMBIENT); 202 context_dirty(ctx, MATERIAL_BACK_AMBIENT); 203 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); 204 context_dirty(ctx, MATERIAL_BACK_DIFFUSE); 205 context_dirty(ctx, MATERIAL_FRONT_SPECULAR); 206 context_dirty(ctx, MATERIAL_BACK_SPECULAR); 207 context_dirty(ctx, MATERIAL_FRONT_SHININESS); 208 context_dirty(ctx, MATERIAL_BACK_SHININESS); 209 break; 210 case GL_LINE_SMOOTH: 211 context_dirty(ctx, LINE_MODE); 212 break; 213 case GL_NORMALIZE: 214 context_dirty(ctx, LIGHT_ENABLE); 215 break; 216 case GL_POINT_SMOOTH: 217 context_dirty(ctx, POINT_MODE); 218 break; 219 case GL_POLYGON_OFFSET_POINT: 220 case GL_POLYGON_OFFSET_LINE: 221 case GL_POLYGON_OFFSET_FILL: 222 context_dirty(ctx, POLYGON_OFFSET); 223 break; 224 case GL_POLYGON_SMOOTH: 225 context_dirty(ctx, POLYGON_MODE); 226 break; 227 case GL_SCISSOR_TEST: 228 context_dirty(ctx, SCISSOR); 229 break; 230 case GL_STENCIL_TEST: 231 context_dirty(ctx, STENCIL_FUNC); 232 break; 233 case GL_TEXTURE_1D: 234 case GL_TEXTURE_2D: 235 case GL_TEXTURE_3D: 236 case GL_TEXTURE_RECTANGLE: 237 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); 238 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); 239 break; 240 case GL_TEXTURE_GEN_S: 241 case GL_TEXTURE_GEN_T: 242 case GL_TEXTURE_GEN_R: 243 case GL_TEXTURE_GEN_Q: 244 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); 245 context_dirty(ctx, MODELVIEW); 246 break; 247 } 248 } 249 250 static void 251 nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params) 252 { 253 context_dirty(ctx, FOG); 254 } 255 256 static void 257 nouveau_light(struct gl_context *ctx, GLenum light, GLenum pname, const GLfloat *params) 258 { 259 switch (pname) { 260 case GL_AMBIENT: 261 context_dirty(ctx, MATERIAL_FRONT_AMBIENT); 262 context_dirty(ctx, MATERIAL_BACK_AMBIENT); 263 break; 264 case GL_DIFFUSE: 265 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); 266 context_dirty(ctx, MATERIAL_BACK_DIFFUSE); 267 break; 268 case GL_SPECULAR: 269 context_dirty(ctx, MATERIAL_FRONT_SPECULAR); 270 context_dirty(ctx, MATERIAL_BACK_SPECULAR); 271 break; 272 case GL_SPOT_CUTOFF: 273 case GL_POSITION: 274 context_dirty(ctx, MODELVIEW); 275 context_dirty(ctx, LIGHT_ENABLE); 276 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0); 277 break; 278 default: 279 context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0); 280 break; 281 } 282 } 283 284 static void 285 nouveau_light_model(struct gl_context *ctx, GLenum pname, const GLfloat *params) 286 { 287 context_dirty(ctx, LIGHT_MODEL); 288 context_dirty(ctx, MODELVIEW); 289 } 290 291 static void 292 nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern ) 293 { 294 context_dirty(ctx, LINE_STIPPLE); 295 } 296 297 static void 298 nouveau_line_width(struct gl_context *ctx, GLfloat width) 299 { 300 context_dirty(ctx, LINE_MODE); 301 } 302 303 static void 304 nouveau_logic_opcode(struct gl_context *ctx, GLenum opcode) 305 { 306 context_dirty(ctx, LOGIC_OPCODE); 307 } 308 309 static void 310 nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params) 311 { 312 context_dirty(ctx, POINT_PARAMETER); 313 } 314 315 static void 316 nouveau_point_size(struct gl_context *ctx, GLfloat size) 317 { 318 context_dirty(ctx, POINT_MODE); 319 } 320 321 static void 322 nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode) 323 { 324 context_dirty(ctx, POLYGON_MODE); 325 } 326 327 static void 328 nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units) 329 { 330 context_dirty(ctx, POLYGON_OFFSET); 331 } 332 333 static void 334 nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask) 335 { 336 context_dirty(ctx, POLYGON_STIPPLE); 337 } 338 339 static void 340 nouveau_render_mode(struct gl_context *ctx, GLenum mode) 341 { 342 context_dirty(ctx, RENDER_MODE); 343 } 344 345 static void 346 nouveau_scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) 347 { 348 context_dirty(ctx, SCISSOR); 349 } 350 351 static void 352 nouveau_shade_model(struct gl_context *ctx, GLenum mode) 353 { 354 context_dirty(ctx, SHADE_MODEL); 355 } 356 357 static void 358 nouveau_stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func, 359 GLint ref, GLuint mask) 360 { 361 context_dirty(ctx, STENCIL_FUNC); 362 } 363 364 static void 365 nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask) 366 { 367 context_dirty(ctx, STENCIL_MASK); 368 } 369 370 static void 371 nouveau_stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum fail, 372 GLenum zfail, GLenum zpass) 373 { 374 context_dirty(ctx, STENCIL_OP); 375 } 376 377 static void 378 nouveau_tex_gen(struct gl_context *ctx, GLenum coord, GLenum pname, 379 const GLfloat *params) 380 { 381 switch (pname) { 382 case GL_TEXTURE_GEN_MODE: 383 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); 384 context_dirty(ctx, MODELVIEW); 385 break; 386 default: 387 context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); 388 break; 389 } 390 } 391 392 static void 393 nouveau_tex_env(struct gl_context *ctx, GLenum target, GLenum pname, 394 const GLfloat *param) 395 { 396 switch (target) { 397 case GL_TEXTURE_FILTER_CONTROL_EXT: 398 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); 399 break; 400 default: 401 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); 402 break; 403 } 404 } 405 406 static void 407 nouveau_tex_parameter(struct gl_context *ctx, GLenum target, 408 struct gl_texture_object *t, GLenum pname, 409 const GLfloat *params) 410 { 411 switch (pname) { 412 case GL_TEXTURE_MAG_FILTER: 413 case GL_TEXTURE_WRAP_S: 414 case GL_TEXTURE_WRAP_T: 415 case GL_TEXTURE_WRAP_R: 416 case GL_TEXTURE_MIN_LOD: 417 case GL_TEXTURE_MAX_LOD: 418 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 419 case GL_TEXTURE_LOD_BIAS: 420 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); 421 break; 422 423 case GL_TEXTURE_MIN_FILTER: 424 case GL_TEXTURE_BASE_LEVEL: 425 case GL_TEXTURE_MAX_LEVEL: 426 nouveau_texture_reallocate(ctx, t); 427 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); 428 break; 429 } 430 } 431 432 static void 433 nouveau_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) 434 { 435 context_dirty(ctx, VIEWPORT); 436 } 437 438 void 439 nouveau_emit_nothing(struct gl_context *ctx, int emit) 440 { 441 } 442 443 int 444 nouveau_next_dirty_state(struct gl_context *ctx) 445 { 446 struct nouveau_context *nctx = to_nouveau_context(ctx); 447 int i = BITSET_FFS(nctx->dirty) - 1; 448 449 if (i < 0 || i >= context_drv(ctx)->num_emit) 450 return -1; 451 452 return i; 453 } 454 455 void 456 nouveau_state_emit(struct gl_context *ctx) 457 { 458 struct nouveau_context *nctx = to_nouveau_context(ctx); 459 const struct nouveau_driver *drv = context_drv(ctx); 460 int i; 461 462 while ((i = nouveau_next_dirty_state(ctx)) >= 0) { 463 BITSET_CLEAR(nctx->dirty, i); 464 drv->emit[i](ctx, i); 465 } 466 467 BITSET_ZERO(nctx->dirty); 468 } 469 470 static void 471 nouveau_update_state(struct gl_context *ctx, GLbitfield new_state) 472 { 473 int i; 474 475 if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW)) 476 context_dirty(ctx, PROJECTION); 477 478 if (new_state & _NEW_MODELVIEW) 479 context_dirty(ctx, MODELVIEW); 480 481 if (new_state & _NEW_TEXTURE_MATRIX) { 482 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) 483 context_dirty_i(ctx, TEX_MAT, i); 484 } 485 486 if (new_state & _NEW_CURRENT_ATTRIB && 487 new_state & _NEW_LIGHT) { 488 context_dirty(ctx, MATERIAL_FRONT_AMBIENT); 489 context_dirty(ctx, MATERIAL_BACK_AMBIENT); 490 context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); 491 context_dirty(ctx, MATERIAL_BACK_DIFFUSE); 492 context_dirty(ctx, MATERIAL_FRONT_SPECULAR); 493 context_dirty(ctx, MATERIAL_BACK_SPECULAR); 494 context_dirty(ctx, MATERIAL_FRONT_SHININESS); 495 context_dirty(ctx, MATERIAL_BACK_SHININESS); 496 } 497 498 if (new_state & _NEW_TEXTURE) { 499 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 500 if (ctx->Texture.Unit[i].Sampler) 501 context_dirty_i(ctx, TEX_OBJ, i); 502 } 503 } 504 505 _swrast_InvalidateState(ctx, new_state); 506 _tnl_InvalidateState(ctx, new_state); 507 508 nouveau_state_emit(ctx); 509 } 510 511 void 512 nouveau_state_init(struct gl_context *ctx) 513 { 514 struct nouveau_context *nctx = to_nouveau_context(ctx); 515 516 ctx->Driver.AlphaFunc = nouveau_alpha_func; 517 ctx->Driver.BlendColor = nouveau_blend_color; 518 ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate; 519 ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate; 520 ctx->Driver.ClipPlane = nouveau_clip_plane; 521 ctx->Driver.ColorMask = nouveau_color_mask; 522 ctx->Driver.ColorMaterial = nouveau_color_material; 523 ctx->Driver.CullFace = nouveau_cull_face; 524 ctx->Driver.FrontFace = nouveau_front_face; 525 ctx->Driver.DepthFunc = nouveau_depth_func; 526 ctx->Driver.DepthMask = nouveau_depth_mask; 527 ctx->Driver.DepthRange = nouveau_depth_range; 528 ctx->Driver.ReadBuffer = nouveau_read_buffer; 529 ctx->Driver.DrawBuffers = nouveau_draw_buffers; 530 ctx->Driver.Enable = nouveau_enable; 531 ctx->Driver.Fogfv = nouveau_fog; 532 ctx->Driver.Lightfv = nouveau_light; 533 ctx->Driver.LightModelfv = nouveau_light_model; 534 ctx->Driver.LineStipple = nouveau_line_stipple; 535 ctx->Driver.LineWidth = nouveau_line_width; 536 ctx->Driver.LogicOpcode = nouveau_logic_opcode; 537 ctx->Driver.PointParameterfv = nouveau_point_parameter; 538 ctx->Driver.PointSize = nouveau_point_size; 539 ctx->Driver.PolygonMode = nouveau_polygon_mode; 540 ctx->Driver.PolygonOffset = nouveau_polygon_offset; 541 ctx->Driver.PolygonStipple = nouveau_polygon_stipple; 542 ctx->Driver.RenderMode = nouveau_render_mode; 543 ctx->Driver.Scissor = nouveau_scissor; 544 ctx->Driver.ShadeModel = nouveau_shade_model; 545 ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate; 546 ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate; 547 ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate; 548 ctx->Driver.TexGen = nouveau_tex_gen; 549 ctx->Driver.TexEnv = nouveau_tex_env; 550 ctx->Driver.TexParameter = nouveau_tex_parameter; 551 ctx->Driver.Viewport = nouveau_viewport; 552 553 ctx->Driver.UpdateState = nouveau_update_state; 554 555 BITSET_ONES(nctx->dirty); 556 } 557