/*
* Mesa 3-D graphics library
- * Version: 6.5.3
+ * Version: 7.1
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Brian Paul
*/
-#include "imports.h"
-#include "bufferobj.h"
-#include "context.h"
-#include "colormac.h"
-#include "mtypes.h"
-#include "prog_statevars.h"
-#include "teximage.h"
+#include "main/imports.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/mtypes.h"
+#include "main/teximage.h"
+#include "program/prog_parameter.h"
+#include "program/prog_statevars.h"
#include "swrast.h"
#include "s_blend.h"
#include "s_context.h"
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLbitfield rasterMask = 0;
+ GLuint i;
if (ctx->Color.AlphaEnabled) rasterMask |= ALPHATEST_BIT;
if (ctx->Color.BlendEnabled) rasterMask |= BLEND_BIT;
if (ctx->Depth.Test) rasterMask |= DEPTH_BIT;
if (swrast->_FogEnabled) rasterMask |= FOG_BIT;
if (ctx->Scissor.Enabled) rasterMask |= CLIP_BIT;
- if (ctx->Stencil.Enabled) rasterMask |= STENCIL_BIT;
- if (ctx->Visual.rgbMode) {
- const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
- if (colorMask != 0xffffffff) rasterMask |= MASKING_BIT;
- if (ctx->Color._LogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
- if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT;
- }
- else {
- if (ctx->Color.IndexMask != 0xffffffff) rasterMask |= MASKING_BIT;
- if (ctx->Color.IndexLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
+ if (ctx->Stencil._Enabled) rasterMask |= STENCIL_BIT;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (!ctx->Color.ColorMask[i][0] ||
+ !ctx->Color.ColorMask[i][1] ||
+ !ctx->Color.ColorMask[i][2] ||
+ !ctx->Color.ColorMask[i][3]) {
+ rasterMask |= MASKING_BIT;
+ break;
+ }
}
-
+ if (ctx->Color._LogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
+ if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT;
if ( ctx->Viewport.X < 0
|| ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width
|| ctx->Viewport.Y < 0
* MULTI_DRAW_BIT flag. Also set it if we're drawing to no
* buffers or the RGBA or CI mask disables all writes.
*/
- if (ctx->DrawBuffer->_NumColorDrawBuffers[0] != 1) {
+ if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
/* more than one color buffer designated for writing (or zero buffers) */
rasterMask |= MULTI_DRAW_BIT;
}
- else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) {
- rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
- }
- else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) {
- rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */
+
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (ctx->Color.ColorMask[i][0] +
+ ctx->Color.ColorMask[i][1] +
+ ctx->Color.ColorMask[i][2] +
+ ctx->Color.ColorMask[i][3] == 0) {
+ rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
+ break;
+ }
}
+
if (ctx->FragmentProgram._Current) {
rasterMask |= FRAGPROG_BIT;
}
/**
- * Examine polycon culls tate to compute the _BackfaceSign field.
- * _BackfaceSign will be 0 if no culling, -1 if culling back-faces,
+ * Examine polygon cull state to compute the _BackfaceCullSign field.
+ * _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces,
* and 1 if culling front-faces. The Polygon FrontFace state also
* factors in.
*/
GLfloat backface_sign;
if (ctx->Polygon.CullFlag) {
- backface_sign = 1.0;
switch (ctx->Polygon.CullFaceMode) {
case GL_BACK:
- if (ctx->Polygon.FrontFace == GL_CCW)
- backface_sign = -1.0;
+ backface_sign = -1.0F;
break;
case GL_FRONT:
- if (ctx->Polygon.FrontFace != GL_CCW)
- backface_sign = -1.0;
+ backface_sign = 1.0F;
break;
case GL_FRONT_AND_BACK:
/* fallthrough */
default:
- backface_sign = 0.0;
- break;
+ backface_sign = 0.0F;
}
}
else {
- backface_sign = 0.0;
+ backface_sign = 0.0F;
}
- SWRAST_CONTEXT(ctx)->_BackfaceSign = backface_sign;
+ SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign;
+
+ /* This is for front/back-face determination, but not for culling */
+ SWRAST_CONTEXT(ctx)->_BackfaceSign
+ = (ctx->Polygon.FrontFace == GL_CW) ? -1.0F : 1.0F;
}
+
/**
* Update the _PreferPixelFog field to indicate if we need to compute
- * fog factors per-fragment.
+ * fog blend factors (from the fog coords) per-fragment.
*/
static void
_swrast_update_fog_hint( GLcontext *ctx )
/**
- * Update the swrast->_AnyTextureCombine flag.
+ * Update the swrast->_TextureCombinePrimary flag.
*/
static void
_swrast_update_texture_env( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
- swrast->_AnyTextureCombine = GL_FALSE;
+
+ swrast->_TextureCombinePrimary = GL_FALSE;
+
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT ||
- ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) {
- swrast->_AnyTextureCombine = GL_TRUE;
- return;
+ const struct gl_tex_env_combine_state *combine =
+ ctx->Texture.Unit[i]._CurrentCombine;
+ GLuint term;
+ for (term = 0; term < combine->_NumArgsRGB; term++) {
+ if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
+ swrast->_TextureCombinePrimary = GL_TRUE;
+ return;
+ }
+ if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
+ swrast->_TextureCombinePrimary = GL_TRUE;
+ return;
+ }
+ }
+ }
+}
+
+
+/**
+ * Determine if we can defer texturing/shading until after Z/stencil
+ * testing. This potentially allows us to skip texturing/shading for
+ * lots of fragments.
+ */
+static void
+_swrast_update_deferred_texture(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (ctx->Color.AlphaEnabled) {
+ /* alpha test depends on post-texture/shader colors */
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else {
+ const struct gl_fragment_program *fprog
+ = ctx->FragmentProgram._Current;
+ if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) {
+ /* Z comes from fragment program/shader */
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else if (fprog && fprog->UsesKill) {
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else if (ctx->Query.CurrentOcclusionObject) {
+ /* occlusion query depends on shader discard/kill results */
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else {
+ swrast->_DeferredTexture = GL_TRUE;
}
}
}
{
const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
if (fp) {
-#if 0
- /* XXX Need a way to trigger the initial loading of parameters
- * even when there's no recent state changes.
- */
- if (fp->Base.Parameters->StateFlags & newState)
-#endif
- _mesa_load_state_parameters(ctx, fp->Base.Parameters);
+ _mesa_load_state_parameters(ctx, fp->Base.Parameters);
}
}
+/**
+ * See if we can do early diffuse+specular (primary+secondary) color
+ * add per vertex instead of per-fragment.
+ */
+static void
+_swrast_update_specular_vertex_add(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLboolean separateSpecular = ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
+
+ swrast->SpecularVertexAdd = (separateSpecular
+ && ctx->Texture._EnabledUnits == 0x0
+ && !ctx->FragmentProgram._Current
+ && !ctx->ATIFragmentShader._Enabled);
+}
+
#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \
+ _NEW_PROGRAM_CONSTANTS | \
_NEW_TEXTURE | \
_NEW_HINT | \
_NEW_POLYGON )
swrast->choose_triangle( ctx );
ASSERT(swrast->Triangle);
- if (ctx->Texture._EnabledUnits == 0
- && NEED_SECONDARY_COLOR(ctx)
- && !ctx->FragmentProgram._Current) {
+ if (swrast->SpecularVertexAdd) {
/* separate specular color, but no texture */
swrast->SpecTriangle = swrast->Triangle;
swrast->Triangle = _swrast_add_spec_terms_triangle;
swrast->choose_line( ctx );
ASSERT(swrast->Line);
- if (ctx->Texture._EnabledUnits == 0
- && NEED_SECONDARY_COLOR(ctx)
- && !ctx->FragmentProgram._Current) {
+ if (swrast->SpecularVertexAdd) {
swrast->SpecLine = swrast->Line;
swrast->Line = _swrast_add_spec_terms_line;
}
-
swrast->Line( ctx, v0, v1 );
}
_swrast_validate_derived( ctx );
swrast->choose_point( ctx );
- if (ctx->Texture._EnabledUnits == 0
- && NEED_SECONDARY_COLOR(ctx)
- && !ctx->FragmentProgram._Current) {
+ if (swrast->SpecularVertexAdd) {
swrast->SpecPoint = swrast->Point;
swrast->Point = _swrast_add_spec_terms_point;
}
}
-static void
+void
_swrast_update_texture_samplers(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint u;
+ if (!swrast)
+ return; /* pipe hack */
+
for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
const struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
/* Note: If tObj is NULL, the sample function will be a simple
/**
- * Update the swrast->_FragmentAttribs field.
+ * Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs,
+ * swrast->_ActiveAtttribMask.
*/
static void
-_swrast_update_fragment_attribs(GLcontext *ctx)
+_swrast_update_active_attribs(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
-
+ GLuint attribsMask;
+
+ /*
+ * Compute _ActiveAttribsMask = which fragment attributes are needed.
+ */
if (ctx->FragmentProgram._Current) {
- swrast->_FragmentAttribs
- = ctx->FragmentProgram._Current->Base.InputsRead;
+ /* fragment program/shader */
+ attribsMask = ctx->FragmentProgram._Current->Base.InputsRead;
+ attribsMask &= ~FRAG_BIT_WPOS; /* WPOS is always handled specially */
+ }
+ else if (ctx->ATIFragmentShader._Enabled) {
+ attribsMask = ~0; /* XXX fix me */
}
else {
- GLuint u;
- swrast->_FragmentAttribs = 0x0;
-
- if (ctx->Depth.Test)
- swrast->_FragmentAttribs |= FRAG_BIT_WPOS;
- if (NEED_SECONDARY_COLOR(ctx))
- swrast->_FragmentAttribs |= FRAG_BIT_COL1;
- if (swrast->_FogEnabled)
- swrast->_FragmentAttribs |= FRAG_BIT_FOGC;
+ /* fixed function */
+ attribsMask = 0x0;
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- if (ctx->Texture.Unit[u]._ReallyEnabled) {
- swrast->_FragmentAttribs |= FRAG_BIT_TEX(u);
- }
- }
- }
+#if CHAN_TYPE == GL_FLOAT
+ attribsMask |= FRAG_BIT_COL0;
+#endif
- /* Find lowest, highest bit set in _FragmentAttribs */
- {
- GLuint bits = swrast->_FragmentAttribs;
- GLuint i = 0;;
- while (bits) {
- i++;
- bits = bits >> 1;
+ if (ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
+ attribsMask |= FRAG_BIT_COL1;
}
- swrast->_MaxFragmentAttrib = i;
- swrast->_MinFragmentAttrib = FRAG_ATTRIB_TEX0; /* XXX temporary */
- }
-}
+ if (swrast->_FogEnabled)
+ attribsMask |= FRAG_BIT_FOGC;
-/**
- * Update the swrast->_ColorOutputsMask which indicates which color
- * renderbuffers (aka rendertargets) are being written to by the current
- * fragment program.
- * We also take glDrawBuffers() into account to skip outputs that are
- * set to GL_NONE.
- */
-static void
-_swrast_update_color_outputs(GLcontext *ctx)
-{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
- const struct gl_framebuffer *fb = ctx->DrawBuffer;
+ attribsMask |= (ctx->Texture._EnabledUnits << FRAG_ATTRIB_TEX0);
+ }
- swrast->_ColorOutputsMask = 0;
- swrast->_NumColorOutputs = 0;
+ swrast->_ActiveAttribMask = attribsMask;
- if (ctx->FragmentProgram._Current) {
- const GLbitfield outputsWritten
- = ctx->FragmentProgram._Current->Base.OutputsWritten;
- GLuint output;
- for (output = 0; output < ctx->Const.MaxDrawBuffers; output++) {
- if ((outputsWritten & (1 << (FRAG_RESULT_DATA0 + output)))
- && (fb->_NumColorDrawBuffers[output] > 0)) {
- swrast->_ColorOutputsMask |= (1 << output);
- swrast->_NumColorOutputs = output + 1;
+ /* Update _ActiveAttribs[] list */
+ {
+ GLuint i, num = 0;
+ for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
+ if (attribsMask & (1 << i)) {
+ swrast->_ActiveAttribs[num++] = i;
+ /* how should this attribute be interpolated? */
+ if (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1)
+ swrast->_InterpMode[i] = ctx->Light.ShadeModel;
+ else
+ swrast->_InterpMode[i] = GL_SMOOTH;
}
}
- }
- if (swrast->_ColorOutputsMask == 0x0) {
- /* no fragment program, or frag prog didn't write to gl_FragData[] */
- if (fb->_NumColorDrawBuffers[0] > 0) {
- swrast->_ColorOutputsMask = 0x1;
- swrast->_NumColorOutputs = 1;
- }
+ swrast->_NumActiveAttribs = num;
}
}
if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
_swrast_update_fog_state( ctx );
- if (swrast->NewState & (_NEW_MODELVIEW |
- _NEW_PROJECTION |
- _NEW_TEXTURE_MATRIX |
- _NEW_FOG |
- _NEW_LIGHT |
- _NEW_LINE |
- _NEW_TEXTURE |
- _NEW_TRANSFORM |
- _NEW_POINT |
- _NEW_VIEWPORT |
- _NEW_PROGRAM))
+ if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM))
_swrast_update_fragment_program( ctx, swrast->NewState );
- if (swrast->NewState & _NEW_TEXTURE)
+ if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) {
_swrast_update_texture_samplers( ctx );
+ _swrast_validate_texture_images(ctx);
+ }
- if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM))
- _swrast_validate_texture_images( ctx );
+ if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM))
+ _swrast_update_deferred_texture(ctx);
if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
_swrast_update_rasterflags( ctx );
if (swrast->NewState & (_NEW_DEPTH |
_NEW_FOG |
+ _NEW_LIGHT |
_NEW_PROGRAM |
_NEW_TEXTURE))
- _swrast_update_fragment_attribs(ctx);
+ _swrast_update_active_attribs(ctx);
- if (swrast->NewState & (_NEW_PROGRAM | _NEW_BUFFERS))
- _swrast_update_color_outputs(ctx);
+ if (swrast->NewState & (_NEW_FOG |
+ _NEW_PROGRAM |
+ _NEW_LIGHT |
+ _NEW_TEXTURE))
+ _swrast_update_specular_vertex_add(ctx);
swrast->NewState = 0;
swrast->StateChanges = 0;
SWRAST_CONTEXT(ctx)->StippleCounter = 0;
}
+void
+_swrast_SetFacing(GLcontext *ctx, GLuint facing)
+{
+ SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
+}
+
void
_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value )
{
}
swrast->SpanArrays->ChanType = CHAN_TYPE;
#if CHAN_TYPE == GL_UNSIGNED_BYTE
- swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz1.rgba;
- swrast->SpanArrays->spec = swrast->SpanArrays->color.sz1.spec;
+ swrast->SpanArrays->rgba = swrast->SpanArrays->rgba8;
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
- swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz2.rgba;
- swrast->SpanArrays->spec = swrast->SpanArrays->color.sz2.spec;
+ swrast->SpanArrays->rgba = swrast->SpanArrays->rgba16;
#else
- swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz4.rgba;
- swrast->SpanArrays->spec = swrast->SpanArrays->color.sz4.spec;
+ swrast->SpanArrays->rgba = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0];
#endif
/* init point span buffer */
swrast->PointSpan.facing = 0;
swrast->PointSpan.array = swrast->SpanArrays;
- swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureImageUnits *
- MAX_WIDTH * 4 * sizeof(GLchan));
+ swrast->TexelBuffer = (GLfloat *) MALLOC(ctx->Const.MaxTextureImageUnits *
+ MAX_WIDTH * 4 * sizeof(GLfloat));
if (!swrast->TexelBuffer) {
FREE(swrast->SpanArrays);
FREE(swrast);
}
FREE( swrast->SpanArrays );
+ if (swrast->ZoomedArrays)
+ FREE( swrast->ZoomedArrays );
FREE( swrast->TexelBuffer );
FREE( swrast );
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* flush any pending fragments from rendering points */
if (swrast->PointSpan.end > 0) {
- if (ctx->Visual.rgbMode) {
- _swrast_write_rgba_span(ctx, &(swrast->PointSpan));
- }
- else {
- _swrast_write_index_span(ctx, &(swrast->PointSpan));
- }
+ _swrast_write_rgba_span(ctx, &(swrast->PointSpan));
swrast->PointSpan.end = 0;
}
}
if (SWRAST_DEBUG_VERTICES) {
_mesa_debug(ctx, "win %f %f %f %f\n",
- v->win[0], v->win[1], v->win[2], v->win[3]);
+ v->attrib[FRAG_ATTRIB_WPOS][0],
+ v->attrib[FRAG_ATTRIB_WPOS][1],
+ v->attrib[FRAG_ATTRIB_WPOS][2],
+ v->attrib[FRAG_ATTRIB_WPOS][3]);
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
if (ctx->Texture.Unit[i]._ReallyEnabled)
#if CHAN_TYPE == GL_FLOAT
_mesa_debug(ctx, "color %f %f %f %f\n",
v->color[0], v->color[1], v->color[2], v->color[3]);
- _mesa_debug(ctx, "spec %f %f %f %f\n",
- v->specular[0], v->specular[1],
- v->specular[2], v->specular[3]);
#else
_mesa_debug(ctx, "color %d %d %d %d\n",
v->color[0], v->color[1], v->color[2], v->color[3]);
- _mesa_debug(ctx, "spec %d %d %d %d\n",
- v->specular[0], v->specular[1],
- v->specular[2], v->specular[3]);
#endif
- _mesa_debug(ctx, "fog %f\n", v->fog);
- _mesa_debug(ctx, "index %d\n", v->index);
+ _mesa_debug(ctx, "spec %g %g %g %g\n",
+ v->attrib[FRAG_ATTRIB_COL1][0],
+ v->attrib[FRAG_ATTRIB_COL1][1],
+ v->attrib[FRAG_ATTRIB_COL1][2],
+ v->attrib[FRAG_ATTRIB_COL1][3]);
+ _mesa_debug(ctx, "fog %f\n", v->attrib[FRAG_ATTRIB_FOGC][0]);
+ _mesa_debug(ctx, "index %d\n", v->attrib[FRAG_ATTRIB_CI][0]);
_mesa_debug(ctx, "pointsize %f\n", v->pointSize);
_mesa_debug(ctx, "\n");
}