xref: /reactos/dll/opengl/mesa/pb.c (revision 40462c92)
1 /* $Id: pb.c,v 1.14 1997/11/13 02:16:48 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: pb.c,v $
26  * Revision 1.14  1997/11/13 02:16:48  brianp
27  * added lambda array, initialized to zeros
28  *
29  * Revision 1.13  1997/07/24 01:24:11  brianp
30  * changed precompiled header symbol from PCH to PC_HEADER
31  *
32  * Revision 1.12  1997/05/28 03:26:02  brianp
33  * added precompiled header (PCH) support
34  *
35  * Revision 1.11  1997/05/09 22:40:19  brianp
36  * added gl_alloc_pb()
37  *
38  * Revision 1.10  1997/05/03 00:51:30  brianp
39  * new texturing function call: gl_texture_pixels()
40  *
41  * Revision 1.9  1997/05/01 02:10:33  brianp
42  * removed manually unrolled loop to stop Purify uninitialized memory read
43  *
44  * Revision 1.8  1997/04/16 23:54:11  brianp
45  * do per-pixel fog if texturing is enabled
46  *
47  * Revision 1.7  1997/02/09 19:53:43  brianp
48  * now use TEXTURE_xD enable constants
49  *
50  * Revision 1.6  1997/02/09 18:43:14  brianp
51  * added GL_EXT_texture3D support
52  *
53  * Revision 1.5  1997/02/03 20:30:54  brianp
54  * added a few DEFARRAY macros for BeOS
55  *
56  * Revision 1.4  1997/01/28 22:17:44  brianp
57  * new RGBA mode logic op support
58  *
59  * Revision 1.3  1996/09/25 03:21:10  brianp
60  * added NO_DRAW_BIT support
61  *
62  * Revision 1.2  1996/09/15 14:18:37  brianp
63  * now use GLframebuffer and GLvisual
64  *
65  * Revision 1.1  1996/09/13 01:38:16  brianp
66  * Initial revision
67  *
68  */
69 
70 
71 /*
72  * Pixel buffer:
73  *
74  * As fragments are produced (by point, line, and bitmap drawing) they
75  * are accumlated in a buffer.  When the buffer is full or has to be
76  * flushed (glEnd), we apply all enabled rasterization functions to the
77  * pixels and write the results to the display buffer.  The goal is to
78  * maximize the number of pixels processed inside loops and to minimize
79  * the number of function calls.
80  */
81 
82 
83 
84 #ifdef PC_HEADER
85 #include "all.h"
86 #else
87 #include <stdlib.h>
88 #include <string.h>
89 #include "alpha.h"
90 #include "alphabuf.h"
91 #include "blend.h"
92 #include "depth.h"
93 #include "fog.h"
94 #include "logic.h"
95 #include "macros.h"
96 #include "masking.h"
97 #include "pb.h"
98 #include "scissor.h"
99 #include "stencil.h"
100 #include "texture.h"
101 #include "types.h"
102 #endif
103 
104 
105 
106 /*
107  * Allocate and initialize a new pixel buffer structure.
108  */
109 struct pixel_buffer *gl_alloc_pb(void)
110 {
111    struct pixel_buffer *pb;
112    pb = (struct pixel_buffer *) calloc(sizeof(struct pixel_buffer), 1);
113    if (pb) {
114       int i;
115       /* set non-zero fields */
116       pb->primitive = GL_BITMAP;
117       /* Set all lambda values to 0.0 since we don't do mipmapping for
118        * points or lines and want to use the level 0 texture image.
119        */
120       for (i=0; i<PB_SIZE; i++) {
121          pb->lambda[i] = 0.0;
122       }
123    }
124    return pb;
125 }
126 
127 
128 
129 
130 /*
131  * When the pixel buffer is full, or needs to be flushed, call this
132  * function.  All the pixels in the pixel buffer will be subjected
133  * to texturing, scissoring, stippling, alpha testing, stenciling,
134  * depth testing, blending, and finally written to the frame buffer.
135  */
136 void gl_flush_pb( GLcontext *ctx )
137 {
138    struct pixel_buffer* PB = ctx->PB;
139 
140    DEFARRAY(GLubyte,mask,PB_SIZE);
141    DEFARRAY(GLubyte, rsave, PB_SIZE);
142    DEFARRAY(GLubyte, gsave, PB_SIZE);
143    DEFARRAY(GLubyte, bsave, PB_SIZE);
144    DEFARRAY(GLubyte, asave, PB_SIZE);
145 
146    if (PB->count==0)  goto CleanUp;
147 
148    /* initialize mask array and clip pixels simultaneously */
149    {
150       GLint xmin = ctx->Buffer->Xmin;
151       GLint xmax = ctx->Buffer->Xmax;
152       GLint ymin = ctx->Buffer->Ymin;
153       GLint ymax = ctx->Buffer->Ymax;
154       GLint *x = PB->x;
155       GLint *y = PB->y;
156       GLuint i, n = PB->count;
157       for (i=0;i<n;i++) {
158          mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
159       }
160    }
161 
162    if (ctx->Visual->RGBAflag) {
163       /* RGBA COLOR PIXELS */
164       if (PB->mono && ctx->MutablePixels) {
165 	 /* Copy flat color to all pixels */
166          MEMSET( PB->r, PB->color[0], PB->count );
167          MEMSET( PB->g, PB->color[1], PB->count );
168          MEMSET( PB->b, PB->color[2], PB->count );
169          MEMSET( PB->a, PB->color[3], PB->count );
170       }
171 
172       /* If each pixel can be of a different color... */
173       if (ctx->MutablePixels || !PB->mono) {
174 
175 	 if (ctx->Texture.Enabled) {
176             /* TODO: need texture lambda valus */
177 	    gl_texture_pixels( ctx, PB->count, PB->s, PB->t, PB->u,
178                                PB->lambda, PB->r, PB->g, PB->b, PB->a);
179 	 }
180 
181 	 if (ctx->Fog.Enabled
182              && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP
183                  || ctx->Texture.Enabled)) {
184 	    gl_fog_color_pixels( ctx, PB->count, PB->z,
185 				 PB->r, PB->g, PB->b, PB->a );
186 	 }
187 
188          /* Scissoring already done above */
189 
190 	 if (ctx->Color.AlphaEnabled) {
191 	    if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
192 	       goto CleanUp;
193 	    }
194 	 }
195 
196 	 if (ctx->Stencil.Enabled) {
197 	    /* first stencil test */
198 	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
199 	       goto CleanUp;
200 	    }
201 	    /* depth buffering w/ stencil */
202 	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
203 	 }
204 	 else if (ctx->Depth.Test) {
205 	    /* regular depth testing */
206 	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
207 	 }
208 
209          if (ctx->RasterMask & NO_DRAW_BIT) {
210             goto CleanUp;
211          }
212 
213          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
214             /* make a copy of the colors */
215             MEMCPY( rsave, PB->r, PB->count * sizeof(GLubyte) );
216             MEMCPY( gsave, PB->r, PB->count * sizeof(GLubyte) );
217             MEMCPY( bsave, PB->r, PB->count * sizeof(GLubyte) );
218             MEMCPY( asave, PB->r, PB->count * sizeof(GLubyte) );
219          }
220 
221          if (ctx->Color.SWLogicOpEnabled) {
222             gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
223                                     PB->r, PB->g, PB->b, PB->a, mask);
224          }
225          else if (ctx->Color.BlendEnabled) {
226             gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
227                              PB->r, PB->g, PB->b, PB->a, mask);
228          }
229 
230          if (ctx->Color.SWmasking) {
231             gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
232                                   PB->r, PB->g, PB->b, PB->a, mask );
233          }
234 
235          /* write pixels */
236          (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
237                                           PB->r, PB->g, PB->b, PB->a, mask );
238          if (ctx->RasterMask & ALPHABUF_BIT) {
239             gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, PB->a, mask );
240          }
241 
242          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
243             /*** Also draw to back buffer ***/
244             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
245             if (ctx->Color.SWLogicOpEnabled) {
246                gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
247                                        PB->r, PB->g, PB->b, PB->a, mask);
248             }
249             else if (ctx->Color.BlendEnabled) {
250                gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
251                                 rsave, gsave, bsave, asave, mask );
252             }
253             if (ctx->Color.SWmasking) {
254                gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
255                                      rsave, gsave, bsave, asave, mask);
256             }
257             (*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
258                                              rsave, gsave, bsave, asave, mask);
259             if (ctx->RasterMask & ALPHABUF_BIT) {
260                ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
261                gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
262                                       asave, mask );
263                ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
264             }
265             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
266             /*** ALL DONE ***/
267          }
268       }
269       else {
270 	 /* Same color for all pixels */
271 
272          /* Scissoring already done above */
273 
274 	 if (ctx->Color.AlphaEnabled) {
275 	    if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
276 	       goto CleanUp;
277 	    }
278 	 }
279 
280 	 if (ctx->Stencil.Enabled) {
281 	    /* first stencil test */
282 	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
283 	       goto CleanUp;
284 	    }
285 	    /* depth buffering w/ stencil */
286 	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
287 	 }
288 	 else if (ctx->Depth.Test) {
289 	    /* regular depth testing */
290 	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
291 	 }
292 
293          if (ctx->RasterMask & NO_DRAW_BIT) {
294             goto CleanUp;
295          }
296 
297          /* write pixels */
298          {
299             GLubyte red, green, blue, alpha;
300             red   = PB->color[0];
301             green = PB->color[1];
302             blue  = PB->color[2];
303             alpha = PB->color[3];
304 	    (*ctx->Driver.Color)( ctx, red, green, blue, alpha );
305          }
306          (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
307          if (ctx->RasterMask & ALPHABUF_BIT) {
308             gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
309                                         PB->color[3], mask );
310          }
311 
312          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
313             /*** Also render to back buffer ***/
314             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
315             (*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
316             if (ctx->RasterMask & ALPHABUF_BIT) {
317                ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
318                gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
319                                            PB->color[3], mask );
320                ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
321             }
322             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
323 	 }
324          /*** ALL DONE ***/
325       }
326    }
327    else {
328       /* COLOR INDEX PIXELS */
329 
330       /* If we may be writting pixels with different indexes... */
331       if (PB->mono && ctx->MutablePixels) {
332 	 /* copy index to all pixels */
333          GLuint n = PB->count, indx = PB->index;
334          GLuint *pbindex = PB->i;
335          do {
336 	    *pbindex++ = indx;
337             n--;
338 	 } while (n);
339       }
340 
341       if (ctx->MutablePixels || !PB->mono) {
342 	 /* Pixel color index may be modified */
343          GLuint isave[PB_SIZE];
344 
345 	 if (ctx->Fog.Enabled
346              && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
347 	    gl_fog_index_pixels( ctx, PB->count, PB->z, PB->i );
348 	 }
349 
350          /* Scissoring already done above */
351 
352 	 if (ctx->Stencil.Enabled) {
353 	    /* first stencil test */
354 	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
355 	       goto CleanUp;
356 	    }
357 	    /* depth buffering w/ stencil */
358 	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
359 	 }
360 	 else if (ctx->Depth.Test) {
361 	    /* regular depth testing */
362 	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
363 	 }
364 
365          if (ctx->RasterMask & NO_DRAW_BIT) {
366             goto CleanUp;
367          }
368 
369          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
370             /* make a copy of the indexes */
371             MEMCPY( isave, PB->i, PB->count * sizeof(GLuint) );
372          }
373 
374          if (ctx->Color.SWLogicOpEnabled) {
375             gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
376          }
377 
378          if (ctx->Color.SWmasking) {
379             gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
380          }
381 
382          /* write pixels */
383          (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
384                                           PB->i, mask );
385 
386          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
387             /*** Also write to back buffer ***/
388             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
389             MEMCPY( PB->i, isave, PB->count * sizeof(GLuint) );
390             if (ctx->Color.SWLogicOpEnabled) {
391                gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
392             }
393             if (ctx->Color.SWmasking) {
394                gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y,
395                                      PB->i, mask );
396             }
397             (*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
398                                              PB->i, mask );
399             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
400          }
401 
402          /*** ALL DONE ***/
403       }
404       else {
405 	 /* Same color index for all pixels */
406 
407          /* Scissoring already done above */
408 
409 	 if (ctx->Stencil.Enabled) {
410 	    /* first stencil test */
411 	    if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
412 	       goto CleanUp;
413 	    }
414 	    /* depth buffering w/ stencil */
415 	    gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
416 	 }
417 	 else if (ctx->Depth.Test) {
418 	    /* regular depth testing */
419 	    (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
420 	 }
421 
422          if (ctx->RasterMask & NO_DRAW_BIT) {
423             goto CleanUp;
424          }
425 
426          /* write pixels */
427          (*ctx->Driver.Index)( ctx, PB->index );
428          (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );
429 
430          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
431             /*** Also write to back buffer ***/
432             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
433             (*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );
434             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
435          }
436          /*** ALL DONE ***/
437       }
438    }
439 
440 CleanUp:
441    PB->count = 0;
442    UNDEFARRAY(mask);
443    UNDEFARRAY(rsave);
444    UNDEFARRAY(gsave);
445    UNDEFARRAY(bsave);
446    UNDEFARRAY(asave);
447 }
448 
449 
450