17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg *
4c1f859d4Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
57117f1b4Smrg *
67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
87117f1b4Smrg * to deal in the Software without restriction, including without limitation
97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
117117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
127117f1b4Smrg *
137117f1b4Smrg * The above copyright notice and this permission notice shall be included
147117f1b4Smrg * in all copies or substantial portions of the Software.
157117f1b4Smrg *
167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22af69d88dSmrg * 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"
36af69d88dSmrg#include "arrayobj.h"
377117f1b4Smrg#include "context.h"
38c1f859d4Smrg#include "debug.h"
39c1f859d4Smrg#include "macros.h"
40c1f859d4Smrg#include "ffvertex_prog.h"
417117f1b4Smrg#include "framebuffer.h"
427117f1b4Smrg#include "light.h"
437117f1b4Smrg#include "matrix.h"
447117f1b4Smrg#include "pixel.h"
453464ebd5Sriastradh#include "program/program.h"
463464ebd5Sriastradh#include "program/prog_parameter.h"
47af69d88dSmrg#include "shaderobj.h"
487117f1b4Smrg#include "state.h"
497117f1b4Smrg#include "stencil.h"
50c1f859d4Smrg#include "texenvprogram.h"
517117f1b4Smrg#include "texobj.h"
527117f1b4Smrg#include "texstate.h"
533464ebd5Sriastradh#include "varray.h"
5401e04c3fSmrg#include "vbo/vbo.h"
5501e04c3fSmrg#include "viewport.h"
56af69d88dSmrg#include "blend.h"
577117f1b4Smrg
587117f1b4Smrg
597ec681f3Smrgvoid
607ec681f3Smrg_mesa_update_allow_draw_out_of_order(struct gl_context *ctx)
617ec681f3Smrg{
627ec681f3Smrg   /* Out-of-order drawing is useful when vertex array draws and immediate
637ec681f3Smrg    * mode are interleaved.
647ec681f3Smrg    *
657ec681f3Smrg    * Example with 3 draws:
667ec681f3Smrg    *   glBegin();
677ec681f3Smrg    *      glVertex();
687ec681f3Smrg    *   glEnd();
697ec681f3Smrg    *   glDrawElements();
707ec681f3Smrg    *   glBegin();
717ec681f3Smrg    *      glVertex();
727ec681f3Smrg    *   glEnd();
737ec681f3Smrg    *
747ec681f3Smrg    * Out-of-order drawing changes the execution order like this:
757ec681f3Smrg    *   glDrawElements();
767ec681f3Smrg    *   glBegin();
777ec681f3Smrg    *      glVertex();
787ec681f3Smrg    *      glVertex();
797ec681f3Smrg    *   glEnd();
807ec681f3Smrg    *
817ec681f3Smrg    * If out-of-order draws are enabled, immediate mode vertices are not
827ec681f3Smrg    * flushed before glDrawElements, resulting in fewer draws and lower CPU
837ec681f3Smrg    * overhead. This helps workstation applications.
847ec681f3Smrg    *
857ec681f3Smrg    * This is a simplified version of out-of-order determination to catch
867ec681f3Smrg    * common cases.
877ec681f3Smrg    *
887ec681f3Smrg    * RadeonSI has a complete and more complicated out-of-order determination
897ec681f3Smrg    * for driver-internal reasons.
907ec681f3Smrg    */
917ec681f3Smrg   /* Only the compatibility profile with immediate mode needs this. */
927ec681f3Smrg   if (ctx->API != API_OPENGL_COMPAT || !ctx->Const.AllowDrawOutOfOrder)
937ec681f3Smrg      return;
947ec681f3Smrg
957ec681f3Smrg   /* If all of these are NULL, GLSL is disabled. */
967ec681f3Smrg   struct gl_program *vs =
977ec681f3Smrg      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
987ec681f3Smrg   struct gl_program *tcs =
997ec681f3Smrg      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
1007ec681f3Smrg   struct gl_program *tes =
1017ec681f3Smrg      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
1027ec681f3Smrg   struct gl_program *gs =
1037ec681f3Smrg      ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
1047ec681f3Smrg   struct gl_program *fs =
1057ec681f3Smrg      ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
1067ec681f3Smrg   GLenum16 depth_func = ctx->Depth.Func;
1077ec681f3Smrg
1087ec681f3Smrg   /* Z fighting and any primitives with equal Z shouldn't be reordered
1097ec681f3Smrg    * with LESS/LEQUAL/GREATER/GEQUAL functions.
1107ec681f3Smrg    *
1117ec681f3Smrg    * When drawing 2 primitive with equal Z:
1127ec681f3Smrg    * - with LEQUAL/GEQUAL, the last primitive wins the Z test.
1137ec681f3Smrg    * - with LESS/GREATER, the first primitive wins the Z test.
1147ec681f3Smrg    *
1157ec681f3Smrg    * Here we ignore that on the basis that such cases don't occur in real
1167ec681f3Smrg    * apps, and we they do occur, they occur with blending where out-of-order
1177ec681f3Smrg    * drawing is always disabled.
1187ec681f3Smrg    */
1197ec681f3Smrg   bool previous_state = ctx->_AllowDrawOutOfOrder;
1207ec681f3Smrg   ctx->_AllowDrawOutOfOrder =
1217ec681f3Smrg         ctx->DrawBuffer &&
1227ec681f3Smrg         ctx->DrawBuffer->Visual.depthBits &&
1237ec681f3Smrg         ctx->Depth.Test &&
1247ec681f3Smrg         ctx->Depth.Mask &&
1257ec681f3Smrg         (depth_func == GL_NEVER ||
1267ec681f3Smrg          depth_func == GL_LESS ||
1277ec681f3Smrg          depth_func == GL_LEQUAL ||
1287ec681f3Smrg          depth_func == GL_GREATER ||
1297ec681f3Smrg          depth_func == GL_GEQUAL) &&
1307ec681f3Smrg         (!ctx->DrawBuffer->Visual.stencilBits ||
1317ec681f3Smrg          !ctx->Stencil.Enabled) &&
1327ec681f3Smrg         (!ctx->Color.ColorMask ||
1337ec681f3Smrg          (!ctx->Color.BlendEnabled &&
1347ec681f3Smrg           (!ctx->Color.ColorLogicOpEnabled ||
1357ec681f3Smrg            ctx->Color._LogicOp == COLOR_LOGICOP_COPY))) &&
1367ec681f3Smrg         (!vs || !vs->info.writes_memory) &&
1377ec681f3Smrg         (!tes || !tes->info.writes_memory) &&
1387ec681f3Smrg         (!tcs || !tcs->info.writes_memory) &&
1397ec681f3Smrg         (!gs || !gs->info.writes_memory) &&
1407ec681f3Smrg         (!fs || !fs->info.writes_memory || !fs->info.fs.early_fragment_tests);
1417ec681f3Smrg
1427ec681f3Smrg   /* If we are disabling out-of-order drawing, we need to flush queued
1437ec681f3Smrg    * vertices.
1447ec681f3Smrg    */
1457ec681f3Smrg   if (previous_state && !ctx->_AllowDrawOutOfOrder)
1467ec681f3Smrg      FLUSH_VERTICES(ctx, 0, 0);
1477ec681f3Smrg}
1487ec681f3Smrg
1497ec681f3Smrg
1507117f1b4Smrg/**
15101e04c3fSmrg * Update the ctx->*Program._Current pointers to point to the
15201e04c3fSmrg * current/active programs.
1533464ebd5Sriastradh *
1543464ebd5Sriastradh * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment
1553464ebd5Sriastradh * programs or programs derived from fixed-function state.
156c1f859d4Smrg *
157c1f859d4Smrg * This function needs to be called after texture state validation in case
158c1f859d4Smrg * we're generating a fragment program from fixed-function texture state.
159c1f859d4Smrg *
160c1f859d4Smrg * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex
161c1f859d4Smrg * or fragment program is being used.
162c1f859d4Smrg */
163c1f859d4Smrgstatic GLbitfield
1643464ebd5Sriastradhupdate_program(struct gl_context *ctx)
165c1f859d4Smrg{
16601e04c3fSmrg   struct gl_program *vsProg =
167af69d88dSmrg      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
16801e04c3fSmrg   struct gl_program *tcsProg =
16901e04c3fSmrg      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
17001e04c3fSmrg   struct gl_program *tesProg =
17101e04c3fSmrg      ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
17201e04c3fSmrg   struct gl_program *gsProg =
173af69d88dSmrg      ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
17401e04c3fSmrg   struct gl_program *fsProg =
175af69d88dSmrg      ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
17601e04c3fSmrg   struct gl_program *csProg =
17701e04c3fSmrg      ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
17801e04c3fSmrg   const struct gl_program *prevVP = ctx->VertexProgram._Current;
17901e04c3fSmrg   const struct gl_program *prevFP = ctx->FragmentProgram._Current;
18001e04c3fSmrg   const struct gl_program *prevGP = ctx->GeometryProgram._Current;
18101e04c3fSmrg   const struct gl_program *prevTCP = ctx->TessCtrlProgram._Current;
18201e04c3fSmrg   const struct gl_program *prevTEP = ctx->TessEvalProgram._Current;
18301e04c3fSmrg   const struct gl_program *prevCP = ctx->ComputeProgram._Current;
1847117f1b4Smrg
1857117f1b4Smrg   /*
1867117f1b4Smrg    * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
187c1f859d4Smrg    * pointers to the programs that should be used for rendering.  If either
188c1f859d4Smrg    * is NULL, use fixed-function code paths.
1897117f1b4Smrg    *
1907117f1b4Smrg    * These programs may come from several sources.  The priority is as
1917117f1b4Smrg    * follows:
1927117f1b4Smrg    *   1. OpenGL 2.0/ARB vertex/fragment shaders
1937117f1b4Smrg    *   2. ARB/NV vertex/fragment programs
19401e04c3fSmrg    *   3. ATI fragment shader
19501e04c3fSmrg    *   4. Programs derived from fixed-function state.
196c1f859d4Smrg    *
197c1f859d4Smrg    * Note: it's possible for a vertex shader to get used with a fragment
198c1f859d4Smrg    * program (and vice versa) here, but in practice that shouldn't ever
199c1f859d4Smrg    * come up, or matter.
2007117f1b4Smrg    */
2017117f1b4Smrg
20201e04c3fSmrg   if (fsProg) {
2033464ebd5Sriastradh      /* Use GLSL fragment shader */
20401e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, fsProg);
20501e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
20601e04c3fSmrg                              NULL);
207c1f859d4Smrg   }
20801e04c3fSmrg   else if (_mesa_arb_fragment_program_enabled(ctx)) {
2093464ebd5Sriastradh      /* Use user-defined fragment program */
21001e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
21101e04c3fSmrg                              ctx->FragmentProgram.Current);
21201e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
21301e04c3fSmrg			      NULL);
21401e04c3fSmrg   }
21501e04c3fSmrg   else if (_mesa_ati_fragment_shader_enabled(ctx) &&
21601e04c3fSmrg            ctx->ATIFragmentShader.Current->Program) {
21701e04c3fSmrg       /* Use the enabled ATI fragment shader's associated program */
21801e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
21901e04c3fSmrg                              ctx->ATIFragmentShader.Current->Program);
22001e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
22101e04c3fSmrg                              NULL);
222c1f859d4Smrg   }
223c1f859d4Smrg   else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
2243464ebd5Sriastradh      /* Use fragment program generated from fixed-function state */
225af69d88dSmrg      struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx);
226af69d88dSmrg
22701e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current,
22801e04c3fSmrg			      f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program);
22901e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
23001e04c3fSmrg			      f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program);
231c1f859d4Smrg   }
232c1f859d4Smrg   else {
2333464ebd5Sriastradh      /* No fragment program */
23401e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, NULL);
23501e04c3fSmrg      _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram,
23601e04c3fSmrg			      NULL);
237c1f859d4Smrg   }
2387117f1b4Smrg
23901e04c3fSmrg   if (gsProg) {
2403464ebd5Sriastradh      /* Use GLSL geometry shader */
24101e04c3fSmrg      _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, gsProg);
2423464ebd5Sriastradh   } else {
2433464ebd5Sriastradh      /* No geometry program */
24401e04c3fSmrg      _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, NULL);
24501e04c3fSmrg   }
24601e04c3fSmrg
24701e04c3fSmrg   if (tesProg) {
24801e04c3fSmrg      /* Use GLSL tessellation evaluation shader */
24901e04c3fSmrg      _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, tesProg);
25001e04c3fSmrg   }
25101e04c3fSmrg   else {
25201e04c3fSmrg      /* No tessellation evaluation program */
25301e04c3fSmrg      _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, NULL);
25401e04c3fSmrg   }
25501e04c3fSmrg
25601e04c3fSmrg   if (tcsProg) {
25701e04c3fSmrg      /* Use GLSL tessellation control shader */
25801e04c3fSmrg      _mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, tcsProg);
25901e04c3fSmrg   }
26001e04c3fSmrg   else {
26101e04c3fSmrg      /* No tessellation control program */
26201e04c3fSmrg      _mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, NULL);
2633464ebd5Sriastradh   }
2643464ebd5Sriastradh
265c1f859d4Smrg   /* Examine vertex program after fragment program as
266c1f859d4Smrg    * _mesa_get_fixed_func_vertex_program() needs to know active
267c1f859d4Smrg    * fragprog inputs.
268c1f859d4Smrg    */
26901e04c3fSmrg   if (vsProg) {
2703464ebd5Sriastradh      /* Use GLSL vertex shader */
27101e04c3fSmrg      assert(VP_MODE_SHADER == ctx->VertexProgram._VPMode);
27201e04c3fSmrg      _mesa_reference_program(ctx, &ctx->VertexProgram._Current, vsProg);
273c1f859d4Smrg   }
27401e04c3fSmrg   else if (_mesa_arb_vertex_program_enabled(ctx)) {
2753464ebd5Sriastradh      /* Use user-defined vertex program */
27601e04c3fSmrg      assert(VP_MODE_SHADER == ctx->VertexProgram._VPMode);
27701e04c3fSmrg      _mesa_reference_program(ctx, &ctx->VertexProgram._Current,
27801e04c3fSmrg                              ctx->VertexProgram.Current);
279c1f859d4Smrg   }
280c1f859d4Smrg   else if (ctx->VertexProgram._MaintainTnlProgram) {
2813464ebd5Sriastradh      /* Use vertex program generated from fixed-function state */
28201e04c3fSmrg      assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
28301e04c3fSmrg      _mesa_reference_program(ctx, &ctx->VertexProgram._Current,
28401e04c3fSmrg                              _mesa_get_fixed_func_vertex_program(ctx));
28501e04c3fSmrg      _mesa_reference_program(ctx, &ctx->VertexProgram._TnlProgram,
28601e04c3fSmrg                              ctx->VertexProgram._Current);
2877117f1b4Smrg   }
2887117f1b4Smrg   else {
289c1f859d4Smrg      /* no vertex program */
29001e04c3fSmrg      assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
29101e04c3fSmrg      _mesa_reference_program(ctx, &ctx->VertexProgram._Current, NULL);
29201e04c3fSmrg   }
29301e04c3fSmrg
29401e04c3fSmrg   if (csProg) {
29501e04c3fSmrg      /* Use GLSL compute shader */
29601e04c3fSmrg      _mesa_reference_program(ctx, &ctx->ComputeProgram._Current, csProg);
29701e04c3fSmrg   } else {
29801e04c3fSmrg      /* no compute program */
29901e04c3fSmrg      _mesa_reference_program(ctx, &ctx->ComputeProgram._Current, NULL);
300c1f859d4Smrg   }
3017117f1b4Smrg
302c1f859d4Smrg   /* Let the driver know what's happening:
303c1f859d4Smrg    */
30401e04c3fSmrg   if (ctx->FragmentProgram._Current != prevFP ||
30501e04c3fSmrg       ctx->VertexProgram._Current != prevVP ||
30601e04c3fSmrg       ctx->GeometryProgram._Current != prevGP ||
30701e04c3fSmrg       ctx->TessEvalProgram._Current != prevTEP ||
30801e04c3fSmrg       ctx->TessCtrlProgram._Current != prevTCP ||
30901e04c3fSmrg       ctx->ComputeProgram._Current != prevCP)
31001e04c3fSmrg      return _NEW_PROGRAM;
31101e04c3fSmrg
31201e04c3fSmrg   return 0;
31301e04c3fSmrg}
3143464ebd5Sriastradh
3153464ebd5Sriastradh
31601e04c3fSmrgstatic GLbitfield
31701e04c3fSmrgupdate_single_program_constants(struct gl_context *ctx,
31801e04c3fSmrg                                struct gl_program *prog,
31901e04c3fSmrg                                gl_shader_stage stage)
32001e04c3fSmrg{
32101e04c3fSmrg   if (prog) {
32201e04c3fSmrg      const struct gl_program_parameter_list *params = prog->Parameters;
32301e04c3fSmrg      if (params && params->StateFlags & ctx->NewState) {
32401e04c3fSmrg         if (ctx->DriverFlags.NewShaderConstants[stage])
32501e04c3fSmrg            ctx->NewDriverState |= ctx->DriverFlags.NewShaderConstants[stage];
32601e04c3fSmrg         else
32701e04c3fSmrg            return _NEW_PROGRAM_CONSTANTS;
3287117f1b4Smrg      }
3297117f1b4Smrg   }
33001e04c3fSmrg   return 0;
3317117f1b4Smrg}
3327117f1b4Smrg
3337117f1b4Smrg
3344a49301eSmrg/**
33501e04c3fSmrg * This updates fixed-func state constants such as gl_ModelViewMatrix.
3364a49301eSmrg * Examine shader constants and return either _NEW_PROGRAM_CONSTANTS or 0.
3374a49301eSmrg */
3384a49301eSmrgstatic GLbitfield
3393464ebd5Sriastradhupdate_program_constants(struct gl_context *ctx)
3404a49301eSmrg{
34101e04c3fSmrg   GLbitfield new_state =
34201e04c3fSmrg      update_single_program_constants(ctx, ctx->VertexProgram._Current,
34301e04c3fSmrg                                      MESA_SHADER_VERTEX) |
34401e04c3fSmrg      update_single_program_constants(ctx, ctx->FragmentProgram._Current,
34501e04c3fSmrg                                      MESA_SHADER_FRAGMENT);
34601e04c3fSmrg
34701e04c3fSmrg   if (ctx->API == API_OPENGL_COMPAT &&
34801e04c3fSmrg       ctx->Const.GLSLVersionCompat >= 150) {
34901e04c3fSmrg      new_state |=
35001e04c3fSmrg         update_single_program_constants(ctx, ctx->GeometryProgram._Current,
35101e04c3fSmrg                                         MESA_SHADER_GEOMETRY);
35201e04c3fSmrg
35301e04c3fSmrg      if (_mesa_has_ARB_tessellation_shader(ctx)) {
35401e04c3fSmrg         new_state |=
35501e04c3fSmrg            update_single_program_constants(ctx, ctx->TessCtrlProgram._Current,
35601e04c3fSmrg                                            MESA_SHADER_TESS_CTRL) |
35701e04c3fSmrg            update_single_program_constants(ctx, ctx->TessEvalProgram._Current,
35801e04c3fSmrg                                            MESA_SHADER_TESS_EVAL);
3594a49301eSmrg      }
3604a49301eSmrg   }
3614a49301eSmrg
3624a49301eSmrg   return new_state;
3634a49301eSmrg}
3644a49301eSmrg
3654a49301eSmrg
3667ec681f3Smrgstatic void
3677ec681f3Smrgupdate_fixed_func_program_usage(struct gl_context *ctx)
3687ec681f3Smrg{
3697ec681f3Smrg   ctx->FragmentProgram._UsesTexEnvProgram =
3707ec681f3Smrg      ctx->FragmentProgram._MaintainTexEnvProgram &&
3717ec681f3Smrg      !ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT] && /* GLSL*/
3727ec681f3Smrg      !_mesa_arb_fragment_program_enabled(ctx) &&
3737ec681f3Smrg      !(_mesa_ati_fragment_shader_enabled(ctx) &&
3747ec681f3Smrg        ctx->ATIFragmentShader.Current->Program);
3757ec681f3Smrg
3767ec681f3Smrg   ctx->VertexProgram._UsesTnlProgram =
3777ec681f3Smrg      ctx->VertexProgram._MaintainTnlProgram &&
3787ec681f3Smrg      !ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] && /* GLSL */
3797ec681f3Smrg      !_mesa_arb_vertex_program_enabled(ctx);
3807ec681f3Smrg}
3817ec681f3Smrg
3827ec681f3Smrg
3837117f1b4Smrg/**
3847117f1b4Smrg * Compute derived GL state.
3853464ebd5Sriastradh * If __struct gl_contextRec::NewState is non-zero then this function \b must
3867117f1b4Smrg * be called before rendering anything.
3877117f1b4Smrg *
3887117f1b4Smrg * Calls dd_function_table::UpdateState to perform any internal state
3897117f1b4Smrg * management necessary.
3907117f1b4Smrg *
3917117f1b4Smrg * \sa _mesa_update_modelview_project(), _mesa_update_texture(),
3927117f1b4Smrg * _mesa_update_buffer_bounds(),
3937117f1b4Smrg * _mesa_update_lighting() and _mesa_update_tnl_spaces().
3947117f1b4Smrg */
3957117f1b4Smrgvoid
3963464ebd5Sriastradh_mesa_update_state_locked( struct gl_context *ctx )
3977117f1b4Smrg{
3987117f1b4Smrg   GLbitfield new_state = ctx->NewState;
399c1f859d4Smrg   GLbitfield new_prog_state = 0x0;
4007ec681f3Smrg   const GLbitfield checked_states =
4017ec681f3Smrg      _NEW_BUFFERS | _NEW_MODELVIEW | _NEW_PROJECTION | _NEW_TEXTURE_MATRIX |
4027ec681f3Smrg      _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE | _NEW_PROGRAM |
4037ec681f3Smrg      _NEW_LIGHT_CONSTANTS | _NEW_POINT | _NEW_FF_VERT_PROGRAM |
4047ec681f3Smrg      _NEW_FF_FRAG_PROGRAM | _NEW_TNL_SPACES;
4057117f1b4Smrg
40601e04c3fSmrg   /* we can skip a bunch of state validation checks if the dirty
40701e04c3fSmrg    * state matches one or more bits in 'computed_states'.
40801e04c3fSmrg    */
4097ec681f3Smrg   if (!(new_state & checked_states))
4104a49301eSmrg      goto out;
4114a49301eSmrg
4127117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_STATE)
4137117f1b4Smrg      _mesa_print_state("_mesa_update_state", new_state);
4147117f1b4Smrg
4154a49301eSmrg   if (new_state & _NEW_BUFFERS)
41601e04c3fSmrg      _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
41701e04c3fSmrg
41801e04c3fSmrg   /* Handle Core and Compatibility contexts separately. */
41901e04c3fSmrg   if (ctx->API == API_OPENGL_COMPAT ||
42001e04c3fSmrg       ctx->API == API_OPENGLES) {
4217ec681f3Smrg      /* Update derived state. */
42201e04c3fSmrg      if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
42301e04c3fSmrg         _mesa_update_modelview_project( ctx, new_state );
4247117f1b4Smrg
42501e04c3fSmrg      if (new_state & _NEW_TEXTURE_MATRIX)
4267ec681f3Smrg         new_state |= _mesa_update_texture_matrices(ctx);
4277117f1b4Smrg
42801e04c3fSmrg      if (new_state & (_NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE | _NEW_PROGRAM))
4297ec681f3Smrg         new_state |= _mesa_update_texture_state(ctx);
4307117f1b4Smrg
4317ec681f3Smrg      if (new_state & _NEW_LIGHT_CONSTANTS)
4327ec681f3Smrg         new_state |= _mesa_update_lighting(ctx);
433c1f859d4Smrg
4347ec681f3Smrg      /* ctx->_NeedEyeCoords is determined here.
43501e04c3fSmrg       *
43601e04c3fSmrg       * If the truth value of this variable has changed, update for the
43701e04c3fSmrg       * new lighting space and recompute the positions of lights and the
43801e04c3fSmrg       * normal transform.
43901e04c3fSmrg       *
44001e04c3fSmrg       * If the lighting space hasn't changed, may still need to recompute
44101e04c3fSmrg       * light positions & normal transforms for other reasons.
442c1f859d4Smrg       */
4437ec681f3Smrg      if (new_state & (_NEW_TNL_SPACES | _NEW_LIGHT_CONSTANTS |
4447ec681f3Smrg                       _NEW_MODELVIEW)) {
4457ec681f3Smrg         if (_mesa_update_tnl_spaces(ctx, new_state))
4467ec681f3Smrg            new_state |= _NEW_FF_VERT_PROGRAM;
4477ec681f3Smrg      }
4487ec681f3Smrg
4497ec681f3Smrg      if (new_state & _NEW_PROGRAM)
4507ec681f3Smrg         update_fixed_func_program_usage(ctx);
4517ec681f3Smrg
4527ec681f3Smrg      /* Determine which states affect fixed-func vertex/fragment program. */
4537ec681f3Smrg      GLbitfield prog_flags = _NEW_PROGRAM;
4547ec681f3Smrg
4557ec681f3Smrg      if (ctx->FragmentProgram._UsesTexEnvProgram) {
4567ec681f3Smrg         prog_flags |= _NEW_BUFFERS | _NEW_TEXTURE_OBJECT |
4577ec681f3Smrg                       _NEW_FF_FRAG_PROGRAM | _NEW_TEXTURE_STATE;
4587ec681f3Smrg      }
4597ec681f3Smrg
4607ec681f3Smrg      if (ctx->VertexProgram._UsesTnlProgram)
4617ec681f3Smrg         prog_flags |= _NEW_FF_VERT_PROGRAM;
46201e04c3fSmrg
46301e04c3fSmrg      if (new_state & prog_flags) {
46401e04c3fSmrg         /* When we generate programs from fixed-function vertex/fragment state
46501e04c3fSmrg          * this call may generate/bind a new program.  If so, we need to
46601e04c3fSmrg          * propogate the _NEW_PROGRAM flag to the driver.
46701e04c3fSmrg          */
46801e04c3fSmrg         new_prog_state |= update_program(ctx);
46901e04c3fSmrg      }
47001e04c3fSmrg   } else {
47101e04c3fSmrg      /* GL Core and GLES 2/3 contexts */
47201e04c3fSmrg      if (new_state & (_NEW_TEXTURE_OBJECT | _NEW_PROGRAM))
47301e04c3fSmrg         _mesa_update_texture_state(ctx);
474af69d88dSmrg
47501e04c3fSmrg      if (new_state & _NEW_PROGRAM)
47601e04c3fSmrg         update_program(ctx);
477af69d88dSmrg   }
4784a49301eSmrg
4794a49301eSmrg out:
4804a49301eSmrg   new_prog_state |= update_program_constants(ctx);
4814a49301eSmrg
48201e04c3fSmrg   ctx->NewState |= new_prog_state;
48301e04c3fSmrg
4847117f1b4Smrg   /*
4857117f1b4Smrg    * Give the driver a chance to act upon the new_state flags.
4867117f1b4Smrg    * The driver might plug in different span functions, for example.
4877117f1b4Smrg    * Also, this is where the driver can invalidate the state of any
4887117f1b4Smrg    * active modules (such as swrast_setup, swrast, tnl, etc).
4897117f1b4Smrg    */
49001e04c3fSmrg   ctx->Driver.UpdateState(ctx);
4917117f1b4Smrg   ctx->NewState = 0;
4927117f1b4Smrg}
4937117f1b4Smrg
4947117f1b4Smrg
4957117f1b4Smrg/* This is the usual entrypoint for state updates:
4967117f1b4Smrg */
4977117f1b4Smrgvoid
4983464ebd5Sriastradh_mesa_update_state( struct gl_context *ctx )
4997117f1b4Smrg{
5007117f1b4Smrg   _mesa_lock_context_textures(ctx);
5017117f1b4Smrg   _mesa_update_state_locked(ctx);
5027117f1b4Smrg   _mesa_unlock_context_textures(ctx);
5037117f1b4Smrg}
5044a49301eSmrg
5054a49301eSmrg
5064a49301eSmrg/**
5074a49301eSmrg * Used by drivers to tell core Mesa that the driver is going to
5084a49301eSmrg * install/ use its own vertex program.  In particular, this will
5094a49301eSmrg * prevent generated fragment programs from using state vars instead
5104a49301eSmrg * of ordinary varyings/inputs.
5114a49301eSmrg */
5124a49301eSmrgvoid
5133464ebd5Sriastradh_mesa_set_vp_override(struct gl_context *ctx, GLboolean flag)
5144a49301eSmrg{
5154a49301eSmrg   if (ctx->VertexProgram._Overriden != flag) {
5164a49301eSmrg      ctx->VertexProgram._Overriden = flag;
5174a49301eSmrg
5184a49301eSmrg      /* Set one of the bits which will trigger fragment program
5194a49301eSmrg       * regeneration:
5204a49301eSmrg       */
5214a49301eSmrg      ctx->NewState |= _NEW_PROGRAM;
5224a49301eSmrg   }
5234a49301eSmrg}
52401e04c3fSmrg
52501e04c3fSmrg
52601e04c3fSmrgstatic void
52701e04c3fSmrgset_vertex_processing_mode(struct gl_context *ctx, gl_vertex_processing_mode m)
52801e04c3fSmrg{
52901e04c3fSmrg   if (ctx->VertexProgram._VPMode == m)
53001e04c3fSmrg      return;
53101e04c3fSmrg
53201e04c3fSmrg   /* On change we may get new maps into the current values */
53301e04c3fSmrg   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
53401e04c3fSmrg
53501e04c3fSmrg   /* Finally memorize the value */
53601e04c3fSmrg   ctx->VertexProgram._VPMode = m;
5377ec681f3Smrg
5387ec681f3Smrg   /* The gl_context::VertexProgram._VaryingInputs value is only used when in
5397ec681f3Smrg    * VP_MODE_FF mode and the fixed-func pipeline is emulated by shaders.
5407ec681f3Smrg    */
5417ec681f3Smrg   ctx->VertexProgram._VPModeOptimizesConstantAttribs =
5427ec681f3Smrg      m == VP_MODE_FF &&
5437ec681f3Smrg      ctx->VertexProgram._MaintainTnlProgram &&
5447ec681f3Smrg      ctx->FragmentProgram._MaintainTexEnvProgram;
5457ec681f3Smrg
5467ec681f3Smrg   /* Set a filter mask for the net enabled vao arrays.
5477ec681f3Smrg    * This is to mask out arrays that would otherwise supersede required current
5487ec681f3Smrg    * values for the fixed function shaders for example.
5497ec681f3Smrg    */
5507ec681f3Smrg   switch (m) {
5517ec681f3Smrg   case VP_MODE_FF:
5527ec681f3Smrg      /* When no vertex program is active (or the vertex program is generated
5537ec681f3Smrg       * from fixed-function state).  We put the material values into the
5547ec681f3Smrg       * generic slots.  Since the vao has no material arrays, mute these
5557ec681f3Smrg       * slots from the enabled arrays so that the current material values
5567ec681f3Smrg       * are pulled instead of the vao arrays.
5577ec681f3Smrg       */
5587ec681f3Smrg      ctx->VertexProgram._VPModeInputFilter = VERT_BIT_FF_ALL;
5597ec681f3Smrg      break;
5607ec681f3Smrg
5617ec681f3Smrg   case VP_MODE_SHADER:
5627ec681f3Smrg      /* There are no shaders in OpenGL ES 1.x, so this code path should be
5637ec681f3Smrg       * impossible to reach.  The meta code is careful to not use shaders in
5647ec681f3Smrg       * ES1.
5657ec681f3Smrg       */
5667ec681f3Smrg      assert(ctx->API != API_OPENGLES);
5677ec681f3Smrg
5687ec681f3Smrg      /* Other parts of the code assume that inputs[VERT_ATTRIB_POS] through
5697ec681f3Smrg       * inputs[VERT_ATTRIB_GENERIC0-1] will be non-NULL.  However, in OpenGL
5707ec681f3Smrg       * ES 2.0+ or OpenGL core profile, none of these arrays should ever
5717ec681f3Smrg       * be enabled.
5727ec681f3Smrg       */
5737ec681f3Smrg      if (ctx->API == API_OPENGL_COMPAT)
5747ec681f3Smrg         ctx->VertexProgram._VPModeInputFilter = VERT_BIT_ALL;
5757ec681f3Smrg      else
5767ec681f3Smrg         ctx->VertexProgram._VPModeInputFilter = VERT_BIT_GENERIC_ALL;
5777ec681f3Smrg      break;
5787ec681f3Smrg
5797ec681f3Smrg   default:
5807ec681f3Smrg      assert(0);
5817ec681f3Smrg   }
5827ec681f3Smrg
5837ec681f3Smrg   /* Since we only track the varying inputs while being in fixed function
5847ec681f3Smrg    * vertex processing mode, we may need to update fixed-func shaders
5857ec681f3Smrg    * for zero-stride vertex attribs.
5867ec681f3Smrg    */
5877ec681f3Smrg   _mesa_set_varying_vp_inputs(ctx, ctx->Array._DrawVAOEnabledAttribs);
58801e04c3fSmrg}
58901e04c3fSmrg
59001e04c3fSmrg
59101e04c3fSmrg/**
59201e04c3fSmrg * Update ctx->VertexProgram._VPMode.
59301e04c3fSmrg * This is to distinguish whether we're running
59401e04c3fSmrg *   a vertex program/shader,
59501e04c3fSmrg *   a fixed-function TNL program or
59601e04c3fSmrg *   a fixed function vertex transformation without any program.
59701e04c3fSmrg */
59801e04c3fSmrgvoid
59901e04c3fSmrg_mesa_update_vertex_processing_mode(struct gl_context *ctx)
60001e04c3fSmrg{
60101e04c3fSmrg   if (ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX])
60201e04c3fSmrg      set_vertex_processing_mode(ctx, VP_MODE_SHADER);
60301e04c3fSmrg   else if (_mesa_arb_vertex_program_enabled(ctx))
60401e04c3fSmrg      set_vertex_processing_mode(ctx, VP_MODE_SHADER);
60501e04c3fSmrg   else
60601e04c3fSmrg      set_vertex_processing_mode(ctx, VP_MODE_FF);
60701e04c3fSmrg}
60801e04c3fSmrg
60901e04c3fSmrg
61001e04c3fSmrgvoid
6117ec681f3Smrg_mesa_reset_vertex_processing_mode(struct gl_context *ctx)
61201e04c3fSmrg{
6137ec681f3Smrg   ctx->VertexProgram._VPMode = -1; /* force the update */
6147ec681f3Smrg   _mesa_update_vertex_processing_mode(ctx);
61501e04c3fSmrg}
616