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