state.c revision 3464ebd5
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 * 303464ebd5Sriastradh * This file manages recalculation of derived values in struct gl_context. 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" 443464ebd5Sriastradh#include "program/program.h" 453464ebd5Sriastradh#include "program/prog_parameter.h" 467117f1b4Smrg#include "state.h" 477117f1b4Smrg#include "stencil.h" 48c1f859d4Smrg#include "texenvprogram.h" 497117f1b4Smrg#include "texobj.h" 507117f1b4Smrg#include "texstate.h" 513464ebd5Sriastradh#include "varray.h" 527117f1b4Smrg 537117f1b4Smrg 547117f1b4Smrgstatic void 553464ebd5Sriastradhupdate_separate_specular(struct gl_context *ctx) 567117f1b4Smrg{ 573464ebd5Sriastradh if (_mesa_need_secondary_color(ctx)) 587117f1b4Smrg ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; 597117f1b4Smrg else 607117f1b4Smrg ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR; 617117f1b4Smrg} 627117f1b4Smrg 637117f1b4Smrg 644a49301eSmrg/** 654a49301eSmrg * Helper for update_arrays(). 664a49301eSmrg * \return min(current min, array->_MaxElement). 674a49301eSmrg */ 684a49301eSmrgstatic GLuint 694a49301eSmrgupdate_min(GLuint min, struct gl_client_array *array) 704a49301eSmrg{ 713464ebd5Sriastradh _mesa_update_array_max_element(array); 724a49301eSmrg return MIN2(min, array->_MaxElement); 734a49301eSmrg} 744a49301eSmrg 754a49301eSmrg 764a49301eSmrg/** 774a49301eSmrg * Update ctx->Array._MaxElement (the max legal index into all enabled arrays). 784a49301eSmrg * Need to do this upon new array state or new buffer object state. 797117f1b4Smrg */ 807117f1b4Smrgstatic void 813464ebd5Sriastradhupdate_arrays( struct gl_context *ctx ) 827117f1b4Smrg{ 834a49301eSmrg struct gl_array_object *arrayObj = ctx->Array.ArrayObj; 844a49301eSmrg GLuint i, min = ~0; 857117f1b4Smrg 867117f1b4Smrg /* find min of _MaxElement values for all enabled arrays */ 877117f1b4Smrg 887117f1b4Smrg /* 0 */ 897117f1b4Smrg if (ctx->VertexProgram._Current 904a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) { 914a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]); 927117f1b4Smrg } 934a49301eSmrg else if (arrayObj->Vertex.Enabled) { 944a49301eSmrg min = update_min(min, &arrayObj->Vertex); 957117f1b4Smrg } 967117f1b4Smrg 977117f1b4Smrg /* 1 */ 987117f1b4Smrg if (ctx->VertexProgram._Enabled 994a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) { 1004a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]); 1017117f1b4Smrg } 1027117f1b4Smrg /* no conventional vertex weight array */ 1037117f1b4Smrg 1047117f1b4Smrg /* 2 */ 1057117f1b4Smrg if (ctx->VertexProgram._Enabled 1064a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { 1074a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]); 1087117f1b4Smrg } 1094a49301eSmrg else if (arrayObj->Normal.Enabled) { 1104a49301eSmrg min = update_min(min, &arrayObj->Normal); 1117117f1b4Smrg } 1127117f1b4Smrg 1137117f1b4Smrg /* 3 */ 1147117f1b4Smrg if (ctx->VertexProgram._Enabled 1154a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { 1164a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]); 1177117f1b4Smrg } 1184a49301eSmrg else if (arrayObj->Color.Enabled) { 1194a49301eSmrg min = update_min(min, &arrayObj->Color); 1207117f1b4Smrg } 1217117f1b4Smrg 1227117f1b4Smrg /* 4 */ 1237117f1b4Smrg if (ctx->VertexProgram._Enabled 1244a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { 1254a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]); 1267117f1b4Smrg } 1274a49301eSmrg else if (arrayObj->SecondaryColor.Enabled) { 1284a49301eSmrg min = update_min(min, &arrayObj->SecondaryColor); 1297117f1b4Smrg } 1307117f1b4Smrg 1317117f1b4Smrg /* 5 */ 1327117f1b4Smrg if (ctx->VertexProgram._Enabled 1334a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { 1344a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]); 1357117f1b4Smrg } 1364a49301eSmrg else if (arrayObj->FogCoord.Enabled) { 1374a49301eSmrg min = update_min(min, &arrayObj->FogCoord); 1387117f1b4Smrg } 1397117f1b4Smrg 1407117f1b4Smrg /* 6 */ 1417117f1b4Smrg if (ctx->VertexProgram._Enabled 1424a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { 1434a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]); 1447117f1b4Smrg } 1454a49301eSmrg else if (arrayObj->Index.Enabled) { 1464a49301eSmrg min = update_min(min, &arrayObj->Index); 1477117f1b4Smrg } 1487117f1b4Smrg 1497117f1b4Smrg /* 7 */ 1507117f1b4Smrg if (ctx->VertexProgram._Enabled 1514a49301eSmrg && arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { 1524a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]); 1537117f1b4Smrg } 1547117f1b4Smrg 1557117f1b4Smrg /* 8..15 */ 1567117f1b4Smrg for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) { 1577117f1b4Smrg if (ctx->VertexProgram._Enabled 1584a49301eSmrg && arrayObj->VertexAttrib[i].Enabled) { 1594a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[i]); 1607117f1b4Smrg } 1617117f1b4Smrg else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits 1624a49301eSmrg && arrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) { 1634a49301eSmrg min = update_min(min, &arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]); 1647117f1b4Smrg } 1657117f1b4Smrg } 1667117f1b4Smrg 1677117f1b4Smrg /* 16..31 */ 1687117f1b4Smrg if (ctx->VertexProgram._Current) { 1694a49301eSmrg for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) { 1704a49301eSmrg if (arrayObj->VertexAttrib[i].Enabled) { 1714a49301eSmrg min = update_min(min, &arrayObj->VertexAttrib[i]); 1727117f1b4Smrg } 1737117f1b4Smrg } 1747117f1b4Smrg } 1757117f1b4Smrg 1764a49301eSmrg if (arrayObj->EdgeFlag.Enabled) { 1774a49301eSmrg min = update_min(min, &arrayObj->EdgeFlag); 1787117f1b4Smrg } 1797117f1b4Smrg 1807117f1b4Smrg /* _MaxElement is one past the last legal array element */ 1814a49301eSmrg arrayObj->_MaxElement = min; 1827117f1b4Smrg} 1837117f1b4Smrg 1847117f1b4Smrg 1857117f1b4Smrg/** 186c1f859d4Smrg * Update the following fields: 187c1f859d4Smrg * ctx->VertexProgram._Enabled 188c1f859d4Smrg * ctx->FragmentProgram._Enabled 189c1f859d4Smrg * ctx->ATIFragmentShader._Enabled 190c1f859d4Smrg * This needs to be done before texture state validation. 1917117f1b4Smrg */ 1927117f1b4Smrgstatic void 1933464ebd5Sriastradhupdate_program_enables(struct gl_context *ctx) 1947117f1b4Smrg{ 1953464ebd5Sriastradh /* These _Enabled flags indicate if the user-defined ARB/NV vertex/fragment 1963464ebd5Sriastradh * program is enabled AND valid. Similarly for ATI fragment shaders. 1973464ebd5Sriastradh * GLSL shaders not relevant here. 1983464ebd5Sriastradh */ 1997117f1b4Smrg ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled 2007117f1b4Smrg && ctx->VertexProgram.Current->Base.Instructions; 2017117f1b4Smrg ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled 2027117f1b4Smrg && ctx->FragmentProgram.Current->Base.Instructions; 2037117f1b4Smrg ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled 2047117f1b4Smrg && ctx->ATIFragmentShader.Current->Instructions[0]; 205c1f859d4Smrg} 206c1f859d4Smrg 207c1f859d4Smrg 208c1f859d4Smrg/** 2093464ebd5Sriastradh * Update the ctx->Vertex/Geometry/FragmentProgram._Current pointers to point 2103464ebd5Sriastradh * to the current/active programs. Then call ctx->Driver.BindProgram() to 2113464ebd5Sriastradh * tell the driver which programs to use. 2123464ebd5Sriastradh * 2133464ebd5Sriastradh * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment 2143464ebd5Sriastradh * programs or programs derived from fixed-function state. 215c1f859d4Smrg * 216c1f859d4Smrg * This function needs to be called after texture state validation in case 217c1f859d4Smrg * we're generating a fragment program from fixed-function texture state. 218c1f859d4Smrg * 219c1f859d4Smrg * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex 220c1f859d4Smrg * or fragment program is being used. 221c1f859d4Smrg */ 222c1f859d4Smrgstatic GLbitfield 2233464ebd5Sriastradhupdate_program(struct gl_context *ctx) 224c1f859d4Smrg{ 2253464ebd5Sriastradh const struct gl_shader_program *vsProg = ctx->Shader.CurrentVertexProgram; 2263464ebd5Sriastradh const struct gl_shader_program *gsProg = ctx->Shader.CurrentGeometryProgram; 2273464ebd5Sriastradh const struct gl_shader_program *fsProg = ctx->Shader.CurrentFragmentProgram; 228c1f859d4Smrg const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; 229c1f859d4Smrg const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; 2303464ebd5Sriastradh const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; 231c1f859d4Smrg GLbitfield new_state = 0x0; 2327117f1b4Smrg 2337117f1b4Smrg /* 2347117f1b4Smrg * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current 235c1f859d4Smrg * pointers to the programs that should be used for rendering. If either 236c1f859d4Smrg * is NULL, use fixed-function code paths. 2377117f1b4Smrg * 2387117f1b4Smrg * These programs may come from several sources. The priority is as 2397117f1b4Smrg * follows: 2407117f1b4Smrg * 1. OpenGL 2.0/ARB vertex/fragment shaders 2417117f1b4Smrg * 2. ARB/NV vertex/fragment programs 2427117f1b4Smrg * 3. Programs derived from fixed-function state. 243c1f859d4Smrg * 244c1f859d4Smrg * Note: it's possible for a vertex shader to get used with a fragment 245c1f859d4Smrg * program (and vice versa) here, but in practice that shouldn't ever 246c1f859d4Smrg * come up, or matter. 2477117f1b4Smrg */ 2487117f1b4Smrg 2493464ebd5Sriastradh if (fsProg && fsProg->LinkStatus && fsProg->FragmentProgram) { 2503464ebd5Sriastradh /* Use GLSL fragment shader */ 251c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 2523464ebd5Sriastradh fsProg->FragmentProgram); 253c1f859d4Smrg } 254c1f859d4Smrg else if (ctx->FragmentProgram._Enabled) { 2553464ebd5Sriastradh /* Use user-defined fragment program */ 256c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 257c1f859d4Smrg ctx->FragmentProgram.Current); 258c1f859d4Smrg } 259c1f859d4Smrg else if (ctx->FragmentProgram._MaintainTexEnvProgram) { 2603464ebd5Sriastradh /* Use fragment program generated from fixed-function state */ 261c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, 262c1f859d4Smrg _mesa_get_fixed_func_fragment_program(ctx)); 263c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, 264c1f859d4Smrg ctx->FragmentProgram._Current); 265c1f859d4Smrg } 266c1f859d4Smrg else { 2673464ebd5Sriastradh /* No fragment program */ 268c1f859d4Smrg _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); 269c1f859d4Smrg } 2707117f1b4Smrg 2713464ebd5Sriastradh if (gsProg && gsProg->LinkStatus && gsProg->GeometryProgram) { 2723464ebd5Sriastradh /* Use GLSL geometry shader */ 2733464ebd5Sriastradh _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, 2743464ebd5Sriastradh gsProg->GeometryProgram); 2753464ebd5Sriastradh } else { 2763464ebd5Sriastradh /* No geometry program */ 2773464ebd5Sriastradh _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); 2783464ebd5Sriastradh } 2793464ebd5Sriastradh 280c1f859d4Smrg /* Examine vertex program after fragment program as 281c1f859d4Smrg * _mesa_get_fixed_func_vertex_program() needs to know active 282c1f859d4Smrg * fragprog inputs. 283c1f859d4Smrg */ 2843464ebd5Sriastradh if (vsProg && vsProg->LinkStatus && vsProg->VertexProgram) { 2853464ebd5Sriastradh /* Use GLSL vertex shader */ 286c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 2873464ebd5Sriastradh vsProg->VertexProgram); 288c1f859d4Smrg } 289c1f859d4Smrg else if (ctx->VertexProgram._Enabled) { 2903464ebd5Sriastradh /* Use user-defined vertex program */ 291c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 292c1f859d4Smrg ctx->VertexProgram.Current); 293c1f859d4Smrg } 294c1f859d4Smrg else if (ctx->VertexProgram._MaintainTnlProgram) { 2953464ebd5Sriastradh /* Use vertex program generated from fixed-function state */ 296c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, 297c1f859d4Smrg _mesa_get_fixed_func_vertex_program(ctx)); 298c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, 299c1f859d4Smrg ctx->VertexProgram._Current); 3007117f1b4Smrg } 3017117f1b4Smrg else { 302c1f859d4Smrg /* no vertex program */ 303c1f859d4Smrg _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); 304c1f859d4Smrg } 3057117f1b4Smrg 306c1f859d4Smrg /* Let the driver know what's happening: 307c1f859d4Smrg */ 308c1f859d4Smrg if (ctx->FragmentProgram._Current != prevFP) { 309c1f859d4Smrg new_state |= _NEW_PROGRAM; 310c1f859d4Smrg if (ctx->Driver.BindProgram) { 311c1f859d4Smrg ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 312c1f859d4Smrg (struct gl_program *) ctx->FragmentProgram._Current); 3137117f1b4Smrg } 314c1f859d4Smrg } 3153464ebd5Sriastradh 3163464ebd5Sriastradh if (ctx->GeometryProgram._Current != prevGP) { 3173464ebd5Sriastradh new_state |= _NEW_PROGRAM; 3183464ebd5Sriastradh if (ctx->Driver.BindProgram) { 3193464ebd5Sriastradh ctx->Driver.BindProgram(ctx, MESA_GEOMETRY_PROGRAM, 3203464ebd5Sriastradh (struct gl_program *) ctx->GeometryProgram._Current); 3213464ebd5Sriastradh } 3223464ebd5Sriastradh } 3233464ebd5Sriastradh 324c1f859d4Smrg if (ctx->VertexProgram._Current != prevVP) { 325c1f859d4Smrg new_state |= _NEW_PROGRAM; 326c1f859d4Smrg if (ctx->Driver.BindProgram) { 327c1f859d4Smrg ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, 328c1f859d4Smrg (struct gl_program *) ctx->VertexProgram._Current); 3297117f1b4Smrg } 3307117f1b4Smrg } 3317117f1b4Smrg 332c1f859d4Smrg return new_state; 3337117f1b4Smrg} 3347117f1b4Smrg 3357117f1b4Smrg 3364a49301eSmrg/** 3374a49301eSmrg * Examine shader constants and return either _NEW_PROGRAM_CONSTANTS or 0. 3384a49301eSmrg */ 3394a49301eSmrgstatic GLbitfield 3403464ebd5Sriastradhupdate_program_constants(struct gl_context *ctx) 3414a49301eSmrg{ 3424a49301eSmrg GLbitfield new_state = 0x0; 3434a49301eSmrg 3444a49301eSmrg if (ctx->FragmentProgram._Current) { 3454a49301eSmrg const struct gl_program_parameter_list *params = 3464a49301eSmrg ctx->FragmentProgram._Current->Base.Parameters; 3474a49301eSmrg if (params && params->StateFlags & ctx->NewState) { 3484a49301eSmrg new_state |= _NEW_PROGRAM_CONSTANTS; 3494a49301eSmrg } 3504a49301eSmrg } 3514a49301eSmrg 3523464ebd5Sriastradh if (ctx->GeometryProgram._Current) { 3533464ebd5Sriastradh const struct gl_program_parameter_list *params = 3543464ebd5Sriastradh ctx->GeometryProgram._Current->Base.Parameters; 3553464ebd5Sriastradh /*FIXME: StateFlags is always 0 because we have unnamed constant 3563464ebd5Sriastradh * not state changes */ 3573464ebd5Sriastradh if (params /*&& params->StateFlags & ctx->NewState*/) { 3583464ebd5Sriastradh new_state |= _NEW_PROGRAM_CONSTANTS; 3593464ebd5Sriastradh } 3603464ebd5Sriastradh } 3613464ebd5Sriastradh 3624a49301eSmrg if (ctx->VertexProgram._Current) { 3634a49301eSmrg const struct gl_program_parameter_list *params = 3644a49301eSmrg ctx->VertexProgram._Current->Base.Parameters; 3654a49301eSmrg if (params && params->StateFlags & ctx->NewState) { 3664a49301eSmrg new_state |= _NEW_PROGRAM_CONSTANTS; 3674a49301eSmrg } 3684a49301eSmrg } 3694a49301eSmrg 3704a49301eSmrg return new_state; 3714a49301eSmrg} 3724a49301eSmrg 3734a49301eSmrg 3744a49301eSmrg 3754a49301eSmrg 3767117f1b4Smrgstatic void 3773464ebd5Sriastradhupdate_viewport_matrix(struct gl_context *ctx) 3787117f1b4Smrg{ 3797117f1b4Smrg const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; 3807117f1b4Smrg 3817117f1b4Smrg ASSERT(depthMax > 0); 3827117f1b4Smrg 3837117f1b4Smrg /* Compute scale and bias values. This is really driver-specific 3847117f1b4Smrg * and should be maintained elsewhere if at all. 3857117f1b4Smrg * NOTE: RasterPos uses this. 3867117f1b4Smrg */ 3877117f1b4Smrg _math_matrix_viewport(&ctx->Viewport._WindowMap, 3887117f1b4Smrg ctx->Viewport.X, ctx->Viewport.Y, 3897117f1b4Smrg ctx->Viewport.Width, ctx->Viewport.Height, 3907117f1b4Smrg ctx->Viewport.Near, ctx->Viewport.Far, 3917117f1b4Smrg depthMax); 3927117f1b4Smrg} 3937117f1b4Smrg 3947117f1b4Smrg 395c1f859d4Smrg/** 396c1f859d4Smrg * Update derived multisample state. 397c1f859d4Smrg */ 398c1f859d4Smrgstatic void 3993464ebd5Sriastradhupdate_multisample(struct gl_context *ctx) 400c1f859d4Smrg{ 401c1f859d4Smrg ctx->Multisample._Enabled = GL_FALSE; 402c1f859d4Smrg if (ctx->Multisample.Enabled && 403c1f859d4Smrg ctx->DrawBuffer && 404c1f859d4Smrg ctx->DrawBuffer->Visual.sampleBuffers) 405c1f859d4Smrg ctx->Multisample._Enabled = GL_TRUE; 406c1f859d4Smrg} 407c1f859d4Smrg 408c1f859d4Smrg 4097117f1b4Smrg/** 4107117f1b4Smrg * Update derived color/blend/logicop state. 4117117f1b4Smrg */ 4127117f1b4Smrgstatic void 4133464ebd5Sriastradhupdate_color(struct gl_context *ctx) 4147117f1b4Smrg{ 4157117f1b4Smrg /* This is needed to support 1.1's RGB logic ops AND 4167117f1b4Smrg * 1.0's blending logicops. 4177117f1b4Smrg */ 4183464ebd5Sriastradh ctx->Color._LogicOpEnabled = _mesa_rgba_logicop_enabled(ctx); 4197117f1b4Smrg} 4207117f1b4Smrg 4217117f1b4Smrg 4223464ebd5Sriastradh/** 4233464ebd5Sriastradh * Update the ctx->Color._ClampFragmentColor field 4243464ebd5Sriastradh */ 4253464ebd5Sriastradhstatic void 4263464ebd5Sriastradhupdate_clamp_fragment_color(struct gl_context *ctx) 4273464ebd5Sriastradh{ 4283464ebd5Sriastradh if (ctx->Color.ClampFragmentColor == GL_FIXED_ONLY_ARB) 4293464ebd5Sriastradh ctx->Color._ClampFragmentColor = 4303464ebd5Sriastradh !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; 4313464ebd5Sriastradh else 4323464ebd5Sriastradh ctx->Color._ClampFragmentColor = ctx->Color.ClampFragmentColor; 4333464ebd5Sriastradh} 4343464ebd5Sriastradh 4353464ebd5Sriastradh 4363464ebd5Sriastradh/** 4373464ebd5Sriastradh * Update the ctx->Color._ClampVertexColor field 4383464ebd5Sriastradh */ 4393464ebd5Sriastradhstatic void 4403464ebd5Sriastradhupdate_clamp_vertex_color(struct gl_context *ctx) 4413464ebd5Sriastradh{ 4423464ebd5Sriastradh if (ctx->Light.ClampVertexColor == GL_FIXED_ONLY_ARB) 4433464ebd5Sriastradh ctx->Light._ClampVertexColor = 4443464ebd5Sriastradh !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; 4453464ebd5Sriastradh else 4463464ebd5Sriastradh ctx->Light._ClampVertexColor = ctx->Light.ClampVertexColor; 4473464ebd5Sriastradh} 4483464ebd5Sriastradh 4493464ebd5Sriastradh 4503464ebd5Sriastradh/** 4513464ebd5Sriastradh * Update the ctx->Color._ClampReadColor field 4523464ebd5Sriastradh */ 4533464ebd5Sriastradhstatic void 4543464ebd5Sriastradhupdate_clamp_read_color(struct gl_context *ctx) 4553464ebd5Sriastradh{ 4563464ebd5Sriastradh if (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB) 4573464ebd5Sriastradh ctx->Color._ClampReadColor = 4583464ebd5Sriastradh !ctx->ReadBuffer || !ctx->ReadBuffer->Visual.floatMode; 4593464ebd5Sriastradh else 4603464ebd5Sriastradh ctx->Color._ClampReadColor = ctx->Color.ClampReadColor; 4613464ebd5Sriastradh} 4623464ebd5Sriastradh 4633464ebd5Sriastradh 4643464ebd5Sriastradh 4653464ebd5Sriastradh 4667117f1b4Smrg/* 4677117f1b4Smrg * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET 4687117f1b4Smrg * in ctx->_TriangleCaps if needed. 4697117f1b4Smrg */ 4707117f1b4Smrgstatic void 4713464ebd5Sriastradhupdate_polygon(struct gl_context *ctx) 4727117f1b4Smrg{ 4737117f1b4Smrg ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET); 4747117f1b4Smrg 4757117f1b4Smrg if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 4767117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; 4777117f1b4Smrg 478c1f859d4Smrg if ( ctx->Polygon.OffsetPoint 479c1f859d4Smrg || ctx->Polygon.OffsetLine 480c1f859d4Smrg || ctx->Polygon.OffsetFill) 4817117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_OFFSET; 4827117f1b4Smrg} 4837117f1b4Smrg 4847117f1b4Smrg 4857117f1b4Smrg/** 4867117f1b4Smrg * Update the ctx->_TriangleCaps bitfield. 4877117f1b4Smrg * XXX that bitfield should really go away someday! 4887117f1b4Smrg * This function must be called after other update_*() functions since 4897117f1b4Smrg * there are dependencies on some other derived values. 4907117f1b4Smrg */ 4917117f1b4Smrg#if 0 4927117f1b4Smrgstatic void 4933464ebd5Sriastradhupdate_tricaps(struct gl_context *ctx, GLbitfield new_state) 4947117f1b4Smrg{ 4957117f1b4Smrg ctx->_TriangleCaps = 0; 4967117f1b4Smrg 4977117f1b4Smrg /* 4987117f1b4Smrg * Points 4997117f1b4Smrg */ 5007117f1b4Smrg if (1/*new_state & _NEW_POINT*/) { 5017117f1b4Smrg if (ctx->Point.SmoothFlag) 5027117f1b4Smrg ctx->_TriangleCaps |= DD_POINT_SMOOTH; 5037117f1b4Smrg if (ctx->Point._Attenuated) 5047117f1b4Smrg ctx->_TriangleCaps |= DD_POINT_ATTEN; 5057117f1b4Smrg } 5067117f1b4Smrg 5077117f1b4Smrg /* 5087117f1b4Smrg * Lines 5097117f1b4Smrg */ 5107117f1b4Smrg if (1/*new_state & _NEW_LINE*/) { 5117117f1b4Smrg if (ctx->Line.SmoothFlag) 5127117f1b4Smrg ctx->_TriangleCaps |= DD_LINE_SMOOTH; 5137117f1b4Smrg if (ctx->Line.StippleFlag) 5147117f1b4Smrg ctx->_TriangleCaps |= DD_LINE_STIPPLE; 5157117f1b4Smrg } 5167117f1b4Smrg 5177117f1b4Smrg /* 5187117f1b4Smrg * Polygons 5197117f1b4Smrg */ 5207117f1b4Smrg if (1/*new_state & _NEW_POLYGON*/) { 5217117f1b4Smrg if (ctx->Polygon.SmoothFlag) 5227117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_SMOOTH; 5237117f1b4Smrg if (ctx->Polygon.StippleFlag) 5247117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_STIPPLE; 5257117f1b4Smrg if (ctx->Polygon.FrontMode != GL_FILL 5267117f1b4Smrg || ctx->Polygon.BackMode != GL_FILL) 5277117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_UNFILLED; 5287117f1b4Smrg if (ctx->Polygon.CullFlag 5297117f1b4Smrg && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 5307117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; 5317117f1b4Smrg if (ctx->Polygon.OffsetPoint || 5327117f1b4Smrg ctx->Polygon.OffsetLine || 5337117f1b4Smrg ctx->Polygon.OffsetFill) 5347117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_OFFSET; 5357117f1b4Smrg } 5367117f1b4Smrg 5377117f1b4Smrg /* 5387117f1b4Smrg * Lighting and shading 5397117f1b4Smrg */ 5407117f1b4Smrg if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) 5417117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; 5427117f1b4Smrg if (ctx->Light.ShadeModel == GL_FLAT) 5437117f1b4Smrg ctx->_TriangleCaps |= DD_FLATSHADE; 5443464ebd5Sriastradh if (_mesa_need_secondary_color(ctx)) 5457117f1b4Smrg ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; 5467117f1b4Smrg 5477117f1b4Smrg /* 5487117f1b4Smrg * Stencil 5497117f1b4Smrg */ 5507117f1b4Smrg if (ctx->Stencil._TestTwoSide) 5517117f1b4Smrg ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL; 5527117f1b4Smrg} 5537117f1b4Smrg#endif 5547117f1b4Smrg 5557117f1b4Smrg 5567117f1b4Smrg/** 5577117f1b4Smrg * Compute derived GL state. 5583464ebd5Sriastradh * If __struct gl_contextRec::NewState is non-zero then this function \b must 5597117f1b4Smrg * be called before rendering anything. 5607117f1b4Smrg * 5617117f1b4Smrg * Calls dd_function_table::UpdateState to perform any internal state 5627117f1b4Smrg * management necessary. 5637117f1b4Smrg * 5647117f1b4Smrg * \sa _mesa_update_modelview_project(), _mesa_update_texture(), 5657117f1b4Smrg * _mesa_update_buffer_bounds(), 5667117f1b4Smrg * _mesa_update_lighting() and _mesa_update_tnl_spaces(). 5677117f1b4Smrg */ 5687117f1b4Smrgvoid 5693464ebd5Sriastradh_mesa_update_state_locked( struct gl_context *ctx ) 5707117f1b4Smrg{ 5717117f1b4Smrg GLbitfield new_state = ctx->NewState; 572c1f859d4Smrg GLbitfield prog_flags = _NEW_PROGRAM; 573c1f859d4Smrg GLbitfield new_prog_state = 0x0; 5747117f1b4Smrg 5754a49301eSmrg if (new_state == _NEW_CURRENT_ATTRIB) 5764a49301eSmrg goto out; 5774a49301eSmrg 5787117f1b4Smrg if (MESA_VERBOSE & VERBOSE_STATE) 5797117f1b4Smrg _mesa_print_state("_mesa_update_state", new_state); 5807117f1b4Smrg 581c1f859d4Smrg /* Determine which state flags effect vertex/fragment program state */ 582c1f859d4Smrg if (ctx->FragmentProgram._MaintainTexEnvProgram) { 5833464ebd5Sriastradh prog_flags |= (_NEW_BUFFERS | _NEW_TEXTURE | _NEW_FOG | 5844a49301eSmrg _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE | 5853464ebd5Sriastradh _NEW_PROGRAM | _NEW_FRAG_CLAMP); 586c1f859d4Smrg } 587c1f859d4Smrg if (ctx->VertexProgram._MaintainTnlProgram) { 588c1f859d4Smrg prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | 589c1f859d4Smrg _NEW_TRANSFORM | _NEW_POINT | 590c1f859d4Smrg _NEW_FOG | _NEW_LIGHT | 591c1f859d4Smrg _MESA_NEW_NEED_EYE_COORDS); 592c1f859d4Smrg } 593c1f859d4Smrg 594c1f859d4Smrg /* 595c1f859d4Smrg * Now update derived state info 596c1f859d4Smrg */ 597c1f859d4Smrg 598c1f859d4Smrg if (new_state & prog_flags) 599c1f859d4Smrg update_program_enables( ctx ); 6007117f1b4Smrg 6017117f1b4Smrg if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 6027117f1b4Smrg _mesa_update_modelview_project( ctx, new_state ); 6037117f1b4Smrg 6047117f1b4Smrg if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) 6057117f1b4Smrg _mesa_update_texture( ctx, new_state ); 6067117f1b4Smrg 6074a49301eSmrg if (new_state & _NEW_BUFFERS) 6087117f1b4Smrg _mesa_update_framebuffer(ctx); 6097117f1b4Smrg 6107117f1b4Smrg if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) 6117117f1b4Smrg _mesa_update_draw_buffer_bounds( ctx ); 6127117f1b4Smrg 6137117f1b4Smrg if (new_state & _NEW_POLYGON) 6147117f1b4Smrg update_polygon( ctx ); 6157117f1b4Smrg 6167117f1b4Smrg if (new_state & _NEW_LIGHT) 6177117f1b4Smrg _mesa_update_lighting( ctx ); 6187117f1b4Smrg 6193464ebd5Sriastradh if (new_state & (_NEW_LIGHT | _NEW_BUFFERS)) 6203464ebd5Sriastradh update_clamp_vertex_color(ctx); 6213464ebd5Sriastradh 6224a49301eSmrg if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) 6237117f1b4Smrg _mesa_update_stencil( ctx ); 6247117f1b4Smrg 6253464ebd5Sriastradh if (new_state & _NEW_PIXEL) 6267117f1b4Smrg _mesa_update_pixel( ctx, new_state ); 6277117f1b4Smrg 6287117f1b4Smrg if (new_state & _DD_NEW_SEPARATE_SPECULAR) 6297117f1b4Smrg update_separate_specular( ctx ); 6307117f1b4Smrg 6317117f1b4Smrg if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) 6327117f1b4Smrg update_viewport_matrix(ctx); 6337117f1b4Smrg 634c1f859d4Smrg if (new_state & _NEW_MULTISAMPLE) 635c1f859d4Smrg update_multisample( ctx ); 636c1f859d4Smrg 6377117f1b4Smrg if (new_state & _NEW_COLOR) 6387117f1b4Smrg update_color( ctx ); 6397117f1b4Smrg 6403464ebd5Sriastradh if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) 6413464ebd5Sriastradh update_clamp_read_color(ctx); 6423464ebd5Sriastradh 6433464ebd5Sriastradh if(new_state & (_NEW_FRAG_CLAMP | _NEW_BUFFERS)) 6443464ebd5Sriastradh update_clamp_fragment_color(ctx); 6453464ebd5Sriastradh 6467117f1b4Smrg#if 0 6477117f1b4Smrg if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT 6487117f1b4Smrg | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR)) 6497117f1b4Smrg update_tricaps( ctx, new_state ); 6507117f1b4Smrg#endif 6517117f1b4Smrg 6527117f1b4Smrg /* ctx->_NeedEyeCoords is now up to date. 6537117f1b4Smrg * 6547117f1b4Smrg * If the truth value of this variable has changed, update for the 6557117f1b4Smrg * new lighting space and recompute the positions of lights and the 6567117f1b4Smrg * normal transform. 6577117f1b4Smrg * 6587117f1b4Smrg * If the lighting space hasn't changed, may still need to recompute 6597117f1b4Smrg * light positions & normal transforms for other reasons. 6607117f1b4Smrg */ 6617117f1b4Smrg if (new_state & _MESA_NEW_NEED_EYE_COORDS) 6627117f1b4Smrg _mesa_update_tnl_spaces( ctx, new_state ); 6637117f1b4Smrg 664c1f859d4Smrg if (new_state & prog_flags) { 665c1f859d4Smrg /* When we generate programs from fixed-function vertex/fragment state 666c1f859d4Smrg * this call may generate/bind a new program. If so, we need to 667c1f859d4Smrg * propogate the _NEW_PROGRAM flag to the driver. 668c1f859d4Smrg */ 669c1f859d4Smrg new_prog_state |= update_program( ctx ); 670c1f859d4Smrg } 671c1f859d4Smrg 672cdc920a0Smrg if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) 673cdc920a0Smrg update_arrays( ctx ); 6744a49301eSmrg 6754a49301eSmrg out: 6764a49301eSmrg new_prog_state |= update_program_constants(ctx); 6774a49301eSmrg 6787117f1b4Smrg /* 6797117f1b4Smrg * Give the driver a chance to act upon the new_state flags. 6807117f1b4Smrg * The driver might plug in different span functions, for example. 6817117f1b4Smrg * Also, this is where the driver can invalidate the state of any 6827117f1b4Smrg * active modules (such as swrast_setup, swrast, tnl, etc). 6837117f1b4Smrg * 6847117f1b4Smrg * Set ctx->NewState to zero to avoid recursion if 6857117f1b4Smrg * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) 6867117f1b4Smrg */ 687c1f859d4Smrg new_state = ctx->NewState | new_prog_state; 6887117f1b4Smrg ctx->NewState = 0; 6897117f1b4Smrg ctx->Driver.UpdateState(ctx, new_state); 6907117f1b4Smrg ctx->Array.NewState = 0; 6913464ebd5Sriastradh if (!ctx->Array.RebindArrays) 6923464ebd5Sriastradh ctx->Array.RebindArrays = (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) != 0; 6937117f1b4Smrg} 6947117f1b4Smrg 6957117f1b4Smrg 6967117f1b4Smrg/* This is the usual entrypoint for state updates: 6977117f1b4Smrg */ 6987117f1b4Smrgvoid 6993464ebd5Sriastradh_mesa_update_state( struct gl_context *ctx ) 7007117f1b4Smrg{ 7017117f1b4Smrg _mesa_lock_context_textures(ctx); 7027117f1b4Smrg _mesa_update_state_locked(ctx); 7037117f1b4Smrg _mesa_unlock_context_textures(ctx); 7047117f1b4Smrg} 7054a49301eSmrg 7064a49301eSmrg 7074a49301eSmrg 7084a49301eSmrg 7094a49301eSmrg/** 7104a49301eSmrg * Want to figure out which fragment program inputs are actually 7114a49301eSmrg * constant/current values from ctx->Current. These should be 7124a49301eSmrg * referenced as a tracked state variable rather than a fragment 7134a49301eSmrg * program input, to save the overhead of putting a constant value in 7144a49301eSmrg * every submitted vertex, transferring it to hardware, interpolating 7154a49301eSmrg * it across the triangle, etc... 7164a49301eSmrg * 7174a49301eSmrg * When there is a VP bound, just use vp->outputs. But when we're 7184a49301eSmrg * generating vp from fixed function state, basically want to 7194a49301eSmrg * calculate: 7204a49301eSmrg * 7214a49301eSmrg * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) | 7224a49301eSmrg * potential_vp_outputs ) 7234a49301eSmrg * 7244a49301eSmrg * Where potential_vp_outputs is calculated by looking at enabled 7254a49301eSmrg * texgen, etc. 7264a49301eSmrg * 7274a49301eSmrg * The generated fragment program should then only declare inputs that 7284a49301eSmrg * may vary or otherwise differ from the ctx->Current values. 7294a49301eSmrg * Otherwise, the fp should track them as state values instead. 7304a49301eSmrg */ 7314a49301eSmrgvoid 7323464ebd5Sriastradh_mesa_set_varying_vp_inputs( struct gl_context *ctx, 7334a49301eSmrg GLbitfield varying_inputs ) 7344a49301eSmrg{ 7354a49301eSmrg if (ctx->varying_vp_inputs != varying_inputs) { 7364a49301eSmrg ctx->varying_vp_inputs = varying_inputs; 7374a49301eSmrg ctx->NewState |= _NEW_ARRAY; 738cdc920a0Smrg /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/ 7394a49301eSmrg } 7404a49301eSmrg} 7414a49301eSmrg 7424a49301eSmrg 7434a49301eSmrg/** 7444a49301eSmrg * Used by drivers to tell core Mesa that the driver is going to 7454a49301eSmrg * install/ use its own vertex program. In particular, this will 7464a49301eSmrg * prevent generated fragment programs from using state vars instead 7474a49301eSmrg * of ordinary varyings/inputs. 7484a49301eSmrg */ 7494a49301eSmrgvoid 7503464ebd5Sriastradh_mesa_set_vp_override(struct gl_context *ctx, GLboolean flag) 7514a49301eSmrg{ 7524a49301eSmrg if (ctx->VertexProgram._Overriden != flag) { 7534a49301eSmrg ctx->VertexProgram._Overriden = flag; 7544a49301eSmrg 7554a49301eSmrg /* Set one of the bits which will trigger fragment program 7564a49301eSmrg * regeneration: 7574a49301eSmrg */ 7584a49301eSmrg ctx->NewState |= _NEW_PROGRAM; 7594a49301eSmrg } 7604a49301eSmrg} 761