s_context.c revision 0bf5dbe002a64e198f55724cc1542602c012490f
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.1
4 *
5 * Copyright (C) 1999-2006  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 "imports.h"
30#include "bufferobj.h"
31#include "context.h"
32#include "colormac.h"
33#include "mtypes.h"
34#include "prog_statevars.h"
35#include "teximage.h"
36#include "swrast.h"
37#include "s_blend.h"
38#include "s_context.h"
39#include "s_lines.h"
40#include "s_points.h"
41#include "s_span.h"
42#include "s_triangle.h"
43#include "s_texfilter.h"
44
45
46/**
47 * Recompute the value of swrast->_RasterMask, etc. according to
48 * the current context.  The _RasterMask field can be easily tested by
49 * drivers to determine certain basic GL state (does the primitive need
50 * stenciling, logic-op, fog, etc?).
51 */
52static void
53_swrast_update_rasterflags( GLcontext *ctx )
54{
55   SWcontext *swrast = SWRAST_CONTEXT(ctx);
56   GLbitfield rasterMask = 0;
57
58   if (ctx->Color.AlphaEnabled)           rasterMask |= ALPHATEST_BIT;
59   if (ctx->Color.BlendEnabled)           rasterMask |= BLEND_BIT;
60   if (ctx->Depth.Test)                   rasterMask |= DEPTH_BIT;
61   if (swrast->_FogEnabled)               rasterMask |= FOG_BIT;
62   if (ctx->Scissor.Enabled)              rasterMask |= CLIP_BIT;
63   if (ctx->Stencil.Enabled)              rasterMask |= STENCIL_BIT;
64   if (ctx->Visual.rgbMode) {
65      const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
66      if (colorMask != 0xffffffff)        rasterMask |= MASKING_BIT;
67      if (ctx->Color._LogicOpEnabled)     rasterMask |= LOGIC_OP_BIT;
68      if (ctx->Texture._EnabledUnits)     rasterMask |= TEXTURE_BIT;
69   }
70   else {
71      if (ctx->Color.IndexMask != 0xffffffff) rasterMask |= MASKING_BIT;
72      if (ctx->Color.IndexLogicOpEnabled)     rasterMask |= LOGIC_OP_BIT;
73   }
74
75   if (   ctx->Viewport.X < 0
76       || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width
77       || ctx->Viewport.Y < 0
78       || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) {
79      rasterMask |= CLIP_BIT;
80   }
81
82   if (ctx->Query.CurrentOcclusionObject)
83      rasterMask |= OCCLUSION_BIT;
84
85
86   /* If we're not drawing to exactly one color buffer set the
87    * MULTI_DRAW_BIT flag.  Also set it if we're drawing to no
88    * buffers or the RGBA or CI mask disables all writes.
89    */
90   if (ctx->DrawBuffer->_NumColorDrawBuffers[0] != 1) {
91      /* more than one color buffer designated for writing (or zero buffers) */
92      rasterMask |= MULTI_DRAW_BIT;
93   }
94   else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) {
95      rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
96   }
97   else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) {
98      rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */
99   }
100
101   if (ctx->FragmentProgram._Current) {
102      rasterMask |= FRAGPROG_BIT;
103   }
104
105   if (ctx->Shader._FragmentShaderPresent) {
106      rasterMask |= FRAGPROG_BIT;
107   }
108
109   if (ctx->ATIFragmentShader._Enabled) {
110      rasterMask |= ATIFRAGSHADER_BIT;
111   }
112
113#if CHAN_TYPE == GL_FLOAT
114   if (ctx->Color.ClampFragmentColor == GL_TRUE) {
115      rasterMask |= CLAMPING_BIT;
116   }
117#endif
118
119   SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
120}
121
122
123/**
124 * Examine polycon culls tate to compute the _BackfaceSign field.
125 * _BackfaceSign will be 0 if no culling, -1 if culling back-faces,
126 * and 1 if culling front-faces.  The Polygon FrontFace state also
127 * factors in.
128 */
129static void
130_swrast_update_polygon( GLcontext *ctx )
131{
132   GLfloat backface_sign = 1;
133
134   if (ctx->Polygon.CullFlag) {
135      backface_sign = 1;
136      switch(ctx->Polygon.CullFaceMode) {
137      case GL_BACK:
138	 if(ctx->Polygon.FrontFace==GL_CCW)
139	    backface_sign = -1;
140	 break;
141      case GL_FRONT:
142	 if(ctx->Polygon.FrontFace!=GL_CCW)
143	    backface_sign = -1;
144	 break;
145      default:
146      case GL_FRONT_AND_BACK:
147	 backface_sign = 0;
148	 break;
149      }
150   }
151   else {
152      backface_sign = 0;
153   }
154
155   SWRAST_CONTEXT(ctx)->_BackfaceSign = backface_sign;
156}
157
158
159/**
160 * Update the _PreferPixelFog field to indicate if we need to compute
161 * fog factors per-fragment.
162 */
163static void
164_swrast_update_fog_hint( GLcontext *ctx )
165{
166   SWcontext *swrast = SWRAST_CONTEXT(ctx);
167   swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
168                              ctx->FragmentProgram._Current ||
169			      (ctx->Hint.Fog == GL_NICEST &&
170			       swrast->AllowPixelFog));
171}
172
173
174
175/**
176 * Update the swrast->_AnyTextureCombine flag.
177 */
178static void
179_swrast_update_texture_env( GLcontext *ctx )
180{
181   SWcontext *swrast = SWRAST_CONTEXT(ctx);
182   GLuint i;
183   swrast->_AnyTextureCombine = GL_FALSE;
184   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
185      if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT ||
186          ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) {
187         swrast->_AnyTextureCombine = GL_TRUE;
188         return;
189      }
190   }
191}
192
193
194/**
195 * Update swrast->_FogColor and swrast->_FogEnable values.
196 */
197static void
198_swrast_update_fog_state( GLcontext *ctx )
199{
200   SWcontext *swrast = SWRAST_CONTEXT(ctx);
201   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
202
203   /* determine if fog is needed, and if so, which fog mode */
204   swrast->_FogEnabled = GL_FALSE;
205   if (fp && fp->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
206      if (fp->FogOption != GL_NONE) {
207         swrast->_FogEnabled = GL_TRUE;
208         swrast->_FogMode = fp->FogOption;
209      }
210   }
211   else if (ctx->Fog.Enabled) {
212      swrast->_FogEnabled = GL_TRUE;
213      swrast->_FogMode = ctx->Fog.Mode;
214   }
215}
216
217
218/**
219 * Update state for running fragment programs.  Basically, load the
220 * program parameters with current state values.
221 */
222static void
223_swrast_update_fragment_program(GLcontext *ctx, GLbitfield newState)
224{
225   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
226   if (fp) {
227#if 0
228      /* XXX Need a way to trigger the initial loading of parameters
229       * even when there's no recent state changes.
230       */
231      if (fp->Base.Parameters->StateFlags & newState)
232#endif
233         _mesa_load_state_parameters(ctx, fp->Base.Parameters);
234   }
235}
236
237
238
239#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK |	\
240			     _NEW_TEXTURE |		\
241			     _NEW_HINT |		\
242			     _NEW_POLYGON )
243
244/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
245 */
246#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED |		\
247			      _NEW_RENDERMODE|			\
248                              _NEW_POLYGON|			\
249                              _NEW_DEPTH|			\
250                              _NEW_STENCIL|			\
251                              _NEW_COLOR|			\
252                              _NEW_TEXTURE|			\
253                              _SWRAST_NEW_RASTERMASK|		\
254                              _NEW_LIGHT|			\
255                              _NEW_FOG |			\
256			      _DD_NEW_SEPARATE_SPECULAR)
257
258#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED |		\
259			  _NEW_RENDERMODE|		\
260                          _NEW_LINE|			\
261                          _NEW_TEXTURE|			\
262                          _NEW_LIGHT|			\
263                          _NEW_FOG|			\
264                          _NEW_DEPTH |			\
265                          _DD_NEW_SEPARATE_SPECULAR)
266
267#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED |	\
268			   _NEW_RENDERMODE |		\
269			   _NEW_POINT |			\
270			   _NEW_TEXTURE |		\
271			   _NEW_LIGHT |			\
272			   _NEW_FOG |			\
273                           _DD_NEW_SEPARATE_SPECULAR)
274
275#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
276
277#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
278
279#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
280
281
282
283/**
284 * Stub for swrast->Triangle to select a true triangle function
285 * after a state change.
286 */
287static void
288_swrast_validate_triangle( GLcontext *ctx,
289			   const SWvertex *v0,
290                           const SWvertex *v1,
291                           const SWvertex *v2 )
292{
293   SWcontext *swrast = SWRAST_CONTEXT(ctx);
294
295   _swrast_validate_derived( ctx );
296   swrast->choose_triangle( ctx );
297   ASSERT(swrast->Triangle);
298
299   if (ctx->Texture._EnabledUnits == 0
300       && NEED_SECONDARY_COLOR(ctx)
301       && !ctx->FragmentProgram._Current) {
302      /* separate specular color, but no texture */
303      swrast->SpecTriangle = swrast->Triangle;
304      swrast->Triangle = _swrast_add_spec_terms_triangle;
305   }
306
307   swrast->Triangle( ctx, v0, v1, v2 );
308}
309
310/**
311 * Called via swrast->Line.  Examine current GL state and choose a software
312 * line routine.  Then call it.
313 */
314static void
315_swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
316{
317   SWcontext *swrast = SWRAST_CONTEXT(ctx);
318
319   _swrast_validate_derived( ctx );
320   swrast->choose_line( ctx );
321   ASSERT(swrast->Line);
322
323   if (ctx->Texture._EnabledUnits == 0
324       && NEED_SECONDARY_COLOR(ctx)
325       && !ctx->FragmentProgram._Current) {
326      swrast->SpecLine = swrast->Line;
327      swrast->Line = _swrast_add_spec_terms_line;
328   }
329
330
331   swrast->Line( ctx, v0, v1 );
332}
333
334/**
335 * Called via swrast->Point.  Examine current GL state and choose a software
336 * point routine.  Then call it.
337 */
338static void
339_swrast_validate_point( GLcontext *ctx, const SWvertex *v0 )
340{
341   SWcontext *swrast = SWRAST_CONTEXT(ctx);
342
343   _swrast_validate_derived( ctx );
344   swrast->choose_point( ctx );
345
346   if (ctx->Texture._EnabledUnits == 0
347       && NEED_SECONDARY_COLOR(ctx)
348       && !ctx->FragmentProgram._Current) {
349      swrast->SpecPoint = swrast->Point;
350      swrast->Point = _swrast_add_spec_terms_point;
351   }
352
353   swrast->Point( ctx, v0 );
354}
355
356
357/**
358 * Called via swrast->BlendFunc.  Examine GL state to choose a blending
359 * function, then call it.
360 */
361static void _ASMAPI
362_swrast_validate_blend_func(GLcontext *ctx, GLuint n, const GLubyte mask[],
363                            GLvoid *src, const GLvoid *dst,
364                            GLenum chanType )
365{
366   SWcontext *swrast = SWRAST_CONTEXT(ctx);
367
368   _swrast_validate_derived( ctx ); /* why is this needed? */
369   _swrast_choose_blend_func( ctx, chanType );
370
371   swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
372}
373
374
375/**
376 * Make sure we have texture image data for all the textures we may need
377 * for subsequent rendering.
378 */
379static void
380_swrast_validate_texture_images(GLcontext *ctx)
381{
382   SWcontext *swrast = SWRAST_CONTEXT(ctx);
383   GLuint u;
384
385   if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) {
386      /* no textures enabled, or no way to validate images! */
387      return;
388   }
389
390   for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
391      if (ctx->Texture.Unit[u]._ReallyEnabled) {
392         struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
393         ASSERT(texObj);
394         if (texObj) {
395            GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
396            GLuint face;
397            for (face = 0; face < numFaces; face++) {
398               GLuint lvl;
399               for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
400                  struct gl_texture_image *texImg = texObj->Image[face][lvl];
401                  if (texImg && !texImg->Data) {
402                     swrast->ValidateTextureImage(ctx, texObj, face, lvl);
403                     ASSERT(texObj->Image[face][lvl]->Data);
404                  }
405               }
406            }
407         }
408      }
409   }
410}
411
412
413/**
414 * Free the texture image data attached to all currently enabled
415 * textures.  Meant to be called by device drivers when transitioning
416 * from software to hardware rendering.
417 */
418void
419_swrast_eject_texture_images(GLcontext *ctx)
420{
421   GLuint u;
422
423   if (!ctx->Texture._EnabledUnits) {
424      /* no textures enabled */
425      return;
426   }
427
428   for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
429      if (ctx->Texture.Unit[u]._ReallyEnabled) {
430         struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
431         ASSERT(texObj);
432         if (texObj) {
433            GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
434            GLuint face;
435            for (face = 0; face < numFaces; face++) {
436               GLuint lvl;
437               for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
438                  struct gl_texture_image *texImg = texObj->Image[face][lvl];
439                  if (texImg && texImg->Data) {
440                     _mesa_free_texmemory(texImg->Data);
441                     texImg->Data = NULL;
442                  }
443               }
444            }
445         }
446      }
447   }
448}
449
450
451
452static void
453_swrast_sleep( GLcontext *ctx, GLbitfield new_state )
454{
455   (void) ctx; (void) new_state;
456}
457
458
459static void
460_swrast_invalidate_state( GLcontext *ctx, GLbitfield new_state )
461{
462   SWcontext *swrast = SWRAST_CONTEXT(ctx);
463   GLuint i;
464
465   swrast->NewState |= new_state;
466
467   /* After 10 statechanges without any swrast functions being called,
468    * put the module to sleep.
469    */
470   if (++swrast->StateChanges > 10) {
471      swrast->InvalidateState = _swrast_sleep;
472      swrast->NewState = ~0;
473      new_state = ~0;
474   }
475
476   if (new_state & swrast->InvalidateTriangleMask)
477      swrast->Triangle = _swrast_validate_triangle;
478
479   if (new_state & swrast->InvalidateLineMask)
480      swrast->Line = _swrast_validate_line;
481
482   if (new_state & swrast->InvalidatePointMask)
483      swrast->Point = _swrast_validate_point;
484
485   if (new_state & _SWRAST_NEW_BLEND_FUNC)
486      swrast->BlendFunc = _swrast_validate_blend_func;
487
488   if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
489      for (i = 0 ; i < ctx->Const.MaxTextureImageUnits ; i++)
490	 swrast->TextureSample[i] = NULL;
491}
492
493
494static void
495_swrast_update_texture_samplers(GLcontext *ctx)
496{
497   SWcontext *swrast = SWRAST_CONTEXT(ctx);
498   GLuint u;
499
500   for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
501      const struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
502      if (tObj)
503         swrast->TextureSample[u] =
504            _swrast_choose_texture_sample_func(ctx, tObj);
505   }
506}
507
508
509void
510_swrast_validate_derived( GLcontext *ctx )
511{
512   SWcontext *swrast = SWRAST_CONTEXT(ctx);
513
514   if (swrast->NewState) {
515      if (swrast->NewState & _NEW_POLYGON)
516	 _swrast_update_polygon( ctx );
517
518      if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM))
519	 _swrast_update_fog_hint( ctx );
520
521      if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
522	 _swrast_update_texture_env( ctx );
523
524      if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
525         _swrast_update_fog_state( ctx );
526
527      if (swrast->NewState & (_NEW_MODELVIEW |
528                              _NEW_PROJECTION |
529                              _NEW_TEXTURE_MATRIX |
530                              _NEW_FOG |
531                              _NEW_LIGHT |
532                              _NEW_LINE |
533                              _NEW_TEXTURE |
534                              _NEW_TRANSFORM |
535                              _NEW_POINT |
536                              _NEW_VIEWPORT |
537                              _NEW_PROGRAM))
538	 _swrast_update_fragment_program( ctx, swrast->NewState );
539
540      if (swrast->NewState & _NEW_TEXTURE)
541         _swrast_update_texture_samplers( ctx );
542
543      if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM))
544         _swrast_validate_texture_images( ctx );
545
546      if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
547 	 _swrast_update_rasterflags( ctx );
548
549      swrast->NewState = 0;
550      swrast->StateChanges = 0;
551      swrast->InvalidateState = _swrast_invalidate_state;
552   }
553}
554
555#define SWRAST_DEBUG 0
556
557/* Public entrypoints:  See also s_accum.c, s_bitmap.c, etc.
558 */
559void
560_swrast_Quad( GLcontext *ctx,
561	      const SWvertex *v0, const SWvertex *v1,
562              const SWvertex *v2, const SWvertex *v3 )
563{
564   if (SWRAST_DEBUG) {
565      _mesa_debug(ctx, "_swrast_Quad\n");
566      _swrast_print_vertex( ctx, v0 );
567      _swrast_print_vertex( ctx, v1 );
568      _swrast_print_vertex( ctx, v2 );
569      _swrast_print_vertex( ctx, v3 );
570   }
571   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
572   SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
573}
574
575void
576_swrast_Triangle( GLcontext *ctx, const SWvertex *v0,
577                  const SWvertex *v1, const SWvertex *v2 )
578{
579   if (SWRAST_DEBUG) {
580      _mesa_debug(ctx, "_swrast_Triangle\n");
581      _swrast_print_vertex( ctx, v0 );
582      _swrast_print_vertex( ctx, v1 );
583      _swrast_print_vertex( ctx, v2 );
584   }
585   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
586}
587
588void
589_swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
590{
591   if (SWRAST_DEBUG) {
592      _mesa_debug(ctx, "_swrast_Line\n");
593      _swrast_print_vertex( ctx, v0 );
594      _swrast_print_vertex( ctx, v1 );
595   }
596   SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
597}
598
599void
600_swrast_Point( GLcontext *ctx, const SWvertex *v0 )
601{
602   if (SWRAST_DEBUG) {
603      _mesa_debug(ctx, "_swrast_Point\n");
604      _swrast_print_vertex( ctx, v0 );
605   }
606   SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
607}
608
609void
610_swrast_InvalidateState( GLcontext *ctx, GLbitfield new_state )
611{
612   if (SWRAST_DEBUG) {
613      _mesa_debug(ctx, "_swrast_InvalidateState\n");
614   }
615   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
616}
617
618void
619_swrast_ResetLineStipple( GLcontext *ctx )
620{
621   if (SWRAST_DEBUG) {
622      _mesa_debug(ctx, "_swrast_ResetLineStipple\n");
623   }
624   SWRAST_CONTEXT(ctx)->StippleCounter = 0;
625}
626
627void
628_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value )
629{
630   if (SWRAST_DEBUG) {
631      _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
632   }
633   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
634   SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
635}
636
637void
638_swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value )
639{
640   if (SWRAST_DEBUG) {
641      _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
642   }
643   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
644   SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
645}
646
647
648GLboolean
649_swrast_CreateContext( GLcontext *ctx )
650{
651   GLuint i;
652   SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext));
653
654   if (SWRAST_DEBUG) {
655      _mesa_debug(ctx, "_swrast_CreateContext\n");
656   }
657
658   if (!swrast)
659      return GL_FALSE;
660
661   swrast->NewState = ~0;
662
663   swrast->choose_point = _swrast_choose_point;
664   swrast->choose_line = _swrast_choose_line;
665   swrast->choose_triangle = _swrast_choose_triangle;
666
667   swrast->InvalidatePointMask = _SWRAST_NEW_POINT;
668   swrast->InvalidateLineMask = _SWRAST_NEW_LINE;
669   swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE;
670
671   swrast->Point = _swrast_validate_point;
672   swrast->Line = _swrast_validate_line;
673   swrast->Triangle = _swrast_validate_triangle;
674   swrast->InvalidateState = _swrast_sleep;
675   swrast->BlendFunc = _swrast_validate_blend_func;
676
677   swrast->AllowVertexFog = GL_TRUE;
678   swrast->AllowPixelFog = GL_TRUE;
679
680   /* Optimized Accum buffer */
681   swrast->_IntegerAccumMode = GL_FALSE;
682   swrast->_IntegerAccumScaler = 0.0;
683
684   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
685      swrast->TextureSample[i] = NULL;
686
687   swrast->SpanArrays = MALLOC_STRUCT(sw_span_arrays);
688   if (!swrast->SpanArrays) {
689      FREE(swrast);
690      return GL_FALSE;
691   }
692   swrast->SpanArrays->ChanType = CHAN_TYPE;
693#if CHAN_TYPE == GL_UNSIGNED_BYTE
694   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz1.rgba;
695   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz1.spec;
696#elif CHAN_TYPE == GL_UNSIGNED_SHORT
697   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz2.rgba;
698   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz2.spec;
699#else
700   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz4.rgba;
701   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz4.spec;
702#endif
703
704   /* init point span buffer */
705   swrast->PointSpan.primitive = GL_POINT;
706   swrast->PointSpan.start = 0;
707   swrast->PointSpan.end = 0;
708   swrast->PointSpan.facing = 0;
709   swrast->PointSpan.array = swrast->SpanArrays;
710
711   swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureImageUnits *
712                                           MAX_WIDTH * 4 * sizeof(GLchan));
713   if (!swrast->TexelBuffer) {
714      FREE(swrast->SpanArrays);
715      FREE(swrast);
716      return GL_FALSE;
717   }
718
719   ctx->swrast_context = swrast;
720
721   return GL_TRUE;
722}
723
724void
725_swrast_DestroyContext( GLcontext *ctx )
726{
727   SWcontext *swrast = SWRAST_CONTEXT(ctx);
728
729   if (SWRAST_DEBUG) {
730      _mesa_debug(ctx, "_swrast_DestroyContext\n");
731   }
732
733   FREE( swrast->SpanArrays );
734   FREE( swrast->TexelBuffer );
735   FREE( swrast );
736
737   ctx->swrast_context = 0;
738}
739
740
741struct swrast_device_driver *
742_swrast_GetDeviceDriverReference( GLcontext *ctx )
743{
744   SWcontext *swrast = SWRAST_CONTEXT(ctx);
745   return &swrast->Driver;
746}
747
748void
749_swrast_flush( GLcontext *ctx )
750{
751   SWcontext *swrast = SWRAST_CONTEXT(ctx);
752   /* flush any pending fragments from rendering points */
753   if (swrast->PointSpan.end > 0) {
754      if (ctx->Visual.rgbMode) {
755         _swrast_write_rgba_span(ctx, &(swrast->PointSpan));
756      }
757      else {
758         _swrast_write_index_span(ctx, &(swrast->PointSpan));
759      }
760      swrast->PointSpan.end = 0;
761   }
762}
763
764void
765_swrast_render_primitive( GLcontext *ctx, GLenum prim )
766{
767   SWcontext *swrast = SWRAST_CONTEXT(ctx);
768   if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
769      _swrast_flush(ctx);
770   }
771   swrast->Primitive = prim;
772}
773
774
775void
776_swrast_render_start( GLcontext *ctx )
777{
778   SWcontext *swrast = SWRAST_CONTEXT(ctx);
779   if (swrast->Driver.SpanRenderStart)
780      swrast->Driver.SpanRenderStart( ctx );
781   swrast->PointSpan.end = 0;
782}
783
784void
785_swrast_render_finish( GLcontext *ctx )
786{
787   SWcontext *swrast = SWRAST_CONTEXT(ctx);
788   if (swrast->Driver.SpanRenderFinish)
789      swrast->Driver.SpanRenderFinish( ctx );
790
791   _swrast_flush(ctx);
792}
793
794
795#define SWRAST_DEBUG_VERTICES 0
796
797void
798_swrast_print_vertex( GLcontext *ctx, const SWvertex *v )
799{
800   GLuint i;
801
802   if (SWRAST_DEBUG_VERTICES) {
803      _mesa_debug(ctx, "win %f %f %f %f\n",
804                  v->win[0], v->win[1], v->win[2], v->win[3]);
805
806      for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
807	 if (ctx->Texture.Unit[i]._ReallyEnabled)
808	    _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
809                        v->texcoord[i][0], v->texcoord[i][1],
810                        v->texcoord[i][2], v->texcoord[i][3]);
811
812#if CHAN_TYPE == GL_FLOAT
813      _mesa_debug(ctx, "color %f %f %f %f\n",
814                  v->color[0], v->color[1], v->color[2], v->color[3]);
815      _mesa_debug(ctx, "spec %f %f %f %f\n",
816                  v->specular[0], v->specular[1],
817                  v->specular[2], v->specular[3]);
818#else
819      _mesa_debug(ctx, "color %d %d %d %d\n",
820                  v->color[0], v->color[1], v->color[2], v->color[3]);
821      _mesa_debug(ctx, "spec %d %d %d %d\n",
822                  v->specular[0], v->specular[1],
823                  v->specular[2], v->specular[3]);
824#endif
825      _mesa_debug(ctx, "fog %f\n", v->fog);
826      _mesa_debug(ctx, "index %d\n", v->index);
827      _mesa_debug(ctx, "pointsize %f\n", v->pointSize);
828      _mesa_debug(ctx, "\n");
829   }
830}
831