1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Keith Whitwell <keith@tungstengraphics.com>
26 *    Brian Paul
27 */
28
29#include "main/imports.h"
30#include "main/bufferobj.h"
31#include "main/colormac.h"
32#include "main/mtypes.h"
33#include "main/samplerobj.h"
34#include "main/teximage.h"
35#include "program/prog_parameter.h"
36#include "program/prog_statevars.h"
37#include "swrast.h"
38#include "s_blend.h"
39#include "s_context.h"
40#include "s_lines.h"
41#include "s_points.h"
42#include "s_span.h"
43#include "s_texfetch.h"
44#include "s_triangle.h"
45#include "s_texfilter.h"
46
47
48/**
49 * Recompute the value of swrast->_RasterMask, etc. according to
50 * the current context.  The _RasterMask field can be easily tested by
51 * drivers to determine certain basic GL state (does the primitive need
52 * stenciling, logic-op, fog, etc?).
53 */
54static void
55_swrast_update_rasterflags( struct gl_context *ctx )
56{
57   SWcontext *swrast = SWRAST_CONTEXT(ctx);
58   GLbitfield rasterMask = 0;
59   GLuint i;
60
61   if (ctx->Color.AlphaEnabled)           rasterMask |= ALPHATEST_BIT;
62   if (ctx->Color.BlendEnabled)           rasterMask |= BLEND_BIT;
63   if (ctx->Depth.Test)                   rasterMask |= DEPTH_BIT;
64   if (swrast->_FogEnabled)               rasterMask |= FOG_BIT;
65   if (ctx->Scissor.Enabled)              rasterMask |= CLIP_BIT;
66   if (ctx->Stencil._Enabled)             rasterMask |= STENCIL_BIT;
67   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
68      if (!ctx->Color.ColorMask[i][0] ||
69          !ctx->Color.ColorMask[i][1] ||
70          !ctx->Color.ColorMask[i][2] ||
71          !ctx->Color.ColorMask[i][3]) {
72         rasterMask |= MASKING_BIT;
73         break;
74      }
75   }
76   if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
77   if (ctx->Texture._EnabledUnits)     rasterMask |= TEXTURE_BIT;
78   if (   ctx->Viewport.X < 0
79       || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width
80       || ctx->Viewport.Y < 0
81       || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) {
82      rasterMask |= CLIP_BIT;
83   }
84
85   if (ctx->Query.CurrentOcclusionObject)
86      rasterMask |= OCCLUSION_BIT;
87
88
89   /* If we're not drawing to exactly one color buffer set the
90    * MULTI_DRAW_BIT flag.  Also set it if we're drawing to no
91    * buffers or the RGBA or CI mask disables all writes.
92    */
93   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
94      /* more than one color buffer designated for writing (or zero buffers) */
95      rasterMask |= MULTI_DRAW_BIT;
96   }
97
98   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
99      if (ctx->Color.ColorMask[i][0] +
100          ctx->Color.ColorMask[i][1] +
101          ctx->Color.ColorMask[i][2] +
102          ctx->Color.ColorMask[i][3] == 0) {
103         rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
104         break;
105      }
106   }
107
108
109   if (_swrast_use_fragment_program(ctx)) {
110      rasterMask |= FRAGPROG_BIT;
111   }
112
113   if (ctx->ATIFragmentShader._Enabled) {
114      rasterMask |= ATIFRAGSHADER_BIT;
115   }
116
117#if CHAN_TYPE == GL_FLOAT
118   if (ctx->Color.ClampFragmentColor == GL_TRUE) {
119      rasterMask |= CLAMPING_BIT;
120   }
121#endif
122
123   SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
124}
125
126
127/**
128 * Examine polygon cull state to compute the _BackfaceCullSign field.
129 * _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces,
130 * and 1 if culling front-faces.  The Polygon FrontFace state also
131 * factors in.
132 */
133static void
134_swrast_update_polygon( struct gl_context *ctx )
135{
136   GLfloat backface_sign;
137
138   if (ctx->Polygon.CullFlag) {
139      switch (ctx->Polygon.CullFaceMode) {
140      case GL_BACK:
141         backface_sign = -1.0F;
142	 break;
143      case GL_FRONT:
144         backface_sign = 1.0F;
145	 break;
146      case GL_FRONT_AND_BACK:
147         /* fallthrough */
148      default:
149	 backface_sign = 0.0F;
150      }
151   }
152   else {
153      backface_sign = 0.0F;
154   }
155
156   SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign;
157
158   /* This is for front/back-face determination, but not for culling */
159   SWRAST_CONTEXT(ctx)->_BackfaceSign
160      = (ctx->Polygon.FrontFace == GL_CW) ? -1.0F : 1.0F;
161}
162
163
164
165/**
166 * Update the _PreferPixelFog field to indicate if we need to compute
167 * fog blend factors (from the fog coords) per-fragment.
168 */
169static void
170_swrast_update_fog_hint( struct gl_context *ctx )
171{
172   SWcontext *swrast = SWRAST_CONTEXT(ctx);
173   swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
174			      _swrast_use_fragment_program(ctx) ||
175			      (ctx->Hint.Fog == GL_NICEST &&
176			       swrast->AllowPixelFog));
177}
178
179
180
181/**
182 * Update the swrast->_TextureCombinePrimary flag.
183 */
184static void
185_swrast_update_texture_env( struct gl_context *ctx )
186{
187   SWcontext *swrast = SWRAST_CONTEXT(ctx);
188   GLuint i;
189
190   swrast->_TextureCombinePrimary = GL_FALSE;
191
192   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
193      const struct gl_tex_env_combine_state *combine =
194         ctx->Texture.Unit[i]._CurrentCombine;
195      GLuint term;
196      for (term = 0; term < combine->_NumArgsRGB; term++) {
197         if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
198            swrast->_TextureCombinePrimary = GL_TRUE;
199            return;
200         }
201         if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
202            swrast->_TextureCombinePrimary = GL_TRUE;
203            return;
204         }
205      }
206   }
207}
208
209
210/**
211 * Determine if we can defer texturing/shading until after Z/stencil
212 * testing.  This potentially allows us to skip texturing/shading for
213 * lots of fragments.
214 */
215static void
216_swrast_update_deferred_texture(struct gl_context *ctx)
217{
218   SWcontext *swrast = SWRAST_CONTEXT(ctx);
219   if (ctx->Color.AlphaEnabled) {
220      /* alpha test depends on post-texture/shader colors */
221      swrast->_DeferredTexture = GL_FALSE;
222   }
223   else {
224      GLboolean use_fprog = _swrast_use_fragment_program(ctx);
225      const struct gl_fragment_program *fprog
226         = ctx->FragmentProgram._Current;
227      if (use_fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) {
228         /* Z comes from fragment program/shader */
229         swrast->_DeferredTexture = GL_FALSE;
230      }
231      else if (use_fprog && fprog->UsesKill) {
232         swrast->_DeferredTexture = GL_FALSE;
233      }
234      else if (ctx->Query.CurrentOcclusionObject) {
235         /* occlusion query depends on shader discard/kill results */
236         swrast->_DeferredTexture = GL_FALSE;
237      }
238      else {
239         swrast->_DeferredTexture = GL_TRUE;
240      }
241   }
242}
243
244
245/**
246 * Update swrast->_FogColor and swrast->_FogEnable values.
247 */
248static void
249_swrast_update_fog_state( struct gl_context *ctx )
250{
251   SWcontext *swrast = SWRAST_CONTEXT(ctx);
252   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
253
254   assert((fp == NULL) ||
255          (fp->Base.Target == GL_FRAGMENT_PROGRAM_ARB) ||
256          (fp->Base.Target == GL_FRAGMENT_PROGRAM_NV));
257
258   /* determine if fog is needed, and if so, which fog mode */
259   swrast->_FogEnabled = (!_swrast_use_fragment_program(ctx) &&
260			  ctx->Fog.Enabled);
261}
262
263
264/**
265 * Update state for running fragment programs.  Basically, load the
266 * program parameters with current state values.
267 */
268static void
269_swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState)
270{
271   if (!_swrast_use_fragment_program(ctx))
272      return;
273
274   _mesa_load_state_parameters(ctx,
275                               ctx->FragmentProgram._Current->Base.Parameters);
276}
277
278
279/**
280 * See if we can do early diffuse+specular (primary+secondary) color
281 * add per vertex instead of per-fragment.
282 */
283static void
284_swrast_update_specular_vertex_add(struct gl_context *ctx)
285{
286   SWcontext *swrast = SWRAST_CONTEXT(ctx);
287   GLboolean separateSpecular = ctx->Fog.ColorSumEnabled ||
288      (ctx->Light.Enabled &&
289       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
290
291   swrast->SpecularVertexAdd = (separateSpecular
292                                && ctx->Texture._EnabledUnits == 0x0
293                                && !_swrast_use_fragment_program(ctx)
294                                && !ctx->ATIFragmentShader._Enabled);
295}
296
297
298#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK |	\
299                             _NEW_PROGRAM_CONSTANTS |   \
300			     _NEW_TEXTURE |		\
301			     _NEW_HINT |		\
302			     _NEW_POLYGON )
303
304/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
305 */
306#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED |		\
307			      _NEW_RENDERMODE|			\
308                              _NEW_POLYGON|			\
309                              _NEW_DEPTH|			\
310                              _NEW_STENCIL|			\
311                              _NEW_COLOR|			\
312                              _NEW_TEXTURE|			\
313                              _SWRAST_NEW_RASTERMASK|		\
314                              _NEW_LIGHT|			\
315                              _NEW_FOG |			\
316			      _MESA_NEW_SEPARATE_SPECULAR)
317
318#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED |		\
319			  _NEW_RENDERMODE|		\
320                          _NEW_LINE|			\
321                          _NEW_TEXTURE|			\
322                          _NEW_LIGHT|			\
323                          _NEW_FOG|			\
324                          _NEW_DEPTH |			\
325                          _MESA_NEW_SEPARATE_SPECULAR)
326
327#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED |	\
328			   _NEW_RENDERMODE |		\
329			   _NEW_POINT |			\
330			   _NEW_TEXTURE |		\
331			   _NEW_LIGHT |			\
332			   _NEW_FOG |			\
333                           _MESA_NEW_SEPARATE_SPECULAR)
334
335#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
336
337#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
338
339#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
340
341
342
343/**
344 * Stub for swrast->Triangle to select a true triangle function
345 * after a state change.
346 */
347static void
348_swrast_validate_triangle( struct gl_context *ctx,
349			   const SWvertex *v0,
350                           const SWvertex *v1,
351                           const SWvertex *v2 )
352{
353   SWcontext *swrast = SWRAST_CONTEXT(ctx);
354
355   _swrast_validate_derived( ctx );
356   swrast->choose_triangle( ctx );
357   ASSERT(swrast->Triangle);
358
359   if (swrast->SpecularVertexAdd) {
360      /* separate specular color, but no texture */
361      swrast->SpecTriangle = swrast->Triangle;
362      swrast->Triangle = _swrast_add_spec_terms_triangle;
363   }
364
365   swrast->Triangle( ctx, v0, v1, v2 );
366}
367
368/**
369 * Called via swrast->Line.  Examine current GL state and choose a software
370 * line routine.  Then call it.
371 */
372static void
373_swrast_validate_line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
374{
375   SWcontext *swrast = SWRAST_CONTEXT(ctx);
376
377   _swrast_validate_derived( ctx );
378   swrast->choose_line( ctx );
379   ASSERT(swrast->Line);
380
381   if (swrast->SpecularVertexAdd) {
382      swrast->SpecLine = swrast->Line;
383      swrast->Line = _swrast_add_spec_terms_line;
384   }
385
386   swrast->Line( ctx, v0, v1 );
387}
388
389/**
390 * Called via swrast->Point.  Examine current GL state and choose a software
391 * point routine.  Then call it.
392 */
393static void
394_swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 )
395{
396   SWcontext *swrast = SWRAST_CONTEXT(ctx);
397
398   _swrast_validate_derived( ctx );
399   swrast->choose_point( ctx );
400
401   if (swrast->SpecularVertexAdd) {
402      swrast->SpecPoint = swrast->Point;
403      swrast->Point = _swrast_add_spec_terms_point;
404   }
405
406   swrast->Point( ctx, v0 );
407}
408
409
410/**
411 * Called via swrast->BlendFunc.  Examine GL state to choose a blending
412 * function, then call it.
413 */
414static void _ASMAPI
415_swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[],
416                            GLvoid *src, const GLvoid *dst,
417                            GLenum chanType )
418{
419   SWcontext *swrast = SWRAST_CONTEXT(ctx);
420
421   _swrast_validate_derived( ctx ); /* why is this needed? */
422   _swrast_choose_blend_func( ctx, chanType );
423
424   swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
425}
426
427static void
428_swrast_sleep( struct gl_context *ctx, GLbitfield new_state )
429{
430   (void) ctx; (void) new_state;
431}
432
433
434static void
435_swrast_invalidate_state( struct gl_context *ctx, GLbitfield new_state )
436{
437   SWcontext *swrast = SWRAST_CONTEXT(ctx);
438   GLuint i;
439
440   swrast->NewState |= new_state;
441
442   /* After 10 statechanges without any swrast functions being called,
443    * put the module to sleep.
444    */
445   if (++swrast->StateChanges > 10) {
446      swrast->InvalidateState = _swrast_sleep;
447      swrast->NewState = ~0;
448      new_state = ~0;
449   }
450
451   if (new_state & swrast->InvalidateTriangleMask)
452      swrast->Triangle = _swrast_validate_triangle;
453
454   if (new_state & swrast->InvalidateLineMask)
455      swrast->Line = _swrast_validate_line;
456
457   if (new_state & swrast->InvalidatePointMask)
458      swrast->Point = _swrast_validate_point;
459
460   if (new_state & _SWRAST_NEW_BLEND_FUNC)
461      swrast->BlendFunc = _swrast_validate_blend_func;
462
463   if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
464      for (i = 0 ; i < ctx->Const.MaxTextureImageUnits ; i++)
465	 swrast->TextureSample[i] = NULL;
466}
467
468
469void
470_swrast_update_texture_samplers(struct gl_context *ctx)
471{
472   SWcontext *swrast = SWRAST_CONTEXT(ctx);
473   GLuint u;
474
475   if (!swrast)
476      return; /* pipe hack */
477
478   for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
479      struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
480      /* Note: If tObj is NULL, the sample function will be a simple
481       * function that just returns opaque black (0,0,0,1).
482       */
483      _mesa_update_fetch_functions(ctx, u);
484      swrast->TextureSample[u] =
485         _swrast_choose_texture_sample_func(ctx, tObj,
486                                            _mesa_get_samplerobj(ctx, u));
487   }
488}
489
490
491/**
492 * Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs,
493 * swrast->_ActiveAtttribMask.
494 */
495static void
496_swrast_update_active_attribs(struct gl_context *ctx)
497{
498   SWcontext *swrast = SWRAST_CONTEXT(ctx);
499   GLbitfield64 attribsMask;
500
501   /*
502    * Compute _ActiveAttribsMask = which fragment attributes are needed.
503    */
504   if (_swrast_use_fragment_program(ctx)) {
505      /* fragment program/shader */
506      attribsMask = ctx->FragmentProgram._Current->Base.InputsRead;
507      attribsMask &= ~FRAG_BIT_WPOS; /* WPOS is always handled specially */
508   }
509   else if (ctx->ATIFragmentShader._Enabled) {
510      attribsMask = ~0;  /* XXX fix me */
511   }
512   else {
513      /* fixed function */
514      attribsMask = 0x0;
515
516#if CHAN_TYPE == GL_FLOAT
517      attribsMask |= FRAG_BIT_COL0;
518#endif
519
520      if (ctx->Fog.ColorSumEnabled ||
521          (ctx->Light.Enabled &&
522           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
523         attribsMask |= FRAG_BIT_COL1;
524      }
525
526      if (swrast->_FogEnabled)
527         attribsMask |= FRAG_BIT_FOGC;
528
529      attribsMask |= (ctx->Texture._EnabledUnits << FRAG_ATTRIB_TEX0);
530   }
531
532   swrast->_ActiveAttribMask = attribsMask;
533
534   /* Update _ActiveAttribs[] list */
535   {
536      GLuint i, num = 0;
537      for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
538         if (attribsMask & BITFIELD64_BIT(i)) {
539            swrast->_ActiveAttribs[num++] = i;
540            /* how should this attribute be interpolated? */
541            if (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1)
542               swrast->_InterpMode[i] = ctx->Light.ShadeModel;
543            else
544               swrast->_InterpMode[i] = GL_SMOOTH;
545         }
546      }
547      swrast->_NumActiveAttribs = num;
548   }
549}
550
551
552void
553_swrast_validate_derived( struct gl_context *ctx )
554{
555   SWcontext *swrast = SWRAST_CONTEXT(ctx);
556
557   if (swrast->NewState) {
558      if (swrast->NewState & _NEW_POLYGON)
559	 _swrast_update_polygon( ctx );
560
561      if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM))
562	 _swrast_update_fog_hint( ctx );
563
564      if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
565	 _swrast_update_texture_env( ctx );
566
567      if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
568         _swrast_update_fog_state( ctx );
569
570      if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM))
571	 _swrast_update_fragment_program( ctx, swrast->NewState );
572
573      if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) {
574         _swrast_update_texture_samplers( ctx );
575      }
576
577      if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM))
578         _swrast_update_deferred_texture(ctx);
579
580      if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
581 	 _swrast_update_rasterflags( ctx );
582
583      if (swrast->NewState & (_NEW_DEPTH |
584                              _NEW_FOG |
585                              _NEW_LIGHT |
586                              _NEW_PROGRAM |
587                              _NEW_TEXTURE))
588         _swrast_update_active_attribs(ctx);
589
590      if (swrast->NewState & (_NEW_FOG |
591                              _NEW_PROGRAM |
592                              _NEW_LIGHT |
593                              _NEW_TEXTURE))
594         _swrast_update_specular_vertex_add(ctx);
595
596      swrast->NewState = 0;
597      swrast->StateChanges = 0;
598      swrast->InvalidateState = _swrast_invalidate_state;
599   }
600}
601
602#define SWRAST_DEBUG 0
603
604/* Public entrypoints:  See also s_bitmap.c, etc.
605 */
606void
607_swrast_Quad( struct gl_context *ctx,
608	      const SWvertex *v0, const SWvertex *v1,
609              const SWvertex *v2, const SWvertex *v3 )
610{
611   if (SWRAST_DEBUG) {
612      _mesa_debug(ctx, "_swrast_Quad\n");
613      _swrast_print_vertex( ctx, v0 );
614      _swrast_print_vertex( ctx, v1 );
615      _swrast_print_vertex( ctx, v2 );
616      _swrast_print_vertex( ctx, v3 );
617   }
618   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
619   SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
620}
621
622void
623_swrast_Triangle( struct gl_context *ctx, const SWvertex *v0,
624                  const SWvertex *v1, const SWvertex *v2 )
625{
626   if (SWRAST_DEBUG) {
627      _mesa_debug(ctx, "_swrast_Triangle\n");
628      _swrast_print_vertex( ctx, v0 );
629      _swrast_print_vertex( ctx, v1 );
630      _swrast_print_vertex( ctx, v2 );
631   }
632   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
633}
634
635void
636_swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
637{
638   if (SWRAST_DEBUG) {
639      _mesa_debug(ctx, "_swrast_Line\n");
640      _swrast_print_vertex( ctx, v0 );
641      _swrast_print_vertex( ctx, v1 );
642   }
643   SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
644}
645
646void
647_swrast_Point( struct gl_context *ctx, const SWvertex *v0 )
648{
649   if (SWRAST_DEBUG) {
650      _mesa_debug(ctx, "_swrast_Point\n");
651      _swrast_print_vertex( ctx, v0 );
652   }
653   SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
654}
655
656void
657_swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state )
658{
659   if (SWRAST_DEBUG) {
660      _mesa_debug(ctx, "_swrast_InvalidateState\n");
661   }
662   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
663}
664
665void
666_swrast_ResetLineStipple( struct gl_context *ctx )
667{
668   if (SWRAST_DEBUG) {
669      _mesa_debug(ctx, "_swrast_ResetLineStipple\n");
670   }
671   SWRAST_CONTEXT(ctx)->StippleCounter = 0;
672}
673
674void
675_swrast_SetFacing(struct gl_context *ctx, GLuint facing)
676{
677   SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
678}
679
680void
681_swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value )
682{
683   if (SWRAST_DEBUG) {
684      _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
685   }
686   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
687   SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
688}
689
690void
691_swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value )
692{
693   if (SWRAST_DEBUG) {
694      _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
695   }
696   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
697   SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
698}
699
700
701/**
702 * Initialize native program limits by copying the logical limits.
703 * See comments in init_program_limits() in context.c
704 */
705static void
706init_program_native_limits(struct gl_program_constants *prog)
707{
708   prog->MaxNativeInstructions = prog->MaxInstructions;
709   prog->MaxNativeAluInstructions = prog->MaxAluInstructions;
710   prog->MaxNativeTexInstructions = prog->MaxTexInstructions;
711   prog->MaxNativeTexIndirections = prog->MaxTexIndirections;
712   prog->MaxNativeAttribs = prog->MaxAttribs;
713   prog->MaxNativeTemps = prog->MaxTemps;
714   prog->MaxNativeAddressRegs = prog->MaxAddressRegs;
715   prog->MaxNativeParameters = prog->MaxParameters;
716}
717
718
719GLboolean
720_swrast_CreateContext( struct gl_context *ctx )
721{
722   GLuint i;
723   SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext));
724#ifdef _OPENMP
725   const GLuint maxThreads = omp_get_max_threads();
726#else
727   const GLuint maxThreads = 1;
728#endif
729
730   assert(ctx->Const.MaxViewportWidth <= SWRAST_MAX_WIDTH);
731   assert(ctx->Const.MaxViewportHeight <= SWRAST_MAX_WIDTH);
732
733   assert(ctx->Const.MaxRenderbufferSize <= SWRAST_MAX_WIDTH);
734
735   /* make sure largest texture image is <= SWRAST_MAX_WIDTH in size */
736   assert((1 << (ctx->Const.MaxTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
737   assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
738   assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
739
740   assert(PROG_MAX_WIDTH == SWRAST_MAX_WIDTH);
741
742   if (SWRAST_DEBUG) {
743      _mesa_debug(ctx, "_swrast_CreateContext\n");
744   }
745
746   if (!swrast)
747      return GL_FALSE;
748
749   swrast->NewState = ~0;
750
751   swrast->choose_point = _swrast_choose_point;
752   swrast->choose_line = _swrast_choose_line;
753   swrast->choose_triangle = _swrast_choose_triangle;
754
755   swrast->InvalidatePointMask = _SWRAST_NEW_POINT;
756   swrast->InvalidateLineMask = _SWRAST_NEW_LINE;
757   swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE;
758
759   swrast->Point = _swrast_validate_point;
760   swrast->Line = _swrast_validate_line;
761   swrast->Triangle = _swrast_validate_triangle;
762   swrast->InvalidateState = _swrast_sleep;
763   swrast->BlendFunc = _swrast_validate_blend_func;
764
765   swrast->AllowVertexFog = GL_TRUE;
766   swrast->AllowPixelFog = GL_TRUE;
767
768   swrast->Driver.SpanRenderStart = _swrast_span_render_start;
769   swrast->Driver.SpanRenderFinish = _swrast_span_render_finish;
770
771   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
772      swrast->TextureSample[i] = NULL;
773
774   /* SpanArrays is global and shared by all SWspan instances. However, when
775    * using multiple threads, it is necessary to have one SpanArrays instance
776    * per thread.
777    */
778   swrast->SpanArrays = (SWspanarrays *) MALLOC(maxThreads * sizeof(SWspanarrays));
779   if (!swrast->SpanArrays) {
780      FREE(swrast);
781      return GL_FALSE;
782   }
783   for(i = 0; i < maxThreads; i++) {
784      swrast->SpanArrays[i].ChanType = CHAN_TYPE;
785#if CHAN_TYPE == GL_UNSIGNED_BYTE
786      swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba8;
787#elif CHAN_TYPE == GL_UNSIGNED_SHORT
788      swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba16;
789#else
790      swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].attribs[FRAG_ATTRIB_COL0];
791#endif
792   }
793
794   /* init point span buffer */
795   swrast->PointSpan.primitive = GL_POINT;
796   swrast->PointSpan.end = 0;
797   swrast->PointSpan.facing = 0;
798   swrast->PointSpan.array = swrast->SpanArrays;
799
800   init_program_native_limits(&ctx->Const.VertexProgram);
801   init_program_native_limits(&ctx->Const.GeometryProgram);
802   init_program_native_limits(&ctx->Const.FragmentProgram);
803
804   ctx->swrast_context = swrast;
805
806   swrast->stencil_temp.buf1 = (GLubyte *) malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
807   swrast->stencil_temp.buf2 = (GLubyte *) malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
808   swrast->stencil_temp.buf3 = (GLubyte *) malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
809   swrast->stencil_temp.buf4 = (GLubyte *) malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
810
811   if (!swrast->stencil_temp.buf1 ||
812       !swrast->stencil_temp.buf2 ||
813       !swrast->stencil_temp.buf3 ||
814       !swrast->stencil_temp.buf4) {
815      _swrast_DestroyContext(ctx);
816      return GL_FALSE;
817   }
818
819   return GL_TRUE;
820}
821
822void
823_swrast_DestroyContext( struct gl_context *ctx )
824{
825   SWcontext *swrast = SWRAST_CONTEXT(ctx);
826
827   if (SWRAST_DEBUG) {
828      _mesa_debug(ctx, "_swrast_DestroyContext\n");
829   }
830
831   FREE( swrast->SpanArrays );
832   if (swrast->ZoomedArrays)
833      FREE( swrast->ZoomedArrays );
834   FREE( swrast->TexelBuffer );
835
836   free(swrast->stencil_temp.buf1);
837   free(swrast->stencil_temp.buf2);
838   free(swrast->stencil_temp.buf3);
839   free(swrast->stencil_temp.buf4);
840
841   FREE( swrast );
842
843   ctx->swrast_context = 0;
844}
845
846
847struct swrast_device_driver *
848_swrast_GetDeviceDriverReference( struct gl_context *ctx )
849{
850   SWcontext *swrast = SWRAST_CONTEXT(ctx);
851   return &swrast->Driver;
852}
853
854void
855_swrast_flush( struct gl_context *ctx )
856{
857   SWcontext *swrast = SWRAST_CONTEXT(ctx);
858   /* flush any pending fragments from rendering points */
859   if (swrast->PointSpan.end > 0) {
860      _swrast_write_rgba_span(ctx, &(swrast->PointSpan));
861      swrast->PointSpan.end = 0;
862   }
863}
864
865void
866_swrast_render_primitive( struct gl_context *ctx, GLenum prim )
867{
868   SWcontext *swrast = SWRAST_CONTEXT(ctx);
869   if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
870      _swrast_flush(ctx);
871   }
872   swrast->Primitive = prim;
873}
874
875
876/** called via swrast->Driver.SpanRenderStart() */
877void
878_swrast_span_render_start(struct gl_context *ctx)
879{
880   _swrast_map_textures(ctx);
881   _swrast_map_renderbuffers(ctx);
882}
883
884
885/** called via swrast->Driver.SpanRenderFinish() */
886void
887_swrast_span_render_finish(struct gl_context *ctx)
888{
889   _swrast_unmap_textures(ctx);
890   _swrast_unmap_renderbuffers(ctx);
891}
892
893
894void
895_swrast_render_start( struct gl_context *ctx )
896{
897   SWcontext *swrast = SWRAST_CONTEXT(ctx);
898   if (swrast->Driver.SpanRenderStart)
899      swrast->Driver.SpanRenderStart( ctx );
900   swrast->PointSpan.end = 0;
901}
902
903void
904_swrast_render_finish( struct gl_context *ctx )
905{
906   SWcontext *swrast = SWRAST_CONTEXT(ctx);
907
908   _swrast_flush(ctx);
909
910   if (swrast->Driver.SpanRenderFinish)
911      swrast->Driver.SpanRenderFinish( ctx );
912}
913
914
915#define SWRAST_DEBUG_VERTICES 0
916
917void
918_swrast_print_vertex( struct gl_context *ctx, const SWvertex *v )
919{
920   GLuint i;
921
922   if (SWRAST_DEBUG_VERTICES) {
923      _mesa_debug(ctx, "win %f %f %f %f\n",
924                  v->attrib[FRAG_ATTRIB_WPOS][0],
925                  v->attrib[FRAG_ATTRIB_WPOS][1],
926                  v->attrib[FRAG_ATTRIB_WPOS][2],
927                  v->attrib[FRAG_ATTRIB_WPOS][3]);
928
929      for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
930	 if (ctx->Texture.Unit[i]._ReallyEnabled)
931	    _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
932                        v->attrib[FRAG_ATTRIB_TEX0 + i][0],
933                        v->attrib[FRAG_ATTRIB_TEX0 + i][1],
934                        v->attrib[FRAG_ATTRIB_TEX0 + i][2],
935                        v->attrib[FRAG_ATTRIB_TEX0 + i][3]);
936
937#if CHAN_TYPE == GL_FLOAT
938      _mesa_debug(ctx, "color %f %f %f %f\n",
939                  v->color[0], v->color[1], v->color[2], v->color[3]);
940#else
941      _mesa_debug(ctx, "color %d %d %d %d\n",
942                  v->color[0], v->color[1], v->color[2], v->color[3]);
943#endif
944      _mesa_debug(ctx, "spec %g %g %g %g\n",
945                  v->attrib[FRAG_ATTRIB_COL1][0],
946                  v->attrib[FRAG_ATTRIB_COL1][1],
947                  v->attrib[FRAG_ATTRIB_COL1][2],
948                  v->attrib[FRAG_ATTRIB_COL1][3]);
949      _mesa_debug(ctx, "fog %f\n", v->attrib[FRAG_ATTRIB_FOGC][0]);
950      _mesa_debug(ctx, "index %f\n", v->attrib[FRAG_ATTRIB_CI][0]);
951      _mesa_debug(ctx, "pointsize %f\n", v->pointSize);
952      _mesa_debug(ctx, "\n");
953   }
954}
955