source: trunk/src/opengl/mesa/pb.c@ 3086

Last change on this file since 3086 was 2938, checked in by sandervl, 25 years ago

created

File size: 15.4 KB
Line 
1/* $Id: pb.c,v 1.1 2000-02-29 00:50:07 sandervl Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
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
30
31/*
32 * Pixel buffer:
33 *
34 * As fragments are produced (by point, line, and bitmap drawing) they
35 * are accumlated in a buffer. When the buffer is full or has to be
36 * flushed (glEnd), we apply all enabled rasterization functions to the
37 * pixels and write the results to the display buffer. The goal is to
38 * maximize the number of pixels processed inside loops and to minimize
39 * the number of function calls.
40 */
41/* $XFree86: xc/lib/GL/mesa/src/pb.c,v 1.3 1999/04/04 00:20:28 dawes Exp $ */
42
43
44#ifdef PC_HEADER
45#include "all.h"
46#else
47#ifndef XFree86Server
48#include <stdlib.h>
49#include <string.h>
50#else
51#include "GL/xf86glx.h"
52#endif
53#include "alpha.h"
54#include "alphabuf.h"
55#include "blend.h"
56#include "depth.h"
57#include "fog.h"
58#include "logic.h"
59#include "macros.h"
60#include "masking.h"
61#include "pb.h"
62#include "scissor.h"
63#include "stencil.h"
64#include "texture.h"
65#include "types.h"
66#endif
67
68
69
70/*
71 * Allocate and initialize a new pixel buffer structure.
72 */
73struct pixel_buffer *gl_alloc_pb(void)
74{
75 struct pixel_buffer *pb;
76 pb = (struct pixel_buffer *) calloc(sizeof(struct pixel_buffer), 1);
77 if (pb) {
78 int i, j;
79 /* set non-zero fields */
80 pb->primitive = GL_BITMAP;
81 /* Set all lambda values to 0.0 since we don't do mipmapping for
82 * points or lines and want to use the level 0 texture image.
83 */
84
85 for (j=0;j<MAX_TEXTURE_UNITS;j++) {
86 for (i=0; i<PB_SIZE; i++) {
87 pb->lambda[j][i] = 0.0;
88 }
89 }
90 }
91 return pb;
92}
93
94
95
96/*
97 * Draw to more than one color buffer (or none).
98 */
99static void multi_write_index_pixels( GLcontext *ctx, GLuint n,
100 const GLint x[], const GLint y[],
101 const GLuint indexes[],
102 const GLubyte mask[] )
103{
104 GLuint bufferBit;
105
106 if (ctx->Color.DrawBuffer == GL_NONE)
107 return;
108
109 /* loop over four possible dest color buffers */
110 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
111 if (bufferBit & ctx->Color.DrawDestMask) {
112 GLuint indexTmp[MAX_WIDTH];
113 ASSERT(n < MAX_WIDTH);
114
115 if (bufferBit == FRONT_LEFT_BIT)
116 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_LEFT);
117 else if (bufferBit == FRONT_RIGHT_BIT)
118 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_RIGHT);
119 else if (bufferBit == BACK_LEFT_BIT)
120 (*ctx->Driver.SetBuffer)( ctx, GL_BACK_LEFT);
121 else
122 (*ctx->Driver.SetBuffer)( ctx, GL_BACK_RIGHT);
123
124 /* make copy of incoming indexes */
125 MEMCPY( indexTmp, indexes, n * sizeof(GLuint) );
126 if (ctx->Color.SWLogicOpEnabled) {
127 gl_logicop_ci_pixels( ctx, n, x, y, indexTmp, mask );
128 }
129 if (ctx->Color.SWmasking) {
130 gl_mask_index_pixels( ctx, n, x, y, indexTmp, mask );
131 }
132 (*ctx->Driver.WriteCI32Pixels)( ctx, n, x, y, indexTmp, mask );
133 }
134 }
135
136 /* restore default dest buffer */
137 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer);
138}
139
140
141
142/*
143 * Draw to more than one RGBA color buffer (or none).
144 */
145static void multi_write_rgba_pixels( GLcontext *ctx, GLuint n,
146 const GLint x[], const GLint y[],
147 CONST GLubyte rgba[][4],
148 const GLubyte mask[] )
149{
150 GLuint bufferBit;
151
152 if (ctx->Color.DrawBuffer == GL_NONE)
153 return;
154
155 /* loop over four possible dest color buffers */
156 for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
157 if (bufferBit & ctx->Color.DrawDestMask) {
158 GLubyte rgbaTmp[MAX_WIDTH][4];
159 ASSERT(n < MAX_WIDTH);
160
161 if (bufferBit == FRONT_LEFT_BIT) {
162 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_LEFT);
163 ctx->Buffer->Alpha = ctx->Buffer->FrontLeftAlpha;
164 }
165 else if (bufferBit == FRONT_RIGHT_BIT) {
166 (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_RIGHT);
167 ctx->Buffer->Alpha = ctx->Buffer->FrontRightAlpha;
168 }
169 else if (bufferBit == BACK_LEFT_BIT) {
170 (*ctx->Driver.SetBuffer)( ctx, GL_BACK_LEFT);
171 ctx->Buffer->Alpha = ctx->Buffer->BackLeftAlpha;
172 }
173 else {
174 (*ctx->Driver.SetBuffer)( ctx, GL_BACK_RIGHT);
175 ctx->Buffer->Alpha = ctx->Buffer->BackRightAlpha;
176 }
177
178 /* make copy of incoming colors */
179 MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLubyte) );
180
181 if (ctx->Color.SWLogicOpEnabled) {
182 gl_logicop_rgba_pixels( ctx, n, x, y, rgbaTmp, mask );
183 }
184 else if (ctx->Color.BlendEnabled) {
185 gl_blend_pixels( ctx, n, x, y, rgbaTmp, mask );
186 }
187 if (ctx->Color.SWmasking) {
188 gl_mask_rgba_pixels( ctx, n, x, y, rgbaTmp, mask );
189 }
190
191 (*ctx->Driver.WriteRGBAPixels)( ctx, n, x, y,
192 (const GLubyte (*)[4])rgbaTmp, mask );
193 if (ctx->RasterMask & ALPHABUF_BIT) {
194 gl_write_alpha_pixels( ctx, n, x, y,
195 (const GLubyte (*)[4])rgbaTmp, mask );
196 }
197 }
198 }
199
200 /* restore default dest buffer */
201 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer);
202}
203
204
205
206/*
207 * Add specular color to primary color. This is used only when
208 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
209 */
210static void add_colors( GLuint n, GLubyte rgba[][4], CONST GLubyte spec[][3] )
211{
212 GLuint i;
213 for (i=0; i<n; i++) {
214 GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
215 GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
216 GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
217 rgba[i][RCOMP] = MIN2(r, 255);
218 rgba[i][GCOMP] = MIN2(g, 255);
219 rgba[i][BCOMP] = MIN2(b, 255);
220 }
221}
222
223
224
225/*
226 * When the pixel buffer is full, or needs to be flushed, call this
227 * function. All the pixels in the pixel buffer will be subjected
228 * to texturing, scissoring, stippling, alpha testing, stenciling,
229 * depth testing, blending, and finally written to the frame buffer.
230 */
231void gl_flush_pb( GLcontext *ctx )
232{
233 struct pixel_buffer* PB = ctx->PB;
234 GLubyte mask[PB_SIZE];
235
236 if (PB->count==0)
237 goto CleanUp;
238
239 /* initialize mask array and clip pixels simultaneously */
240 {
241 GLint xmin = ctx->Buffer->Xmin;
242 GLint xmax = ctx->Buffer->Xmax;
243 GLint ymin = ctx->Buffer->Ymin;
244 GLint ymax = ctx->Buffer->Ymax;
245 GLint *x = PB->x;
246 GLint *y = PB->y;
247 GLuint i, n = PB->count;
248 for (i=0;i<n;i++) {
249 mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
250 }
251 }
252
253 if (ctx->Visual->RGBAflag) {
254 /*
255 * RGBA COLOR PIXELS
256 */
257 if (PB->mono && ctx->MutablePixels) {
258 /* Copy mono color to all pixels */
259 GLuint i;
260 for (i=0; i<PB->count; i++) {
261 PB->rgba[i][RCOMP] = PB->color[RCOMP];
262 PB->rgba[i][GCOMP] = PB->color[GCOMP];
263 PB->rgba[i][BCOMP] = PB->color[BCOMP];
264 PB->rgba[i][ACOMP] = PB->color[ACOMP];
265 }
266 }
267
268 /* If each pixel can be of a different color... */
269 if (ctx->MutablePixels || !PB->mono) {
270
271 if (ctx->Texture.ReallyEnabled) {
272 int texUnit;
273 for (texUnit=0;texUnit<MAX_TEXTURE_UNITS;texUnit++) {
274 gl_texture_pixels( ctx, texUnit,
275 PB->count, PB->s[texUnit], PB->t[texUnit],
276 PB->u[texUnit], PB->lambda[texUnit],
277 PB->rgba);
278 }
279 }
280
281 if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR
282 && ctx->Light.Enabled) {
283 /* add specular color to primary color */
284 add_colors( PB->count, PB->rgba, (const GLubyte (*)[3]) PB->spec );
285 }
286
287 if (ctx->Fog.Enabled
288 && (ctx->FogMode == FOG_FRAGMENT || PB->primitive==GL_BITMAP)) {
289 gl_fog_rgba_pixels( ctx, PB->count, PB->z, PB->rgba );
290 }
291
292 /* Scissoring already done above */
293
294 if (ctx->Color.AlphaEnabled) {
295 if (gl_alpha_test( ctx, PB->count,
296 (const GLubyte (*)[4])PB->rgba, mask )==0) {
297 goto CleanUp;
298 }
299 }
300
301 if (ctx->Stencil.Enabled) {
302 /* first stencil test */
303 if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
304 goto CleanUp;
305 }
306 /* depth buffering w/ stencil */
307 gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
308 }
309 else if (ctx->Depth.Test) {
310 /* regular depth testing */
311 (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y,
312 PB->z, mask );
313 }
314
315
316 if (ctx->RasterMask & MULTI_DRAW_BIT) {
317 multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y,
318 (const GLubyte (*)[4])PB->rgba, mask );
319 }
320 else {
321 /* normal case: write to exactly one buffer */
322
323 if (ctx->Color.SWLogicOpEnabled) {
324 gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
325 PB->rgba, mask);
326 }
327 else if (ctx->Color.BlendEnabled) {
328 gl_blend_pixels( ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
329 }
330 if (ctx->Color.SWmasking) {
331 gl_mask_rgba_pixels(ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
332 }
333
334 (*ctx->Driver.WriteRGBAPixels)( ctx, PB->count, PB->x, PB->y,
335 (const GLubyte (*)[4]) PB->rgba,
336 mask );
337 if (ctx->RasterMask & ALPHABUF_BIT) {
338 gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
339 (const GLubyte (*)[4]) PB->rgba, mask );
340 }
341 }
342 }
343 else {
344 /* Same color for all pixels */
345
346 /* Scissoring already done above */
347
348 if (ctx->Color.AlphaEnabled) {
349 if (gl_alpha_test( ctx, PB->count,
350 (const GLubyte (*)[4]) PB->rgba, mask )==0) {
351 goto CleanUp;
352 }
353 }
354
355 if (ctx->Stencil.Enabled) {
356 /* first stencil test */
357 if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
358 goto CleanUp;
359 }
360 /* depth buffering w/ stencil */
361 gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
362 }
363 else if (ctx->Depth.Test) {
364 /* regular depth testing */
365 (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
366 }
367
368 if (ctx->Color.DrawBuffer == GL_NONE) {
369 goto CleanUp;
370 }
371
372 if (ctx->RasterMask & MULTI_DRAW_BIT) {
373 /* Copy mono color to all pixels */
374 GLuint i;
375 for (i=0; i<PB->count; i++) {
376 PB->rgba[i][RCOMP] = PB->color[RCOMP];
377 PB->rgba[i][GCOMP] = PB->color[GCOMP];
378 PB->rgba[i][BCOMP] = PB->color[BCOMP];
379 PB->rgba[i][ACOMP] = PB->color[ACOMP];
380 }
381 multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y,
382 (const GLubyte (*)[4]) PB->rgba, mask );
383 }
384 else {
385 /* normal case: write to exactly one buffer */
386
387 GLubyte red, green, blue, alpha;
388 red = PB->color[RCOMP];
389 green = PB->color[GCOMP];
390 blue = PB->color[BCOMP];
391 alpha = PB->color[ACOMP];
392 (*ctx->Driver.Color)( ctx, red, green, blue, alpha );
393
394 (*ctx->Driver.WriteMonoRGBAPixels)( ctx, PB->count, PB->x, PB->y, mask );
395 if (ctx->RasterMask & ALPHABUF_BIT) {
396 gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
397 PB->color[ACOMP], mask );
398 }
399 }
400 /*** ALL DONE ***/
401 }
402 }
403 else {
404 /*
405 * COLOR INDEX PIXELS
406 */
407
408 /* If we may be writting pixels with different indexes... */
409 if (PB->mono && ctx->MutablePixels) {
410 /* copy index to all pixels */
411 GLuint n = PB->count, indx = PB->index;
412 GLuint *pbindex = PB->i;
413 do {
414 *pbindex++ = indx;
415 n--;
416 } while (n);
417 }
418
419 if (ctx->MutablePixels || !PB->mono) {
420
421 if (ctx->Fog.Enabled
422 && (ctx->FogMode==FOG_FRAGMENT || PB->primitive==GL_BITMAP)) {
423 gl_fog_ci_pixels( ctx, PB->count, PB->z, PB->i );
424 }
425
426 /* Scissoring already done above */
427
428 if (ctx->Stencil.Enabled) {
429 /* first stencil test */
430 if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
431 goto CleanUp;
432 }
433 /* depth buffering w/ stencil */
434 gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
435 }
436 else if (ctx->Depth.Test) {
437 /* regular depth testing */
438 (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
439 }
440
441 if (ctx->RasterMask & MULTI_DRAW_BIT) {
442 multi_write_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
443 }
444 else {
445 /* normal case: write to exactly one buffer */
446
447 if (ctx->Color.SWLogicOpEnabled) {
448 gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
449 }
450 if (ctx->Color.SWmasking) {
451 gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
452 }
453
454 (*ctx->Driver.WriteCI32Pixels)( ctx, PB->count, PB->x, PB->y,
455 PB->i, mask );
456 }
457
458 /*** ALL DONE ***/
459 }
460 else {
461 /* Same color index for all pixels */
462
463 /* Scissoring already done above */
464
465 if (ctx->Stencil.Enabled) {
466 /* first stencil test */
467 if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
468 goto CleanUp;
469 }
470 /* depth buffering w/ stencil */
471 gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
472 }
473 else if (ctx->Depth.Test) {
474 /* regular depth testing */
475 (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
476 }
477
478 if (ctx->RasterMask & MULTI_DRAW_BIT) {
479 GLuint n = PB->count, indx = PB->index;
480 GLuint *pbindex = PB->i;
481 do {
482 *pbindex++ = indx;
483 n--;
484 } while (n);
485
486 multi_write_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
487 }
488 else {
489 /* normal case: write to exactly one buffer */
490
491 (*ctx->Driver.Index)( ctx, PB->index );
492 (*ctx->Driver.WriteMonoCIPixels)( ctx, PB->count, PB->x, PB->y, mask );
493 }
494 }
495 }
496
497CleanUp:
498 PB->count = 0;
499}
500
501
Note: See TracBrowser for help on using the repository browser.