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 35static void 36nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref) 37{ 38 context_dirty(ctx, ALPHA_FUNC); 39} 40 41static void 42nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4]) 43{ 44 context_dirty(ctx, BLEND_COLOR); 45} 46 47static void 48nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA) 49{ 50 context_dirty(ctx, BLEND_EQUATION); 51} 52 53static void 54nouveau_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 60static void 61nouveau_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 66static void 67nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask, 68 GLboolean bmask, GLboolean amask) 69{ 70 context_dirty(ctx, COLOR_MASK); 71} 72 73static void 74nouveau_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 85static void 86nouveau_cull_face(struct gl_context *ctx, GLenum mode) 87{ 88 context_dirty(ctx, CULL_FACE); 89} 90 91static void 92nouveau_front_face(struct gl_context *ctx, GLenum mode) 93{ 94 context_dirty(ctx, FRONT_FACE); 95} 96 97static void 98nouveau_depth_func(struct gl_context *ctx, GLenum func) 99{ 100 context_dirty(ctx, DEPTH); 101} 102 103static void 104nouveau_depth_mask(struct gl_context *ctx, GLboolean flag) 105{ 106 context_dirty(ctx, DEPTH); 107} 108 109static void 110nouveau_depth_range(struct gl_context *ctx, GLclampd nearval, GLclampd farval) 111{ 112 context_dirty(ctx, VIEWPORT); 113} 114 115static void 116nouveau_read_buffer(struct gl_context *ctx, GLenum buffer) 117{ 118 nouveau_validate_framebuffer(ctx); 119} 120 121static void 122nouveau_draw_buffers(struct gl_context *ctx, GLsizei n, const GLenum *buffers) 123{ 124 nouveau_validate_framebuffer(ctx); 125 context_dirty(ctx, FRAMEBUFFER); 126} 127 128static void 129nouveau_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 250static void 251nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params) 252{ 253 context_dirty(ctx, FOG); 254} 255 256static void 257nouveau_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 284static void 285nouveau_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 291static void 292nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern ) 293{ 294 context_dirty(ctx, LINE_STIPPLE); 295} 296 297static void 298nouveau_line_width(struct gl_context *ctx, GLfloat width) 299{ 300 context_dirty(ctx, LINE_MODE); 301} 302 303static void 304nouveau_logic_opcode(struct gl_context *ctx, GLenum opcode) 305{ 306 context_dirty(ctx, LOGIC_OPCODE); 307} 308 309static void 310nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params) 311{ 312 context_dirty(ctx, POINT_PARAMETER); 313} 314 315static void 316nouveau_point_size(struct gl_context *ctx, GLfloat size) 317{ 318 context_dirty(ctx, POINT_MODE); 319} 320 321static void 322nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode) 323{ 324 context_dirty(ctx, POLYGON_MODE); 325} 326 327static void 328nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units) 329{ 330 context_dirty(ctx, POLYGON_OFFSET); 331} 332 333static void 334nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask) 335{ 336 context_dirty(ctx, POLYGON_STIPPLE); 337} 338 339static void 340nouveau_render_mode(struct gl_context *ctx, GLenum mode) 341{ 342 context_dirty(ctx, RENDER_MODE); 343} 344 345static void 346nouveau_scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) 347{ 348 context_dirty(ctx, SCISSOR); 349} 350 351static void 352nouveau_shade_model(struct gl_context *ctx, GLenum mode) 353{ 354 context_dirty(ctx, SHADE_MODEL); 355} 356 357static void 358nouveau_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 364static void 365nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask) 366{ 367 context_dirty(ctx, STENCIL_MASK); 368} 369 370static void 371nouveau_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 377static void 378nouveau_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 392static void 393nouveau_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 406static void 407nouveau_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 432static void 433nouveau_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) 434{ 435 context_dirty(ctx, VIEWPORT); 436} 437 438void 439nouveau_emit_nothing(struct gl_context *ctx, int emit) 440{ 441} 442 443int 444nouveau_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 455void 456nouveau_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 470static void 471nouveau_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 511void 512nouveau_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