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

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

* empty log message *

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