s_context.c revision 7117f1b4
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.0.3
4 *
5 * Copyright (C) 1999-2007  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->ATIFragmentShader._Enabled) {
106      rasterMask |= ATIFRAGSHADER_BIT;
107   }
108
109#if CHAN_TYPE == GL_FLOAT
110   if (ctx->Color.ClampFragmentColor == GL_TRUE) {
111      rasterMask |= CLAMPING_BIT;
112   }
113#endif
114
115   SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
116}
117
118
119/**
120 * Examine polycon culls tate to compute the _BackfaceCullSign field.
121 * _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces,
122 * and 1 if culling front-faces.  The Polygon FrontFace state also
123 * factors in.
124 */
125static void
126_swrast_update_polygon( GLcontext *ctx )
127{
128   GLfloat backface_sign;
129
130   if (ctx->Polygon.CullFlag) {
131      switch (ctx->Polygon.CullFaceMode) {
132      case GL_BACK:
133         backface_sign = -1.0;
134	 break;
135      case GL_FRONT:
136         backface_sign = 1.0;
137	 break;
138      case GL_FRONT_AND_BACK:
139         /* fallthrough */
140      default:
141	 backface_sign = 0.0;
142      }
143   }
144   else {
145      backface_sign = 0.0;
146   }
147
148   SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign;
149
150   /* This is for front/back-face determination, but not for culling */
151   SWRAST_CONTEXT(ctx)->_BackfaceSign
152      = (ctx->Polygon.FrontFace == GL_CW) ? -1.0 : 1.0;
153}
154
155
156
157/**
158 * Update the _PreferPixelFog field to indicate if we need to compute
159 * fog blend factors (from the fog coords) per-fragment.
160 */
161static void
162_swrast_update_fog_hint( GLcontext *ctx )
163{
164   SWcontext *swrast = SWRAST_CONTEXT(ctx);
165   swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
166                              ctx->FragmentProgram._Current ||
167			      (ctx->Hint.Fog == GL_NICEST &&
168			       swrast->AllowPixelFog));
169}
170
171
172
173/**
174 * Update the swrast->_AnyTextureCombine flag.
175 */
176static void
177_swrast_update_texture_env( GLcontext *ctx )
178{
179   SWcontext *swrast = SWRAST_CONTEXT(ctx);
180   GLuint i;
181   swrast->_AnyTextureCombine = GL_FALSE;
182   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
183      if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT ||
184          ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) {
185         swrast->_AnyTextureCombine = GL_TRUE;
186         return;
187      }
188   }
189}
190
191
192/**
193 * Update swrast->_FogColor and swrast->_FogEnable values.
194 */
195static void
196_swrast_update_fog_state( GLcontext *ctx )
197{
198   SWcontext *swrast = SWRAST_CONTEXT(ctx);
199   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
200
201   /* determine if fog is needed, and if so, which fog mode */
202   swrast->_FogEnabled = GL_FALSE;
203   if (fp && fp->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
204      if (fp->FogOption != GL_NONE) {
205         swrast->_FogEnabled = GL_TRUE;
206         swrast->_FogMode = fp->FogOption;
207      }
208   }
209   else if (ctx->Fog.Enabled) {
210      swrast->_FogEnabled = GL_TRUE;
211      swrast->_FogMode = ctx->Fog.Mode;
212   }
213}
214
215
216/**
217 * Update state for running fragment programs.  Basically, load the
218 * program parameters with current state values.
219 */
220static void
221_swrast_update_fragment_program(GLcontext *ctx, GLbitfield newState)
222{
223   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
224   if (fp) {
225#if 0
226      /* XXX Need a way to trigger the initial loading of parameters
227       * even when there's no recent state changes.
228       */
229      if (fp->Base.Parameters->StateFlags & newState)
230#endif
231         _mesa_load_state_parameters(ctx, fp->Base.Parameters);
232   }
233}
234
235
236
237#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK |	\
238			     _NEW_TEXTURE |		\
239			     _NEW_HINT |		\
240			     _NEW_POLYGON )
241
242/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
243 */
244#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED |		\
245			      _NEW_RENDERMODE|			\
246                              _NEW_POLYGON|			\
247                              _NEW_DEPTH|			\
248                              _NEW_STENCIL|			\
249                              _NEW_COLOR|			\
250                              _NEW_TEXTURE|			\
251                              _SWRAST_NEW_RASTERMASK|		\
252                              _NEW_LIGHT|			\
253                              _NEW_FOG |			\
254			      _DD_NEW_SEPARATE_SPECULAR)
255
256#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED |		\
257			  _NEW_RENDERMODE|		\
258                          _NEW_LINE|			\
259                          _NEW_TEXTURE|			\
260                          _NEW_LIGHT|			\
261                          _NEW_FOG|			\
262                          _NEW_DEPTH |			\
263                          _DD_NEW_SEPARATE_SPECULAR)
264
265#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED |	\
266			   _NEW_RENDERMODE |		\
267			   _NEW_POINT |			\
268			   _NEW_TEXTURE |		\
269			   _NEW_LIGHT |			\
270			   _NEW_FOG |			\
271                           _DD_NEW_SEPARATE_SPECULAR)
272
273#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
274
275#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
276
277#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
278
279
280
281/**
282 * Stub for swrast->Triangle to select a true triangle function
283 * after a state change.
284 */
285static void
286_swrast_validate_triangle( GLcontext *ctx,
287			   const SWvertex *v0,
288                           const SWvertex *v1,
289                           const SWvertex *v2 )
290{
291   SWcontext *swrast = SWRAST_CONTEXT(ctx);
292
293   _swrast_validate_derived( ctx );
294   swrast->choose_triangle( ctx );
295   ASSERT(swrast->Triangle);
296
297   if (ctx->Texture._EnabledUnits == 0
298       && NEED_SECONDARY_COLOR(ctx)
299       && !ctx->FragmentProgram._Current) {
300      /* separate specular color, but no texture */
301      swrast->SpecTriangle = swrast->Triangle;
302      swrast->Triangle = _swrast_add_spec_terms_triangle;
303   }
304
305   swrast->Triangle( ctx, v0, v1, v2 );
306}
307
308/**
309 * Called via swrast->Line.  Examine current GL state and choose a software
310 * line routine.  Then call it.
311 */
312static void
313_swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
314{
315   SWcontext *swrast = SWRAST_CONTEXT(ctx);
316
317   _swrast_validate_derived( ctx );
318   swrast->choose_line( ctx );
319   ASSERT(swrast->Line);
320
321   if (ctx->Texture._EnabledUnits == 0
322       && NEED_SECONDARY_COLOR(ctx)
323       && !ctx->FragmentProgram._Current) {
324      swrast->SpecLine = swrast->Line;
325      swrast->Line = _swrast_add_spec_terms_line;
326   }
327
328
329   swrast->Line( ctx, v0, v1 );
330}
331
332/**
333 * Called via swrast->Point.  Examine current GL state and choose a software
334 * point routine.  Then call it.
335 */
336static void
337_swrast_validate_point( GLcontext *ctx, const SWvertex *v0 )
338{
339   SWcontext *swrast = SWRAST_CONTEXT(ctx);
340
341   _swrast_validate_derived( ctx );
342   swrast->choose_point( ctx );
343
344   if (ctx->Texture._EnabledUnits == 0
345       && NEED_SECONDARY_COLOR(ctx)
346       && !ctx->FragmentProgram._Current) {
347      swrast->SpecPoint = swrast->Point;
348      swrast->Point = _swrast_add_spec_terms_point;
349   }
350
351   swrast->Point( ctx, v0 );
352}
353
354
355/**
356 * Called via swrast->BlendFunc.  Examine GL state to choose a blending
357 * function, then call it.
358 */
359static void _ASMAPI
360_swrast_validate_blend_func(GLcontext *ctx, GLuint n, const GLubyte mask[],
361                            GLvoid *src, const GLvoid *dst,
362                            GLenum chanType )
363{
364   SWcontext *swrast = SWRAST_CONTEXT(ctx);
365
366   _swrast_validate_derived( ctx ); /* why is this needed? */
367   _swrast_choose_blend_func( ctx, chanType );
368
369   swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
370}
371
372
373/**
374 * Make sure we have texture image data for all the textures we may need
375 * for subsequent rendering.
376 */
377static void
378_swrast_validate_texture_images(GLcontext *ctx)
379{
380   SWcontext *swrast = SWRAST_CONTEXT(ctx);
381   GLuint u;
382
383   if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) {
384      /* no textures enabled, or no way to validate images! */
385      return;
386   }
387
388   for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
389      if (ctx->Texture.Unit[u]._ReallyEnabled) {
390         struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
391         ASSERT(texObj);
392         if (texObj) {
393            GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
394            GLuint face;
395            for (face = 0; face < numFaces; face++) {
396               GLint lvl;
397               for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
398                  struct gl_texture_image *texImg = texObj->Image[face][lvl];
399                  if (texImg && !texImg->Data) {
400                     swrast->ValidateTextureImage(ctx, texObj, face, lvl);
401                     ASSERT(texObj->Image[face][lvl]->Data);
402                  }
403               }
404            }
405         }
406      }
407   }
408}
409
410
411/**
412 * Free the texture image data attached to all currently enabled
413 * textures.  Meant to be called by device drivers when transitioning
414 * from software to hardware rendering.
415 */
416void
417_swrast_eject_texture_images(GLcontext *ctx)
418{
419   GLuint u;
420
421   if (!ctx->Texture._EnabledUnits) {
422      /* no textures enabled */
423      return;
424   }
425
426   for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
427      if (ctx->Texture.Unit[u]._ReallyEnabled) {
428         struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
429         ASSERT(texObj);
430         if (texObj) {
431            GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
432            GLuint face;
433            for (face = 0; face < numFaces; face++) {
434               GLint lvl;
435               for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
436                  struct gl_texture_image *texImg = texObj->Image[face][lvl];
437                  if (texImg && texImg->Data) {
438                     _mesa_free_texmemory(texImg->Data);
439                     texImg->Data = NULL;
440                  }
441               }
442            }
443         }
444      }
445   }
446}
447
448
449
450static void
451_swrast_sleep( GLcontext *ctx, GLbitfield new_state )
452{
453   (void) ctx; (void) new_state;
454}
455
456
457static void
458_swrast_invalidate_state( GLcontext *ctx, GLbitfield new_state )
459{
460   SWcontext *swrast = SWRAST_CONTEXT(ctx);
461   GLuint i;
462
463   swrast->NewState |= new_state;
464
465   /* After 10 statechanges without any swrast functions being called,
466    * put the module to sleep.
467    */
468   if (++swrast->StateChanges > 10) {
469      swrast->InvalidateState = _swrast_sleep;
470      swrast->NewState = ~0;
471      new_state = ~0;
472   }
473
474   if (new_state & swrast->InvalidateTriangleMask)
475      swrast->Triangle = _swrast_validate_triangle;
476
477   if (new_state & swrast->InvalidateLineMask)
478      swrast->Line = _swrast_validate_line;
479
480   if (new_state & swrast->InvalidatePointMask)
481      swrast->Point = _swrast_validate_point;
482
483   if (new_state & _SWRAST_NEW_BLEND_FUNC)
484      swrast->BlendFunc = _swrast_validate_blend_func;
485
486   if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
487      for (i = 0 ; i < ctx->Const.MaxTextureImageUnits ; i++)
488	 swrast->TextureSample[i] = NULL;
489}
490
491
492void
493_swrast_update_texture_samplers(GLcontext *ctx)
494{
495   SWcontext *swrast = SWRAST_CONTEXT(ctx);
496   GLuint u;
497
498   for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
499      const struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
500      /* Note: If tObj is NULL, the sample function will be a simple
501       * function that just returns opaque black (0,0,0,1).
502       */
503      swrast->TextureSample[u] = _swrast_choose_texture_sample_func(ctx, tObj);
504   }
505}
506
507
508/**
509 * Update swrast->_ActiveAttribs and swrast->_NumActiveAttribs
510 */
511static void
512_swrast_update_fragment_attribs(GLcontext *ctx)
513{
514   SWcontext *swrast = SWRAST_CONTEXT(ctx);
515   GLuint attribsMask;
516
517   if (ctx->FragmentProgram._Current) {
518      attribsMask = ctx->FragmentProgram._Current->Base.InputsRead;
519   }
520   else {
521      GLuint u;
522      attribsMask = 0x0;
523
524#if 0 /* not yet */
525      if (ctx->Depth.Test)
526         attribsMask |= FRAG_BIT_WPOS;
527      if (NEED_SECONDARY_COLOR(ctx))
528         attribsMask |= FRAG_BIT_COL1;
529#endif
530      if (swrast->_FogEnabled)
531         attribsMask |= FRAG_BIT_FOGC;
532
533      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
534         if (ctx->Texture.Unit[u]._ReallyEnabled) {
535            attribsMask |= FRAG_BIT_TEX(u);
536         }
537      }
538   }
539
540   /* don't want to interpolate these generic attribs just yet */
541   /* XXX temporary */
542   attribsMask &= ~(FRAG_BIT_WPOS |
543                    FRAG_BIT_COL0 |
544                    FRAG_BIT_COL1 |
545                    FRAG_BIT_FOGC);
546
547   /* Update _ActiveAttribs[] list */
548   {
549      GLuint i, num = 0;
550      for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
551         if (attribsMask & (1 << i))
552            swrast->_ActiveAttribs[num++] = i;
553      }
554      swrast->_NumActiveAttribs = num;
555   }
556}
557
558
559/**
560 * Update the swrast->_ColorOutputsMask which indicates which color
561 * renderbuffers (aka rendertargets) are being written to by the current
562 * fragment program.
563 * We also take glDrawBuffers() into account to skip outputs that are
564 * set to GL_NONE.
565 */
566static void
567_swrast_update_color_outputs(GLcontext *ctx)
568{
569   SWcontext *swrast = SWRAST_CONTEXT(ctx);
570   const struct gl_framebuffer *fb = ctx->DrawBuffer;
571
572   swrast->_ColorOutputsMask = 0;
573   swrast->_NumColorOutputs = 0;
574
575   if (ctx->FragmentProgram._Current) {
576      const GLbitfield outputsWritten
577         = ctx->FragmentProgram._Current->Base.OutputsWritten;
578      GLuint output;
579      for (output = 0; output < ctx->Const.MaxDrawBuffers; output++) {
580         if ((outputsWritten & (1 << (FRAG_RESULT_DATA0 + output)))
581             && (fb->_NumColorDrawBuffers[output] > 0)) {
582            swrast->_ColorOutputsMask |= (1 << output);
583            swrast->_NumColorOutputs = output + 1;
584         }
585      }
586   }
587   if (swrast->_ColorOutputsMask == 0x0) {
588      /* no fragment program, or frag prog didn't write to gl_FragData[] */
589      if (fb->_NumColorDrawBuffers[0] > 0) {
590         swrast->_ColorOutputsMask = 0x1;
591         swrast->_NumColorOutputs = 1;
592      }
593   }
594}
595
596
597void
598_swrast_validate_derived( GLcontext *ctx )
599{
600   SWcontext *swrast = SWRAST_CONTEXT(ctx);
601
602   if (swrast->NewState) {
603      if (swrast->NewState & _NEW_POLYGON)
604	 _swrast_update_polygon( ctx );
605
606      if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM))
607	 _swrast_update_fog_hint( ctx );
608
609      if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
610	 _swrast_update_texture_env( ctx );
611
612      if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
613         _swrast_update_fog_state( ctx );
614
615      if (swrast->NewState & (_NEW_MODELVIEW |
616                              _NEW_PROJECTION |
617                              _NEW_TEXTURE_MATRIX |
618                              _NEW_FOG |
619                              _NEW_LIGHT |
620                              _NEW_LINE |
621                              _NEW_TEXTURE |
622                              _NEW_TRANSFORM |
623                              _NEW_POINT |
624                              _NEW_VIEWPORT |
625                              _NEW_PROGRAM))
626	 _swrast_update_fragment_program( ctx, swrast->NewState );
627
628      if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM))
629         _swrast_update_texture_samplers( ctx );
630
631      if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM))
632         _swrast_validate_texture_images( ctx );
633
634      if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
635 	 _swrast_update_rasterflags( ctx );
636
637      if (swrast->NewState & (_NEW_DEPTH |
638                              _NEW_FOG |
639                              _NEW_PROGRAM |
640                              _NEW_TEXTURE))
641         _swrast_update_fragment_attribs(ctx);
642
643      if (swrast->NewState & (_NEW_PROGRAM | _NEW_BUFFERS))
644         _swrast_update_color_outputs(ctx);
645
646      swrast->NewState = 0;
647      swrast->StateChanges = 0;
648      swrast->InvalidateState = _swrast_invalidate_state;
649   }
650}
651
652#define SWRAST_DEBUG 0
653
654/* Public entrypoints:  See also s_accum.c, s_bitmap.c, etc.
655 */
656void
657_swrast_Quad( GLcontext *ctx,
658	      const SWvertex *v0, const SWvertex *v1,
659              const SWvertex *v2, const SWvertex *v3 )
660{
661   if (SWRAST_DEBUG) {
662      _mesa_debug(ctx, "_swrast_Quad\n");
663      _swrast_print_vertex( ctx, v0 );
664      _swrast_print_vertex( ctx, v1 );
665      _swrast_print_vertex( ctx, v2 );
666      _swrast_print_vertex( ctx, v3 );
667   }
668   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
669   SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
670}
671
672void
673_swrast_Triangle( GLcontext *ctx, const SWvertex *v0,
674                  const SWvertex *v1, const SWvertex *v2 )
675{
676   if (SWRAST_DEBUG) {
677      _mesa_debug(ctx, "_swrast_Triangle\n");
678      _swrast_print_vertex( ctx, v0 );
679      _swrast_print_vertex( ctx, v1 );
680      _swrast_print_vertex( ctx, v2 );
681   }
682   SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
683}
684
685void
686_swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
687{
688   if (SWRAST_DEBUG) {
689      _mesa_debug(ctx, "_swrast_Line\n");
690      _swrast_print_vertex( ctx, v0 );
691      _swrast_print_vertex( ctx, v1 );
692   }
693   SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
694}
695
696void
697_swrast_Point( GLcontext *ctx, const SWvertex *v0 )
698{
699   if (SWRAST_DEBUG) {
700      _mesa_debug(ctx, "_swrast_Point\n");
701      _swrast_print_vertex( ctx, v0 );
702   }
703   SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
704}
705
706void
707_swrast_InvalidateState( GLcontext *ctx, GLbitfield new_state )
708{
709   if (SWRAST_DEBUG) {
710      _mesa_debug(ctx, "_swrast_InvalidateState\n");
711   }
712   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
713}
714
715void
716_swrast_ResetLineStipple( GLcontext *ctx )
717{
718   if (SWRAST_DEBUG) {
719      _mesa_debug(ctx, "_swrast_ResetLineStipple\n");
720   }
721   SWRAST_CONTEXT(ctx)->StippleCounter = 0;
722}
723
724void
725_swrast_SetFacing(GLcontext *ctx, GLuint facing)
726{
727   SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
728}
729
730void
731_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value )
732{
733   if (SWRAST_DEBUG) {
734      _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
735   }
736   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
737   SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
738}
739
740void
741_swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value )
742{
743   if (SWRAST_DEBUG) {
744      _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
745   }
746   SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
747   SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
748}
749
750
751GLboolean
752_swrast_CreateContext( GLcontext *ctx )
753{
754   GLuint i;
755   SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext));
756
757   if (SWRAST_DEBUG) {
758      _mesa_debug(ctx, "_swrast_CreateContext\n");
759   }
760
761   if (!swrast)
762      return GL_FALSE;
763
764   swrast->NewState = ~0;
765
766   swrast->choose_point = _swrast_choose_point;
767   swrast->choose_line = _swrast_choose_line;
768   swrast->choose_triangle = _swrast_choose_triangle;
769
770   swrast->InvalidatePointMask = _SWRAST_NEW_POINT;
771   swrast->InvalidateLineMask = _SWRAST_NEW_LINE;
772   swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE;
773
774   swrast->Point = _swrast_validate_point;
775   swrast->Line = _swrast_validate_line;
776   swrast->Triangle = _swrast_validate_triangle;
777   swrast->InvalidateState = _swrast_sleep;
778   swrast->BlendFunc = _swrast_validate_blend_func;
779
780   swrast->AllowVertexFog = GL_TRUE;
781   swrast->AllowPixelFog = GL_TRUE;
782
783   /* Optimized Accum buffer */
784   swrast->_IntegerAccumMode = GL_FALSE;
785   swrast->_IntegerAccumScaler = 0.0;
786
787   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
788      swrast->TextureSample[i] = NULL;
789
790   swrast->SpanArrays = MALLOC_STRUCT(sw_span_arrays);
791   if (!swrast->SpanArrays) {
792      FREE(swrast);
793      return GL_FALSE;
794   }
795   swrast->SpanArrays->ChanType = CHAN_TYPE;
796#if CHAN_TYPE == GL_UNSIGNED_BYTE
797   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz1.rgba;
798   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz1.spec;
799#elif CHAN_TYPE == GL_UNSIGNED_SHORT
800   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz2.rgba;
801   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz2.spec;
802#else
803   swrast->SpanArrays->rgba = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0];
804   swrast->SpanArrays->spec = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL1];
805#endif
806
807   /* init point span buffer */
808   swrast->PointSpan.primitive = GL_POINT;
809   swrast->PointSpan.end = 0;
810   swrast->PointSpan.facing = 0;
811   swrast->PointSpan.array = swrast->SpanArrays;
812
813   swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureImageUnits *
814                                           MAX_WIDTH * 4 * sizeof(GLchan));
815   if (!swrast->TexelBuffer) {
816      FREE(swrast->SpanArrays);
817      FREE(swrast);
818      return GL_FALSE;
819   }
820
821   ctx->swrast_context = swrast;
822
823   return GL_TRUE;
824}
825
826void
827_swrast_DestroyContext( GLcontext *ctx )
828{
829   SWcontext *swrast = SWRAST_CONTEXT(ctx);
830
831   if (SWRAST_DEBUG) {
832      _mesa_debug(ctx, "_swrast_DestroyContext\n");
833   }
834
835   FREE( swrast->SpanArrays );
836   FREE( swrast->TexelBuffer );
837   FREE( swrast );
838
839   ctx->swrast_context = 0;
840}
841
842
843struct swrast_device_driver *
844_swrast_GetDeviceDriverReference( GLcontext *ctx )
845{
846   SWcontext *swrast = SWRAST_CONTEXT(ctx);
847   return &swrast->Driver;
848}
849
850void
851_swrast_flush( GLcontext *ctx )
852{
853   SWcontext *swrast = SWRAST_CONTEXT(ctx);
854   /* flush any pending fragments from rendering points */
855   if (swrast->PointSpan.end > 0) {
856      if (ctx->Visual.rgbMode) {
857         _swrast_write_rgba_span(ctx, &(swrast->PointSpan));
858      }
859      else {
860         _swrast_write_index_span(ctx, &(swrast->PointSpan));
861      }
862      swrast->PointSpan.end = 0;
863   }
864}
865
866void
867_swrast_render_primitive( GLcontext *ctx, GLenum prim )
868{
869   SWcontext *swrast = SWRAST_CONTEXT(ctx);
870   if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
871      _swrast_flush(ctx);
872   }
873   swrast->Primitive = prim;
874}
875
876
877void
878_swrast_render_start( GLcontext *ctx )
879{
880   SWcontext *swrast = SWRAST_CONTEXT(ctx);
881   if (swrast->Driver.SpanRenderStart)
882      swrast->Driver.SpanRenderStart( ctx );
883   swrast->PointSpan.end = 0;
884}
885
886void
887_swrast_render_finish( GLcontext *ctx )
888{
889   SWcontext *swrast = SWRAST_CONTEXT(ctx);
890   if (swrast->Driver.SpanRenderFinish)
891      swrast->Driver.SpanRenderFinish( ctx );
892
893   _swrast_flush(ctx);
894}
895
896
897#define SWRAST_DEBUG_VERTICES 0
898
899void
900_swrast_print_vertex( GLcontext *ctx, const SWvertex *v )
901{
902   GLuint i;
903
904   if (SWRAST_DEBUG_VERTICES) {
905      _mesa_debug(ctx, "win %f %f %f %f\n",
906                  v->win[0], v->win[1], v->win[2], v->win[3]);
907
908      for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
909	 if (ctx->Texture.Unit[i]._ReallyEnabled)
910	    _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
911                        v->attrib[FRAG_ATTRIB_TEX0 + i][0],
912                        v->attrib[FRAG_ATTRIB_TEX0 + i][1],
913                        v->attrib[FRAG_ATTRIB_TEX0 + i][2],
914                        v->attrib[FRAG_ATTRIB_TEX0 + i][3]);
915
916#if CHAN_TYPE == GL_FLOAT
917      _mesa_debug(ctx, "color %f %f %f %f\n",
918                  v->color[0], v->color[1], v->color[2], v->color[3]);
919      _mesa_debug(ctx, "spec %f %f %f %f\n",
920                  v->specular[0], v->specular[1],
921                  v->specular[2], v->specular[3]);
922#else
923      _mesa_debug(ctx, "color %d %d %d %d\n",
924                  v->color[0], v->color[1], v->color[2], v->color[3]);
925      _mesa_debug(ctx, "spec %d %d %d %d\n",
926                  v->specular[0], v->specular[1],
927                  v->specular[2], v->specular[3]);
928#endif
929      _mesa_debug(ctx, "fog %f\n", v->attrib[FRAG_ATTRIB_FOGC][0]);
930      _mesa_debug(ctx, "index %d\n", v->index);
931      _mesa_debug(ctx, "pointsize %f\n", v->pointSize);
932      _mesa_debug(ctx, "\n");
933   }
934}
935