xref: /reactos/dll/opengl/mesa/span.c (revision 5f2bebf7)
1 /* $Id: span.c,v 1.12 1997/08/14 01:12:37 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.4
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: span.c,v $
26  * Revision 1.12  1997/08/14 01:12:37  brianp
27  * replaced a few for loops with MEMSET calls
28  *
29  * Revision 1.11  1997/07/24 01:21:56  brianp
30  * changed precompiled header symbol from PCH to PC_HEADER
31  *
32  * Revision 1.10  1997/05/28 03:26:29  brianp
33  * added precompiled header (PCH) support
34  *
35  * Revision 1.9  1997/05/03 00:51:30  brianp
36  * new texturing function call: gl_texture_pixels()
37  *
38  * Revision 1.8  1997/04/16 23:54:11  brianp
39  * do per-pixel fog if texturing is enabled
40  *
41  * Revision 1.7  1997/02/09 19:53:43  brianp
42  * now use TEXTURE_xD enable constants
43  *
44  * Revision 1.6  1997/02/09 18:43:34  brianp
45  * added GL_EXT_texture3D support
46  *
47  * Revision 1.5  1997/01/28 22:17:44  brianp
48  * new RGBA mode logic op support
49  *
50  * Revision 1.4  1996/09/25 03:22:05  brianp
51  * added NO_DRAW_BIT support
52  *
53  * Revision 1.3  1996/09/15 14:18:55  brianp
54  * now use GLframebuffer and GLvisual
55  *
56  * Revision 1.2  1996/09/15 01:48:58  brianp
57  * removed #define NULL 0
58  *
59  * Revision 1.1  1996/09/13 01:38:16  brianp
60  * Initial revision
61  *
62  */
63 
64 
65 /*
66  * pixel span rasterization:
67  * These functions simulate the rasterization pipeline.
68  */
69 
70 
71 #ifdef PC_HEADER
72 #include "all.h"
73 #else
74 #include <string.h>
75 #include "alpha.h"
76 #include "alphabuf.h"
77 #include "blend.h"
78 #include "depth.h"
79 #include "fog.h"
80 #include "logic.h"
81 #include "macros.h"
82 #include "masking.h"
83 #include "scissor.h"
84 #include "span.h"
85 #include "stencil.h"
86 #include "texture.h"
87 #include "types.h"
88 #endif
89 
90 
91 
92 
93 /*
94  * Apply the current polygon stipple pattern to a span of pixels.
95  */
stipple_polygon_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLubyte mask[])96 static void stipple_polygon_span( GLcontext *ctx,
97                                   GLuint n, GLint x, GLint y, GLubyte mask[] )
98 {
99    register GLuint i, m, stipple, highbit=0x80000000;
100 
101    stipple = ctx->PolygonStipple[y % 32];
102    m = highbit >> (GLuint) (x % 32);
103 
104    for (i=0;i<n;i++) {
105       if ((m & stipple)==0) {
106 	 mask[i] = 0;
107       }
108       m = m >> 1;
109       if (m==0) {
110 	 m = 0x80000000;
111       }
112    }
113 }
114 
115 
116 
117 /*
118  * Clip a pixel span to the current buffer/window boundaries.
119  * Return:  0 = all pixels clipped
120  *          1 = at least one pixel is visible
121  */
clip_span(GLcontext * ctx,GLint n,GLint x,GLint y,GLubyte mask[])122 static GLuint clip_span( GLcontext *ctx,
123                          GLint n, GLint x, GLint y, GLubyte mask[] )
124 {
125    GLint i;
126 
127    /* Clip to top and bottom */
128    if (y<0 || y>=ctx->Buffer->Height) {
129       return 0;
130    }
131 
132    /* Clip to left and right */
133    if (x>=0 && x+n<=ctx->Buffer->Width) {
134       /* no clipping needed */
135       return 1;
136    }
137    else if (x+n<=0) {
138       /* completely off left side */
139       return 0;
140    }
141    else if (x>=ctx->Buffer->Width) {
142       /* completely off right side */
143       return 0;
144    }
145    else {
146       /* clip-test each pixel, this could be done better */
147       for (i=0;i<n;i++) {
148          if (x+i<0 || x+i>=ctx->Buffer->Width) {
149             mask[i] = 0;
150          }
151       }
152       return 1;
153    }
154 }
155 
156 
157 
158 /*
159  * Write a horizontal span of color index pixels to the frame buffer.
160  * Stenciling, Depth-testing, etc. are done as needed.
161  * Input:  n - number of pixels in the span
162  *         x, y - location of leftmost pixel in the span
163  *         z - array of [n] z-values
164  *         index - array of [n] color indexes
165  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
166  */
gl_write_index_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLdepth z[],GLuint index[],GLenum primitive)167 void gl_write_index_span( GLcontext *ctx,
168                           GLuint n, GLint x, GLint y, GLdepth z[],
169 			  GLuint index[], GLenum primitive )
170 {
171    GLubyte mask[MAX_WIDTH];
172    GLuint index_save[MAX_WIDTH];
173 
174    /* init mask to 1's (all pixels are to be written) */
175    MEMSET(mask, 1, n);
176 
177    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
178       if (clip_span(ctx,n,x,y,mask)==0) {
179 	 return;
180       }
181    }
182 
183    /* Per-pixel fog */
184    if (ctx->Fog.Enabled
185        && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
186       gl_fog_index_pixels( ctx, n, z, index );
187    }
188 
189    /* Do the scissor test */
190    if (ctx->Scissor.Enabled) {
191       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
192 	 return;
193       }
194    }
195 
196    /* Polygon Stippling */
197    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
198       stipple_polygon_span( ctx, n, x, y, mask );
199    }
200 
201    if (ctx->Stencil.Enabled) {
202       /* first stencil test */
203       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
204 	 return;
205       }
206       /* depth buffering w/ stencil */
207       gl_depth_stencil_span( ctx, n, x, y, z, mask );
208    }
209    else if (ctx->Depth.Test) {
210       /* regular depth testing */
211       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
212    }
213 
214    if (ctx->RasterMask & NO_DRAW_BIT) {
215       /* write no pixels */
216       return;
217    }
218 
219    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
220       /* Save a copy of the indexes since LogicOp and IndexMask
221        * may change them
222        */
223       MEMCPY( index_save, index, n * sizeof(GLuint) );
224    }
225 
226    if (ctx->Color.SWLogicOpEnabled) {
227       gl_logicop_ci_span( ctx, n, x, y, index, mask );
228    }
229    if (ctx->Color.SWmasking) {
230       gl_mask_index_span( ctx, n, x, y, index );
231    }
232 
233    /* write pixels */
234    (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask );
235 
236 
237    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
238       /*** Also draw to back buffer ***/
239       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
240       MEMCPY( index, index_save, n * sizeof(GLuint) );
241       if (ctx->Color.SWLogicOpEnabled) {
242          gl_logicop_ci_span( ctx, n, x, y, index, mask );
243       }
244       if (ctx->Color.SWmasking) {
245          gl_mask_index_span( ctx, n, x, y, index );
246       }
247       (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask );
248       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
249    }
250 }
251 
252 
253 
254 
gl_write_monoindex_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLdepth z[],GLuint index,GLenum primitive)255 void gl_write_monoindex_span( GLcontext *ctx,
256                               GLuint n, GLint x, GLint y, GLdepth z[],
257 			      GLuint index, GLenum primitive )
258 {
259     GLuint i;
260     GLubyte mask[MAX_WIDTH];
261     GLuint index_save[MAX_WIDTH];
262 
263     /* init mask to 1's (all pixels are to be written) */
264     MEMSET(mask, 1, n);
265 
266     if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP)
267     {
268         if (clip_span( ctx,n,x,y,mask)==0) {
269             return;
270         }
271     }
272 
273     /* Do the scissor test */
274     if (ctx->Scissor.Enabled)
275     {
276         if (gl_scissor_span( ctx, n, x, y, mask )==0) {
277             return;
278         }
279     }
280 
281     /* Polygon Stippling */
282     if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON)
283     {
284         stipple_polygon_span( ctx, n, x, y, mask );
285     }
286 
287     if (ctx->Stencil.Enabled)
288     {
289         /* first stencil test */
290         if (gl_stencil_span( ctx, n, x, y, mask )==0)
291         {
292             return;
293         }
294         /* depth buffering w/ stencil */
295         gl_depth_stencil_span( ctx, n, x, y, z, mask );
296     }
297     else if (ctx->Depth.Test)
298     {
299         /* regular depth testing */
300         if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)
301             return;
302     }
303 
304     if (ctx->RasterMask & NO_DRAW_BIT)
305     {
306         /* write no pixels */
307         return;
308    }
309 
310     if ((ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP))
311             || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking)
312     {
313         GLuint ispan[MAX_WIDTH];
314         /* index may change, replicate single index into an array */
315         for (i=0;i<n;i++)
316         {
317             ispan[i] = index;
318         }
319 
320         if (ctx->Fog.Enabled
321                 && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP))
322         {
323             gl_fog_index_pixels( ctx, n, z, ispan );
324         }
325 
326         if (ctx->RasterMask & FRONT_AND_BACK_BIT)
327         {
328             MEMCPY( index_save, ispan, n * sizeof(GLuint) );
329         }
330 
331         if (ctx->Color.SWLogicOpEnabled)
332         {
333             gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
334         }
335 
336         if (ctx->Color.SWmasking)
337         {
338             gl_mask_index_span( ctx, n, x, y, ispan );
339         }
340 
341         (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask );
342 
343         if (ctx->RasterMask & FRONT_AND_BACK_BIT)
344         {
345              /*** Also draw to back buffer ***/
346              (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
347              for (i=0;i<n;i++)
348              {
349                 ispan[i] = index;
350              }
351 
352              if (ctx->Color.SWLogicOpEnabled) {
353                  gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
354              }
355              if (ctx->Color.SWmasking) {
356                  gl_mask_index_span( ctx, n, x, y, ispan );
357              }
358              (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask );
359              (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
360         }
361     }
362     else
363     {
364         (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask );
365 
366         if (ctx->RasterMask & FRONT_AND_BACK_BIT)
367         {
368             /*** Also draw to back buffer ***/
369             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
370             (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask );
371             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
372         }
373     }
374 }
375 
376 
377 
gl_write_color_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLdepth z[],GLubyte r[],GLubyte g[],GLubyte b[],GLubyte a[],GLenum primitive)378 void gl_write_color_span( GLcontext *ctx,
379                           GLuint n, GLint x, GLint y, GLdepth z[],
380 			  GLubyte r[], GLubyte g[],
381 			  GLubyte b[], GLubyte a[],
382 			  GLenum primitive )
383 {
384    GLubyte mask[MAX_WIDTH];
385    GLboolean write_all = GL_TRUE;
386    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
387    GLubyte *red, *green, *blue, *alpha;
388 
389    /* init mask to 1's (all pixels are to be written) */
390    MEMSET(mask, 1, n);
391 
392    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
393       if (clip_span( ctx,n,x,y,mask)==0) {
394 	 return;
395       }
396       write_all = GL_FALSE;
397    }
398 
399    if ((primitive==GL_BITMAP && ctx->MutablePixels)
400        || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
401       /* must make a copy of the colors since they may be modified */
402       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
403       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
404       MEMCPY( btmp, b, n * sizeof(GLubyte) );
405       MEMCPY( atmp, a, n * sizeof(GLubyte) );
406       red = rtmp;
407       green = gtmp;
408       blue = btmp;
409       alpha = atmp;
410    }
411    else {
412       red   = r;
413       green = g;
414       blue  = b;
415       alpha = a;
416    }
417 
418    /* Per-pixel fog */
419    if (ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP
420                             || ctx->Texture.Enabled)) {
421       gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha );
422    }
423 
424    /* Do the scissor test */
425    if (ctx->Scissor.Enabled) {
426       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
427 	 return;
428       }
429       write_all = GL_FALSE;
430    }
431 
432    /* Polygon Stippling */
433    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
434       stipple_polygon_span( ctx, n, x, y, mask );
435       write_all = GL_FALSE;
436    }
437 
438    /* Do the alpha test */
439    if (ctx->Color.AlphaEnabled) {
440       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
441 	 return;
442       }
443       write_all = GL_FALSE;
444    }
445 
446    if (ctx->Stencil.Enabled) {
447       /* first stencil test */
448       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
449 	 return;
450       }
451       /* depth buffering w/ stencil */
452       gl_depth_stencil_span( ctx, n, x, y, z, mask );
453       write_all = GL_FALSE;
454    }
455    else if (ctx->Depth.Test) {
456       /* regular depth testing */
457       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
458       if (m==0) {
459          return;
460       }
461       if (m<n) {
462          write_all = GL_FALSE;
463       }
464    }
465 
466    if (ctx->RasterMask & NO_DRAW_BIT) {
467       /* write no pixels */
468       return;
469    }
470 
471    /* logic op or blending */
472    if (ctx->Color.SWLogicOpEnabled) {
473       gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
474    }
475    else if (ctx->Color.BlendEnabled) {
476       gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
477    }
478 
479    /* Color component masking */
480    if (ctx->Color.SWmasking) {
481       gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
482    }
483 
484    /* write pixels */
485    (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
486                                   write_all ? NULL : mask );
487    if (ctx->RasterMask & ALPHABUF_BIT) {
488       gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
489    }
490 
491    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
492       /*** Also render to back buffer ***/
493       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
494       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
495       MEMCPY( btmp, b, n * sizeof(GLubyte) );
496       MEMCPY( atmp, a, n * sizeof(GLubyte) );
497       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
498       if (ctx->Color.SWLogicOpEnabled) {
499          gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
500       }
501       else  if (ctx->Color.BlendEnabled) {
502          gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
503       }
504       if (ctx->Color.SWmasking) {
505          gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
506       }
507       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
508                               write_all ? NULL : mask );
509       if (ctx->RasterMask & ALPHABUF_BIT) {
510          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
511          gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
512          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
513       }
514       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
515    }
516 
517 }
518 
519 
520 
521 /*
522  * Write a horizontal span of color pixels to the frame buffer.
523  * The color is initially constant for the whole span.
524  * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
525  * Input:  n - number of pixels in the span
526  *         x, y - location of leftmost pixel in the span
527  *         z - array of [n] z-values
528  *         r, g, b, a - the color of the pixels
529  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
530  */
gl_write_monocolor_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLdepth z[],GLint r,GLint g,GLint b,GLint a,GLenum primitive)531 void gl_write_monocolor_span( GLcontext *ctx,
532                               GLuint n, GLint x, GLint y, GLdepth z[],
533 			      GLint r, GLint g, GLint b, GLint a,
534                               GLenum primitive )
535 {
536    GLuint i;
537    GLubyte mask[MAX_WIDTH];
538    GLboolean write_all = GL_TRUE;
539    GLubyte red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH];
540 
541    /* init mask to 1's (all pixels are to be written) */
542    MEMSET(mask, 1, n);
543 
544    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
545       if (clip_span( ctx,n,x,y,mask)==0) {
546 	 return;
547       }
548       write_all = GL_FALSE;
549    }
550 
551    /* Do the scissor test */
552    if (ctx->Scissor.Enabled) {
553       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
554 	 return;
555       }
556       write_all = GL_FALSE;
557    }
558 
559    /* Polygon Stippling */
560    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
561       stipple_polygon_span( ctx, n, x, y, mask );
562       write_all = GL_FALSE;
563    }
564 
565    /* Do the alpha test */
566    if (ctx->Color.AlphaEnabled) {
567       GLubyte alpha[MAX_WIDTH];
568       for (i=0;i<n;i++) {
569          alpha[i] = a;
570       }
571       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
572 	 return;
573       }
574       write_all = GL_FALSE;
575    }
576 
577    if (ctx->Stencil.Enabled) {
578       /* first stencil test */
579       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
580 	 return;
581       }
582       /* depth buffering w/ stencil */
583       gl_depth_stencil_span( ctx, n, x, y, z, mask );
584       write_all = GL_FALSE;
585    }
586    else if (ctx->Depth.Test) {
587       /* regular depth testing */
588       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
589       if (m==0) {
590          return;
591       }
592       if (m<n) {
593          write_all = GL_FALSE;
594       }
595    }
596 
597    if (ctx->RasterMask & NO_DRAW_BIT) {
598       /* write no pixels */
599       return;
600    }
601 
602    if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled
603        || ctx->Color.SWmasking) {
604       /* assign same color to each pixel */
605       for (i=0;i<n;i++) {
606 	 if (mask[i]) {
607 	    red[i]   = r;
608 	    green[i] = g;
609 	    blue[i]  = b;
610 	    alpha[i] = a;
611 	 }
612       }
613 
614       if (ctx->Color.SWLogicOpEnabled) {
615          gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
616       }
617       else if (ctx->Color.BlendEnabled) {
618          gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
619       }
620 
621       /* Color component masking */
622       if (ctx->Color.SWmasking) {
623          gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
624       }
625 
626       /* write pixels */
627       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
628                                      write_all ? NULL : mask );
629       if (ctx->RasterMask & ALPHABUF_BIT) {
630          gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
631       }
632 
633       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
634          /*** Also draw to back buffer ***/
635          for (i=0;i<n;i++) {
636             if (mask[i]) {
637                red[i]   = r;
638                green[i] = g;
639                blue[i]  = b;
640                alpha[i] = a;
641             }
642          }
643          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
644          if (ctx->Color.SWLogicOpEnabled) {
645             gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask);
646          }
647          else if (ctx->Color.BlendEnabled) {
648             gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
649          }
650          if (ctx->Color.SWmasking) {
651             gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
652          }
653          (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
654                                         write_all ? NULL : mask );
655          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
656          if (ctx->RasterMask & ALPHABUF_BIT) {
657             ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
658             gl_write_alpha_span( ctx, n, x, y, alpha,
659                                  write_all ? NULL : mask );
660             ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
661          }
662       }
663    }
664    else {
665       (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask );
666       if (ctx->RasterMask & ALPHABUF_BIT) {
667          gl_write_mono_alpha_span( ctx, n, x, y, a, write_all ? NULL : mask );
668       }
669       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
670          /* Also draw to back buffer */
671          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
672          (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask );
673          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
674          if (ctx->RasterMask & ALPHABUF_BIT) {
675             ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
676             gl_write_mono_alpha_span( ctx, n, x, y, a,
677                                       write_all ? NULL : mask );
678             ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
679          }
680       }
681    }
682 }
683 
684 
685 
686 /*
687  * Write a horizontal span of textured pixels to the frame buffer.
688  * The color of each pixel is different.
689  * Alpha-testing, stenciling, depth-testing, and blending are done
690  * as needed.
691  * Input:  n - number of pixels in the span
692  *         x, y - location of leftmost pixel in the span
693  *         z - array of [n] z-values
694  *         s, t - array of (s,t) texture coordinates for each pixel
695  *         lambda - array of texture lambda values
696  *         red, green, blue, alpha - array of [n] color components
697  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
698  */
gl_write_texture_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLdepth z[],GLfloat s[],GLfloat t[],GLfloat u[],GLfloat lambda[],GLubyte r[],GLubyte g[],GLubyte b[],GLubyte a[],GLenum primitive)699 void gl_write_texture_span( GLcontext *ctx,
700                             GLuint n, GLint x, GLint y, GLdepth z[],
701 			    GLfloat s[], GLfloat t[], GLfloat u[],
702                             GLfloat lambda[],
703 			    GLubyte r[], GLubyte g[],
704 			    GLubyte b[], GLubyte a[],
705 			    GLenum primitive )
706 {
707    GLubyte mask[MAX_WIDTH];
708    GLboolean write_all = GL_TRUE;
709    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
710    GLubyte *red, *green, *blue, *alpha;
711 
712    /* init mask to 1's (all pixels are to be written) */
713    MEMSET(mask, 1, n);
714 
715    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
716       if (clip_span( ctx,n,x,y,mask)==0) {
717 	 return;
718       }
719       write_all = GL_FALSE;
720    }
721 
722 
723    if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
724       /* must make a copy of the colors since they may be modified */
725       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
726       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
727       MEMCPY( btmp, b, n * sizeof(GLubyte) );
728       MEMCPY( atmp, a, n * sizeof(GLubyte) );
729       red = rtmp;
730       green = gtmp;
731       blue = btmp;
732       alpha = atmp;
733    }
734    else {
735       red   = r;
736       green = g;
737       blue  = b;
738       alpha = a;
739    }
740 
741    /* Texture */
742    ASSERT(ctx->Texture.Enabled);
743    gl_texture_pixels( ctx, n, s, t, u, lambda, red, green, blue, alpha );
744 
745    /* Per-pixel fog */
746    if (ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP
747                             || ctx->Texture.Enabled)) {
748       gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha );
749    }
750 
751    /* Do the scissor test */
752    if (ctx->Scissor.Enabled) {
753       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
754 	 return;
755       }
756       write_all = GL_FALSE;
757    }
758 
759    /* Polygon Stippling */
760    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
761       stipple_polygon_span( ctx, n, x, y, mask );
762       write_all = GL_FALSE;
763    }
764 
765    /* Do the alpha test */
766    if (ctx->Color.AlphaEnabled) {
767       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
768 	 return;
769       }
770       write_all = GL_FALSE;
771    }
772 
773    if (ctx->Stencil.Enabled) {
774       /* first stencil test */
775       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
776 	 return;
777       }
778       /* depth buffering w/ stencil */
779       gl_depth_stencil_span( ctx, n, x, y, z, mask );
780       write_all = GL_FALSE;
781    }
782    else if (ctx->Depth.Test) {
783       /* regular depth testing */
784       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
785       if (m==0) {
786          return;
787       }
788       if (m<n) {
789          write_all = GL_FALSE;
790       }
791    }
792 
793    if (ctx->RasterMask & NO_DRAW_BIT) {
794       /* write no pixels */
795       return;
796    }
797 
798    /* blending */
799    if (ctx->Color.SWLogicOpEnabled) {
800       gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
801    }
802    else  if (ctx->Color.BlendEnabled) {
803       gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
804    }
805 
806    if (ctx->Color.SWmasking) {
807       gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
808    }
809 
810    /* write pixels */
811    (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
812                                   write_all ? NULL : mask );
813    if (ctx->RasterMask & ALPHABUF_BIT) {
814       gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
815    }
816 
817    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
818       /* Also draw to back buffer */
819       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
820       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
821       MEMCPY( btmp, b, n * sizeof(GLubyte) );
822       MEMCPY( atmp, a, n * sizeof(GLubyte) );
823       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
824       if (ctx->Color.SWLogicOpEnabled) {
825          gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
826       }
827       else if (ctx->Color.BlendEnabled) {
828          gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
829       }
830       if (ctx->Color.SWmasking) {
831          gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
832       }
833       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
834                                      write_all ? NULL : mask );
835       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
836       if (ctx->RasterMask & ALPHABUF_BIT) {
837          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
838          gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
839          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
840       }
841    }
842 }
843 
844 
845 
846 /*
847  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
848  * reading ouside the buffer's boundaries.
849  */
gl_read_color_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLubyte red[],GLubyte green[],GLubyte blue[],GLubyte alpha[])850 void gl_read_color_span( GLcontext *ctx,
851                          GLuint n, GLint x, GLint y,
852 			 GLubyte red[], GLubyte green[],
853 			 GLubyte blue[], GLubyte alpha[] )
854 {
855    register GLuint i;
856 
857    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
858       /* completely above, below, or right */
859       for (i=0;i<n;i++) {
860 	 red[i] = green[i] = blue[i] = alpha[i] = 0;
861       }
862    }
863    else {
864       if (x>=0 && x+n<=ctx->Buffer->Width) {
865 	 /* OK */
866 	 (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red, green, blue, alpha );
867          if (ctx->RasterMask & ALPHABUF_BIT) {
868             gl_read_alpha_span( ctx, n, x, y, alpha );
869          }
870       }
871       else {
872 	 i = 0;
873 	 if (x<0) {
874 	    while (x<0 && n>0) {
875 	       red[i] = green[i] =  blue[i] = alpha[i] = 0;
876 	       x++;
877 	       n--;
878 	       i++;
879 	    }
880 	 }
881 	 n = MIN2( n, ctx->Buffer->Width - x );
882 	 (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red+i, green+i, blue+i, alpha+i);
883          if (ctx->RasterMask & ALPHABUF_BIT) {
884             gl_read_alpha_span( ctx, n, x, y, alpha+i );
885          }
886       }
887    }
888 }
889 
890 
891 
892 
893 /*
894  * Read CI pixels from frame buffer.  Clipping will be done to prevent
895  * reading ouside the buffer's boundaries.
896  */
gl_read_index_span(GLcontext * ctx,GLuint n,GLint x,GLint y,GLuint indx[])897 void gl_read_index_span( GLcontext *ctx,
898                          GLuint n, GLint x, GLint y, GLuint indx[] )
899 {
900    register GLuint i;
901 
902    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
903       /* completely above, below, or right */
904       for (i=0;i<n;i++) {
905 	 indx[i] = 0;
906       }
907    }
908    else {
909       if (x>=0 && x+n<=ctx->Buffer->Width) {
910 	 /* OK */
911 	 (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx );
912       }
913       else {
914 	 i = 0;
915 	 if (x<0) {
916 	    while (x<0 && n>0) {
917 	       indx[i] = 0;
918 	       x++;
919 	       n--;
920 	       i++;
921 	    }
922 	 }
923 	 n = MIN2( n, ctx->Buffer->Width - x );
924 	 (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx+i );
925       }
926    }
927 }
928 
929 
930