This is pb.c in view mode; [Download] [Up]
/* $Id: pb.c,v 1.3 1996/09/25 03:21:10 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 2.0
* Copyright (C) 1995-1996 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* $Log: pb.c,v $
* Revision 1.3 1996/09/25 03:21:10 brianp
* added NO_DRAW_BIT support
*
* Revision 1.2 1996/09/15 14:18:37 brianp
* now use GLframebuffer and GLvisual
*
* Revision 1.1 1996/09/13 01:38:16 brianp
* Initial revision
*
*/
/*
* Pixel buffer:
*
* As fragments are produced (by point, line, and bitmap drawing) they
* are accumlated in a buffer. When the buffer is full or has to be
* flushed (glEnd), we apply all enabled rasterization functions to the
* pixels and write the results to the display buffer. The goal is to
* maximize the number of pixels processed inside loops and to minimize
* the number of function calls.
*/
#include <stdlib.h>
#include <string.h>
#include "alpha.h"
#include "alphabuf.h"
#include "blend.h"
#include "depth.h"
#include "fog.h"
#include "logic.h"
#include "macros.h"
#include "masking.h"
#include "pb.h"
#include "scissor.h"
#include "stencil.h"
#include "texture.h"
#include "types.h"
/*
* When the pixel buffer is full, or needs to be flushed, call this
* function. All the pixels in the pixel buffer will be subjected
* to texturing, scissoring, stippling, alpha testing, stenciling,
* depth testing, blending, and finally written to the frame buffer.
*/
void gl_flush_pb( GLcontext *ctx )
{
struct pixel_buffer* PB = ctx->PB;
DEFARRAY(GLubyte,mask,PB_SIZE+4); /* add 4 for manually unrolled loop, below */
if (PB->count==0) goto CleanUp;
/* initialize mask array and clip pixels simultaneously */
{
GLint xmin = ctx->Buffer->Xmin;
GLint xmax = ctx->Buffer->Xmax;
GLint ymin = ctx->Buffer->Ymin;
GLint ymax = ctx->Buffer->Ymax;
GLint *x = PB->x;
GLint *y = PB->y;
GLuint i = 0;
/* manually unrolled loop, OK to go past PB->count */
do {
mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
i++;
mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
i++;
mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
i++;
mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
i++;
} while (i<PB->count);
}
if (ctx->Visual->RGBAflag) {
/* RGBA COLOR PIXELS */
GLubyte rsave[PB_SIZE], gsave[PB_SIZE], bsave[PB_SIZE], asave[PB_SIZE];
if (PB->mono && ctx->MutablePixels) {
/* Copy flat color to all pixels */
MEMSET( PB->r, PB->color[0], PB->count );
MEMSET( PB->g, PB->color[1], PB->count );
MEMSET( PB->b, PB->color[2], PB->count );
MEMSET( PB->a, PB->color[3], PB->count );
}
/* If each pixel can be of a different color... */
if (ctx->MutablePixels || !PB->mono) {
if (ctx->Texture.Enabled & 2) {
/* TODO: need texture lambda valus */
gl_texture_pixels_2d( ctx, PB->count, PB->s, PB->t, NULL,
PB->r, PB->g, PB->b, PB->a);
}
else if (ctx->Texture.Enabled & 1) {
/* TODO: need texture lambda values */
gl_texture_pixels_1d( ctx, PB->count, PB->s, NULL,
PB->r, PB->g, PB->b, PB->a );
}
if (ctx->Fog.Enabled
&& (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
gl_fog_color_pixels( ctx, PB->count, PB->z,
PB->r, PB->g, PB->b, PB->a );
}
/* Scissoring already done above */
if (ctx->Color.AlphaEnabled) {
if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
goto CleanUp;
}
}
if (ctx->Stencil.Enabled) {
/* first stencil test */
if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
goto CleanUp;
}
/* depth buffering w/ stencil */
gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
else if (ctx->Depth.Test) {
/* regular depth testing */
(*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
if (ctx->RasterMask & NO_DRAW_BIT) {
goto CleanUp;
}
if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
/* make a copy of the colors */
MEMCPY( rsave, PB->r, PB->count * sizeof(GLubyte) );
MEMCPY( gsave, PB->r, PB->count * sizeof(GLubyte) );
MEMCPY( bsave, PB->r, PB->count * sizeof(GLubyte) );
MEMCPY( asave, PB->r, PB->count * sizeof(GLubyte) );
}
if (ctx->Color.BlendEnabled) {
gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
PB->r, PB->g, PB->b, PB->a, mask);
}
if (ctx->Color.SWmasking) {
gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
PB->r, PB->g, PB->b, PB->a, mask );
}
/* write pixels */
(*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
PB->r, PB->g, PB->b, PB->a, mask );
if (ctx->RasterMask & ALPHABUF_BIT) {
gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, PB->a, mask );
}
if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
/*** Also draw to back buffer ***/
(*ctx->Driver.SetBuffer)( ctx, GL_BACK );
if (ctx->Color.BlendEnabled) {
gl_blend_pixels( ctx, PB->count, PB->x, PB->y,
rsave, gsave, bsave, asave, mask );
}
if (ctx->Color.SWmasking) {
gl_mask_color_pixels( ctx, PB->count, PB->x, PB->y,
rsave, gsave, bsave, asave, mask);
}
(*ctx->Driver.WriteColorPixels)( ctx, PB->count, PB->x, PB->y,
rsave, gsave, bsave, asave, mask);
if (ctx->RasterMask & ALPHABUF_BIT) {
ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
asave, mask );
ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
}
(*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
/*** ALL DONE ***/
}
}
else {
/* Same color for all pixels */
/* Scissoring already done above */
if (ctx->Color.AlphaEnabled) {
if (gl_alpha_test( ctx, PB->count, PB->a, mask )==0) {
goto CleanUp;
}
}
if (ctx->Stencil.Enabled) {
/* first stencil test */
if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
goto CleanUp;
}
/* depth buffering w/ stencil */
gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
else if (ctx->Depth.Test) {
/* regular depth testing */
(*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
if (ctx->RasterMask & NO_DRAW_BIT) {
goto CleanUp;
}
/* write pixels */
{
GLubyte red, green, blue, alpha;
red = PB->color[0];
green = PB->color[1];
blue = PB->color[2];
alpha = PB->color[3];
(*ctx->Driver.Color)( ctx, red, green, blue, alpha );
}
(*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
if (ctx->RasterMask & ALPHABUF_BIT) {
gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
PB->color[3], mask );
}
if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
/*** Also render to back buffer ***/
(*ctx->Driver.SetBuffer)( ctx, GL_BACK );
(*ctx->Driver.WriteMonocolorPixels)( ctx, PB->count, PB->x, PB->y, mask );
if (ctx->RasterMask & ALPHABUF_BIT) {
ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
PB->color[3], mask );
ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
}
(*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
}
/*** ALL DONE ***/
}
}
else {
/* COLOR INDEX PIXELS */
/* If we may be writting pixels with different indexes... */
if (PB->mono && ctx->MutablePixels) {
/* copy index to all pixels */
GLuint n = PB->count, indx = PB->index;
GLuint *pbindex = PB->i;
do {
*pbindex++ = indx;
n--;
} while (n);
}
if (ctx->MutablePixels || !PB->mono) {
/* Pixel color index may be modified */
GLuint isave[PB_SIZE];
if (ctx->Fog.Enabled
&& (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
gl_fog_index_pixels( ctx, PB->count, PB->z, PB->i );
}
/* Scissoring already done above */
if (ctx->Stencil.Enabled) {
/* first stencil test */
if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
goto CleanUp;
}
/* depth buffering w/ stencil */
gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
else if (ctx->Depth.Test) {
/* regular depth testing */
(*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
if (ctx->RasterMask & NO_DRAW_BIT) {
goto CleanUp;
}
if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
/* make a copy of the indexes */
MEMCPY( isave, PB->i, PB->count * sizeof(GLuint) );
}
if (ctx->Color.SWLogicOpEnabled) {
gl_logic_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
}
if (ctx->Color.SWmasking) {
gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
}
/* write pixels */
(*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
PB->i, mask );
if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
/*** Also write to back buffer ***/
(*ctx->Driver.SetBuffer)( ctx, GL_BACK );
MEMCPY( PB->i, isave, PB->count * sizeof(GLuint) );
if (ctx->Color.SWLogicOpEnabled) {
gl_logic_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
}
if (ctx->Color.SWmasking) {
gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y,
PB->i, mask );
}
(*ctx->Driver.WriteIndexPixels)( ctx, PB->count, PB->x, PB->y,
PB->i, mask );
(*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
}
/*** ALL DONE ***/
}
else {
/* Same color index for all pixels */
/* Scissoring already done above */
if (ctx->Stencil.Enabled) {
/* first stencil test */
if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
goto CleanUp;
}
/* depth buffering w/ stencil */
gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
else if (ctx->Depth.Test) {
/* regular depth testing */
(*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
}
if (ctx->RasterMask & NO_DRAW_BIT) {
goto CleanUp;
}
/* write pixels */
(*ctx->Driver.Index)( ctx, PB->index );
(*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );
if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
/*** Also write to back buffer ***/
(*ctx->Driver.SetBuffer)( ctx, GL_BACK );
(*ctx->Driver.WriteMonoindexPixels)( ctx, PB->count, PB->x, PB->y, mask );
(*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
}
/*** ALL DONE ***/
}
}
CleanUp:
PB->count = 0;
UNDEFARRAY(mask);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.