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 37static void 38nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref) 39{ 40 context_dirty(ctx, ALPHA_FUNC); 41} 42 43static void 44nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4]) 45{ 46 context_dirty(ctx, BLEND_COLOR); 47} 48 49static void 50nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA) 51{ 52 context_dirty(ctx, BLEND_EQUATION); 53} 54 55static void 56nouveau_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 62static void 63nouveau_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 68static void 69nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask, 70 GLboolean bmask, GLboolean amask) 71{ 72 context_dirty(ctx, COLOR_MASK); 73} 74 75static void 76nouveau_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 87static void 88nouveau_cull_face(struct gl_context *ctx, GLenum mode) 89{ 90 context_dirty(ctx, CULL_FACE); 91} 92 93static void 94nouveau_front_face(struct gl_context *ctx, GLenum mode) 95{ 96 context_dirty(ctx, FRONT_FACE); 97} 98 99static void 100nouveau_depth_func(struct gl_context *ctx, GLenum func) 101{ 102 context_dirty(ctx, DEPTH); 103} 104 105static void 106nouveau_depth_mask(struct gl_context *ctx, GLboolean flag) 107{ 108 context_dirty(ctx, DEPTH); 109} 110 111static void 112nouveau_read_buffer(struct gl_context *ctx, GLenum buffer) 113{ 114 nouveau_validate_framebuffer(ctx); 115} 116 117static void 118nouveau_draw_buffer(struct gl_context *ctx) 119{ 120 nouveau_validate_framebuffer(ctx); 121 context_dirty(ctx, FRAMEBUFFER); 122} 123 124static void 125nouveau_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 247static void 248nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params) 249{ 250 context_dirty(ctx, FOG); 251} 252 253static void 254nouveau_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 281static void 282nouveau_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 288static void 289nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern ) 290{ 291 context_dirty(ctx, LINE_STIPPLE); 292} 293 294static void 295nouveau_line_width(struct gl_context *ctx, GLfloat width) 296{ 297 context_dirty(ctx, LINE_MODE); 298} 299 300static void 301nouveau_logic_opcode(struct gl_context *ctx, UNUSED enum gl_logicop_mode opcode) 302{ 303 context_dirty(ctx, LOGIC_OPCODE); 304} 305 306static void 307nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params) 308{ 309 context_dirty(ctx, POINT_PARAMETER); 310} 311 312static void 313nouveau_point_size(struct gl_context *ctx, GLfloat size) 314{ 315 context_dirty(ctx, POINT_MODE); 316} 317 318static void 319nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode) 320{ 321 context_dirty(ctx, POLYGON_MODE); 322} 323 324static void 325nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units, GLfloat clamp) 326{ 327 context_dirty(ctx, POLYGON_OFFSET); 328} 329 330static void 331nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask) 332{ 333 context_dirty(ctx, POLYGON_STIPPLE); 334} 335 336static void 337nouveau_render_mode(struct gl_context *ctx, GLenum mode) 338{ 339 context_dirty(ctx, RENDER_MODE); 340} 341 342static void 343nouveau_shade_model(struct gl_context *ctx, GLenum mode) 344{ 345 context_dirty(ctx, SHADE_MODEL); 346} 347 348static void 349nouveau_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 355static void 356nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask) 357{ 358 context_dirty(ctx, STENCIL_MASK); 359} 360 361static void 362nouveau_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 368static void 369nouveau_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 383static void 384nouveau_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 397static void 398nouveau_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 422void 423nouveau_emit_nothing(struct gl_context *ctx, int emit) 424{ 425} 426 427int 428nouveau_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 439void 440nouveau_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 454static void 455nouveau_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 505void 506nouveau_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.DrawBuffer = nouveau_draw_buffer; 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