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