source: trunk/src/opengl/mesa/span.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

File size: 30.5 KB
Line 
1/* $Id: span.c,v 1.2 2000-05-23 20:40:53 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * pixel span rasterization:
30 * These functions implement the rasterization pipeline.
31 */
32
33
34#ifdef PC_HEADER
35#include "all.h"
36#else
37#include "glheader.h"
38#include "alpha.h"
39#include "alphabuf.h"
40#include "blend.h"
41#include "depth.h"
42#include "fog.h"
43#include "logic.h"
44#include "macros.h"
45#include "masking.h"
46#include "mem.h"
47#include "scissor.h"
48#include "span.h"
49#include "stencil.h"
50#include "texture.h"
51#include "types.h"
52#endif
53
54
55
56
57/*
58 * Apply the current polygon stipple pattern to a span of pixels.
59 */
60static void stipple_polygon_span( GLcontext *ctx,
61 GLuint n, GLint x, GLint y, GLubyte mask[] )
62{
63 register GLuint i, m, stipple, highbit=0x80000000;
64
65 stipple = ctx->PolygonStipple[y % 32];
66 m = highbit >> (GLuint) (x % 32);
67
68 for (i=0;i<n;i++) {
69 if ((m & stipple)==0) {
70 mask[i] = 0;
71 }
72 m = m >> 1;
73 if (m==0) {
74 m = 0x80000000;
75 }
76 }
77}
78
79
80
81/*
82 * Clip a pixel span to the current buffer/window boundaries.
83 * Return: 0 = all pixels clipped
84 * 1 = at least one pixel is visible
85 */
86static GLuint clip_span( GLcontext *ctx,
87 GLint n, GLint x, GLint y, GLubyte mask[] )
88{
89 GLint i;
90
91 /* Clip to top and bottom */
92 if (y < 0 || y >= ctx->DrawBuffer->Height) {
93 return 0;
94 }
95
96 /* Clip to left and right */
97 if (x >= 0 && x + n <= ctx->DrawBuffer->Width) {
98 /* no clipping needed */
99 return 1;
100 }
101 else if (x + n <= 0) {
102 /* completely off left side */
103 return 0;
104 }
105 else if (x >= ctx->DrawBuffer->Width) {
106 /* completely off right side */
107 return 0;
108 }
109 else {
110 /* clip-test each pixel, this could be done better */
111 for (i=0;i<n;i++) {
112 if (x + i < 0 || x + i >= ctx->DrawBuffer->Width) {
113 mask[i] = 0;
114 }
115 }
116 return 1;
117 }
118}
119
120
121
122/*
123 * Draw to more than one color buffer (or none).
124 */
125static void multi_write_index_span( GLcontext *ctx, GLuint n,
126 GLint x, GLint y, const GLuint indexes[],
127 const GLubyte mask[] )
128{
129 GLuint bufferBit;
130
131 if (ctx->Color.DrawBuffer == GL_NONE)
132 return;
133
134 /* loop over four possible dest color buffers */
135 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
136 if (bufferBit & ctx->Color.DrawDestMask) {
137 GLuint indexTmp[MAX_WIDTH];
138 ASSERT(n < MAX_WIDTH);
139
140 if (bufferBit == FRONT_LEFT_BIT)
141 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
142 else if (bufferBit == FRONT_RIGHT_BIT)
143 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
144 else if (bufferBit == BACK_LEFT_BIT)
145 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
146 else
147 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
148
149 /* make copy of incoming indexes */
150 MEMCPY( indexTmp, indexes, n * sizeof(GLuint) );
151 if (ctx->Color.SWLogicOpEnabled) {
152 gl_logicop_ci_span( ctx, n, x, y, indexTmp, mask );
153 }
154 if (ctx->Color.SWmasking) {
155 gl_mask_index_span( ctx, n, x, y, indexTmp );
156 }
157 (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, indexTmp, mask );
158 }
159 }
160
161 /* restore default dest buffer */
162 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer);
163}
164
165
166
167/*
168 * Write a horizontal span of color index pixels to the frame buffer.
169 * Stenciling, Depth-testing, etc. are done as needed.
170 * Input: n - number of pixels in the span
171 * x, y - location of leftmost pixel in the span
172 * z - array of [n] z-values
173 * index - array of [n] color indexes
174 * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
175 */
176void gl_write_index_span( GLcontext *ctx,
177 GLuint n, GLint x, GLint y, const GLdepth z[],
178 GLuint indexIn[], GLenum primitive )
179{
180 GLubyte mask[MAX_WIDTH];
181 GLuint indexBackup[MAX_WIDTH];
182 GLuint *index; /* points to indexIn or indexBackup */
183
184 /* init mask to 1's (all pixels are to be written) */
185 MEMSET(mask, 1, n);
186
187 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
188 if (clip_span(ctx,n,x,y,mask)==0) {
189 return;
190 }
191 }
192
193 if ((primitive==GL_BITMAP && ctx->MutablePixels)
194 || (ctx->RasterMask & MULTI_DRAW_BIT)) {
195 /* Make copy of color indexes */
196 MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
197 index = indexBackup;
198 }
199 else {
200 index = indexIn;
201 }
202
203 /* Per-pixel fog */
204 if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode == FOG_FRAGMENT)) {
205 _mesa_fog_ci_pixels( ctx, n, z, index );
206 }
207
208 /* Do the scissor test */
209 if (ctx->Scissor.Enabled) {
210 if (gl_scissor_span( ctx, n, x, y, mask )==0) {
211 return;
212 }
213 }
214
215 /* Polygon Stippling */
216 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
217 stipple_polygon_span( ctx, n, x, y, mask );
218 }
219
220 if (ctx->Stencil.Enabled) {
221 /* first stencil test */
222 if (gl_stencil_and_depth_test_span(ctx, n, x, y, z, mask) == GL_FALSE) {
223 return;
224 }
225 }
226 else if (ctx->Depth.Test) {
227 /* regular depth testing */
228 if (_mesa_depth_test_span( ctx, n, x, y, z, mask )==0) return;
229 }
230
231 /* if we get here, something passed the depth test */
232 ctx->OcclusionResult = GL_TRUE;
233
234 if (ctx->RasterMask & MULTI_DRAW_BIT) {
235 /* draw to zero or two or more buffers */
236 multi_write_index_span( ctx, n, x, y, index, mask );
237 }
238 else {
239 /* normal situation: draw to exactly one buffer */
240 if (ctx->Color.SWLogicOpEnabled) {
241 gl_logicop_ci_span( ctx, n, x, y, index, mask );
242 }
243 if (ctx->Color.SWmasking) {
244 gl_mask_index_span( ctx, n, x, y, index );
245 }
246
247 /* write pixels */
248 (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
249 }
250}
251
252
253
254
255void gl_write_monoindex_span( GLcontext *ctx,
256 GLuint n, GLint x, GLint y, const GLdepth z[],
257 GLuint index, GLenum primitive )
258{
259 GLubyte mask[MAX_WIDTH];
260 GLuint i;
261
262 /* init mask to 1's (all pixels are to be written) */
263 MEMSET(mask, 1, n);
264
265 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
266 if (clip_span( ctx, n, x, y, mask)==0) {
267 return;
268 }
269 }
270
271 /* Do the scissor test */
272 if (ctx->Scissor.Enabled) {
273 if (gl_scissor_span( ctx, n, x, y, mask )==0) {
274 return;
275 }
276 }
277
278 /* Polygon Stippling */
279 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
280 stipple_polygon_span( ctx, n, x, y, mask );
281 }
282
283 if (ctx->Stencil.Enabled) {
284 /* first stencil test */
285 if (gl_stencil_and_depth_test_span(ctx, n, x, y, z, mask) == GL_FALSE) {
286 return;
287 }
288 }
289 else if (ctx->Depth.Test) {
290 /* regular depth testing */
291 if (_mesa_depth_test_span( ctx, n, x, y, z, mask )==0) return;
292 }
293
294 /* if we get here, something passed the depth test */
295 ctx->OcclusionResult = GL_TRUE;
296
297 if (ctx->Color.DrawBuffer == GL_NONE) {
298 /* write no pixels */
299 return;
300 }
301
302 if ((ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT))
303 || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking) {
304 /* different index per pixel */
305 GLuint indexes[MAX_WIDTH];
306 for (i=0;i<n;i++) {
307 indexes[i] = index;
308 }
309
310 if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
311 _mesa_fog_ci_pixels( ctx, n, z, indexes );
312 }
313
314 if (ctx->Color.SWLogicOpEnabled) {
315 gl_logicop_ci_span( ctx, n, x, y, indexes, mask );
316 }
317
318 if (ctx->Color.SWmasking) {
319 gl_mask_index_span( ctx, n, x, y, indexes );
320 }
321
322 if (ctx->RasterMask & MULTI_DRAW_BIT) {
323 /* draw to zero or two or more buffers */
324 multi_write_index_span( ctx, n, x, y, indexes, mask );
325 }
326 else {
327 /* normal situation: draw to exactly one buffer */
328 if (ctx->Color.SWLogicOpEnabled) {
329 gl_logicop_ci_span( ctx, n, x, y, indexes, mask );
330 }
331 if (ctx->Color.SWmasking) {
332 gl_mask_index_span( ctx, n, x, y, indexes );
333 }
334 (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, indexes, mask );
335 }
336 }
337 else {
338 /* same color index for all pixels */
339 ASSERT(!ctx->Color.SWLogicOpEnabled);
340 ASSERT(!ctx->Color.SWmasking);
341 if (ctx->RasterMask & MULTI_DRAW_BIT) {
342 /* draw to zero or two or more buffers */
343 GLuint indexes[MAX_WIDTH];
344 for (i=0;i<n;i++)
345 indexes[i] = index;
346 multi_write_index_span( ctx, n, x, y, indexes, mask );
347 }
348 else {
349 /* normal situation: draw to exactly one buffer */
350 (*ctx->Driver.WriteMonoCISpan)( ctx, n, x, y, mask );
351 }
352 }
353}
354
355
356
357/*
358 * Draw to more than one RGBA color buffer (or none).
359 */
360static void multi_write_rgba_span( GLcontext *ctx, GLuint n,
361 GLint x, GLint y, CONST GLubyte rgba[][4],
362 const GLubyte mask[] )
363{
364 GLuint bufferBit;
365
366 if (ctx->Color.DrawBuffer == GL_NONE)
367 return;
368
369 /* loop over four possible dest color buffers */
370 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
371 if (bufferBit & ctx->Color.DrawDestMask) {
372 GLubyte rgbaTmp[MAX_WIDTH][4];
373 ASSERT(n < MAX_WIDTH);
374
375 if (bufferBit == FRONT_LEFT_BIT) {
376 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
377 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
378 }
379 else if (bufferBit == FRONT_RIGHT_BIT) {
380 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
381 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
382 }
383 else if (bufferBit == BACK_LEFT_BIT) {
384 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
385 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
386 }
387 else {
388 (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
389 ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
390 }
391
392 /* make copy of incoming colors */
393 MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLubyte) );
394
395 if (ctx->Color.SWLogicOpEnabled) {
396 gl_logicop_rgba_span( ctx, n, x, y, rgbaTmp, mask );
397 }
398 else if (ctx->Color.BlendEnabled) {
399 _mesa_blend_span( ctx, n, x, y, rgbaTmp, mask );
400 }
401 if (ctx->Color.SWmasking) {
402 gl_mask_rgba_span( ctx, n, x, y, rgbaTmp );
403 }
404
405 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y,
406 (const GLubyte (*)[4]) rgbaTmp, mask );
407 if (ctx->RasterMask & ALPHABUF_BIT) {
408 gl_write_alpha_span( ctx, n, x, y,
409 (const GLubyte (*)[4])rgbaTmp, mask );
410 }
411 }
412 }
413
414 /* restore default dest buffer */
415 (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
416}
417
418
419
420void gl_write_rgba_span( GLcontext *ctx,
421 GLuint n, GLint x, GLint y, const GLdepth z[],
422 GLubyte rgbaIn[][4],
423 GLenum primitive )
424{
425 GLubyte mask[MAX_WIDTH];
426 GLboolean write_all = GL_TRUE;
427 GLubyte rgbaBackup[MAX_WIDTH][4];
428 GLubyte (*rgba)[4];
429 const GLubyte *Null = 0;
430
431 /* init mask to 1's (all pixels are to be written) */
432 MEMSET(mask, 1, n);
433
434 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
435 if (clip_span( ctx,n,x,y,mask)==0) {
436 return;
437 }
438 write_all = GL_FALSE;
439 }
440
441 if ((primitive==GL_BITMAP && ctx->MutablePixels)
442 || (ctx->RasterMask & MULTI_DRAW_BIT)) {
443 /* must make a copy of the colors since they may be modified */
444 MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte) );
445 rgba = rgbaBackup;
446 }
447 else {
448 rgba = rgbaIn;
449 }
450
451 /* Per-pixel fog */
452 if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
453 _mesa_fog_rgba_pixels( ctx, n, z, rgba );
454 }
455
456 /* Do the scissor test */
457 if (ctx->Scissor.Enabled) {
458 if (gl_scissor_span( ctx, n, x, y, mask )==0) {
459 return;
460 }
461 write_all = GL_FALSE;
462 }
463
464 /* Polygon Stippling */
465 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
466 stipple_polygon_span( ctx, n, x, y, mask );
467 write_all = GL_FALSE;
468 }
469
470 /* Do the alpha test */
471 if (ctx->Color.AlphaEnabled) {
472 if (_mesa_alpha_test( ctx, n, (const GLubyte (*)[4]) rgba, mask )==0) {
473 return;
474 }
475 write_all = GL_FALSE;
476 }
477
478 if (ctx->Stencil.Enabled) {
479 /* first stencil test */
480 if (gl_stencil_and_depth_test_span(ctx, n, x, y, z, mask) == GL_FALSE) {
481 return;
482 }
483 write_all = GL_FALSE;
484 }
485 else if (ctx->Depth.Test) {
486 /* regular depth testing */
487 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
488 if (m==0) {
489 return;
490 }
491 if (m<n) {
492 write_all = GL_FALSE;
493 }
494 }
495
496 /* if we get here, something passed the depth test */
497 ctx->OcclusionResult = GL_TRUE;
498
499 if (ctx->RasterMask & MULTI_DRAW_BIT) {
500 multi_write_rgba_span( ctx, n, x, y,
501 (const GLubyte (*)[4]) rgba,
502 write_all ? Null : mask );
503 }
504 else {
505 /* normal: write to exactly one buffer */
506 /* logic op or blending */
507 if (ctx->Color.SWLogicOpEnabled) {
508 gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
509 }
510 else if (ctx->Color.BlendEnabled) {
511 _mesa_blend_span( ctx, n, x, y, rgba, mask );
512 }
513
514 /* Color component masking */
515 if (ctx->Color.SWmasking) {
516 gl_mask_rgba_span( ctx, n, x, y, rgba );
517 }
518
519 /* write pixels */
520 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y,
521 (const GLubyte (*)[4]) rgba,
522 write_all ? Null : mask );
523
524 if (ctx->RasterMask & ALPHABUF_BIT) {
525 gl_write_alpha_span( ctx, n, x, y,
526 (const GLubyte (*)[4]) rgba,
527 write_all ? Null : mask );
528 }
529
530 }
531}
532
533
534
535/*
536 * Write a horizontal span of color pixels to the frame buffer.
537 * The color is initially constant for the whole span.
538 * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
539 * Input: n - number of pixels in the span
540 * x, y - location of leftmost pixel in the span
541 * z - array of [n] z-values
542 * r, g, b, a - the color of the pixels
543 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
544 */
545void gl_write_monocolor_span( GLcontext *ctx,
546 GLuint n, GLint x, GLint y, const GLdepth z[],
547 const GLubyte color[4],
548 GLenum primitive )
549{
550 GLuint i;
551 GLubyte mask[MAX_WIDTH];
552 GLboolean write_all = GL_TRUE;
553 GLubyte rgba[MAX_WIDTH][4];
554 const GLubyte *Null = 0;
555
556 /* init mask to 1's (all pixels are to be written) */
557 MEMSET(mask, 1, n);
558
559 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
560 if (clip_span( ctx,n,x,y,mask)==0) {
561 return;
562 }
563 write_all = GL_FALSE;
564 }
565
566 /* Do the scissor test */
567 if (ctx->Scissor.Enabled) {
568 if (gl_scissor_span( ctx, n, x, y, mask )==0) {
569 return;
570 }
571 write_all = GL_FALSE;
572 }
573
574 /* Polygon Stippling */
575 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
576 stipple_polygon_span( ctx, n, x, y, mask );
577 write_all = GL_FALSE;
578 }
579
580 /* Do the alpha test */
581 if (ctx->Color.AlphaEnabled) {
582 for (i=0;i<n;i++) {
583 rgba[i][ACOMP] = color[ACOMP];
584 }
585 if (_mesa_alpha_test( ctx, n, (const GLubyte (*)[4])rgba, mask )==0) {
586 return;
587 }
588 write_all = GL_FALSE;
589 }
590
591 if (ctx->Stencil.Enabled) {
592 /* first stencil test */
593 if (gl_stencil_and_depth_test_span(ctx, n, x, y, z, mask) == GL_FALSE) {
594 return;
595 }
596 write_all = GL_FALSE;
597 }
598 else if (ctx->Depth.Test) {
599 /* regular depth testing */
600 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
601 if (m==0) {
602 return;
603 }
604 if (m<n) {
605 write_all = GL_FALSE;
606 }
607 }
608
609 /* if we get here, something passed the depth test */
610 ctx->OcclusionResult = GL_TRUE;
611
612 if (ctx->Color.DrawBuffer == GL_NONE) {
613 /* write no pixels */
614 return;
615 }
616
617 if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled
618 || ctx->Color.SWmasking) {
619 /* assign same color to each pixel */
620 for (i=0;i<n;i++) {
621 if (mask[i]) {
622 COPY_4UBV(rgba[i], color);
623 }
624 }
625
626 if (ctx->RasterMask & MULTI_DRAW_BIT) {
627 multi_write_rgba_span( ctx, n, x, y, (const GLubyte (*)[4]) rgba,
628 mask );
629 }
630 else {
631 /* normal: write to exactly one buffer */
632 if (ctx->Color.SWLogicOpEnabled) {
633 gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
634 }
635 else if (ctx->Color.BlendEnabled) {
636 _mesa_blend_span( ctx, n, x, y, rgba, mask );
637 }
638
639 /* Color component masking */
640 if (ctx->Color.SWmasking) {
641 gl_mask_rgba_span( ctx, n, x, y, rgba );
642 }
643
644 /* write pixels */
645 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y,
646 (const GLubyte (*)[4]) rgba,
647 write_all ? Null : mask );
648 if (ctx->RasterMask & ALPHABUF_BIT) {
649 gl_write_alpha_span( ctx, n, x, y,
650 (const GLubyte (*)[4]) rgba,
651 write_all ? Null : mask );
652 }
653 }
654 }
655 else {
656 /* same color for all pixels */
657 ASSERT(!ctx->Color.BlendEnabled);
658 ASSERT(!ctx->Color.SWLogicOpEnabled);
659 ASSERT(!ctx->Color.SWmasking);
660
661 if (ctx->RasterMask & MULTI_DRAW_BIT) {
662 for (i=0;i<n;i++) {
663 if (mask[i]) {
664 COPY_4UBV(rgba[i], color);
665 }
666 }
667 multi_write_rgba_span( ctx, n, x, y,
668 (const GLubyte (*)[4]) rgba,
669 mask );
670 }
671 else {
672 (*ctx->Driver.WriteMonoRGBASpan)( ctx, n, x, y, mask );
673 if (ctx->RasterMask & ALPHABUF_BIT) {
674 gl_write_mono_alpha_span( ctx, n, x, y, (GLubyte) color[ACOMP],
675 write_all ? Null : mask );
676 }
677 }
678 }
679}
680
681
682
683/*
684 * Add specular color to base color. This is used only when
685 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
686 */
687static void add_colors(GLuint n, GLubyte rgba[][4], CONST GLubyte specular[][4] )
688{
689 GLuint i;
690 for (i=0; i<n; i++) {
691 GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
692 GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
693 GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
694 rgba[i][RCOMP] = (GLubyte) MIN2(r, 255);
695 rgba[i][GCOMP] = (GLubyte) MIN2(g, 255);
696 rgba[i][BCOMP] = (GLubyte) MIN2(b, 255);
697 }
698}
699
700
701/*
702 * Write a horizontal span of textured pixels to the frame buffer.
703 * The color of each pixel is different.
704 * Alpha-testing, stenciling, depth-testing, and blending are done
705 * as needed.
706 * Input: n - number of pixels in the span
707 * x, y - location of leftmost pixel in the span
708 * z - array of [n] z-values
709 * s, t - array of (s,t) texture coordinates for each pixel
710 * lambda - array of texture lambda values
711 * rgba - array of [n] color components
712 * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
713 */
714void gl_write_texture_span( GLcontext *ctx,
715 GLuint n, GLint x, GLint y, const GLdepth z[],
716 const GLfloat s[], const GLfloat t[],
717 const GLfloat u[], GLfloat lambda[],
718 GLubyte rgbaIn[][4], CONST GLubyte spec[][4],
719 GLenum primitive )
720{
721 GLubyte mask[MAX_WIDTH];
722 GLboolean write_all = GL_TRUE;
723 GLubyte rgbaBackup[MAX_WIDTH][4];
724 GLubyte (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
725 const GLubyte *Null = 0;
726
727 /* init mask to 1's (all pixels are to be written) */
728 MEMSET(mask, 1, n);
729
730 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
731 if (clip_span(ctx, n, x, y, mask)==0) {
732 return;
733 }
734 write_all = GL_FALSE;
735 }
736
737
738 if (primitive==GL_BITMAP || (ctx->RasterMask & MULTI_DRAW_BIT)) {
739 /* must make a copy of the colors since they may be modified */
740 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte));
741 rgba = rgbaBackup;
742 }
743 else {
744 rgba = rgbaIn;
745 }
746
747 /* Texture */
748 ASSERT(ctx->Texture.Enabled);
749 gl_texture_pixels( ctx, 0, n, s, t, u, lambda, rgba );
750
751 /* Add base and specular colors */
752 if (spec && ctx->Light.Enabled
753 && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
754 add_colors( n, rgba, spec ); /* rgba = rgba + spec*/
755
756 /* Per-pixel fog */
757 if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
758 _mesa_fog_rgba_pixels( ctx, n, z, rgba );
759 }
760
761 /* Do the scissor test */
762 if (ctx->Scissor.Enabled) {
763 if (gl_scissor_span( ctx, n, x, y, mask )==0) {
764 return;
765 }
766 write_all = GL_FALSE;
767 }
768
769 /* Polygon Stippling */
770 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
771 stipple_polygon_span( ctx, n, x, y, mask );
772 write_all = GL_FALSE;
773 }
774
775 /* Do the alpha test */
776 if (ctx->Color.AlphaEnabled) {
777 if (_mesa_alpha_test( ctx, n, (const GLubyte (*)[4]) rgba, mask )==0) {
778 return;
779 }
780 write_all = GL_FALSE;
781 }
782
783 if (ctx->Stencil.Enabled) {
784 /* first stencil test */
785 if (gl_stencil_and_depth_test_span(ctx, n, x, y, z, mask) == GL_FALSE) {
786 return;
787 }
788 write_all = GL_FALSE;
789 }
790 else if (ctx->Depth.Test) {
791 /* regular depth testing */
792 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
793 if (m==0) {
794 return;
795 }
796 if (m<n) {
797 write_all = GL_FALSE;
798 }
799 }
800
801 /* if we get here, something passed the depth test */
802 ctx->OcclusionResult = GL_TRUE;
803
804 if (ctx->RasterMask & MULTI_DRAW_BIT) {
805 multi_write_rgba_span( ctx, n, x, y, (const GLubyte (*)[4])rgba,
806 write_all ? Null : mask );
807 }
808 else {
809 /* normal: write to exactly one buffer */
810 if (ctx->Color.SWLogicOpEnabled) {
811 gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
812 }
813 else if (ctx->Color.BlendEnabled) {
814 _mesa_blend_span( ctx, n, x, y, rgba, mask );
815 }
816 if (ctx->Color.SWmasking) {
817 gl_mask_rgba_span( ctx, n, x, y, rgba );
818 }
819
820 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLubyte (*)[4])rgba,
821 write_all ? Null : mask );
822 if (ctx->RasterMask & ALPHABUF_BIT) {
823 gl_write_alpha_span( ctx, n, x, y, (const GLubyte (*)[4]) rgba,
824 write_all ? Null : mask );
825 }
826 }
827}
828
829
830
831/*
832 * As above but perform multiple stages of texture application.
833 * Input: texUnits - number of texture units to apply
834 */
835void
836gl_write_multitexture_span( GLcontext *ctx, GLuint texUnits,
837 GLuint n, GLint x, GLint y,
838 const GLdepth z[],
839 CONST GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH],
840 CONST GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH],
841 CONST GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH],
842 GLfloat lambda[][MAX_WIDTH],
843 GLubyte rgbaIn[MAX_TEXTURE_UNITS][4],
844 CONST GLubyte spec[MAX_TEXTURE_UNITS][4],
845 GLenum primitive )
846{
847 GLubyte mask[MAX_WIDTH];
848 GLboolean write_all = GL_TRUE;
849 GLubyte rgbaBackup[MAX_WIDTH][4];
850 GLubyte (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
851 GLuint i;
852 const GLubyte *Null = 0;
853
854 /* init mask to 1's (all pixels are to be written) */
855 MEMSET(mask, 1, n);
856
857 if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
858 if (clip_span(ctx, n, x, y, mask)==0) {
859 return;
860 }
861 write_all = GL_FALSE;
862 }
863
864
865 if (primitive==GL_BITMAP || (ctx->RasterMask & MULTI_DRAW_BIT)) {
866 /* must make a copy of the colors since they may be modified */
867 MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte));
868 rgba = rgbaBackup;
869 }
870 else {
871 rgba = rgbaIn;
872 }
873
874 /* Texture */
875 ASSERT(ctx->Texture.Enabled);
876 ASSERT(texUnits <= MAX_TEXTURE_UNITS);
877 for (i=0;i<texUnits;i++) {
878 gl_texture_pixels( ctx, i, n, s[i], t[i], u[i], lambda[i], rgba );
879 }
880
881 /* Add base and specular colors */
882 if (spec && ctx->Light.Enabled
883 && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
884 add_colors( n, rgba, spec ); /* rgba = rgba + spec*/
885
886 /* Per-pixel fog */
887 if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
888 _mesa_fog_rgba_pixels( ctx, n, z, rgba );
889 }
890
891 /* Do the scissor test */
892 if (ctx->Scissor.Enabled) {
893 if (gl_scissor_span( ctx, n, x, y, mask )==0) {
894 return;
895 }
896 write_all = GL_FALSE;
897 }
898
899 /* Polygon Stippling */
900 if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
901 stipple_polygon_span( ctx, n, x, y, mask );
902 write_all = GL_FALSE;
903 }
904
905 /* Do the alpha test */
906 if (ctx->Color.AlphaEnabled) {
907 if (_mesa_alpha_test( ctx, n, (const GLubyte (*)[4])rgba, mask )==0) {
908 return;
909 }
910 write_all = GL_FALSE;
911 }
912
913 if (ctx->Stencil.Enabled) {
914 /* first stencil test */
915 if (gl_stencil_and_depth_test_span(ctx, n, x, y, z, mask) == GL_FALSE) {
916 return;
917 }
918 write_all = GL_FALSE;
919 }
920 else if (ctx->Depth.Test) {
921 /* regular depth testing */
922 GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask );
923 if (m==0) {
924 return;
925 }
926 if (m<n) {
927 write_all = GL_FALSE;
928 }
929 }
930
931 /* if we get here, something passed the depth test */
932 ctx->OcclusionResult = GL_TRUE;
933
934 if (ctx->RasterMask & MULTI_DRAW_BIT) {
935 multi_write_rgba_span( ctx, n, x, y, (const GLubyte (*)[4]) rgba,
936 write_all ? Null : mask );
937 }
938 else {
939 /* normal: write to exactly one buffer */
940
941 if (ctx->Color.SWLogicOpEnabled) {
942 gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
943 }
944 else if (ctx->Color.BlendEnabled) {
945 _mesa_blend_span( ctx, n, x, y, rgba, mask );
946 }
947 if (ctx->Color.SWmasking) {
948 gl_mask_rgba_span( ctx, n, x, y, rgba );
949 }
950
951 (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLubyte (*)[4])rgba, write_all ? Null : mask );
952 if (ctx->RasterMask & ALPHABUF_BIT) {
953 gl_write_alpha_span( ctx, n, x, y, (const GLubyte (*)[4])rgba,
954 write_all ? Null : mask );
955 }
956 }
957}
958
959
960
961/*
962 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
963 * reading ouside the buffer's boundaries.
964 */
965void gl_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
966 GLuint n, GLint x, GLint y,
967 GLubyte rgba[][4] )
968{
969 if (y < 0 || y >= buffer->Height
970 || x + (GLint) n < 0 || x >= buffer->Width) {
971 /* completely above, below, or right */
972 /* XXX maybe leave undefined? */
973 MEMSET( rgba, 0, 4 * n * sizeof(GLubyte));
974 }
975 else {
976 GLint skip, length;
977 if (x < 0) {
978 /* left edge clippping */
979 skip = -x;
980 length = (GLint) n - skip;
981 if (length < 0) {
982 /* completely left of window */
983 return;
984 }
985 if (length > buffer->Width) {
986 length = buffer->Width;
987 }
988 }
989 else if ((GLint) (x + n) > buffer->Width) {
990 /* right edge clipping */
991 skip = 0;
992 length = buffer->Width - x;
993 if (length < 0) {
994 /* completely to right of window */
995 return;
996 }
997 }
998 else {
999 /* no clipping */
1000 skip = 0;
1001 length = (GLint) n;
1002 }
1003
1004 (*ctx->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1005 if (ctx->Visual->SoftwareAlpha) {
1006 gl_read_alpha_span( ctx, length, x + skip, y, rgba + skip );
1007 }
1008 }
1009}
1010
1011
1012
1013
1014/*
1015 * Read CI pixels from frame buffer. Clipping will be done to prevent
1016 * reading ouside the buffer's boundaries.
1017 */
1018void gl_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
1019 GLuint n, GLint x, GLint y, GLuint indx[] )
1020{
1021 if (y < 0 || y >= buffer->Height
1022 || x + (GLint) n < 0 || x >= buffer->Width) {
1023 /* completely above, below, or right */
1024 MEMSET(indx, 0, n * sizeof(GLuint));
1025 }
1026 else {
1027 GLint skip, length;
1028 if (x < 0) {
1029 /* left edge clippping */
1030 skip = -x;
1031 length = (GLint) n - skip;
1032 if (length < 0) {
1033 /* completely left of window */
1034 return;
1035 }
1036 if (length > buffer->Width) {
1037 length = buffer->Width;
1038 }
1039 }
1040 else if ((GLint) (x + n) > buffer->Width) {
1041 /* right edge clipping */
1042 skip = 0;
1043 length = buffer->Width - x;
1044 if (length < 0) {
1045 /* completely to right of window */
1046 return;
1047 }
1048 }
1049 else {
1050 /* no clipping */
1051 skip = 0;
1052 length = (GLint) n;
1053 }
1054
1055 (*ctx->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1056 }
1057}
Note: See TracBrowser for help on using the repository browser.