From 1c0f1dd42a50464eeb81de4aad8eecf24b3d6c89 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 25 Jan 2012 19:38:10 -0800 Subject: [PATCH] swrast: Fix fixed-function fragment processing On i965, _mesa_ir_link_shader is never called. As a consequence, the current fragment program (ctx->FragmentProgram->_Current) exists but is invalid because it has no instructions. Yet swrast continued to attempt to use the empty program. To avoid using the empty program, this patch 1) defines a new function, _swrast_use_fragment_program, which checks if the current fragment program exists and differs from the fixed function fragment program, and, when appropriate, 2) replaces checks of the form if (ctx->FragmentProgram->_Current == NULL) with if (_swrast_use_fragment_program(ctx)) Fixes the following oglconform regressions on i965/gen6: api-fogcoord(basic.allCases.log) api-mtexcoord(basic.allCases.log) api-seccolor(basic.allCases.log) api-texcoord(basic.allCases.log) blend-separate(basic.allCases) colorsum(basic.allCases.log) The tests were ran with the GLXFBConfig: visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat ---------------------------------------------------------------------------- 0x021 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None (Note: I originally believed that the hunk in _swrast_update_fragment_program was unnecessary. But it is required to fix blend-separate.) Note: This is a candidate for the 8.0 branch. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=43327 Reveiwed-by: Eric Anholt Reviewed-by: Ian Romanick Signed-off-by: Chad Versace --- src/mesa/swrast/s_aaline.c | 2 +- src/mesa/swrast/s_aalinetemp.h | 2 +- src/mesa/swrast/s_aatriangle.c | 2 +- src/mesa/swrast/s_context.c | 25 ++++++++++++---------- src/mesa/swrast/s_fragprog.c | 12 +++++++++++ src/mesa/swrast/s_fragprog.h | 2 ++ src/mesa/swrast/s_lines.c | 2 +- src/mesa/swrast/s_span.c | 38 ++++++++++------------------------ src/mesa/swrast/s_triangle.c | 4 ++-- 9 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/mesa/swrast/s_aaline.c b/src/mesa/swrast/s_aaline.c index d4b1805d9ec..d36d876974e 100644 --- a/src/mesa/swrast/s_aaline.c +++ b/src/mesa/swrast/s_aaline.c @@ -479,7 +479,7 @@ _swrast_choose_aa_line_function(struct gl_context *ctx) ASSERT(ctx->Line.SmoothFlag); if (ctx->Texture._EnabledCoordUnits != 0 - || ctx->FragmentProgram._Current + || _swrast_use_fragment_program(ctx) || (ctx->Light.Enabled && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) || ctx->Fog.ColorSumEnabled diff --git a/src/mesa/swrast/s_aalinetemp.h b/src/mesa/swrast/s_aalinetemp.h index 376ef32d06e..ba9f8abb9c3 100644 --- a/src/mesa/swrast/s_aalinetemp.h +++ b/src/mesa/swrast/s_aalinetemp.h @@ -67,7 +67,7 @@ NAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy) ATTRIB_LOOP_BEGIN GLfloat (*attribArray)[4] = line->span.array->attribs[attr]; if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0 - && !ctx->FragmentProgram._Current) { + && !_swrast_use_fragment_program(ctx)) { /* texcoord w/ divide by Q */ const GLuint unit = attr - FRAG_ATTRIB_TEX0; const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]); diff --git a/src/mesa/swrast/s_aatriangle.c b/src/mesa/swrast/s_aatriangle.c index c68fdf63b68..b59177fa762 100644 --- a/src/mesa/swrast/s_aatriangle.c +++ b/src/mesa/swrast/s_aatriangle.c @@ -299,7 +299,7 @@ _swrast_set_aa_triangle_function(struct gl_context *ctx) ASSERT(ctx->Polygon.SmoothFlag); if (ctx->Texture._EnabledCoordUnits != 0 - || ctx->FragmentProgram._Current + || _swrast_use_fragment_program(ctx) || swrast->_FogEnabled || _mesa_need_secondary_color(ctx)) { SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri; diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c index 14cb9b180c3..cc304d70c06 100644 --- a/src/mesa/swrast/s_context.c +++ b/src/mesa/swrast/s_context.c @@ -105,7 +105,7 @@ _swrast_update_rasterflags( struct gl_context *ctx ) } - if (ctx->FragmentProgram._Current) { + if (_swrast_use_fragment_program(ctx)) { rasterMask |= FRAGPROG_BIT; } @@ -170,7 +170,7 @@ _swrast_update_fog_hint( struct gl_context *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); swrast->_PreferPixelFog = (!swrast->AllowVertexFog || - ctx->FragmentProgram._Current || + _swrast_use_fragment_program(ctx) || (ctx->Hint.Fog == GL_NICEST && swrast->AllowPixelFog)); } @@ -220,13 +220,14 @@ _swrast_update_deferred_texture(struct gl_context *ctx) swrast->_DeferredTexture = GL_FALSE; } else { + GLboolean use_fprog = _swrast_use_fragment_program(ctx); const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; - if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) { + if (use_fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) { /* Z comes from fragment program/shader */ swrast->_DeferredTexture = GL_FALSE; } - else if (fprog && fprog->UsesKill) { + else if (use_fprog && fprog->UsesKill) { swrast->_DeferredTexture = GL_FALSE; } else if (ctx->Query.CurrentOcclusionObject) { @@ -254,7 +255,8 @@ _swrast_update_fog_state( struct gl_context *ctx ) (fp->Base.Target == GL_FRAGMENT_PROGRAM_NV)); /* determine if fog is needed, and if so, which fog mode */ - swrast->_FogEnabled = (fp == NULL && ctx->Fog.Enabled); + swrast->_FogEnabled = (!_swrast_use_fragment_program(ctx) && + ctx->Fog.Enabled); } @@ -265,10 +267,11 @@ _swrast_update_fog_state( struct gl_context *ctx ) static void _swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState) { - const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; - if (fp) { - _mesa_load_state_parameters(ctx, fp->Base.Parameters); - } + if (!_swrast_use_fragment_program(ctx)) + return; + + _mesa_load_state_parameters(ctx, + ctx->FragmentProgram._Current->Base.Parameters); } @@ -286,7 +289,7 @@ _swrast_update_specular_vertex_add(struct gl_context *ctx) swrast->SpecularVertexAdd = (separateSpecular && ctx->Texture._EnabledUnits == 0x0 - && !ctx->FragmentProgram._Current + && !_swrast_use_fragment_program(ctx) && !ctx->ATIFragmentShader._Enabled); } @@ -497,7 +500,7 @@ _swrast_update_active_attribs(struct gl_context *ctx) /* * Compute _ActiveAttribsMask = which fragment attributes are needed. */ - if (ctx->FragmentProgram._Current) { + if (_swrast_use_fragment_program(ctx)) { /* fragment program/shader */ attribsMask = ctx->FragmentProgram._Current->Base.InputsRead; attribsMask &= ~FRAG_BIT_WPOS; /* WPOS is always handled specially */ diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c index 1caa0ebc226..cd20d8e3647 100644 --- a/src/mesa/swrast/s_fragprog.c +++ b/src/mesa/swrast/s_fragprog.c @@ -30,6 +30,18 @@ #include "s_fragprog.h" #include "s_span.h" +/** + * \brief Should swrast use a fragment program? + * + * \return true if the current fragment program exists and is not the fixed + * function fragment program + */ +GLboolean +_swrast_use_fragment_program(struct gl_context *ctx) +{ + struct gl_fragment_program *fp = ctx->FragmentProgram._Current; + return fp && fp != ctx->FragmentProgram._TexEnvProgram; +} /** * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel' diff --git a/src/mesa/swrast/s_fragprog.h b/src/mesa/swrast/s_fragprog.h index 62a68361769..ac1f5ff4cf4 100644 --- a/src/mesa/swrast/s_fragprog.h +++ b/src/mesa/swrast/s_fragprog.h @@ -31,6 +31,8 @@ struct gl_context; +GLboolean +_swrast_use_fragment_program(struct gl_context *ctx); extern void _swrast_exec_fragment_program(struct gl_context *ctx, SWspan *span); diff --git a/src/mesa/swrast/s_lines.c b/src/mesa/swrast/s_lines.c index 95a2a5d96fc..ee997b08a7b 100644 --- a/src/mesa/swrast/s_lines.c +++ b/src/mesa/swrast/s_lines.c @@ -236,7 +236,7 @@ _swrast_choose_line( struct gl_context *ctx ) ASSERT(swrast->Line); } else if (ctx->Texture._EnabledCoordUnits - || ctx->FragmentProgram._Current + || _swrast_use_fragment_program(ctx) || swrast->_FogEnabled || specular) { USE(general_line); diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index ccdbe5f79c4..28f2f3d3fff 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -139,7 +139,8 @@ _swrast_span_default_attribs(struct gl_context *ctx, SWspan *span) for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { const GLuint attr = FRAG_ATTRIB_TEX0 + i; const GLfloat *tc = ctx->Current.RasterTexCoords[i]; - if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) { + if (_swrast_use_fragment_program(ctx) || + ctx->ATIFragmentShader._Enabled) { COPY_4V(span->attrStart[attr], tc); } else if (tc[3] > 0.0F) { @@ -498,7 +499,7 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span) swrast_texture_image_const(img); needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter) - || ctx->FragmentProgram._Current; + || _swrast_use_fragment_program(ctx); /* LOD is calculated directly in the ansiotropic filter, we can * skip the normal lambda function as the result is ignored. */ @@ -518,7 +519,7 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span) if (needLambda) { GLuint i; - if (ctx->FragmentProgram._Current + if (_swrast_use_fragment_program(ctx) || ctx->ATIFragmentShader._Enabled) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; @@ -559,7 +560,7 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span) } else { GLuint i; - if (ctx->FragmentProgram._Current || + if (_swrast_use_fragment_program(ctx) || ctx->ATIFragmentShader._Enabled) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; @@ -833,7 +834,7 @@ add_specular(struct gl_context *ctx, SWspan *span) GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1]; GLuint i; - ASSERT(!ctx->FragmentProgram._Current); + ASSERT(!_swrast_use_fragment_program(ctx)); ASSERT(span->arrayMask & SPAN_RGBA); ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1); (void) swrast; /* silence warning */ @@ -971,25 +972,7 @@ convert_color_type(SWspan *span, GLenum newType, GLuint output) static inline void shade_texture_span(struct gl_context *ctx, SWspan *span) { - /* This is a hack to work around drivers such as i965 that: - * - * - Set _MaintainTexEnvProgram to generate GLSL IR for - * fixed-function fragment processing. - * - Don't call _mesa_ir_link_shader to generate Mesa IR from - * the GLSL IR. - * - May use swrast to handle glDrawPixels. - * - * Since _mesa_ir_link_shader is never called, there is no Mesa IR - * to execute. Instead do regular fixed-function processing. - * - * It is also worth noting that the software fixed-function path is - * much faster than the software shader path. - */ - const bool use_fragment_program = - ctx->FragmentProgram._Current - && ctx->FragmentProgram._Current != ctx->FragmentProgram._TexEnvProgram; - - if (use_fragment_program || + if (_swrast_use_fragment_program(ctx) || ctx->ATIFragmentShader._Enabled) { /* programmable shading */ if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) { @@ -1018,7 +1001,7 @@ shade_texture_span(struct gl_context *ctx, SWspan *span) interpolate_wpos(ctx, span); /* Run fragment program/shader now */ - if (use_fragment_program) { + if (_swrast_use_fragment_program(ctx)) { _swrast_exec_fragment_program(ctx, span); } else { @@ -1151,7 +1134,7 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span) const GLbitfield64 origArrayAttribs = span->arrayAttribs; const GLenum origChanType = span->array->ChanType; void * const origRgba = span->array->rgba; - const GLboolean shader = (ctx->FragmentProgram._Current + const GLboolean shader = (_swrast_use_fragment_program(ctx) || ctx->ATIFragmentShader._Enabled); const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits; struct gl_framebuffer *fb = ctx->DrawBuffer; @@ -1326,7 +1309,8 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span) const GLuint numBuffers = fb->_NumColorDrawBuffers; const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; const GLboolean multiFragOutputs = - (fp && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0)); + _swrast_use_fragment_program(ctx) + && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0); GLuint buf; for (buf = 0; buf < numBuffers; buf++) { diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index 124aa5f8edd..ddb4792f7e9 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -1038,7 +1038,7 @@ _swrast_choose_triangle( struct gl_context *ctx ) * needs to be interpolated. */ if (ctx->Texture._EnabledCoordUnits || - ctx->FragmentProgram._Current || + _swrast_use_fragment_program(ctx) || ctx->ATIFragmentShader._Enabled || _mesa_need_secondary_color(ctx) || swrast->_FogEnabled) { @@ -1060,7 +1060,7 @@ _swrast_choose_triangle( struct gl_context *ctx ) /* First see if we can use an optimized 2-D texture function */ if (ctx->Texture._EnabledCoordUnits == 0x1 - && !ctx->FragmentProgram._Current + && !_swrast_use_fragment_program(ctx) && !ctx->ATIFragmentShader._Enabled && ctx->Texture._EnabledUnits == 0x1 && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT -- 2.30.2