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 * Authors:
25af69d88dSmrg *    Keith Whitwell <keithw@vmware.com> Brian Paul
267117f1b4Smrg */
277117f1b4Smrg
2801e04c3fSmrg#include "main/errors.h"
297ec681f3Smrg
30c1f859d4Smrg#include "main/bufferobj.h"
31c1f859d4Smrg#include "main/mtypes.h"
32af69d88dSmrg#include "main/samplerobj.h"
3301e04c3fSmrg#include "main/state.h"
3401e04c3fSmrg#include "main/stencil.h"
35c1f859d4Smrg#include "main/teximage.h"
363464ebd5Sriastradh#include "program/prog_parameter.h"
373464ebd5Sriastradh#include "program/prog_statevars.h"
387117f1b4Smrg#include "swrast.h"
397117f1b4Smrg#include "s_blend.h"
407117f1b4Smrg#include "s_context.h"
417117f1b4Smrg#include "s_lines.h"
427117f1b4Smrg#include "s_points.h"
437117f1b4Smrg#include "s_span.h"
44af69d88dSmrg#include "s_texfetch.h"
457117f1b4Smrg#include "s_triangle.h"
467117f1b4Smrg#include "s_texfilter.h"
477117f1b4Smrg
487117f1b4Smrg
497117f1b4Smrg/**
507117f1b4Smrg * Recompute the value of swrast->_RasterMask, etc. according to
517117f1b4Smrg * the current context.  The _RasterMask field can be easily tested by
527117f1b4Smrg * drivers to determine certain basic GL state (does the primitive need
537117f1b4Smrg * stenciling, logic-op, fog, etc?).
547117f1b4Smrg */
557117f1b4Smrgstatic void
563464ebd5Sriastradh_swrast_update_rasterflags( struct gl_context *ctx )
577117f1b4Smrg{
587117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
597117f1b4Smrg   GLbitfield rasterMask = 0;
60cdc920a0Smrg   GLuint i;
617117f1b4Smrg
627117f1b4Smrg   if (ctx->Color.AlphaEnabled)           rasterMask |= ALPHATEST_BIT;
637117f1b4Smrg   if (ctx->Color.BlendEnabled)           rasterMask |= BLEND_BIT;
647117f1b4Smrg   if (ctx->Depth.Test)                   rasterMask |= DEPTH_BIT;
657117f1b4Smrg   if (swrast->_FogEnabled)               rasterMask |= FOG_BIT;
66af69d88dSmrg   if (ctx->Scissor.EnableFlags)          rasterMask |= CLIP_BIT;
6701e04c3fSmrg   if (_mesa_stencil_is_enabled(ctx))     rasterMask |= STENCIL_BIT;
68cdc920a0Smrg   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
6901e04c3fSmrg      if (GET_COLORMASK(ctx->Color.ColorMask, i) != 0xf) {
70cdc920a0Smrg         rasterMask |= MASKING_BIT;
71cdc920a0Smrg         break;
72cdc920a0Smrg      }
737117f1b4Smrg   }
74af69d88dSmrg   if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
75af69d88dSmrg   if (ctx->Texture._MaxEnabledTexImageUnit >= 0) rasterMask |= TEXTURE_BIT;
76af69d88dSmrg   if (   ctx->ViewportArray[0].X < 0
77af69d88dSmrg       || ctx->ViewportArray[0].X + ctx->ViewportArray[0].Width > (GLfloat) ctx->DrawBuffer->Width
78af69d88dSmrg       || ctx->ViewportArray[0].Y < 0
79af69d88dSmrg       || ctx->ViewportArray[0].Y + ctx->ViewportArray[0].Height > (GLfloat) ctx->DrawBuffer->Height) {
807117f1b4Smrg      rasterMask |= CLIP_BIT;
817117f1b4Smrg   }
827117f1b4Smrg
837117f1b4Smrg   if (ctx->Query.CurrentOcclusionObject)
847117f1b4Smrg      rasterMask |= OCCLUSION_BIT;
857117f1b4Smrg
867117f1b4Smrg
877117f1b4Smrg   /* If we're not drawing to exactly one color buffer set the
887117f1b4Smrg    * MULTI_DRAW_BIT flag.  Also set it if we're drawing to no
897117f1b4Smrg    * buffers or the RGBA or CI mask disables all writes.
907117f1b4Smrg    */
91c1f859d4Smrg   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
927117f1b4Smrg      /* more than one color buffer designated for writing (or zero buffers) */
937117f1b4Smrg      rasterMask |= MULTI_DRAW_BIT;
947117f1b4Smrg   }
95cdc920a0Smrg
96cdc920a0Smrg   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
9701e04c3fSmrg      if (GET_COLORMASK(ctx->Color.ColorMask, i) == 0) {
98cdc920a0Smrg         rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
99cdc920a0Smrg         break;
100cdc920a0Smrg      }
1017117f1b4Smrg   }
1027117f1b4Smrg
103cdc920a0Smrg
104af69d88dSmrg   if (_swrast_use_fragment_program(ctx)) {
1057117f1b4Smrg      rasterMask |= FRAGPROG_BIT;
1067117f1b4Smrg   }
1077117f1b4Smrg
10801e04c3fSmrg   if (_mesa_ati_fragment_shader_enabled(ctx)) {
1097117f1b4Smrg      rasterMask |= ATIFRAGSHADER_BIT;
1107117f1b4Smrg   }
1117117f1b4Smrg
1127117f1b4Smrg#if CHAN_TYPE == GL_FLOAT
1137117f1b4Smrg   if (ctx->Color.ClampFragmentColor == GL_TRUE) {
1147117f1b4Smrg      rasterMask |= CLAMPING_BIT;
1157117f1b4Smrg   }
1167117f1b4Smrg#endif
1177117f1b4Smrg
1187117f1b4Smrg   SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
1197117f1b4Smrg}
1207117f1b4Smrg
1217117f1b4Smrg
1227117f1b4Smrg/**
123c1f859d4Smrg * Examine polygon cull state to compute the _BackfaceCullSign field.
1247117f1b4Smrg * _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces,
1257117f1b4Smrg * and 1 if culling front-faces.  The Polygon FrontFace state also
1267117f1b4Smrg * factors in.
1277117f1b4Smrg */
1287117f1b4Smrgstatic void
1293464ebd5Sriastradh_swrast_update_polygon( struct gl_context *ctx )
1307117f1b4Smrg{
1317117f1b4Smrg   GLfloat backface_sign;
1327117f1b4Smrg
1337117f1b4Smrg   if (ctx->Polygon.CullFlag) {
1347117f1b4Smrg      switch (ctx->Polygon.CullFaceMode) {
1357117f1b4Smrg      case GL_BACK:
136cdc920a0Smrg         backface_sign = -1.0F;
1377117f1b4Smrg	 break;
1387117f1b4Smrg      case GL_FRONT:
139cdc920a0Smrg         backface_sign = 1.0F;
1407117f1b4Smrg	 break;
1417117f1b4Smrg      case GL_FRONT_AND_BACK:
1427ec681f3Smrg         FALLTHROUGH;
1437117f1b4Smrg      default:
144cdc920a0Smrg	 backface_sign = 0.0F;
1457117f1b4Smrg      }
1467117f1b4Smrg   }
1477117f1b4Smrg   else {
148cdc920a0Smrg      backface_sign = 0.0F;
1497117f1b4Smrg   }
1507117f1b4Smrg
1517117f1b4Smrg   SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign;
1527117f1b4Smrg
1537117f1b4Smrg   /* This is for front/back-face determination, but not for culling */
1547117f1b4Smrg   SWRAST_CONTEXT(ctx)->_BackfaceSign
155cdc920a0Smrg      = (ctx->Polygon.FrontFace == GL_CW) ? -1.0F : 1.0F;
1567117f1b4Smrg}
1577117f1b4Smrg
1587117f1b4Smrg
1597117f1b4Smrg
1607117f1b4Smrg/**
1617117f1b4Smrg * Update the _PreferPixelFog field to indicate if we need to compute
1627117f1b4Smrg * fog blend factors (from the fog coords) per-fragment.
1637117f1b4Smrg */
1647117f1b4Smrgstatic void
1653464ebd5Sriastradh_swrast_update_fog_hint( struct gl_context *ctx )
1667117f1b4Smrg{
1677117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1687117f1b4Smrg   swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
169af69d88dSmrg			      _swrast_use_fragment_program(ctx) ||
1707117f1b4Smrg			      (ctx->Hint.Fog == GL_NICEST &&
1717117f1b4Smrg			       swrast->AllowPixelFog));
1727117f1b4Smrg}
1737117f1b4Smrg
1747117f1b4Smrg
1757117f1b4Smrg
1767117f1b4Smrg/**
1774a49301eSmrg * Update the swrast->_TextureCombinePrimary flag.
1787117f1b4Smrg */
1797117f1b4Smrgstatic void
1803464ebd5Sriastradh_swrast_update_texture_env( struct gl_context *ctx )
1817117f1b4Smrg{
1827117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1837117f1b4Smrg   GLuint i;
1844a49301eSmrg
1854a49301eSmrg   swrast->_TextureCombinePrimary = GL_FALSE;
1864a49301eSmrg
1877117f1b4Smrg   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1884a49301eSmrg      const struct gl_tex_env_combine_state *combine =
18901e04c3fSmrg         ctx->Texture.FixedFuncUnit[i]._CurrentCombine;
1904a49301eSmrg      GLuint term;
1914a49301eSmrg      for (term = 0; term < combine->_NumArgsRGB; term++) {
1924a49301eSmrg         if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
1934a49301eSmrg            swrast->_TextureCombinePrimary = GL_TRUE;
1944a49301eSmrg            return;
1954a49301eSmrg         }
1964a49301eSmrg         if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
1974a49301eSmrg            swrast->_TextureCombinePrimary = GL_TRUE;
1984a49301eSmrg            return;
1994a49301eSmrg         }
2007117f1b4Smrg      }
2017117f1b4Smrg   }
2027117f1b4Smrg}
2037117f1b4Smrg
2047117f1b4Smrg
205c1f859d4Smrg/**
206c1f859d4Smrg * Determine if we can defer texturing/shading until after Z/stencil
207c1f859d4Smrg * testing.  This potentially allows us to skip texturing/shading for
208c1f859d4Smrg * lots of fragments.
209c1f859d4Smrg */
210c1f859d4Smrgstatic void
2113464ebd5Sriastradh_swrast_update_deferred_texture(struct gl_context *ctx)
212c1f859d4Smrg{
213c1f859d4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
214c1f859d4Smrg   if (ctx->Color.AlphaEnabled) {
215c1f859d4Smrg      /* alpha test depends on post-texture/shader colors */
216c1f859d4Smrg      swrast->_DeferredTexture = GL_FALSE;
217c1f859d4Smrg   }
218c1f859d4Smrg   else {
219af69d88dSmrg      GLboolean use_fprog = _swrast_use_fragment_program(ctx);
22001e04c3fSmrg      const struct gl_program *fprog = ctx->FragmentProgram._Current;
22101e04c3fSmrg      if (use_fprog &&
22201e04c3fSmrg          (fprog->info.outputs_written & (1 << FRAG_RESULT_DEPTH))) {
223c1f859d4Smrg         /* Z comes from fragment program/shader */
224c1f859d4Smrg         swrast->_DeferredTexture = GL_FALSE;
225c1f859d4Smrg      }
22601e04c3fSmrg      else if (use_fprog && fprog->info.fs.uses_discard) {
2274a49301eSmrg         swrast->_DeferredTexture = GL_FALSE;
2284a49301eSmrg      }
229c1f859d4Smrg      else if (ctx->Query.CurrentOcclusionObject) {
230c1f859d4Smrg         /* occlusion query depends on shader discard/kill results */
231c1f859d4Smrg         swrast->_DeferredTexture = GL_FALSE;
232c1f859d4Smrg      }
233c1f859d4Smrg      else {
234c1f859d4Smrg         swrast->_DeferredTexture = GL_TRUE;
235c1f859d4Smrg      }
236c1f859d4Smrg   }
237c1f859d4Smrg}
238c1f859d4Smrg
239c1f859d4Smrg
2407117f1b4Smrg/**
2417117f1b4Smrg * Update swrast->_FogColor and swrast->_FogEnable values.
2427117f1b4Smrg */
2437117f1b4Smrgstatic void
2443464ebd5Sriastradh_swrast_update_fog_state( struct gl_context *ctx )
2457117f1b4Smrg{
2467117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
24701e04c3fSmrg   const struct gl_program *fp = ctx->FragmentProgram._Current;
2487117f1b4Smrg
24901e04c3fSmrg   assert(fp == NULL || fp->Target == GL_FRAGMENT_PROGRAM_ARB);
25001e04c3fSmrg   (void) fp; /* silence unused var warning */
2513464ebd5Sriastradh
2527117f1b4Smrg   /* determine if fog is needed, and if so, which fog mode */
253af69d88dSmrg   swrast->_FogEnabled = (!_swrast_use_fragment_program(ctx) &&
254af69d88dSmrg			  ctx->Fog.Enabled);
2557117f1b4Smrg}
2567117f1b4Smrg
2577117f1b4Smrg
2587117f1b4Smrg/**
2597117f1b4Smrg * Update state for running fragment programs.  Basically, load the
2607117f1b4Smrg * program parameters with current state values.
2617117f1b4Smrg */
2627117f1b4Smrgstatic void
2633464ebd5Sriastradh_swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState)
2647117f1b4Smrg{
265af69d88dSmrg   if (!_swrast_use_fragment_program(ctx))
266af69d88dSmrg      return;
267af69d88dSmrg
268af69d88dSmrg   _mesa_load_state_parameters(ctx,
26901e04c3fSmrg                               ctx->FragmentProgram._Current->Parameters);
2707117f1b4Smrg}
2717117f1b4Smrg
2727117f1b4Smrg
2734a49301eSmrg/**
2744a49301eSmrg * See if we can do early diffuse+specular (primary+secondary) color
2754a49301eSmrg * add per vertex instead of per-fragment.
2764a49301eSmrg */
2774a49301eSmrgstatic void
2783464ebd5Sriastradh_swrast_update_specular_vertex_add(struct gl_context *ctx)
2794a49301eSmrg{
2804a49301eSmrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
2814a49301eSmrg   GLboolean separateSpecular = ctx->Fog.ColorSumEnabled ||
2824a49301eSmrg      (ctx->Light.Enabled &&
2834a49301eSmrg       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
2844a49301eSmrg
2854a49301eSmrg   swrast->SpecularVertexAdd = (separateSpecular
286af69d88dSmrg                                && ctx->Texture._MaxEnabledTexImageUnit == -1
287af69d88dSmrg                                && !_swrast_use_fragment_program(ctx)
28801e04c3fSmrg                                && !_mesa_ati_fragment_shader_enabled(ctx));
2894a49301eSmrg}
2904a49301eSmrg
2917117f1b4Smrg
2927117f1b4Smrg#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK |	\
2934a49301eSmrg                             _NEW_PROGRAM_CONSTANTS |   \
2947117f1b4Smrg			     _NEW_TEXTURE |		\
2957117f1b4Smrg			     _NEW_HINT |		\
2967117f1b4Smrg			     _NEW_POLYGON )
2977117f1b4Smrg
2987117f1b4Smrg/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
2997117f1b4Smrg */
3007117f1b4Smrg#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED |		\
3017117f1b4Smrg			      _NEW_RENDERMODE|			\
3027117f1b4Smrg                              _NEW_POLYGON|			\
3037117f1b4Smrg                              _NEW_DEPTH|			\
3047117f1b4Smrg                              _NEW_STENCIL|			\
3057117f1b4Smrg                              _NEW_COLOR|			\
3067117f1b4Smrg                              _NEW_TEXTURE|			\
3077117f1b4Smrg                              _SWRAST_NEW_RASTERMASK|		\
3087117f1b4Smrg                              _NEW_LIGHT|			\
3097117f1b4Smrg                              _NEW_FOG |			\
310af69d88dSmrg			      _MESA_NEW_SEPARATE_SPECULAR)
3117117f1b4Smrg
3127117f1b4Smrg#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED |		\
3137117f1b4Smrg			  _NEW_RENDERMODE|		\
3147117f1b4Smrg                          _NEW_LINE|			\
3157117f1b4Smrg                          _NEW_TEXTURE|			\
3167117f1b4Smrg                          _NEW_LIGHT|			\
3177117f1b4Smrg                          _NEW_FOG|			\
3187117f1b4Smrg                          _NEW_DEPTH |			\
319af69d88dSmrg                          _MESA_NEW_SEPARATE_SPECULAR)
3207117f1b4Smrg
3217117f1b4Smrg#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED |	\
3227117f1b4Smrg			   _NEW_RENDERMODE |		\
3237117f1b4Smrg			   _NEW_POINT |			\
3247117f1b4Smrg			   _NEW_TEXTURE |		\
3257117f1b4Smrg			   _NEW_LIGHT |			\
3267117f1b4Smrg			   _NEW_FOG |			\
327af69d88dSmrg                           _MESA_NEW_SEPARATE_SPECULAR)
3287117f1b4Smrg
3297117f1b4Smrg#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
3307117f1b4Smrg
3317117f1b4Smrg#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
3327117f1b4Smrg
3337117f1b4Smrg#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
3347117f1b4Smrg
3357117f1b4Smrg
3367117f1b4Smrg
3377117f1b4Smrg/**
3387117f1b4Smrg * Stub for swrast->Triangle to select a true triangle function
3397117f1b4Smrg * after a state change.
3407117f1b4Smrg */
3417117f1b4Smrgstatic void
3423464ebd5Sriastradh_swrast_validate_triangle( struct gl_context *ctx,
3437117f1b4Smrg			   const SWvertex *v0,
3447117f1b4Smrg                           const SWvertex *v1,
3457117f1b4Smrg                           const SWvertex *v2 )
3467117f1b4Smrg{
3477117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
3487117f1b4Smrg
3497117f1b4Smrg   _swrast_validate_derived( ctx );
3507117f1b4Smrg   swrast->choose_triangle( ctx );
35101e04c3fSmrg   assert(swrast->Triangle);
3527117f1b4Smrg
3534a49301eSmrg   if (swrast->SpecularVertexAdd) {
3547117f1b4Smrg      /* separate specular color, but no texture */
3557117f1b4Smrg      swrast->SpecTriangle = swrast->Triangle;
3567117f1b4Smrg      swrast->Triangle = _swrast_add_spec_terms_triangle;
3577117f1b4Smrg   }
3587117f1b4Smrg
3597117f1b4Smrg   swrast->Triangle( ctx, v0, v1, v2 );
3607117f1b4Smrg}
3617117f1b4Smrg
3627117f1b4Smrg/**
3637117f1b4Smrg * Called via swrast->Line.  Examine current GL state and choose a software
3647117f1b4Smrg * line routine.  Then call it.
3657117f1b4Smrg */
3667117f1b4Smrgstatic void
3673464ebd5Sriastradh_swrast_validate_line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
3687117f1b4Smrg{
3697117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
3707117f1b4Smrg
3717117f1b4Smrg   _swrast_validate_derived( ctx );
3727117f1b4Smrg   swrast->choose_line( ctx );
37301e04c3fSmrg   assert(swrast->Line);
3747117f1b4Smrg
3754a49301eSmrg   if (swrast->SpecularVertexAdd) {
3767117f1b4Smrg      swrast->SpecLine = swrast->Line;
3777117f1b4Smrg      swrast->Line = _swrast_add_spec_terms_line;
3787117f1b4Smrg   }
3797117f1b4Smrg
3807117f1b4Smrg   swrast->Line( ctx, v0, v1 );
3817117f1b4Smrg}
3827117f1b4Smrg
3837117f1b4Smrg/**
3847117f1b4Smrg * Called via swrast->Point.  Examine current GL state and choose a software
3857117f1b4Smrg * point routine.  Then call it.
3867117f1b4Smrg */
3877117f1b4Smrgstatic void
3883464ebd5Sriastradh_swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 )
3897117f1b4Smrg{
3907117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
3917117f1b4Smrg
3927117f1b4Smrg   _swrast_validate_derived( ctx );
3937117f1b4Smrg   swrast->choose_point( ctx );
3947117f1b4Smrg
3954a49301eSmrg   if (swrast->SpecularVertexAdd) {
3967117f1b4Smrg      swrast->SpecPoint = swrast->Point;
3977117f1b4Smrg      swrast->Point = _swrast_add_spec_terms_point;
3987117f1b4Smrg   }
3997117f1b4Smrg
4007117f1b4Smrg   swrast->Point( ctx, v0 );
4017117f1b4Smrg}
4027117f1b4Smrg
4037117f1b4Smrg
4047117f1b4Smrg/**
4057117f1b4Smrg * Called via swrast->BlendFunc.  Examine GL state to choose a blending
4067117f1b4Smrg * function, then call it.
4077117f1b4Smrg */
40801e04c3fSmrgstatic void
4093464ebd5Sriastradh_swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[],
4107117f1b4Smrg                            GLvoid *src, const GLvoid *dst,
4117117f1b4Smrg                            GLenum chanType )
4127117f1b4Smrg{
4137117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
4147117f1b4Smrg
4157117f1b4Smrg   _swrast_validate_derived( ctx ); /* why is this needed? */
4167117f1b4Smrg   _swrast_choose_blend_func( ctx, chanType );
4177117f1b4Smrg
4187117f1b4Smrg   swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
4197117f1b4Smrg}
4207117f1b4Smrg
4217117f1b4Smrgstatic void
4223464ebd5Sriastradh_swrast_sleep( struct gl_context *ctx, GLbitfield new_state )
4237117f1b4Smrg{
4247117f1b4Smrg   (void) ctx; (void) new_state;
4257117f1b4Smrg}
4267117f1b4Smrg
4277117f1b4Smrg
4287117f1b4Smrgstatic void
4293464ebd5Sriastradh_swrast_invalidate_state( struct gl_context *ctx, GLbitfield new_state )
4307117f1b4Smrg{
4317117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
4327117f1b4Smrg   GLuint i;
4337117f1b4Smrg
4347117f1b4Smrg   swrast->NewState |= new_state;
4357117f1b4Smrg
4367117f1b4Smrg   /* After 10 statechanges without any swrast functions being called,
4377117f1b4Smrg    * put the module to sleep.
4387117f1b4Smrg    */
4397117f1b4Smrg   if (++swrast->StateChanges > 10) {
4407117f1b4Smrg      swrast->InvalidateState = _swrast_sleep;
4417117f1b4Smrg      swrast->NewState = ~0;
4427117f1b4Smrg      new_state = ~0;
4437117f1b4Smrg   }
4447117f1b4Smrg
4457117f1b4Smrg   if (new_state & swrast->InvalidateTriangleMask)
4467117f1b4Smrg      swrast->Triangle = _swrast_validate_triangle;
4477117f1b4Smrg
4487117f1b4Smrg   if (new_state & swrast->InvalidateLineMask)
4497117f1b4Smrg      swrast->Line = _swrast_validate_line;
4507117f1b4Smrg
4517117f1b4Smrg   if (new_state & swrast->InvalidatePointMask)
4527117f1b4Smrg      swrast->Point = _swrast_validate_point;
4537117f1b4Smrg
4547117f1b4Smrg   if (new_state & _SWRAST_NEW_BLEND_FUNC)
4557117f1b4Smrg      swrast->BlendFunc = _swrast_validate_blend_func;
4567117f1b4Smrg
4577117f1b4Smrg   if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
458af69d88dSmrg      for (i = 0 ; i < ARRAY_SIZE(swrast->TextureSample); i++)
4597117f1b4Smrg	 swrast->TextureSample[i] = NULL;
4607117f1b4Smrg}
4617117f1b4Smrg
4627117f1b4Smrg
4637117f1b4Smrgvoid
4643464ebd5Sriastradh_swrast_update_texture_samplers(struct gl_context *ctx)
4657117f1b4Smrg{
4667117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
4677117f1b4Smrg   GLuint u;
4687117f1b4Smrg
4694a49301eSmrg   if (!swrast)
4704a49301eSmrg      return; /* pipe hack */
4714a49301eSmrg
472af69d88dSmrg   for (u = 0; u < ARRAY_SIZE(swrast->TextureSample); u++) {
473af69d88dSmrg      struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
4747117f1b4Smrg      /* Note: If tObj is NULL, the sample function will be a simple
4757117f1b4Smrg       * function that just returns opaque black (0,0,0,1).
4767117f1b4Smrg       */
477af69d88dSmrg      _mesa_update_fetch_functions(ctx, u);
478af69d88dSmrg      swrast->TextureSample[u] =
479af69d88dSmrg         _swrast_choose_texture_sample_func(ctx, tObj,
480af69d88dSmrg                                            _mesa_get_samplerobj(ctx, u));
4817117f1b4Smrg   }
4827117f1b4Smrg}
4837117f1b4Smrg
4847117f1b4Smrg
4857117f1b4Smrg/**
486c1f859d4Smrg * Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs,
487c1f859d4Smrg * swrast->_ActiveAtttribMask.
4887117f1b4Smrg */
4897117f1b4Smrgstatic void
4903464ebd5Sriastradh_swrast_update_active_attribs(struct gl_context *ctx)
4917117f1b4Smrg{
4927117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
493af69d88dSmrg   GLbitfield64 attribsMask;
494c1f859d4Smrg
495c1f859d4Smrg   /*
496c1f859d4Smrg    * Compute _ActiveAttribsMask = which fragment attributes are needed.
497c1f859d4Smrg    */
498af69d88dSmrg   if (_swrast_use_fragment_program(ctx)) {
499c1f859d4Smrg      /* fragment program/shader */
50001e04c3fSmrg      attribsMask = ctx->FragmentProgram._Current->info.inputs_read;
501af69d88dSmrg      attribsMask &= ~VARYING_BIT_POS; /* WPOS is always handled specially */
502c1f859d4Smrg   }
50301e04c3fSmrg   else if (_mesa_ati_fragment_shader_enabled(ctx)) {
50401e04c3fSmrg      attribsMask = VARYING_BIT_COL0 | VARYING_BIT_COL1 |
50501e04c3fSmrg                    VARYING_BIT_FOGC | VARYING_BITS_TEX_ANY;
5067117f1b4Smrg   }
5077117f1b4Smrg   else {
508c1f859d4Smrg      /* fixed function */
5097117f1b4Smrg      attribsMask = 0x0;
5107117f1b4Smrg
511c1f859d4Smrg#if CHAN_TYPE == GL_FLOAT
512af69d88dSmrg      attribsMask |= VARYING_BIT_COL0;
5137117f1b4Smrg#endif
514c1f859d4Smrg
515c1f859d4Smrg      if (ctx->Fog.ColorSumEnabled ||
516c1f859d4Smrg          (ctx->Light.Enabled &&
517c1f859d4Smrg           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
518af69d88dSmrg         attribsMask |= VARYING_BIT_COL1;
519c1f859d4Smrg      }
520c1f859d4Smrg
5217117f1b4Smrg      if (swrast->_FogEnabled)
522af69d88dSmrg         attribsMask |= VARYING_BIT_FOGC;
5237117f1b4Smrg
524af69d88dSmrg      attribsMask |= (ctx->Texture._EnabledCoordUnits << VARYING_SLOT_TEX0);
5257117f1b4Smrg   }
5267117f1b4Smrg
527c1f859d4Smrg   swrast->_ActiveAttribMask = attribsMask;
5287117f1b4Smrg
5297117f1b4Smrg   /* Update _ActiveAttribs[] list */
5307117f1b4Smrg   {
5317117f1b4Smrg      GLuint i, num = 0;
532af69d88dSmrg      for (i = 0; i < VARYING_SLOT_MAX; i++) {
533af69d88dSmrg         if (attribsMask & BITFIELD64_BIT(i)) {
5347117f1b4Smrg            swrast->_ActiveAttribs[num++] = i;
535c1f859d4Smrg            /* how should this attribute be interpolated? */
536af69d88dSmrg            if (i == VARYING_SLOT_COL0 || i == VARYING_SLOT_COL1)
537c1f859d4Smrg               swrast->_InterpMode[i] = ctx->Light.ShadeModel;
538c1f859d4Smrg            else
539c1f859d4Smrg               swrast->_InterpMode[i] = GL_SMOOTH;
5407117f1b4Smrg         }
5417117f1b4Smrg      }
542c1f859d4Smrg      swrast->_NumActiveAttribs = num;
5437117f1b4Smrg   }
5447117f1b4Smrg}
5457117f1b4Smrg
5467117f1b4Smrg
5477117f1b4Smrgvoid
5483464ebd5Sriastradh_swrast_validate_derived( struct gl_context *ctx )
5497117f1b4Smrg{
5507117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
5517117f1b4Smrg
5527117f1b4Smrg   if (swrast->NewState) {
5537117f1b4Smrg      if (swrast->NewState & _NEW_POLYGON)
5547117f1b4Smrg	 _swrast_update_polygon( ctx );
5557117f1b4Smrg
5567117f1b4Smrg      if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM))
5577117f1b4Smrg	 _swrast_update_fog_hint( ctx );
5587117f1b4Smrg
5597117f1b4Smrg      if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
5607117f1b4Smrg	 _swrast_update_texture_env( ctx );
5617117f1b4Smrg
5627117f1b4Smrg      if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
5637117f1b4Smrg         _swrast_update_fog_state( ctx );
5647117f1b4Smrg
5654a49301eSmrg      if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM))
5667117f1b4Smrg	 _swrast_update_fragment_program( ctx, swrast->NewState );
5677117f1b4Smrg
568c1f859d4Smrg      if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) {
5697117f1b4Smrg         _swrast_update_texture_samplers( ctx );
570c1f859d4Smrg      }
5717117f1b4Smrg
572c1f859d4Smrg      if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM))
573c1f859d4Smrg         _swrast_update_deferred_texture(ctx);
5747117f1b4Smrg
5757117f1b4Smrg      if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
5767117f1b4Smrg 	 _swrast_update_rasterflags( ctx );
5777117f1b4Smrg
5787117f1b4Smrg      if (swrast->NewState & (_NEW_DEPTH |
5797117f1b4Smrg                              _NEW_FOG |
580c1f859d4Smrg                              _NEW_LIGHT |
5817117f1b4Smrg                              _NEW_PROGRAM |
5827117f1b4Smrg                              _NEW_TEXTURE))
583c1f859d4Smrg         _swrast_update_active_attribs(ctx);
5847117f1b4Smrg
5857ec681f3Smrg      if (swrast->NewState & (_NEW_FOG |
5864a49301eSmrg                              _NEW_PROGRAM |
5874a49301eSmrg                              _NEW_LIGHT |
5884a49301eSmrg                              _NEW_TEXTURE))
5894a49301eSmrg         _swrast_update_specular_vertex_add(ctx);
5904a49301eSmrg
5917117f1b4Smrg      swrast->NewState = 0;
5927117f1b4Smrg      swrast->StateChanges = 0;
5937117f1b4Smrg      swrast->InvalidateState = _swrast_invalidate_state;
5947117f1b4Smrg   }
5957117f1b4Smrg}
5967117f1b4Smrg
5977117f1b4Smrg#define SWRAST_DEBUG 0
5987117f1b4Smrg
599af69d88dSmrg/* Public entrypoints:  See also s_bitmap.c, etc.
6007117f1b4Smrg */
6017117f1b4Smrgvoid
6023464ebd5Sriastradh_swrast_Quad( struct gl_context *ctx,
6037117f1b4Smrg	      const SWvertex *v0, const SWvertex *v1,
6047117f1b4Smrg              const SWvertex *v2, const SWvertex *v3 )
6057117f1b4Smrg{
6067117f1b4Smrg   if (SWRAST_DEBUG) {
6077117f1b4Smrg      _mesa_debug(ctx, "_swrast_Quad\n");
6087117f1b4Smrg      _swrast_print_vertex( ctx, v0 );
6097117f1b4Smrg      _swrast_print_vertex( ctx, v1 );
6107117f1b4Smrg      _swrast_print_vertex( ctx, v2 );
6117117f1b4Smrg      _swrast_print_vertex( ctx, v3 );
6127117f1b4Smrg   }
6137117f1b4Smrg   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
6147117f1b4Smrg   SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
6157117f1b4Smrg}
6167117f1b4Smrg
6177117f1b4Smrgvoid
6183464ebd5Sriastradh_swrast_Triangle( struct gl_context *ctx, const SWvertex *v0,
6197117f1b4Smrg                  const SWvertex *v1, const SWvertex *v2 )
6207117f1b4Smrg{
6217117f1b4Smrg   if (SWRAST_DEBUG) {
6227117f1b4Smrg      _mesa_debug(ctx, "_swrast_Triangle\n");
6237117f1b4Smrg      _swrast_print_vertex( ctx, v0 );
6247117f1b4Smrg      _swrast_print_vertex( ctx, v1 );
6257117f1b4Smrg      _swrast_print_vertex( ctx, v2 );
6267117f1b4Smrg   }
6277117f1b4Smrg   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
6287117f1b4Smrg}
6297117f1b4Smrg
6307117f1b4Smrgvoid
6313464ebd5Sriastradh_swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
6327117f1b4Smrg{
6337117f1b4Smrg   if (SWRAST_DEBUG) {
6347117f1b4Smrg      _mesa_debug(ctx, "_swrast_Line\n");
6357117f1b4Smrg      _swrast_print_vertex( ctx, v0 );
6367117f1b4Smrg      _swrast_print_vertex( ctx, v1 );
6377117f1b4Smrg   }
6387117f1b4Smrg   SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
6397117f1b4Smrg}
6407117f1b4Smrg
6417117f1b4Smrgvoid
6423464ebd5Sriastradh_swrast_Point( struct gl_context *ctx, const SWvertex *v0 )
6437117f1b4Smrg{
6447117f1b4Smrg   if (SWRAST_DEBUG) {
6457117f1b4Smrg      _mesa_debug(ctx, "_swrast_Point\n");
6467117f1b4Smrg      _swrast_print_vertex( ctx, v0 );
6477117f1b4Smrg   }
6487117f1b4Smrg   SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
6497117f1b4Smrg}
6507117f1b4Smrg
6517117f1b4Smrgvoid
6523464ebd5Sriastradh_swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state )
6537117f1b4Smrg{
6547117f1b4Smrg   if (SWRAST_DEBUG) {
6557117f1b4Smrg      _mesa_debug(ctx, "_swrast_InvalidateState\n");
6567117f1b4Smrg   }
6577117f1b4Smrg   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
6587117f1b4Smrg}
6597117f1b4Smrg
6607117f1b4Smrgvoid
6613464ebd5Sriastradh_swrast_ResetLineStipple( struct gl_context *ctx )
6627117f1b4Smrg{
6637117f1b4Smrg   if (SWRAST_DEBUG) {
6647117f1b4Smrg      _mesa_debug(ctx, "_swrast_ResetLineStipple\n");
6657117f1b4Smrg   }
6667117f1b4Smrg   SWRAST_CONTEXT(ctx)->StippleCounter = 0;
6677117f1b4Smrg}
6687117f1b4Smrg
6697117f1b4Smrgvoid
6703464ebd5Sriastradh_swrast_SetFacing(struct gl_context *ctx, GLuint facing)
6717117f1b4Smrg{
6727117f1b4Smrg   SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
6737117f1b4Smrg}
6747117f1b4Smrg
6757117f1b4Smrgvoid
6763464ebd5Sriastradh_swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value )
6777117f1b4Smrg{
6787117f1b4Smrg   if (SWRAST_DEBUG) {
6797117f1b4Smrg      _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
6807117f1b4Smrg   }
6817117f1b4Smrg   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
6827117f1b4Smrg   SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
6837117f1b4Smrg}
6847117f1b4Smrg
6857117f1b4Smrgvoid
6863464ebd5Sriastradh_swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value )
6877117f1b4Smrg{
6887117f1b4Smrg   if (SWRAST_DEBUG) {
6897117f1b4Smrg      _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
6907117f1b4Smrg   }
6917117f1b4Smrg   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
6927117f1b4Smrg   SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
6937117f1b4Smrg}
6947117f1b4Smrg
6957117f1b4Smrg
696af69d88dSmrg/**
697af69d88dSmrg * Initialize native program limits by copying the logical limits.
698af69d88dSmrg * See comments in init_program_limits() in context.c
699af69d88dSmrg */
700af69d88dSmrgstatic void
701af69d88dSmrginit_program_native_limits(struct gl_program_constants *prog)
702af69d88dSmrg{
703af69d88dSmrg   prog->MaxNativeInstructions = prog->MaxInstructions;
704af69d88dSmrg   prog->MaxNativeAluInstructions = prog->MaxAluInstructions;
705af69d88dSmrg   prog->MaxNativeTexInstructions = prog->MaxTexInstructions;
706af69d88dSmrg   prog->MaxNativeTexIndirections = prog->MaxTexIndirections;
707af69d88dSmrg   prog->MaxNativeAttribs = prog->MaxAttribs;
708af69d88dSmrg   prog->MaxNativeTemps = prog->MaxTemps;
709af69d88dSmrg   prog->MaxNativeAddressRegs = prog->MaxAddressRegs;
710af69d88dSmrg   prog->MaxNativeParameters = prog->MaxParameters;
711af69d88dSmrg}
712af69d88dSmrg
713af69d88dSmrg
7147117f1b4SmrgGLboolean
7153464ebd5Sriastradh_swrast_CreateContext( struct gl_context *ctx )
7167117f1b4Smrg{
7177117f1b4Smrg   GLuint i;
718af69d88dSmrg   SWcontext *swrast = calloc(1, sizeof(SWcontext));
719af69d88dSmrg#ifdef _OPENMP
720af69d88dSmrg   const GLuint maxThreads = omp_get_max_threads();
721af69d88dSmrg#else
722af69d88dSmrg   const GLuint maxThreads = 1;
723af69d88dSmrg#endif
724af69d88dSmrg
725af69d88dSmrg   assert(ctx->Const.MaxViewportWidth <= SWRAST_MAX_WIDTH);
726af69d88dSmrg   assert(ctx->Const.MaxViewportHeight <= SWRAST_MAX_WIDTH);
727af69d88dSmrg
728af69d88dSmrg   assert(ctx->Const.MaxRenderbufferSize <= SWRAST_MAX_WIDTH);
729af69d88dSmrg
730af69d88dSmrg   /* make sure largest texture image is <= SWRAST_MAX_WIDTH in size */
7317ec681f3Smrg   assert(ctx->Const.MaxTextureSize <= SWRAST_MAX_WIDTH);
732af69d88dSmrg   assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
733af69d88dSmrg   assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
734af69d88dSmrg
735af69d88dSmrg   assert(PROG_MAX_WIDTH == SWRAST_MAX_WIDTH);
7367117f1b4Smrg
7377117f1b4Smrg   if (SWRAST_DEBUG) {
7387117f1b4Smrg      _mesa_debug(ctx, "_swrast_CreateContext\n");
7397117f1b4Smrg   }
7407117f1b4Smrg
7417117f1b4Smrg   if (!swrast)
7427117f1b4Smrg      return GL_FALSE;
7437117f1b4Smrg
7447117f1b4Smrg   swrast->NewState = ~0;
7457117f1b4Smrg
7467117f1b4Smrg   swrast->choose_point = _swrast_choose_point;
7477117f1b4Smrg   swrast->choose_line = _swrast_choose_line;
7487117f1b4Smrg   swrast->choose_triangle = _swrast_choose_triangle;
7497117f1b4Smrg
7507117f1b4Smrg   swrast->InvalidatePointMask = _SWRAST_NEW_POINT;
7517117f1b4Smrg   swrast->InvalidateLineMask = _SWRAST_NEW_LINE;
7527117f1b4Smrg   swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE;
7537117f1b4Smrg
7547117f1b4Smrg   swrast->Point = _swrast_validate_point;
7557117f1b4Smrg   swrast->Line = _swrast_validate_line;
7567117f1b4Smrg   swrast->Triangle = _swrast_validate_triangle;
7577117f1b4Smrg   swrast->InvalidateState = _swrast_sleep;
7587117f1b4Smrg   swrast->BlendFunc = _swrast_validate_blend_func;
7597117f1b4Smrg
7607117f1b4Smrg   swrast->AllowVertexFog = GL_TRUE;
7617117f1b4Smrg   swrast->AllowPixelFog = GL_TRUE;
7627117f1b4Smrg
763af69d88dSmrg   swrast->Driver.SpanRenderStart = _swrast_span_render_start;
764af69d88dSmrg   swrast->Driver.SpanRenderFinish = _swrast_span_render_finish;
7657117f1b4Smrg
766af69d88dSmrg   for (i = 0; i < ARRAY_SIZE(swrast->TextureSample); i++)
7677117f1b4Smrg      swrast->TextureSample[i] = NULL;
7687117f1b4Smrg
769af69d88dSmrg   /* SpanArrays is global and shared by all SWspan instances. However, when
770af69d88dSmrg    * using multiple threads, it is necessary to have one SpanArrays instance
771af69d88dSmrg    * per thread.
772af69d88dSmrg    */
773af69d88dSmrg   swrast->SpanArrays = malloc(maxThreads * sizeof(SWspanarrays));
7747117f1b4Smrg   if (!swrast->SpanArrays) {
775af69d88dSmrg      free(swrast);
7767117f1b4Smrg      return GL_FALSE;
7777117f1b4Smrg   }
778af69d88dSmrg   for(i = 0; i < maxThreads; i++) {
779af69d88dSmrg      swrast->SpanArrays[i].ChanType = CHAN_TYPE;
7807117f1b4Smrg#if CHAN_TYPE == GL_UNSIGNED_BYTE
781af69d88dSmrg      swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba8;
7827117f1b4Smrg#elif CHAN_TYPE == GL_UNSIGNED_SHORT
783af69d88dSmrg      swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba16;
7847117f1b4Smrg#else
785af69d88dSmrg      swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].attribs[VARYING_SLOT_COL0];
7867117f1b4Smrg#endif
787af69d88dSmrg   }
7887117f1b4Smrg
7897117f1b4Smrg   /* init point span buffer */
7907117f1b4Smrg   swrast->PointSpan.primitive = GL_POINT;
7917117f1b4Smrg   swrast->PointSpan.end = 0;
7927117f1b4Smrg   swrast->PointSpan.facing = 0;
7937117f1b4Smrg   swrast->PointSpan.array = swrast->SpanArrays;
7947117f1b4Smrg
795af69d88dSmrg   init_program_native_limits(&ctx->Const.Program[MESA_SHADER_VERTEX]);
796af69d88dSmrg   init_program_native_limits(&ctx->Const.Program[MESA_SHADER_GEOMETRY]);
797af69d88dSmrg   init_program_native_limits(&ctx->Const.Program[MESA_SHADER_FRAGMENT]);
7987117f1b4Smrg
7997117f1b4Smrg   ctx->swrast_context = swrast;
8007117f1b4Smrg
801af69d88dSmrg   swrast->stencil_temp.buf1 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
802af69d88dSmrg   swrast->stencil_temp.buf2 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
803af69d88dSmrg   swrast->stencil_temp.buf3 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
804af69d88dSmrg   swrast->stencil_temp.buf4 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
805af69d88dSmrg
806af69d88dSmrg   if (!swrast->stencil_temp.buf1 ||
807af69d88dSmrg       !swrast->stencil_temp.buf2 ||
808af69d88dSmrg       !swrast->stencil_temp.buf3 ||
809af69d88dSmrg       !swrast->stencil_temp.buf4) {
810af69d88dSmrg      _swrast_DestroyContext(ctx);
811af69d88dSmrg      return GL_FALSE;
812af69d88dSmrg   }
813af69d88dSmrg
8147117f1b4Smrg   return GL_TRUE;
8157117f1b4Smrg}
8167117f1b4Smrg
8177117f1b4Smrgvoid
8183464ebd5Sriastradh_swrast_DestroyContext( struct gl_context *ctx )
8197117f1b4Smrg{
8207117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8217117f1b4Smrg
8227117f1b4Smrg   if (SWRAST_DEBUG) {
8237117f1b4Smrg      _mesa_debug(ctx, "_swrast_DestroyContext\n");
8247117f1b4Smrg   }
8257117f1b4Smrg
826af69d88dSmrg   free( swrast->SpanArrays );
827af69d88dSmrg   free( swrast->ZoomedArrays );
828af69d88dSmrg   free( swrast->TexelBuffer );
829af69d88dSmrg
830af69d88dSmrg   free(swrast->stencil_temp.buf1);
831af69d88dSmrg   free(swrast->stencil_temp.buf2);
832af69d88dSmrg   free(swrast->stencil_temp.buf3);
833af69d88dSmrg   free(swrast->stencil_temp.buf4);
834af69d88dSmrg
835af69d88dSmrg   free( swrast );
8367117f1b4Smrg
8377117f1b4Smrg   ctx->swrast_context = 0;
8387117f1b4Smrg}
8397117f1b4Smrg
8407117f1b4Smrg
8417117f1b4Smrgstruct swrast_device_driver *
8423464ebd5Sriastradh_swrast_GetDeviceDriverReference( struct gl_context *ctx )
8437117f1b4Smrg{
8447117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8457117f1b4Smrg   return &swrast->Driver;
8467117f1b4Smrg}
8477117f1b4Smrg
8487117f1b4Smrgvoid
8493464ebd5Sriastradh_swrast_flush( struct gl_context *ctx )
8507117f1b4Smrg{
8517117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8527117f1b4Smrg   /* flush any pending fragments from rendering points */
8537117f1b4Smrg   if (swrast->PointSpan.end > 0) {
854cdc920a0Smrg      _swrast_write_rgba_span(ctx, &(swrast->PointSpan));
8557117f1b4Smrg      swrast->PointSpan.end = 0;
8567117f1b4Smrg   }
8577117f1b4Smrg}
8587117f1b4Smrg
8597117f1b4Smrgvoid
8603464ebd5Sriastradh_swrast_render_primitive( struct gl_context *ctx, GLenum prim )
8617117f1b4Smrg{
8627117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8637117f1b4Smrg   if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
8647117f1b4Smrg      _swrast_flush(ctx);
8657117f1b4Smrg   }
8667117f1b4Smrg   swrast->Primitive = prim;
8677117f1b4Smrg}
8687117f1b4Smrg
8697117f1b4Smrg
870af69d88dSmrg/** called via swrast->Driver.SpanRenderStart() */
871af69d88dSmrgvoid
872af69d88dSmrg_swrast_span_render_start(struct gl_context *ctx)
873af69d88dSmrg{
874af69d88dSmrg   _swrast_map_textures(ctx);
875af69d88dSmrg   _swrast_map_renderbuffers(ctx);
876af69d88dSmrg}
877af69d88dSmrg
878af69d88dSmrg
879af69d88dSmrg/** called via swrast->Driver.SpanRenderFinish() */
880af69d88dSmrgvoid
881af69d88dSmrg_swrast_span_render_finish(struct gl_context *ctx)
882af69d88dSmrg{
883af69d88dSmrg   _swrast_unmap_textures(ctx);
884af69d88dSmrg   _swrast_unmap_renderbuffers(ctx);
885af69d88dSmrg}
886af69d88dSmrg
887af69d88dSmrg
8887117f1b4Smrgvoid
8893464ebd5Sriastradh_swrast_render_start( struct gl_context *ctx )
8907117f1b4Smrg{
8917117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8927117f1b4Smrg   if (swrast->Driver.SpanRenderStart)
8937117f1b4Smrg      swrast->Driver.SpanRenderStart( ctx );
8947117f1b4Smrg   swrast->PointSpan.end = 0;
8957117f1b4Smrg}
8967ec681f3Smrg
8977117f1b4Smrgvoid
8983464ebd5Sriastradh_swrast_render_finish( struct gl_context *ctx )
8997117f1b4Smrg{
9007117f1b4Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
90101e04c3fSmrg   struct gl_query_object *query = ctx->Query.CurrentOcclusionObject;
9027117f1b4Smrg
9037117f1b4Smrg   _swrast_flush(ctx);
904af69d88dSmrg
905af69d88dSmrg   if (swrast->Driver.SpanRenderFinish)
906af69d88dSmrg      swrast->Driver.SpanRenderFinish( ctx );
90701e04c3fSmrg
90801e04c3fSmrg   if (query && (query->Target == GL_ANY_SAMPLES_PASSED ||
90901e04c3fSmrg                 query->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE))
91001e04c3fSmrg      query->Result = !!query->Result;
9117117f1b4Smrg}
9127117f1b4Smrg
9137117f1b4Smrg
9147117f1b4Smrg#define SWRAST_DEBUG_VERTICES 0
9157117f1b4Smrg
9167117f1b4Smrgvoid
9173464ebd5Sriastradh_swrast_print_vertex( struct gl_context *ctx, const SWvertex *v )
9187117f1b4Smrg{
9197117f1b4Smrg   GLuint i;
9207117f1b4Smrg
9217117f1b4Smrg   if (SWRAST_DEBUG_VERTICES) {
9227117f1b4Smrg      _mesa_debug(ctx, "win %f %f %f %f\n",
923af69d88dSmrg                  v->attrib[VARYING_SLOT_POS][0],
924af69d88dSmrg                  v->attrib[VARYING_SLOT_POS][1],
925af69d88dSmrg                  v->attrib[VARYING_SLOT_POS][2],
926af69d88dSmrg                  v->attrib[VARYING_SLOT_POS][3]);
9277117f1b4Smrg
9287117f1b4Smrg      for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
929af69d88dSmrg	 if (ctx->Texture.Unit[i]._Current)
9307117f1b4Smrg	    _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
931af69d88dSmrg                        v->attrib[VARYING_SLOT_TEX0 + i][0],
932af69d88dSmrg                        v->attrib[VARYING_SLOT_TEX0 + i][1],
933af69d88dSmrg                        v->attrib[VARYING_SLOT_TEX0 + i][2],
934af69d88dSmrg                        v->attrib[VARYING_SLOT_TEX0 + i][3]);
9357117f1b4Smrg
9367117f1b4Smrg#if CHAN_TYPE == GL_FLOAT
9377117f1b4Smrg      _mesa_debug(ctx, "color %f %f %f %f\n",
9387117f1b4Smrg                  v->color[0], v->color[1], v->color[2], v->color[3]);
9397117f1b4Smrg#else
9407117f1b4Smrg      _mesa_debug(ctx, "color %d %d %d %d\n",
9417117f1b4Smrg                  v->color[0], v->color[1], v->color[2], v->color[3]);
9427117f1b4Smrg#endif
943c1f859d4Smrg      _mesa_debug(ctx, "spec %g %g %g %g\n",
944af69d88dSmrg                  v->attrib[VARYING_SLOT_COL1][0],
945af69d88dSmrg                  v->attrib[VARYING_SLOT_COL1][1],
946af69d88dSmrg                  v->attrib[VARYING_SLOT_COL1][2],
947af69d88dSmrg                  v->attrib[VARYING_SLOT_COL1][3]);
948af69d88dSmrg      _mesa_debug(ctx, "fog %f\n", v->attrib[VARYING_SLOT_FOGC][0]);
949af69d88dSmrg      _mesa_debug(ctx, "index %f\n", v->attrib[VARYING_SLOT_CI][0]);
9507117f1b4Smrg      _mesa_debug(ctx, "pointsize %f\n", v->pointSize);
9517117f1b4Smrg      _mesa_debug(ctx, "\n");
9527117f1b4Smrg   }
9537117f1b4Smrg}
954