state.c revision 4a49301e
17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 34a49301eSmrg * Version: 7.3 47117f1b4Smrg * 5c1f859d4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 67117f1b4Smrg * 77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 97117f1b4Smrg * to deal in the Software without restriction, including without limitation 107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 127117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 137117f1b4Smrg * 147117f1b4Smrg * The above copyright notice and this permission notice shall be included 157117f1b4Smrg * in all copies or substantial portions of the Software. 167117f1b4Smrg * 177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 207117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 217117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 227117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 237117f1b4Smrg */ 247117f1b4Smrg 257117f1b4Smrg 267117f1b4Smrg/** 277117f1b4Smrg * \file state.c 287117f1b4Smrg * State management. 297117f1b4Smrg * 30c1f859d4Smrg * This file manages recalculation of derived values in GLcontext. 317117f1b4Smrg */ 327117f1b4Smrg 33c1f859d4Smrg 347117f1b4Smrg#include "glheader.h" 35c1f859d4Smrg#include "mtypes.h" 367117f1b4Smrg#include "context.h" 37c1f859d4Smrg#include "debug.h" 38c1f859d4Smrg#include "macros.h" 39c1f859d4Smrg#include "ffvertex_prog.h" 407117f1b4Smrg#include "framebuffer.h" 417117f1b4Smrg#include "light.h" 427117f1b4Smrg#include "matrix.h" 437117f1b4Smrg#include "pixel.h" 44c1f859d4Smrg#include "shader/program.h" 454a49301eSmrg#include "shader/prog_parameter.h" 467117f1b4Smrg#include "state.h" 477117f1b4Smrg#include "stencil.h" 48c1f859d4Smrg#include "texenvprogram.h" 497117f1b4Smrg#include "texobj.h" 507117f1b4Smrg#include "texstate.h" 517117f1b4Smrg 527117f1b4Smrg 537117f1b4Smrgstatic void 54c1f859d4Smrgupdate_separate_specular(GLcontext *ctx) 557117f1b4Smrg{ 567117f1b4Smrg if (NEED_SECONDARY_COLOR(ctx)) 577117f1b4Smrg ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; 587117f1b4Smrg else 597117f1b4Smrg ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR; 607117f1b4Smrg} 617117f1b4Smrg 627117f1b4Smrg 637117f1b4Smrg/** 644a49301eSmrg * Compute the index of the last array element that can be safely accessed 654a49301eSmrg * in a vertex array. We can really only do this when the array lives in 664a49301eSmrg * a VBO. 674a49301eSmrg * The array->_MaxElement field will be updated. 684a49301eSmrg * Later in glDrawArrays/Elements/etc we can do some bounds checking. 694a49301eSmrg */ 704a49301eSmrgstatic void 714a49301eSmrgcompute_max_element(struct gl_client_array *array) 724a49301eSmrg{ 734a49301eSmrg assert(array->Enabled); 744a49301eSmrg if (array->BufferObj->Name) { 754a49301eSmrg GLsizeiptrARB offset = (GLsizeiptrARB) array->Ptr; 764a49301eSmrg GLsizeiptrARB obj_size = (GLsizeiptrARB) array->BufferObj->Size; 774a49301eSmrg 784a49301eSmrg if (offset < obj_size) { 794a49301eSmrg array->_MaxElement = (obj_size - offset + 804a49301eSmrg array->StrideB - 814a49301eSmrg array->_ElementSize) / array->StrideB; 824a49301eSmrg } else { 834a49301eSmrg array->_MaxElement = 0; 844a49301eSmrg } 854a49301eSmrg } 864a49301eSmrg else { 874a49301eSmrg /* user-space array, no idea how big it is */ 884a49301eSmrg array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */ 894a49301eSmrg } 904a49301eSmrg} 914a49301eSmrg 924a49301eSmrg 934a49301eSmrg/** 944a49301eSmrg * Helper for update_arrays(). 954a49301eSmrg * \return min(current min, array->_MaxElement). 964a49301eSmrg */ 974a49301eSmrgstatic GLuint 984a49301eSmrgupdate_min(GLuint min, struct gl_client_array *array) 994a49301eSmrg{ 1004a49301eSmrg compute_max_element(array); 1014a49301eSmrg return MIN2(min, array->_MaxElement); 1024a49301eSmrg} 1034a49301eSmrg 1044a49301eSmrg 1054a49301eSmrg/** 1064a49301eSmrg * Update ctx->Array._MaxElement (the max legal index into all enabled arrays). 1074a49301eSmrg * Need to do this upon new array state or new buffer object state. 1087117f1b4Smrg */ 1097117f1b4Smrgstatic void 1107117f1b4Smrgupdate_arrays( GLcontext *ctx ) 1117117f1b4Smrg{ 1124a49301eSmrg struct gl_array_object *arrayObj = ctx->Array.ArrayObj; 1134a49301eSmrg GLuint i, min = ~0; 1147117f1b4Smrg 1157117f1b4Smrg /* find min of _MaxElement values for all enabled arrays */ 1167117f1b4Smrg 1177117f1b4Smrg /* 0 */ 1187117f1b4Smrg if (ctx->VertexProgram._Current 1194a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) { 1204a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]); 1217117f1b4Smrg } 1224a49301eSmrg else if (arrayObj->Vertex.Enabled) { 1234a49301eSmrg min = update_min(min, &arrayObj->Vertex); 1247117f1b4Smrg } 1257117f1b4Smrg 1267117f1b4Smrg /* 1 */ 1277117f1b4Smrg if (ctx->VertexProgram._Enabled 1284a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) { 1294a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]); 1307117f1b4Smrg } 1317117f1b4Smrg /* no conventional vertex weight array */ 1327117f1b4Smrg 1337117f1b4Smrg /* 2 */ 1347117f1b4Smrg if (ctx->VertexProgram._Enabled 1354a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { 1364a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]); 1377117f1b4Smrg } 1384a49301eSmrg else if (arrayObj->Normal.Enabled) { 1394a49301eSmrg min = update_min(min, &arrayObj->Normal); 1407117f1b4Smrg } 1417117f1b4Smrg 1427117f1b4Smrg /* 3 */ 1437117f1b4Smrg if (ctx->VertexProgram._Enabled 1444a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { 1454a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]); 1467117f1b4Smrg } 1474a49301eSmrg else if (arrayObj->Color.Enabled) { 1484a49301eSmrg min = update_min(min, &arrayObj->Color); 1497117f1b4Smrg } 1507117f1b4Smrg 1517117f1b4Smrg /* 4 */ 1527117f1b4Smrg if (ctx->VertexProgram._Enabled 1534a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { 1544a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]); 1557117f1b4Smrg } 1564a49301eSmrg else if (arrayObj->SecondaryColor.Enabled) { 1574a49301eSmrg min = update_min(min, &arrayObj->SecondaryColor); 1587117f1b4Smrg } 1597117f1b4Smrg 1607117f1b4Smrg /* 5 */ 1617117f1b4Smrg if (ctx->VertexProgram._Enabled 1624a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { 1634a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]); 1647117f1b4Smrg } 1654a49301eSmrg else if (arrayObj->FogCoord.Enabled) { 1664a49301eSmrg min = update_min(min, &arrayObj->FogCoord); 1677117f1b4Smrg } 1687117f1b4Smrg 1697117f1b4Smrg /* 6 */ 1707117f1b4Smrg if (ctx->VertexProgram._Enabled 1714a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { 1724a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]); 1737117f1b4Smrg } 1744a49301eSmrg else if (arrayObj->Index.Enabled) { 1754a49301eSmrg min = update_min(min, &arrayObj->Index); 1767117f1b4Smrg } 1777117f1b4Smrg 1787117f1b4Smrg /* 7 */ 1797117f1b4Smrg if (ctx->VertexProgram._Enabled 1804a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { 1814a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]); 1827117f1b4Smrg } 1837117f1b4Smrg 1847117f1b4Smrg /* 8..15 */ 1857117f1b4Smrg for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) { 1867117f1b4Smrg if (ctx->VertexProgram._Enabled 1874a49301eSmrg && arrayObj->VertexAttrib[i].Enabled) { 1884a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[i]); 1897117f1b4Smrg } 1907117f1b4Smrg else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits 1914a49301eSmrg && arrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) { 1924a49301eSmrg min = update_min(min, &arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]); 1937117f1b4Smrg } 1947117f1b4Smrg } 1957117f1b4Smrg 1967117f1b4Smrg /* 16..31 */ 1977117f1b4Smrg if (ctx->VertexProgram._Current) { 1984a49301eSmrg for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) { 1994a49301eSmrg if (arrayObj->VertexAttrib[i].Enabled) { 2004a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[i]); 2017117f1b4Smrg } 2027117f1b4Smrg } 2037117f1b4Smrg } 2047117f1b4Smrg 2054a49301eSmrg if (arrayObj->EdgeFlag.Enabled) { 2064a49301eSmrg min = update_min(min, &arrayObj->EdgeFlag); 2077117f1b4Smrg } 2087117f1b4Smrg 2097117f1b4Smrg /* _MaxElement is one past the last legal array element */ 2104a49301eSmrg arrayObj->_MaxElement = min; 2117117f1b4Smrg} 2127117f1b4Smrg 2137117f1b4Smrg 2147117f1b4Smrg/** 215c1f859d4Smrg * Update the following fields: 216c1f859d4Smrg * ctx->VertexProgram._Enabled 217c1f859d4Smrg * ctx->FragmentProgram._Enabled 218c1f859d4Smrg * ctx->ATIFragmentShader._Enabled 219c1f859d4Smrg * This needs to be done before texture state validation. 2207117f1b4Smrg */ 2217117f1b4Smrgstatic void 222c1f859d4Smrgupdate_program_enables(GLcontext *ctx) 2237117f1b4Smrg{ 2247117f1b4Smrg /* These _Enabled flags indicate if the program is enabled AND valid. */ 2257117f1b4Smrg ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled 2267117f1b4Smrg && ctx->VertexProgram.Current->Base.Instructions; 2277117f1b4Smrg ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled 2287117f1b4Smrg && ctx->FragmentProgram.Current->Base.Instructions; 2297117f1b4Smrg ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled 2307117f1b4Smrg && ctx->ATIFragmentShader.Current->Instructions[0]; 231c1f859d4Smrg} 232c1f859d4Smrg 233c1f859d4Smrg 234c1f859d4Smrg/** 235c1f859d4Smrg * Update vertex/fragment program state. In particular, update these fields: 236c1f859d4Smrg * ctx->VertexProgram._Current 237c1f859d4Smrg * ctx->VertexProgram._TnlProgram, 238c1f859d4Smrg * These point to the highest priority enabled vertex/fragment program or are 239c1f859d4Smrg * NULL if fixed-function processing is to be done. 240c1f859d4Smrg * 241c1f859d4Smrg * This function needs to be called after texture state validation in case 242c1f859d4Smrg * we're generating a fragment program from fixed-function texture state. 243c1f859d4Smrg * 244c1f859d4Smrg * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex 245c1f859d4Smrg * or fragment program is being used. 246c1f859d4Smrg */ 247c1f859d4Smrgstatic GLbitfield 248c1f859d4Smrgupdate_program(GLcontext *ctx) 249c1f859d4Smrg{ 250c1f859d4Smrg const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; 251c1f859d4Smrg const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; 252c1f859d4Smrg const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; 253c1f859d4Smrg GLbitfield new_state = 0x0; 2547117f1b4Smrg 2557117f1b4Smrg /* 2567117f1b4Smrg * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current 257c1f859d4Smrg * pointers to the programs that should be used for rendering. If either 258c1f859d4Smrg * is NULL, use fixed-function code paths. 2597117f1b4Smrg * 2607117f1b4Smrg * These programs may come from several sources. The priority is as 2617117f1b4Smrg * follows: 2627117f1b4Smrg * 1. OpenGL 2.0/ARB vertex/fragment shaders 2637117f1b4Smrg * 2. ARB/NV vertex/fragment programs 2647117f1b4Smrg * 3. Programs derived from fixed-function state. 265c1f859d4Smrg * 266c1f859d4Smrg * Note: it's possible for a vertex shader to get used with a fragment 267c1f859d4Smrg * program (and vice versa) here, but in practice that shouldn't ever 268c1f859d4Smrg * come up, or matter. 2697117f1b4Smrg */ 2707117f1b4Smrg 271c1f859d4Smrg if (shProg && shProg->LinkStatus && shProg->FragmentProgram) { 272c1f859d4Smrg /* Use shader programs */ 273c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 274c1f859d4Smrg shProg->FragmentProgram); 275c1f859d4Smrg } 276c1f859d4Smrg else if (ctx->FragmentProgram._Enabled) { 277c1f859d4Smrg /* use user-defined vertex program */ 278c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 279c1f859d4Smrg ctx->FragmentProgram.Current); 280c1f859d4Smrg } 281c1f859d4Smrg else if (ctx->FragmentProgram._MaintainTexEnvProgram) { 282c1f859d4Smrg /* Use fragment program generated from fixed-function state. 283c1f859d4Smrg */ 284c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 285c1f859d4Smrg _mesa_get_fixed_func_fragment_program(ctx)); 286c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, 287c1f859d4Smrg ctx->FragmentProgram._Current); 288c1f859d4Smrg } 289c1f859d4Smrg else { 290c1f859d4Smrg /* no fragment program */ 291c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); 292c1f859d4Smrg } 2937117f1b4Smrg 294c1f859d4Smrg /* Examine vertex program after fragment program as 295c1f859d4Smrg * _mesa_get_fixed_func_vertex_program() needs to know active 296c1f859d4Smrg * fragprog inputs. 297c1f859d4Smrg */ 298c1f859d4Smrg if (shProg && shProg->LinkStatus && shProg->VertexProgram) { 2997117f1b4Smrg /* Use shader programs */ 300c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 301c1f859d4Smrg shProg->VertexProgram); 302c1f859d4Smrg } 303c1f859d4Smrg else if (ctx->VertexProgram._Enabled) { 304c1f859d4Smrg /* use user-defined vertex program */ 305c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 306c1f859d4Smrg ctx->VertexProgram.Current); 307c1f859d4Smrg } 308c1f859d4Smrg else if (ctx->VertexProgram._MaintainTnlProgram) { 309c1f859d4Smrg /* Use vertex program generated from fixed-function state. 3107117f1b4Smrg */ 311c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 312c1f859d4Smrg _mesa_get_fixed_func_vertex_program(ctx)); 313c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, 314c1f859d4Smrg ctx->VertexProgram._Current); 3157117f1b4Smrg } 3167117f1b4Smrg else { 317c1f859d4Smrg /* no vertex program */ 318c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); 319c1f859d4Smrg } 3207117f1b4Smrg 321c1f859d4Smrg /* Let the driver know what's happening: 322c1f859d4Smrg */ 323c1f859d4Smrg if (ctx->FragmentProgram._Current != prevFP) { 324c1f859d4Smrg new_state |= _NEW_PROGRAM; 325c1f859d4Smrg if (ctx->Driver.BindProgram) { 326c1f859d4Smrg ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 327c1f859d4Smrg (struct gl_program *) ctx->FragmentProgram._Current); 3287117f1b4Smrg } 329c1f859d4Smrg } 330c1f859d4Smrg 331c1f859d4Smrg if (ctx->VertexProgram._Current != prevVP) { 332c1f859d4Smrg new_state |= _NEW_PROGRAM; 333c1f859d4Smrg if (ctx->Driver.BindProgram) { 334c1f859d4Smrg ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, 335c1f859d4Smrg (struct gl_program *) ctx->VertexProgram._Current); 3367117f1b4Smrg } 3377117f1b4Smrg } 3387117f1b4Smrg 339c1f859d4Smrg return new_state; 3407117f1b4Smrg} 3417117f1b4Smrg 3427117f1b4Smrg 3434a49301eSmrg/** 3444a49301eSmrg * Examine shader constants and return either _NEW_PROGRAM_CONSTANTS or 0. 3454a49301eSmrg */ 3464a49301eSmrgstatic GLbitfield 3474a49301eSmrgupdate_program_constants(GLcontext *ctx) 3484a49301eSmrg{ 3494a49301eSmrg GLbitfield new_state = 0x0; 3504a49301eSmrg 3514a49301eSmrg if (ctx->FragmentProgram._Current) { 3524a49301eSmrg const struct gl_program_parameter_list *params = 3534a49301eSmrg ctx->FragmentProgram._Current->Base.Parameters; 3544a49301eSmrg if (params && params->StateFlags & ctx->NewState) { 3554a49301eSmrg new_state |= _NEW_PROGRAM_CONSTANTS; 3564a49301eSmrg } 3574a49301eSmrg } 3584a49301eSmrg 3594a49301eSmrg if (ctx->VertexProgram._Current) { 3604a49301eSmrg const struct gl_program_parameter_list *params = 3614a49301eSmrg ctx->VertexProgram._Current->Base.Parameters; 3624a49301eSmrg if (params && params->StateFlags & ctx->NewState) { 3634a49301eSmrg new_state |= _NEW_PROGRAM_CONSTANTS; 3644a49301eSmrg } 3654a49301eSmrg } 3664a49301eSmrg 3674a49301eSmrg return new_state; 3684a49301eSmrg} 3694a49301eSmrg 3704a49301eSmrg 3714a49301eSmrg 3724a49301eSmrg 3737117f1b4Smrgstatic void 3747117f1b4Smrgupdate_viewport_matrix(GLcontext *ctx) 3757117f1b4Smrg{ 3767117f1b4Smrg const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; 3777117f1b4Smrg 3787117f1b4Smrg ASSERT(depthMax > 0); 3797117f1b4Smrg 3807117f1b4Smrg /* Compute scale and bias values. This is really driver-specific 3817117f1b4Smrg * and should be maintained elsewhere if at all. 3827117f1b4Smrg * NOTE: RasterPos uses this. 3837117f1b4Smrg */ 3847117f1b4Smrg _math_matrix_viewport(&ctx->Viewport._WindowMap, 3857117f1b4Smrg ctx->Viewport.X, ctx->Viewport.Y, 3867117f1b4Smrg ctx->Viewport.Width, ctx->Viewport.Height, 3877117f1b4Smrg ctx->Viewport.Near, ctx->Viewport.Far, 3887117f1b4Smrg depthMax); 3897117f1b4Smrg} 3907117f1b4Smrg 3917117f1b4Smrg 392c1f859d4Smrg/** 393c1f859d4Smrg * Update derived multisample state. 394c1f859d4Smrg */ 395c1f859d4Smrgstatic void 396c1f859d4Smrgupdate_multisample(GLcontext *ctx) 397c1f859d4Smrg{ 398c1f859d4Smrg ctx->Multisample._Enabled = GL_FALSE; 399c1f859d4Smrg if (ctx->Multisample.Enabled && 400c1f859d4Smrg ctx->DrawBuffer && 401c1f859d4Smrg ctx->DrawBuffer->Visual.sampleBuffers) 402c1f859d4Smrg ctx->Multisample._Enabled = GL_TRUE; 403c1f859d4Smrg} 404c1f859d4Smrg 405c1f859d4Smrg 4067117f1b4Smrg/** 4077117f1b4Smrg * Update derived color/blend/logicop state. 4087117f1b4Smrg */ 4097117f1b4Smrgstatic void 4107117f1b4Smrgupdate_color(GLcontext *ctx) 4117117f1b4Smrg{ 4127117f1b4Smrg /* This is needed to support 1.1's RGB logic ops AND 4137117f1b4Smrg * 1.0's blending logicops. 4147117f1b4Smrg */ 4157117f1b4Smrg ctx->Color._LogicOpEnabled = RGBA_LOGICOP_ENABLED(ctx); 4167117f1b4Smrg} 4177117f1b4Smrg 4187117f1b4Smrg 4197117f1b4Smrg/* 4207117f1b4Smrg * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET 4217117f1b4Smrg * in ctx->_TriangleCaps if needed. 4227117f1b4Smrg */ 4237117f1b4Smrgstatic void 424c1f859d4Smrgupdate_polygon(GLcontext *ctx) 4257117f1b4Smrg{ 4267117f1b4Smrg ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET); 4277117f1b4Smrg 4287117f1b4Smrg if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 4297117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; 4307117f1b4Smrg 431c1f859d4Smrg if ( ctx->Polygon.OffsetPoint 432c1f859d4Smrg || ctx->Polygon.OffsetLine 433c1f859d4Smrg || ctx->Polygon.OffsetFill) 4347117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_OFFSET; 4357117f1b4Smrg} 4367117f1b4Smrg 4377117f1b4Smrg 4387117f1b4Smrg/** 4397117f1b4Smrg * Update the ctx->_TriangleCaps bitfield. 4407117f1b4Smrg * XXX that bitfield should really go away someday! 4417117f1b4Smrg * This function must be called after other update_*() functions since 4427117f1b4Smrg * there are dependencies on some other derived values. 4437117f1b4Smrg */ 4447117f1b4Smrg#if 0 4457117f1b4Smrgstatic void 4467117f1b4Smrgupdate_tricaps(GLcontext *ctx, GLbitfield new_state) 4477117f1b4Smrg{ 4487117f1b4Smrg ctx->_TriangleCaps = 0; 4497117f1b4Smrg 4507117f1b4Smrg /* 4517117f1b4Smrg * Points 4527117f1b4Smrg */ 4537117f1b4Smrg if (1/*new_state & _NEW_POINT*/) { 4547117f1b4Smrg if (ctx->Point.SmoothFlag) 4557117f1b4Smrg ctx->_TriangleCaps |= DD_POINT_SMOOTH; 456c1f859d4Smrg if (ctx->Point.Size != 1.0F) 4577117f1b4Smrg ctx->_TriangleCaps |= DD_POINT_SIZE; 4587117f1b4Smrg if (ctx->Point._Attenuated) 4597117f1b4Smrg ctx->_TriangleCaps |= DD_POINT_ATTEN; 4607117f1b4Smrg } 4617117f1b4Smrg 4627117f1b4Smrg /* 4637117f1b4Smrg * Lines 4647117f1b4Smrg */ 4657117f1b4Smrg if (1/*new_state & _NEW_LINE*/) { 4667117f1b4Smrg if (ctx->Line.SmoothFlag) 4677117f1b4Smrg ctx->_TriangleCaps |= DD_LINE_SMOOTH; 4687117f1b4Smrg if (ctx->Line.StippleFlag) 4697117f1b4Smrg ctx->_TriangleCaps |= DD_LINE_STIPPLE; 470c1f859d4Smrg if (ctx->Line.Width != 1.0) 4717117f1b4Smrg ctx->_TriangleCaps |= DD_LINE_WIDTH; 4727117f1b4Smrg } 4737117f1b4Smrg 4747117f1b4Smrg /* 4757117f1b4Smrg * Polygons 4767117f1b4Smrg */ 4777117f1b4Smrg if (1/*new_state & _NEW_POLYGON*/) { 4787117f1b4Smrg if (ctx->Polygon.SmoothFlag) 4797117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_SMOOTH; 4807117f1b4Smrg if (ctx->Polygon.StippleFlag) 4817117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_STIPPLE; 4827117f1b4Smrg if (ctx->Polygon.FrontMode != GL_FILL 4837117f1b4Smrg || ctx->Polygon.BackMode != GL_FILL) 4847117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_UNFILLED; 4857117f1b4Smrg if (ctx->Polygon.CullFlag 4867117f1b4Smrg && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 4877117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; 4887117f1b4Smrg if (ctx->Polygon.OffsetPoint || 4897117f1b4Smrg ctx->Polygon.OffsetLine || 4907117f1b4Smrg ctx->Polygon.OffsetFill) 4917117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_OFFSET; 4927117f1b4Smrg } 4937117f1b4Smrg 4947117f1b4Smrg /* 4957117f1b4Smrg * Lighting and shading 4967117f1b4Smrg */ 4977117f1b4Smrg if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) 4987117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; 4997117f1b4Smrg if (ctx->Light.ShadeModel == GL_FLAT) 5007117f1b4Smrg ctx->_TriangleCaps |= DD_FLATSHADE; 5017117f1b4Smrg if (NEED_SECONDARY_COLOR(ctx)) 5027117f1b4Smrg ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; 5037117f1b4Smrg 5047117f1b4Smrg /* 5057117f1b4Smrg * Stencil 5067117f1b4Smrg */ 5077117f1b4Smrg if (ctx->Stencil._TestTwoSide) 5087117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL; 5097117f1b4Smrg} 5107117f1b4Smrg#endif 5117117f1b4Smrg 5127117f1b4Smrg 5137117f1b4Smrg/** 5147117f1b4Smrg * Compute derived GL state. 5157117f1b4Smrg * If __GLcontextRec::NewState is non-zero then this function \b must 5167117f1b4Smrg * be called before rendering anything. 5177117f1b4Smrg * 5187117f1b4Smrg * Calls dd_function_table::UpdateState to perform any internal state 5197117f1b4Smrg * management necessary. 5207117f1b4Smrg * 5217117f1b4Smrg * \sa _mesa_update_modelview_project(), _mesa_update_texture(), 5227117f1b4Smrg * _mesa_update_buffer_bounds(), 5237117f1b4Smrg * _mesa_update_lighting() and _mesa_update_tnl_spaces(). 5247117f1b4Smrg */ 5257117f1b4Smrgvoid 5267117f1b4Smrg_mesa_update_state_locked( GLcontext *ctx ) 5277117f1b4Smrg{ 5287117f1b4Smrg GLbitfield new_state = ctx->NewState; 529c1f859d4Smrg GLbitfield prog_flags = _NEW_PROGRAM; 530c1f859d4Smrg GLbitfield new_prog_state = 0x0; 5317117f1b4Smrg 5324a49301eSmrg if (new_state == _NEW_CURRENT_ATTRIB) 5334a49301eSmrg goto out; 5344a49301eSmrg 5357117f1b4Smrg if (MESA_VERBOSE & VERBOSE_STATE) 5367117f1b4Smrg _mesa_print_state("_mesa_update_state", new_state); 5377117f1b4Smrg 538c1f859d4Smrg /* Determine which state flags effect vertex/fragment program state */ 539c1f859d4Smrg if (ctx->FragmentProgram._MaintainTexEnvProgram) { 5404a49301eSmrg prog_flags |= (_NEW_TEXTURE | _NEW_FOG | 5414a49301eSmrg _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE | 5424a49301eSmrg _NEW_PROGRAM); 543c1f859d4Smrg } 544c1f859d4Smrg if (ctx->VertexProgram._MaintainTnlProgram) { 545c1f859d4Smrg prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | 546c1f859d4Smrg _NEW_TRANSFORM | _NEW_POINT | 547c1f859d4Smrg _NEW_FOG | _NEW_LIGHT | 548c1f859d4Smrg _MESA_NEW_NEED_EYE_COORDS); 549c1f859d4Smrg } 550c1f859d4Smrg 551c1f859d4Smrg /* 552c1f859d4Smrg * Now update derived state info 553c1f859d4Smrg */ 554c1f859d4Smrg 555c1f859d4Smrg if (new_state & prog_flags) 556c1f859d4Smrg update_program_enables( ctx ); 5577117f1b4Smrg 5587117f1b4Smrg if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 5597117f1b4Smrg _mesa_update_modelview_project( ctx, new_state ); 5607117f1b4Smrg 5617117f1b4Smrg if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) 5627117f1b4Smrg _mesa_update_texture( ctx, new_state ); 5637117f1b4Smrg 5644a49301eSmrg if (new_state & _NEW_BUFFERS) 5657117f1b4Smrg _mesa_update_framebuffer(ctx); 5667117f1b4Smrg 5677117f1b4Smrg if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) 5687117f1b4Smrg _mesa_update_draw_buffer_bounds( ctx ); 5697117f1b4Smrg 5707117f1b4Smrg if (new_state & _NEW_POLYGON) 5717117f1b4Smrg update_polygon( ctx ); 5727117f1b4Smrg 5737117f1b4Smrg if (new_state & _NEW_LIGHT) 5747117f1b4Smrg _mesa_update_lighting( ctx ); 5757117f1b4Smrg 5764a49301eSmrg if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) 5777117f1b4Smrg _mesa_update_stencil( ctx ); 5787117f1b4Smrg 5794a49301eSmrg if (new_state & _MESA_NEW_TRANSFER_STATE) 5807117f1b4Smrg _mesa_update_pixel( ctx, new_state ); 5817117f1b4Smrg 5827117f1b4Smrg if (new_state & _DD_NEW_SEPARATE_SPECULAR) 5837117f1b4Smrg update_separate_specular( ctx ); 5847117f1b4Smrg 5854a49301eSmrg if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) 5867117f1b4Smrg update_arrays( ctx ); 5877117f1b4Smrg 5887117f1b4Smrg if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) 5897117f1b4Smrg update_viewport_matrix(ctx); 5907117f1b4Smrg 591c1f859d4Smrg if (new_state & _NEW_MULTISAMPLE) 592c1f859d4Smrg update_multisample( ctx ); 593c1f859d4Smrg 5947117f1b4Smrg if (new_state & _NEW_COLOR) 5957117f1b4Smrg update_color( ctx ); 5967117f1b4Smrg 5977117f1b4Smrg#if 0 5987117f1b4Smrg if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT 5997117f1b4Smrg | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR)) 6007117f1b4Smrg update_tricaps( ctx, new_state ); 6017117f1b4Smrg#endif 6027117f1b4Smrg 6037117f1b4Smrg /* ctx->_NeedEyeCoords is now up to date. 6047117f1b4Smrg * 6057117f1b4Smrg * If the truth value of this variable has changed, update for the 6067117f1b4Smrg * new lighting space and recompute the positions of lights and the 6077117f1b4Smrg * normal transform. 6087117f1b4Smrg * 6097117f1b4Smrg * If the lighting space hasn't changed, may still need to recompute 6107117f1b4Smrg * light positions & normal transforms for other reasons. 6117117f1b4Smrg */ 6127117f1b4Smrg if (new_state & _MESA_NEW_NEED_EYE_COORDS) 6137117f1b4Smrg _mesa_update_tnl_spaces( ctx, new_state ); 6147117f1b4Smrg 615c1f859d4Smrg if (new_state & prog_flags) { 616c1f859d4Smrg /* When we generate programs from fixed-function vertex/fragment state 617c1f859d4Smrg * this call may generate/bind a new program. If so, we need to 618c1f859d4Smrg * propogate the _NEW_PROGRAM flag to the driver. 619c1f859d4Smrg */ 620c1f859d4Smrg new_prog_state |= update_program( ctx ); 621c1f859d4Smrg } 622c1f859d4Smrg 6234a49301eSmrg 6244a49301eSmrg out: 6254a49301eSmrg new_prog_state |= update_program_constants(ctx); 6264a49301eSmrg 6277117f1b4Smrg /* 6287117f1b4Smrg * Give the driver a chance to act upon the new_state flags. 6297117f1b4Smrg * The driver might plug in different span functions, for example. 6307117f1b4Smrg * Also, this is where the driver can invalidate the state of any 6317117f1b4Smrg * active modules (such as swrast_setup, swrast, tnl, etc). 6327117f1b4Smrg * 6337117f1b4Smrg * Set ctx->NewState to zero to avoid recursion if 6347117f1b4Smrg * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) 6357117f1b4Smrg */ 636c1f859d4Smrg new_state = ctx->NewState | new_prog_state; 6377117f1b4Smrg ctx->NewState = 0; 6387117f1b4Smrg ctx->Driver.UpdateState(ctx, new_state); 6397117f1b4Smrg ctx->Array.NewState = 0; 6407117f1b4Smrg} 6417117f1b4Smrg 6427117f1b4Smrg 6437117f1b4Smrg/* This is the usual entrypoint for state updates: 6447117f1b4Smrg */ 6457117f1b4Smrgvoid 6467117f1b4Smrg_mesa_update_state( GLcontext *ctx ) 6477117f1b4Smrg{ 6487117f1b4Smrg _mesa_lock_context_textures(ctx); 6497117f1b4Smrg _mesa_update_state_locked(ctx); 6507117f1b4Smrg _mesa_unlock_context_textures(ctx); 6517117f1b4Smrg} 6524a49301eSmrg 6534a49301eSmrg 6544a49301eSmrg 6554a49301eSmrg 6564a49301eSmrg/** 6574a49301eSmrg * Want to figure out which fragment program inputs are actually 6584a49301eSmrg * constant/current values from ctx->Current. These should be 6594a49301eSmrg * referenced as a tracked state variable rather than a fragment 6604a49301eSmrg * program input, to save the overhead of putting a constant value in 6614a49301eSmrg * every submitted vertex, transferring it to hardware, interpolating 6624a49301eSmrg * it across the triangle, etc... 6634a49301eSmrg * 6644a49301eSmrg * When there is a VP bound, just use vp->outputs. But when we're 6654a49301eSmrg * generating vp from fixed function state, basically want to 6664a49301eSmrg * calculate: 6674a49301eSmrg * 6684a49301eSmrg * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) | 6694a49301eSmrg * potential_vp_outputs ) 6704a49301eSmrg * 6714a49301eSmrg * Where potential_vp_outputs is calculated by looking at enabled 6724a49301eSmrg * texgen, etc. 6734a49301eSmrg * 6744a49301eSmrg * The generated fragment program should then only declare inputs that 6754a49301eSmrg * may vary or otherwise differ from the ctx->Current values. 6764a49301eSmrg * Otherwise, the fp should track them as state values instead. 6774a49301eSmrg */ 6784a49301eSmrgvoid 6794a49301eSmrg_mesa_set_varying_vp_inputs( GLcontext *ctx, 6804a49301eSmrg GLbitfield varying_inputs ) 6814a49301eSmrg{ 6824a49301eSmrg if (ctx->varying_vp_inputs != varying_inputs) { 6834a49301eSmrg ctx->varying_vp_inputs = varying_inputs; 6844a49301eSmrg ctx->NewState |= _NEW_ARRAY; 6854a49301eSmrg /*_mesa_printf("%s %x\n", __FUNCTION__, varying_inputs);*/ 6864a49301eSmrg } 6874a49301eSmrg} 6884a49301eSmrg 6894a49301eSmrg 6904a49301eSmrg/** 6914a49301eSmrg * Used by drivers to tell core Mesa that the driver is going to 6924a49301eSmrg * install/ use its own vertex program. In particular, this will 6934a49301eSmrg * prevent generated fragment programs from using state vars instead 6944a49301eSmrg * of ordinary varyings/inputs. 6954a49301eSmrg */ 6964a49301eSmrgvoid 6974a49301eSmrg_mesa_set_vp_override(GLcontext *ctx, GLboolean flag) 6984a49301eSmrg{ 6994a49301eSmrg if (ctx->VertexProgram._Overriden != flag) { 7004a49301eSmrg ctx->VertexProgram._Overriden = flag; 7014a49301eSmrg 7024a49301eSmrg /* Set one of the bits which will trigger fragment program 7034a49301eSmrg * regeneration: 7044a49301eSmrg */ 7054a49301eSmrg ctx->NewState |= _NEW_PROGRAM; 7064a49301eSmrg } 7074a49301eSmrg} 708