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