X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fstate.c;h=fb8b71cfe22932ae577935462b0161db6414e2cd;hb=27d70b7266cc5e8562b4cccae763976834eb0ce2;hp=cf9fe8921f3c60508e4e4d12e5f9c8e3e46b4c99;hpb=b4452c3baad6e0379eeb7f22f2e51d13999e1323;p=mesa.git diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index cf9fe8921f3..fb8b71cfe22 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -33,6 +33,7 @@ #include "glheader.h" #include "mtypes.h" +#include "arrayobj.h" #include "context.h" #include "debug.h" #include "macros.h" @@ -49,6 +50,7 @@ #include "texenvprogram.h" #include "texobj.h" #include "texstate.h" +#include "varray.h" static void @@ -61,157 +63,6 @@ update_separate_specular(struct gl_context *ctx) } -/** - * Compute the index of the last array element that can be safely accessed - * in a vertex array. We can really only do this when the array lives in - * a VBO. - * The array->_MaxElement field will be updated. - * Later in glDrawArrays/Elements/etc we can do some bounds checking. - */ -static void -compute_max_element(struct gl_client_array *array) -{ - assert(array->Enabled); - if (array->BufferObj->Name) { - GLsizeiptrARB offset = (GLsizeiptrARB) array->Ptr; - GLsizeiptrARB obj_size = (GLsizeiptrARB) array->BufferObj->Size; - - if (offset < obj_size) { - array->_MaxElement = (obj_size - offset + - array->StrideB - - array->_ElementSize) / array->StrideB; - } else { - array->_MaxElement = 0; - } - } - else { - /* user-space array, no idea how big it is */ - array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */ - } -} - - -/** - * Helper for update_arrays(). - * \return min(current min, array->_MaxElement). - */ -static GLuint -update_min(GLuint min, struct gl_client_array *array) -{ - compute_max_element(array); - return MIN2(min, array->_MaxElement); -} - - -/** - * Update ctx->Array._MaxElement (the max legal index into all enabled arrays). - * Need to do this upon new array state or new buffer object state. - */ -static void -update_arrays( struct gl_context *ctx ) -{ - struct gl_array_object *arrayObj = ctx->Array.ArrayObj; - GLuint i, min = ~0; - - /* find min of _MaxElement values for all enabled arrays */ - - /* 0 */ - if (ctx->VertexProgram._Current - && arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]); - } - else if (arrayObj->Vertex.Enabled) { - min = update_min(min, &arrayObj->Vertex); - } - - /* 1 */ - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]); - } - /* no conventional vertex weight array */ - - /* 2 */ - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]); - } - else if (arrayObj->Normal.Enabled) { - min = update_min(min, &arrayObj->Normal); - } - - /* 3 */ - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]); - } - else if (arrayObj->Color.Enabled) { - min = update_min(min, &arrayObj->Color); - } - - /* 4 */ - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]); - } - else if (arrayObj->SecondaryColor.Enabled) { - min = update_min(min, &arrayObj->SecondaryColor); - } - - /* 5 */ - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]); - } - else if (arrayObj->FogCoord.Enabled) { - min = update_min(min, &arrayObj->FogCoord); - } - - /* 6 */ - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]); - } - else if (arrayObj->Index.Enabled) { - min = update_min(min, &arrayObj->Index); - } - - /* 7 */ - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]); - } - - /* 8..15 */ - for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) { - if (ctx->VertexProgram._Enabled - && arrayObj->VertexAttrib[i].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[i]); - } - else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits - && arrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) { - min = update_min(min, &arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]); - } - } - - /* 16..31 */ - if (ctx->VertexProgram._Current) { - for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) { - if (arrayObj->VertexAttrib[i].Enabled) { - min = update_min(min, &arrayObj->VertexAttrib[i]); - } - } - } - - if (arrayObj->EdgeFlag.Enabled) { - min = update_min(min, &arrayObj->EdgeFlag); - } - - /* _MaxElement is one past the last legal array element */ - arrayObj->_MaxElement = min; -} - - /** * Update the following fields: * ctx->VertexProgram._Enabled @@ -222,7 +73,10 @@ update_arrays( struct gl_context *ctx ) static void update_program_enables(struct gl_context *ctx) { - /* These _Enabled flags indicate if the program is enabled AND valid. */ + /* These _Enabled flags indicate if the user-defined ARB/NV vertex/fragment + * program is enabled AND valid. Similarly for ATI fragment shaders. + * GLSL shaders not relevant here. + */ ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled && ctx->VertexProgram.Current->Base.Instructions; ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled @@ -233,11 +87,12 @@ update_program_enables(struct gl_context *ctx) /** - * Update vertex/fragment program state. In particular, update these fields: - * ctx->VertexProgram._Current - * ctx->VertexProgram._TnlProgram, - * These point to the highest priority enabled vertex/fragment program or are - * NULL if fixed-function processing is to be done. + * Update the ctx->Vertex/Geometry/FragmentProgram._Current pointers to point + * to the current/active programs. Then call ctx->Driver.BindProgram() to + * tell the driver which programs to use. + * + * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment + * programs or programs derived from fixed-function state. * * This function needs to be called after texture state validation in case * we're generating a fragment program from fixed-function texture state. @@ -272,43 +127,53 @@ update_program(struct gl_context *ctx) * come up, or matter. */ - if (fsProg && fsProg->LinkStatus && fsProg->FragmentProgram) { - /* Use shader programs */ - _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, - fsProg->FragmentProgram); - _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, + if (fsProg && fsProg->LinkStatus + && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { + /* Use GLSL fragment shader */ + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, fsProg); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, + gl_fragment_program(fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, + NULL); } else if (ctx->FragmentProgram._Enabled) { - /* use user-defined fragment program */ + /* Use user-defined fragment program */ + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, ctx->FragmentProgram.Current); - _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, - NULL); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, + NULL); } else if (ctx->FragmentProgram._MaintainTexEnvProgram) { - /* Use fragment program generated from fixed-function state. - */ + /* Use fragment program generated from fixed-function state */ struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx); - _mesa_reference_shader_program(ctx, - &ctx->Shader._CurrentFragmentProgram, f); + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + f); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, - f->FragmentProgram); + gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, + gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); } else { - /* no fragment program */ + /* No fragment program */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); - _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, - NULL); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, + NULL); } - if (gsProg && gsProg->LinkStatus && gsProg->GeometryProgram) { - /* Use shader programs */ + if (gsProg && gsProg->LinkStatus + && gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) { + /* Use GLSL geometry shader */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, - gsProg->GeometryProgram); + gl_geometry_program(gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program)); } else { - /* no fragment program */ + /* No geometry program */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); } @@ -316,19 +181,19 @@ update_program(struct gl_context *ctx) * _mesa_get_fixed_func_vertex_program() needs to know active * fragprog inputs. */ - if (vsProg && vsProg->LinkStatus && vsProg->VertexProgram) { - /* Use shader programs */ + if (vsProg && vsProg->LinkStatus + && vsProg->_LinkedShaders[MESA_SHADER_VERTEX]) { + /* Use GLSL vertex shader */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, - vsProg->VertexProgram); + gl_vertex_program(vsProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program)); } else if (ctx->VertexProgram._Enabled) { - /* use user-defined vertex program */ + /* Use user-defined vertex program */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, ctx->VertexProgram.Current); } else if (ctx->VertexProgram._MaintainTnlProgram) { - /* Use vertex program generated from fixed-function state. - */ + /* Use vertex program generated from fixed-function state */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, _mesa_get_fixed_func_vertex_program(ctx)); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, @@ -443,29 +308,70 @@ update_multisample(struct gl_context *ctx) /** - * Update derived color/blend/logicop state. + * Update the ctx->Color._ClampFragmentColor field */ static void -update_color(struct gl_context *ctx) +update_clamp_fragment_color(struct gl_context *ctx) { - /* This is needed to support 1.1's RGB logic ops AND - * 1.0's blending logicops. - */ - ctx->Color._LogicOpEnabled = _mesa_rgba_logicop_enabled(ctx); + if (ctx->Color.ClampFragmentColor == GL_FIXED_ONLY_ARB) + ctx->Color._ClampFragmentColor = + !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; + else + ctx->Color._ClampFragmentColor = ctx->Color.ClampFragmentColor; +} + + +/** + * Update the ctx->Color._ClampVertexColor field + */ +static void +update_clamp_vertex_color(struct gl_context *ctx) +{ + if (ctx->Light.ClampVertexColor == GL_FIXED_ONLY_ARB) + ctx->Light._ClampVertexColor = + !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; + else + ctx->Light._ClampVertexColor = ctx->Light.ClampVertexColor; +} + + +/** + * Update the ctx->Color._ClampReadColor field + */ +static void +update_clamp_read_color(struct gl_context *ctx) +{ + if (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB) + ctx->Color._ClampReadColor = + !ctx->ReadBuffer || !ctx->ReadBuffer->Visual.floatMode; + else + ctx->Color._ClampReadColor = ctx->Color.ClampReadColor; +} + +/** + * Update the ctx->VertexProgram._TwoSideEnabled flag. + */ +static void +update_twoside(struct gl_context *ctx) +{ + if (ctx->Shader.CurrentVertexProgram || + ctx->VertexProgram._Enabled) { + ctx->VertexProgram._TwoSideEnabled = ctx->VertexProgram.TwoSideEnabled; + } else { + ctx->VertexProgram._TwoSideEnabled = (ctx->Light.Enabled && + ctx->Light.Model.TwoSide); + } } /* - * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET + * Check polygon state and set DD_TRI_OFFSET * in ctx->_TriangleCaps if needed. */ static void update_polygon(struct gl_context *ctx) { - ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET); - - if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) - ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; + ctx->_TriangleCaps &= ~DD_TRI_OFFSET; if ( ctx->Polygon.OffsetPoint || ctx->Polygon.OffsetLine @@ -517,9 +423,6 @@ update_tricaps(struct gl_context *ctx, GLbitfield new_state) if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) ctx->_TriangleCaps |= DD_TRI_UNFILLED; - if (ctx->Polygon.CullFlag - && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) - ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; if (ctx->Polygon.OffsetPoint || ctx->Polygon.OffsetLine || ctx->Polygon.OffsetFill) @@ -531,16 +434,8 @@ update_tricaps(struct gl_context *ctx, GLbitfield new_state) */ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; - if (ctx->Light.ShadeModel == GL_FLAT) - ctx->_TriangleCaps |= DD_FLATSHADE; if (_mesa_need_secondary_color(ctx)) ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; - - /* - * Stencil - */ - if (ctx->Stencil._TestTwoSide) - ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL; } #endif @@ -573,12 +468,13 @@ _mesa_update_state_locked( struct gl_context *ctx ) /* Determine which state flags effect vertex/fragment program state */ if (ctx->FragmentProgram._MaintainTexEnvProgram) { prog_flags |= (_NEW_BUFFERS | _NEW_TEXTURE | _NEW_FOG | - _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE | - _NEW_PROGRAM); + _NEW_VARYING_VP_INPUTS | _NEW_LIGHT | _NEW_POINT | + _NEW_RENDERMODE | _NEW_PROGRAM | _NEW_FRAG_CLAMP | + _NEW_COLOR); } if (ctx->VertexProgram._MaintainTnlProgram) { - prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | - _NEW_TRANSFORM | _NEW_POINT | + prog_flags |= (_NEW_VARYING_VP_INPUTS | _NEW_TEXTURE | + _NEW_TEXTURE_MATRIX | _NEW_TRANSFORM | _NEW_POINT | _NEW_FOG | _NEW_LIGHT | _MESA_NEW_NEED_EYE_COORDS); } @@ -608,27 +504,36 @@ _mesa_update_state_locked( struct gl_context *ctx ) if (new_state & _NEW_LIGHT) _mesa_update_lighting( ctx ); + if (new_state & (_NEW_LIGHT | _NEW_PROGRAM)) + update_twoside( ctx ); + + if (new_state & (_NEW_LIGHT | _NEW_BUFFERS)) + update_clamp_vertex_color(ctx); + if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) _mesa_update_stencil( ctx ); - if (new_state & _MESA_NEW_TRANSFER_STATE) + if (new_state & _NEW_PIXEL) _mesa_update_pixel( ctx, new_state ); - if (new_state & _DD_NEW_SEPARATE_SPECULAR) + if (new_state & _MESA_NEW_SEPARATE_SPECULAR) update_separate_specular( ctx ); if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) update_viewport_matrix(ctx); - if (new_state & _NEW_MULTISAMPLE) + if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS)) update_multisample( ctx ); - if (new_state & _NEW_COLOR) - update_color( ctx ); + if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) + update_clamp_read_color(ctx); + + if(new_state & (_NEW_FRAG_CLAMP | _NEW_BUFFERS)) + update_clamp_fragment_color(ctx); #if 0 if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT - | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR)) + | _NEW_STENCIL | _MESA_NEW_SEPARATE_SPECULAR)) update_tricaps( ctx, new_state ); #endif @@ -653,7 +558,7 @@ _mesa_update_state_locked( struct gl_context *ctx ) } if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) - update_arrays( ctx ); + _mesa_update_array_object_max_element(ctx, ctx->Array.ArrayObj); out: new_prog_state |= update_program_constants(ctx); @@ -670,9 +575,7 @@ _mesa_update_state_locked( struct gl_context *ctx ) new_state = ctx->NewState | new_prog_state; ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); - ctx->Array.NewState = 0; - if (!ctx->Array.RebindArrays) - ctx->Array.RebindArrays = (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) != 0; + ctx->Array.ArrayObj->NewArrays = 0x0; } @@ -713,11 +616,21 @@ _mesa_update_state( struct gl_context *ctx ) */ void _mesa_set_varying_vp_inputs( struct gl_context *ctx, - GLbitfield varying_inputs ) + GLbitfield64 varying_inputs ) { if (ctx->varying_vp_inputs != varying_inputs) { ctx->varying_vp_inputs = varying_inputs; - ctx->NewState |= _NEW_ARRAY; + + /* Only the fixed-func generated programs need to use the flag + * and the fixed-func fragment program uses it only if there is also + * a fixed-func vertex program, so this only depends on the latter. + * + * It's okay to check the VP pointer here, because this is called after + * _mesa_update_state in the vbo module. */ + if (ctx->VertexProgram._TnlProgram || + ctx->FragmentProgram._TexEnvProgram) { + ctx->NewState |= _NEW_VARYING_VP_INPUTS; + } /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/ } }