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