state.c revision c1f859d4
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26/** 27 * \file state.c 28 * State management. 29 * 30 * This file manages recalculation of derived values in GLcontext. 31 */ 32 33 34#include "glheader.h" 35#include "mtypes.h" 36#include "context.h" 37#include "debug.h" 38#include "macros.h" 39#include "ffvertex_prog.h" 40#include "framebuffer.h" 41#include "light.h" 42#include "matrix.h" 43#if FEATURE_pixel_transfer 44#include "pixel.h" 45#endif 46#include "shader/program.h" 47#include "state.h" 48#include "stencil.h" 49#include "texenvprogram.h" 50#include "texobj.h" 51#include "texstate.h" 52 53 54static void 55update_separate_specular(GLcontext *ctx) 56{ 57 if (NEED_SECONDARY_COLOR(ctx)) 58 ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; 59 else 60 ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR; 61} 62 63 64/** 65 * Update state dependent on vertex arrays. 66 */ 67static void 68update_arrays( GLcontext *ctx ) 69{ 70 GLuint i, min; 71 72 /* find min of _MaxElement values for all enabled arrays */ 73 74 /* 0 */ 75 if (ctx->VertexProgram._Current 76 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) { 77 min = ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS]._MaxElement; 78 } 79 else if (ctx->Array.ArrayObj->Vertex.Enabled) { 80 min = ctx->Array.ArrayObj->Vertex._MaxElement; 81 } 82 else { 83 /* can't draw anything without vertex positions! */ 84 min = 0; 85 } 86 87 /* 1 */ 88 if (ctx->VertexProgram._Enabled 89 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) { 90 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]._MaxElement); 91 } 92 /* no conventional vertex weight array */ 93 94 /* 2 */ 95 if (ctx->VertexProgram._Enabled 96 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { 97 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]._MaxElement); 98 } 99 else if (ctx->Array.ArrayObj->Normal.Enabled) { 100 min = MIN2(min, ctx->Array.ArrayObj->Normal._MaxElement); 101 } 102 103 /* 3 */ 104 if (ctx->VertexProgram._Enabled 105 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { 106 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]._MaxElement); 107 } 108 else if (ctx->Array.ArrayObj->Color.Enabled) { 109 min = MIN2(min, ctx->Array.ArrayObj->Color._MaxElement); 110 } 111 112 /* 4 */ 113 if (ctx->VertexProgram._Enabled 114 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { 115 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]._MaxElement); 116 } 117 else if (ctx->Array.ArrayObj->SecondaryColor.Enabled) { 118 min = MIN2(min, ctx->Array.ArrayObj->SecondaryColor._MaxElement); 119 } 120 121 /* 5 */ 122 if (ctx->VertexProgram._Enabled 123 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { 124 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG]._MaxElement); 125 } 126 else if (ctx->Array.ArrayObj->FogCoord.Enabled) { 127 min = MIN2(min, ctx->Array.ArrayObj->FogCoord._MaxElement); 128 } 129 130 /* 6 */ 131 if (ctx->VertexProgram._Enabled 132 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { 133 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]._MaxElement); 134 } 135 else if (ctx->Array.ArrayObj->Index.Enabled) { 136 min = MIN2(min, ctx->Array.ArrayObj->Index._MaxElement); 137 } 138 139 140 /* 7 */ 141 if (ctx->VertexProgram._Enabled 142 && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { 143 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]._MaxElement); 144 } 145 146 /* 8..15 */ 147 for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) { 148 if (ctx->VertexProgram._Enabled 149 && ctx->Array.ArrayObj->VertexAttrib[i].Enabled) { 150 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[i]._MaxElement); 151 } 152 else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits 153 && ctx->Array.ArrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) { 154 min = MIN2(min, ctx->Array.ArrayObj->TexCoord[i - VERT_ATTRIB_TEX0]._MaxElement); 155 } 156 } 157 158 /* 16..31 */ 159 if (ctx->VertexProgram._Current) { 160 for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) { 161 if (ctx->Array.ArrayObj->VertexAttrib[i].Enabled) { 162 min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[i]._MaxElement); 163 } 164 } 165 } 166 167 if (ctx->Array.ArrayObj->EdgeFlag.Enabled) { 168 min = MIN2(min, ctx->Array.ArrayObj->EdgeFlag._MaxElement); 169 } 170 171 /* _MaxElement is one past the last legal array element */ 172 ctx->Array._MaxElement = min; 173} 174 175 176/** 177 * Update the following fields: 178 * ctx->VertexProgram._Enabled 179 * ctx->FragmentProgram._Enabled 180 * ctx->ATIFragmentShader._Enabled 181 * This needs to be done before texture state validation. 182 */ 183static void 184update_program_enables(GLcontext *ctx) 185{ 186 /* These _Enabled flags indicate if the program is enabled AND valid. */ 187 ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled 188 && ctx->VertexProgram.Current->Base.Instructions; 189 ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled 190 && ctx->FragmentProgram.Current->Base.Instructions; 191 ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled 192 && ctx->ATIFragmentShader.Current->Instructions[0]; 193} 194 195 196/** 197 * Update vertex/fragment program state. In particular, update these fields: 198 * ctx->VertexProgram._Current 199 * ctx->VertexProgram._TnlProgram, 200 * These point to the highest priority enabled vertex/fragment program or are 201 * NULL if fixed-function processing is to be done. 202 * 203 * This function needs to be called after texture state validation in case 204 * we're generating a fragment program from fixed-function texture state. 205 * 206 * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex 207 * or fragment program is being used. 208 */ 209static GLbitfield 210update_program(GLcontext *ctx) 211{ 212 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; 213 const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; 214 const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; 215 GLbitfield new_state = 0x0; 216 217 /* 218 * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current 219 * pointers to the programs that should be used for rendering. If either 220 * is NULL, use fixed-function code paths. 221 * 222 * These programs may come from several sources. The priority is as 223 * follows: 224 * 1. OpenGL 2.0/ARB vertex/fragment shaders 225 * 2. ARB/NV vertex/fragment programs 226 * 3. Programs derived from fixed-function state. 227 * 228 * Note: it's possible for a vertex shader to get used with a fragment 229 * program (and vice versa) here, but in practice that shouldn't ever 230 * come up, or matter. 231 */ 232 233 if (shProg && shProg->LinkStatus && shProg->FragmentProgram) { 234 /* Use shader programs */ 235 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 236 shProg->FragmentProgram); 237 } 238 else if (ctx->FragmentProgram._Enabled) { 239 /* use user-defined vertex program */ 240 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 241 ctx->FragmentProgram.Current); 242 } 243 else if (ctx->FragmentProgram._MaintainTexEnvProgram) { 244 /* Use fragment program generated from fixed-function state. 245 */ 246 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 247 _mesa_get_fixed_func_fragment_program(ctx)); 248 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, 249 ctx->FragmentProgram._Current); 250 } 251 else { 252 /* no fragment program */ 253 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); 254 } 255 256 /* Examine vertex program after fragment program as 257 * _mesa_get_fixed_func_vertex_program() needs to know active 258 * fragprog inputs. 259 */ 260 if (shProg && shProg->LinkStatus && shProg->VertexProgram) { 261 /* Use shader programs */ 262 _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 263 shProg->VertexProgram); 264 } 265 else if (ctx->VertexProgram._Enabled) { 266 /* use user-defined vertex program */ 267 _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 268 ctx->VertexProgram.Current); 269 } 270 else if (ctx->VertexProgram._MaintainTnlProgram) { 271 /* Use vertex program generated from fixed-function state. 272 */ 273 _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 274 _mesa_get_fixed_func_vertex_program(ctx)); 275 _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, 276 ctx->VertexProgram._Current); 277 } 278 else { 279 /* no vertex program */ 280 _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); 281 } 282 283 /* Let the driver know what's happening: 284 */ 285 if (ctx->FragmentProgram._Current != prevFP) { 286 new_state |= _NEW_PROGRAM; 287 if (ctx->Driver.BindProgram) { 288 ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 289 (struct gl_program *) ctx->FragmentProgram._Current); 290 } 291 } 292 293 if (ctx->VertexProgram._Current != prevVP) { 294 new_state |= _NEW_PROGRAM; 295 if (ctx->Driver.BindProgram) { 296 ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, 297 (struct gl_program *) ctx->VertexProgram._Current); 298 } 299 } 300 301 return new_state; 302} 303 304 305static void 306update_viewport_matrix(GLcontext *ctx) 307{ 308 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; 309 310 ASSERT(depthMax > 0); 311 312 /* Compute scale and bias values. This is really driver-specific 313 * and should be maintained elsewhere if at all. 314 * NOTE: RasterPos uses this. 315 */ 316 _math_matrix_viewport(&ctx->Viewport._WindowMap, 317 ctx->Viewport.X, ctx->Viewport.Y, 318 ctx->Viewport.Width, ctx->Viewport.Height, 319 ctx->Viewport.Near, ctx->Viewport.Far, 320 depthMax); 321} 322 323 324/** 325 * Update derived multisample state. 326 */ 327static void 328update_multisample(GLcontext *ctx) 329{ 330 ctx->Multisample._Enabled = GL_FALSE; 331 if (ctx->Multisample.Enabled && 332 ctx->DrawBuffer && 333 ctx->DrawBuffer->Visual.sampleBuffers) 334 ctx->Multisample._Enabled = GL_TRUE; 335} 336 337 338/** 339 * Update derived color/blend/logicop state. 340 */ 341static void 342update_color(GLcontext *ctx) 343{ 344 /* This is needed to support 1.1's RGB logic ops AND 345 * 1.0's blending logicops. 346 */ 347 ctx->Color._LogicOpEnabled = RGBA_LOGICOP_ENABLED(ctx); 348} 349 350 351/* 352 * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET 353 * in ctx->_TriangleCaps if needed. 354 */ 355static void 356update_polygon(GLcontext *ctx) 357{ 358 ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET); 359 360 if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 361 ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; 362 363 if ( ctx->Polygon.OffsetPoint 364 || ctx->Polygon.OffsetLine 365 || ctx->Polygon.OffsetFill) 366 ctx->_TriangleCaps |= DD_TRI_OFFSET; 367} 368 369 370/** 371 * Update the ctx->_TriangleCaps bitfield. 372 * XXX that bitfield should really go away someday! 373 * This function must be called after other update_*() functions since 374 * there are dependencies on some other derived values. 375 */ 376#if 0 377static void 378update_tricaps(GLcontext *ctx, GLbitfield new_state) 379{ 380 ctx->_TriangleCaps = 0; 381 382 /* 383 * Points 384 */ 385 if (1/*new_state & _NEW_POINT*/) { 386 if (ctx->Point.SmoothFlag) 387 ctx->_TriangleCaps |= DD_POINT_SMOOTH; 388 if (ctx->Point.Size != 1.0F) 389 ctx->_TriangleCaps |= DD_POINT_SIZE; 390 if (ctx->Point._Attenuated) 391 ctx->_TriangleCaps |= DD_POINT_ATTEN; 392 } 393 394 /* 395 * Lines 396 */ 397 if (1/*new_state & _NEW_LINE*/) { 398 if (ctx->Line.SmoothFlag) 399 ctx->_TriangleCaps |= DD_LINE_SMOOTH; 400 if (ctx->Line.StippleFlag) 401 ctx->_TriangleCaps |= DD_LINE_STIPPLE; 402 if (ctx->Line.Width != 1.0) 403 ctx->_TriangleCaps |= DD_LINE_WIDTH; 404 } 405 406 /* 407 * Polygons 408 */ 409 if (1/*new_state & _NEW_POLYGON*/) { 410 if (ctx->Polygon.SmoothFlag) 411 ctx->_TriangleCaps |= DD_TRI_SMOOTH; 412 if (ctx->Polygon.StippleFlag) 413 ctx->_TriangleCaps |= DD_TRI_STIPPLE; 414 if (ctx->Polygon.FrontMode != GL_FILL 415 || ctx->Polygon.BackMode != GL_FILL) 416 ctx->_TriangleCaps |= DD_TRI_UNFILLED; 417 if (ctx->Polygon.CullFlag 418 && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 419 ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; 420 if (ctx->Polygon.OffsetPoint || 421 ctx->Polygon.OffsetLine || 422 ctx->Polygon.OffsetFill) 423 ctx->_TriangleCaps |= DD_TRI_OFFSET; 424 } 425 426 /* 427 * Lighting and shading 428 */ 429 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) 430 ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; 431 if (ctx->Light.ShadeModel == GL_FLAT) 432 ctx->_TriangleCaps |= DD_FLATSHADE; 433 if (NEED_SECONDARY_COLOR(ctx)) 434 ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; 435 436 /* 437 * Stencil 438 */ 439 if (ctx->Stencil._TestTwoSide) 440 ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL; 441} 442#endif 443 444 445/** 446 * Compute derived GL state. 447 * If __GLcontextRec::NewState is non-zero then this function \b must 448 * be called before rendering anything. 449 * 450 * Calls dd_function_table::UpdateState to perform any internal state 451 * management necessary. 452 * 453 * \sa _mesa_update_modelview_project(), _mesa_update_texture(), 454 * _mesa_update_buffer_bounds(), 455 * _mesa_update_lighting() and _mesa_update_tnl_spaces(). 456 */ 457void 458_mesa_update_state_locked( GLcontext *ctx ) 459{ 460 GLbitfield new_state = ctx->NewState; 461 GLbitfield prog_flags = _NEW_PROGRAM; 462 GLbitfield new_prog_state = 0x0; 463 464 if (MESA_VERBOSE & VERBOSE_STATE) 465 _mesa_print_state("_mesa_update_state", new_state); 466 467 /* Determine which state flags effect vertex/fragment program state */ 468 if (ctx->FragmentProgram._MaintainTexEnvProgram) { 469 prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR); 470 } 471 if (ctx->VertexProgram._MaintainTnlProgram) { 472 prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | 473 _NEW_TRANSFORM | _NEW_POINT | 474 _NEW_FOG | _NEW_LIGHT | 475 _MESA_NEW_NEED_EYE_COORDS); 476 } 477 478 /* 479 * Now update derived state info 480 */ 481 482 if (new_state & prog_flags) 483 update_program_enables( ctx ); 484 485 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 486 _mesa_update_modelview_project( ctx, new_state ); 487 488 if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) 489 _mesa_update_texture( ctx, new_state ); 490 491 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) 492 _mesa_update_framebuffer(ctx); 493 494 if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) 495 _mesa_update_draw_buffer_bounds( ctx ); 496 497 if (new_state & _NEW_POLYGON) 498 update_polygon( ctx ); 499 500 if (new_state & _NEW_LIGHT) 501 _mesa_update_lighting( ctx ); 502 503 if (new_state & _NEW_STENCIL) 504 _mesa_update_stencil( ctx ); 505 506#if FEATURE_pixel_transfer 507 if (new_state & _IMAGE_NEW_TRANSFER_STATE) 508 _mesa_update_pixel( ctx, new_state ); 509#endif 510 511 if (new_state & _DD_NEW_SEPARATE_SPECULAR) 512 update_separate_specular( ctx ); 513 514 if (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) 515 update_arrays( ctx ); 516 517 if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) 518 update_viewport_matrix(ctx); 519 520 if (new_state & _NEW_MULTISAMPLE) 521 update_multisample( ctx ); 522 523 if (new_state & _NEW_COLOR) 524 update_color( ctx ); 525 526#if 0 527 if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT 528 | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR)) 529 update_tricaps( ctx, new_state ); 530#endif 531 532 /* ctx->_NeedEyeCoords is now up to date. 533 * 534 * If the truth value of this variable has changed, update for the 535 * new lighting space and recompute the positions of lights and the 536 * normal transform. 537 * 538 * If the lighting space hasn't changed, may still need to recompute 539 * light positions & normal transforms for other reasons. 540 */ 541 if (new_state & _MESA_NEW_NEED_EYE_COORDS) 542 _mesa_update_tnl_spaces( ctx, new_state ); 543 544 if (new_state & prog_flags) { 545 /* When we generate programs from fixed-function vertex/fragment state 546 * this call may generate/bind a new program. If so, we need to 547 * propogate the _NEW_PROGRAM flag to the driver. 548 */ 549 new_prog_state |= update_program( ctx ); 550 } 551 552 /* 553 * Give the driver a chance to act upon the new_state flags. 554 * The driver might plug in different span functions, for example. 555 * Also, this is where the driver can invalidate the state of any 556 * active modules (such as swrast_setup, swrast, tnl, etc). 557 * 558 * Set ctx->NewState to zero to avoid recursion if 559 * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) 560 */ 561 new_state = ctx->NewState | new_prog_state; 562 ctx->NewState = 0; 563 ctx->Driver.UpdateState(ctx, new_state); 564 ctx->Array.NewState = 0; 565} 566 567 568/* This is the usual entrypoint for state updates: 569 */ 570void 571_mesa_update_state( GLcontext *ctx ) 572{ 573 _mesa_lock_context_textures(ctx); 574 _mesa_update_state_locked(ctx); 575 _mesa_unlock_context_textures(ctx); 576} 577