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