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 
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  */
55 static void
_swrast_update_rasterflags(struct gl_context * ctx)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  */
128 static void
_swrast_update_polygon(struct gl_context * ctx)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  */
164 static void
_swrast_update_fog_hint(struct gl_context * ctx)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  */
179 static void
_swrast_update_texture_env(struct gl_context * ctx)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  */
210 static void
_swrast_update_deferred_texture(struct gl_context * ctx)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  */
243 static void
_swrast_update_fog_state(struct gl_context * ctx)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  */
262 static void
_swrast_update_fragment_program(struct gl_context * ctx,GLbitfield newState)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  */
277 static void
_swrast_update_specular_vertex_add(struct gl_context * ctx)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  */
341 static void
_swrast_validate_triangle(struct gl_context * ctx,const SWvertex * v0,const SWvertex * v1,const SWvertex * v2)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  */
366 static void
_swrast_validate_line(struct gl_context * ctx,const SWvertex * v0,const SWvertex * v1)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  */
387 static void
_swrast_validate_point(struct gl_context * ctx,const SWvertex * v0)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  */
408 static void
_swrast_validate_blend_func(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)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 
421 static void
_swrast_sleep(struct gl_context * ctx,GLbitfield new_state)422 _swrast_sleep( struct gl_context *ctx, GLbitfield new_state )
423 {
424    (void) ctx; (void) new_state;
425 }
426 
427 
428 static void
_swrast_invalidate_state(struct gl_context * ctx,GLbitfield new_state)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 
463 void
_swrast_update_texture_samplers(struct gl_context * ctx)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  */
489 static void
_swrast_update_active_attribs(struct gl_context * ctx)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 
547 void
_swrast_validate_derived(struct gl_context * ctx)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  */
601 void
_swrast_Quad(struct gl_context * ctx,const SWvertex * v0,const SWvertex * v1,const SWvertex * v2,const SWvertex * v3)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 
617 void
_swrast_Triangle(struct gl_context * ctx,const SWvertex * v0,const SWvertex * v1,const SWvertex * v2)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 
630 void
_swrast_Line(struct gl_context * ctx,const SWvertex * v0,const SWvertex * v1)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 
641 void
_swrast_Point(struct gl_context * ctx,const SWvertex * v0)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 
651 void
_swrast_InvalidateState(struct gl_context * ctx,GLbitfield new_state)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 
660 void
_swrast_ResetLineStipple(struct gl_context * ctx)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 
669 void
_swrast_SetFacing(struct gl_context * ctx,GLuint facing)670 _swrast_SetFacing(struct gl_context *ctx, GLuint facing)
671 {
672    SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
673 }
674 
675 void
_swrast_allow_vertex_fog(struct gl_context * ctx,GLboolean value)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 
685 void
_swrast_allow_pixel_fog(struct gl_context * ctx,GLboolean value)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  */
700 static void
init_program_native_limits(struct gl_program_constants * prog)701 init_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 
714 GLboolean
_swrast_CreateContext(struct gl_context * ctx)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(ctx->Const.MaxTextureSize <= 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 
817 void
_swrast_DestroyContext(struct gl_context * ctx)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 
841 struct swrast_device_driver *
_swrast_GetDeviceDriverReference(struct gl_context * ctx)842 _swrast_GetDeviceDriverReference( struct gl_context *ctx )
843 {
844    SWcontext *swrast = SWRAST_CONTEXT(ctx);
845    return &swrast->Driver;
846 }
847 
848 void
_swrast_flush(struct gl_context * ctx)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 
859 void
_swrast_render_primitive(struct gl_context * ctx,GLenum prim)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() */
871 void
_swrast_span_render_start(struct gl_context * ctx)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() */
880 void
_swrast_span_render_finish(struct gl_context * ctx)881 _swrast_span_render_finish(struct gl_context *ctx)
882 {
883    _swrast_unmap_textures(ctx);
884    _swrast_unmap_renderbuffers(ctx);
885 }
886 
887 
888 void
_swrast_render_start(struct gl_context * ctx)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 
897 void
_swrast_render_finish(struct gl_context * ctx)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 
916 void
_swrast_print_vertex(struct gl_context * ctx,const SWvertex * v)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