Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 56 → Rev 57

/shark/trunk/ports/mesa/src/swrast/s_points.c
0,0 → 1,278
/* $Id: s_points.c,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "mmath.h"
#include "texstate.h"
#include "s_context.h"
#include "s_feedback.h"
#include "s_points.h"
#include "s_span.h"
 
 
 
#define RGBA 0x1
#define INDEX 0x2
#define SMOOTH 0x4
#define TEXTURE 0x8
#define SPECULAR 0x10
#define LARGE 0x20
#define ATTENUATE 0x40
#define SPRITE 0x80
 
 
/*
* CI points with size == 1.0
*/
#define FLAGS (INDEX)
#define NAME size1_ci_point
#include "s_pointtemp.h"
 
 
/*
* General CI points.
*/
#define FLAGS (INDEX | LARGE)
#define NAME general_ci_point
#include "s_pointtemp.h"
 
 
/*
* Antialiased CI points.
*/
#define FLAGS (INDEX | SMOOTH)
#define NAME antialiased_ci_point
#include "s_pointtemp.h"
 
 
/*
* Distance attenuated, general CI points.
*/
#define FLAGS (INDEX | ATTENUATE)
#define NAME atten_general_ci_point
#include "s_pointtemp.h"
 
 
/*
* RGBA points with size == 1.0
*/
#define FLAGS (RGBA)
#define NAME size1_rgba_point
#include "s_pointtemp.h"
 
 
/*
* General RGBA points.
*/
#define FLAGS (RGBA | LARGE)
#define NAME general_rgba_point
#include "s_pointtemp.h"
 
 
/*
* Antialiased RGBA points.
*/
#define FLAGS (RGBA | SMOOTH)
#define NAME antialiased_rgba_point
#include "s_pointtemp.h"
 
 
/*
* Textured RGBA points.
*/
#define FLAGS (RGBA | LARGE | TEXTURE | SPECULAR)
#define NAME textured_rgba_point
#include "s_pointtemp.h"
 
 
/*
* Antialiased points with texture mapping.
*/
#define FLAGS (RGBA | SMOOTH | TEXTURE | SPECULAR)
#define NAME antialiased_tex_rgba_point
#include "s_pointtemp.h"
 
 
/*
* Distance attenuated, general RGBA points.
*/
#define FLAGS (RGBA | ATTENUATE)
#define NAME atten_general_rgba_point
#include "s_pointtemp.h"
 
 
/*
* Distance attenuated, textured RGBA points.
*/
#define FLAGS (RGBA | ATTENUATE | TEXTURE | SPECULAR)
#define NAME atten_textured_rgba_point
#include "s_pointtemp.h"
 
 
/*
* Distance attenuated, antialiased points with or without texture mapping.
*/
#define FLAGS (RGBA | ATTENUATE | TEXTURE | SMOOTH)
#define NAME atten_antialiased_rgba_point
#include "s_pointtemp.h"
 
 
/*
* Sprite (textured point)
*/
#define FLAGS (RGBA | SPRITE)
#define NAME sprite_point
#include "s_pointtemp.h"
 
 
#define FLAGS (RGBA | ATTENUATE | SPRITE)
#define NAME atten_sprite_point
#include "s_pointtemp.h"
 
 
 
void _swrast_add_spec_terms_point( GLcontext *ctx,
const SWvertex *v0 )
{
SWvertex *ncv0 = (SWvertex *)v0;
GLchan c[1][4];
COPY_CHAN4( c[0], ncv0->color );
ACC_3V( ncv0->color, ncv0->specular );
SWRAST_CONTEXT(ctx)->SpecPoint( ctx, ncv0 );
COPY_CHAN4( ncv0->color, c[0] );
}
 
 
 
/* record the current point function name */
#ifdef DEBUG
 
static const char *pntFuncName = NULL;
 
#define USE(pntFunc) \
do { \
pntFuncName = #pntFunc; \
/*printf("%s\n", pntFuncName);*/ \
swrast->Point = pntFunc; \
} while (0)
 
#else
 
#define USE(pntFunc) swrast->Point = pntFunc
 
#endif
 
 
/*
* Examine the current context to determine which point drawing function
* should be used.
*/
void
_swrast_choose_point( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLboolean rgbMode = ctx->Visual.rgbMode;
 
if (ctx->RenderMode==GL_RENDER) {
if (ctx->Point.PointSprite) {
/* GL_NV_point_sprite */
/* XXX this might not be good enough */
if (ctx->Point._Attenuated)
USE(atten_sprite_point);
else
USE(sprite_point);
}
else if (ctx->Point.SmoothFlag) {
/* Smooth points */
if (rgbMode) {
if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
USE(atten_antialiased_rgba_point);
}
else if (ctx->Texture._EnabledUnits) {
USE(antialiased_tex_rgba_point);
}
else {
USE(antialiased_rgba_point);
}
}
else {
USE(antialiased_ci_point);
}
}
else if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
if (rgbMode) {
if (ctx->Texture._EnabledUnits) {
if (ctx->Point.SmoothFlag) {
USE(atten_antialiased_rgba_point);
}
else {
USE(atten_textured_rgba_point);
}
}
else {
USE(atten_general_rgba_point);
}
}
else {
/* ci, atten */
USE(atten_general_ci_point);
}
}
else if (ctx->Texture._EnabledUnits && rgbMode) {
/* textured */
USE(textured_rgba_point);
}
else if (ctx->Point.Size != 1.0) {
/* large points */
if (rgbMode) {
USE(general_rgba_point);
}
else {
USE(general_ci_point);
}
}
else {
/* single pixel points */
if (rgbMode) {
USE(size1_rgba_point);
}
else {
USE(size1_ci_point);
}
}
}
else if (ctx->RenderMode==GL_FEEDBACK) {
USE(_mesa_feedback_point);
}
else {
/* GL_SELECT mode */
USE(_mesa_select_point);
}
}
/shark/trunk/ports/mesa/src/swrast/s_texstore.c
0,0 → 1,429
/* $Id: s_texstore.c,v 1.1 2003-02-28 11:49:43 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/*
* Authors:
* Brian Paul
*/
 
 
/*
* The functions in this file are mostly related to software texture fallbacks.
* This includes texture image transfer/packing and texel fetching.
* Hardware drivers will likely override most of this.
*/
 
 
 
#include "colormac.h"
#include "context.h"
#include "convolve.h"
#include "image.h"
#include "imports.h"
#include "macros.h"
#include "texformat.h"
#include "teximage.h"
#include "texstore.h"
 
#include "s_context.h"
#include "s_depth.h"
#include "s_span.h"
 
/*
* Read an RGBA image from the frame buffer.
* This is used by glCopyTex[Sub]Image[12]D().
* Input: ctx - the context
* x, y - lower left corner
* width, height - size of region to read
* Return: pointer to block of GL_RGBA, GLchan data.
*/
static GLchan *
read_color_image( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLint stride, i;
GLchan *image, *dst;
 
image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
if (!image)
return NULL;
 
/* Select buffer to read from */
_swrast_use_read_buffer(ctx);
 
RENDER_START(swrast,ctx);
 
dst = image;
stride = width * 4;
for (i = 0; i < height; i++) {
_mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
(GLchan (*)[4]) dst );
dst += stride;
}
 
RENDER_FINISH(swrast,ctx);
 
/* Read from draw buffer (the default) */
_swrast_use_draw_buffer(ctx);
 
return image;
}
 
 
/*
* As above, but read data from depth buffer.
*/
static GLfloat *
read_depth_image( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat *image, *dst;
GLint i;
 
image = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
if (!image)
return NULL;
 
RENDER_START(swrast,ctx);
 
dst = image;
for (i = 0; i < height; i++) {
_mesa_read_depth_span_float(ctx, width, x, y + i, dst);
dst += width;
}
 
RENDER_FINISH(swrast,ctx);
 
return image;
}
 
 
 
static GLboolean
is_depth_format(GLenum format)
{
switch (format) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_SGIX:
case GL_DEPTH_COMPONENT24_SGIX:
case GL_DEPTH_COMPONENT32_SGIX:
return GL_TRUE;
default:
return GL_FALSE;
}
}
 
 
/*
* Fallback for Driver.CopyTexImage1D().
*/
void
_swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLint border )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
 
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
 
ASSERT(ctx->Driver.TexImage1D);
 
if (is_depth_format(internalFormat)) {
/* read depth image from framebuffer */
GLfloat *image = read_depth_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
return;
}
 
/* call glTexImage1D to redefine the texture */
(*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
width, border,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
return;
}
 
/* call glTexImage1D to redefine the texture */
(*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
width, border,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
 
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
 
 
/*
* Fallback for Driver.CopyTexImage2D().
*/
void
_swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
 
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
 
ASSERT(ctx->Driver.TexImage2D);
 
if (is_depth_format(internalFormat)) {
/* read depth image from framebuffer */
GLfloat *image = read_depth_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
return;
}
 
/* call glTexImage2D to redefine the texture */
(*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
width, height, border,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
return;
}
 
/* call glTexImage2D to redefine the texture */
(*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
width, height, border,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
 
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
 
 
/*
* Fallback for Driver.CopyTexSubImage1D().
*/
void
_swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint x, GLint y, GLsizei width )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
 
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
 
ASSERT(ctx->Driver.TexImage1D);
 
if (texImage->Format == GL_DEPTH_COMPONENT) {
/* read depth image from framebuffer */
GLfloat *image = read_depth_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
return;
}
 
/* call glTexSubImage1D to redefine the texture */
(*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, 1);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
return;
}
 
/* now call glTexSubImage1D to do the real work */
(*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
 
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
 
 
/*
* Fallback for Driver.CopyTexSubImage2D().
*/
void
_swrast_copy_texsubimage2d( GLcontext *ctx,
GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
 
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
 
ASSERT(ctx->Driver.TexImage2D);
 
if (texImage->Format == GL_DEPTH_COMPONENT) {
/* read depth image from framebuffer */
GLfloat *image = read_depth_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
return;
}
 
/* call glTexImage1D to redefine the texture */
(*ctx->Driver.TexSubImage2D)(ctx, target, level,
xoffset, yoffset, width, height,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, height);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
return;
}
 
/* now call glTexSubImage2D to do the real work */
(*ctx->Driver.TexSubImage2D)(ctx, target, level,
xoffset, yoffset, width, height,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
 
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
 
 
/*
* Fallback for Driver.CopyTexSubImage3D().
*/
void
_swrast_copy_texsubimage3d( GLcontext *ctx,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
 
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
 
ASSERT(ctx->Driver.TexImage3D);
 
if (texImage->Format == GL_DEPTH_COMPONENT) {
/* read depth image from framebuffer */
GLfloat *image = read_depth_image(ctx, x, y, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
return;
}
 
/* call glTexImage1D to redefine the texture */
(*ctx->Driver.TexSubImage3D)(ctx, target, level,
xoffset, yoffset, zoffset, width, height, 1,
GL_DEPTH_COMPONENT, GL_FLOAT, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, height);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
return;
}
 
/* now call glTexSubImage3D to do the real work */
(*ctx->Driver.TexSubImage3D)(ctx, target, level,
xoffset, yoffset, zoffset, width, height, 1,
GL_RGBA, CHAN_TYPE, image,
&_mesa_native_packing, texObj, texImage);
FREE(image);
}
 
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
}
/shark/trunk/ports/mesa/src/swrast/s_drawpix.c
0,0 → 1,957
/* $Id: s_drawpix.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "convolve.h"
#include "image.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "pixel.h"
 
#include "s_context.h"
#include "s_drawpix.h"
#include "s_pixeltex.h"
#include "s_span.h"
#include "s_stencil.h"
#include "s_texture.h"
#include "s_zoom.h"
 
 
 
/*
* Given the dest position, size and skipPixels and skipRows values
* for a glDrawPixels command, perform clipping of the image bounds
* so the result lies withing the context's buffer bounds.
* Return: GL_TRUE if image is ready for drawing
* GL_FALSE if image was completely clipped away (draw nothing)
*/
GLboolean
_mesa_clip_pixelrect(const GLcontext *ctx,
GLint *destX, GLint *destY,
GLsizei *width, GLsizei *height,
GLint *skipPixels, GLint *skipRows)
{
const GLframebuffer *buffer = ctx->DrawBuffer;
 
/* left clipping */
if (*destX < buffer->_Xmin) {
*skipPixels += (buffer->_Xmin - *destX);
*width -= (buffer->_Xmin - *destX);
*destX = buffer->_Xmin;
}
/* right clipping */
if (*destX + *width > buffer->_Xmax)
*width -= (*destX + *width - buffer->_Xmax);
 
if (*width <= 0)
return GL_FALSE;
 
/* bottom clipping */
if (*destY < buffer->_Ymin) {
*skipRows += (buffer->_Ymin - *destY);
*height -= (buffer->_Ymin - *destY);
*destY = buffer->_Ymin;
}
/* top clipping */
if (*destY + *height > buffer->_Ymax)
*height -= (*destY + *height - buffer->_Ymax);
 
if (*height <= 0)
return GL_TRUE;
 
return GL_TRUE;
}
 
 
 
/*
* Try to do a fast and simple RGB(a) glDrawPixels.
* Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
*/
static GLboolean
fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type, const GLvoid *pixels)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
struct sw_span span;
 
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
 
if (!ctx->Current.RasterPosValid) {
return GL_TRUE; /* no-op */
}
 
if (ctx->Depth.Test)
_mesa_span_default_z(ctx, &span);
if (ctx->Fog.Enabled)
_mesa_span_default_fog(ctx, &span);
 
if ((SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) == 0
&& ctx->Texture._EnabledUnits == 0
&& unpack->Alignment == 1
&& !unpack->SwapBytes
&& !unpack->LsbFirst) {
 
GLint destX = x;
GLint destY = y;
GLint drawWidth = width; /* actual width drawn */
GLint drawHeight = height; /* actual height drawn */
GLint skipPixels = unpack->SkipPixels;
GLint skipRows = unpack->SkipRows;
GLint rowLength;
GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */
GLint zoomY0 = 0;
 
if (unpack->RowLength > 0)
rowLength = unpack->RowLength;
else
rowLength = width;
 
/* If we're not using pixel zoom then do all clipping calculations
* now. Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
* handle the clipping.
*/
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
/* horizontal clipping */
if (destX < ctx->DrawBuffer->_Xmin) {
skipPixels += (ctx->DrawBuffer->_Xmin - destX);
drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
destX = ctx->DrawBuffer->_Xmin;
}
if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
if (drawWidth <= 0)
return GL_TRUE;
 
/* vertical clipping */
if (destY < ctx->DrawBuffer->_Ymin) {
skipRows += (ctx->DrawBuffer->_Ymin - destY);
drawHeight -= (ctx->DrawBuffer->_Ymin - destY);
destY = ctx->DrawBuffer->_Ymin;
}
if (destY + drawHeight > ctx->DrawBuffer->_Ymax)
drawHeight -= (destY + drawHeight - ctx->DrawBuffer->_Ymax);
if (drawHeight <= 0)
return GL_TRUE;
}
else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
/* upside-down image */
/* horizontal clipping */
if (destX < ctx->DrawBuffer->_Xmin) {
skipPixels += (ctx->DrawBuffer->_Xmin - destX);
drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
destX = ctx->DrawBuffer->_Xmin;
}
if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
if (drawWidth <= 0)
return GL_TRUE;
 
/* vertical clipping */
if (destY > ctx->DrawBuffer->_Ymax) {
skipRows += (destY - ctx->DrawBuffer->_Ymax);
drawHeight -= (destY - ctx->DrawBuffer->_Ymax);
destY = ctx->DrawBuffer->_Ymax;
}
if (destY - drawHeight < ctx->DrawBuffer->_Ymin)
drawHeight -= (ctx->DrawBuffer->_Ymin - (destY - drawHeight));
if (drawHeight <= 0)
return GL_TRUE;
}
else {
/* setup array of fragment Z value to pass to zoom function */
GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF);
GLint i;
ASSERT(drawWidth < MAX_WIDTH);
for (i=0; i<drawWidth; i++)
zSpan[i] = z;
 
/* save Y value of first row */
zoomY0 = IROUND(ctx->Current.RasterPos[1]);
}
 
 
/*
* Ready to draw!
* The window region at (destX, destY) of size (drawWidth, drawHeight)
* will be written to.
* We'll take pixel data from buffer pointed to by "pixels" but we'll
* skip "skipRows" rows and skip "skipPixels" pixels/row.
*/
 
if (format == GL_RGBA && type == CHAN_TYPE
&& ctx->_ImageTransferState==0) {
if (ctx->Visual.rgbMode) {
GLchan *src = (GLchan *) pixels
+ (skipRows * rowLength + skipPixels) * 4;
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
/* no zooming */
GLint row;
for (row=0; row<drawHeight; row++) {
(*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[4]) src, NULL);
src += rowLength * 4;
destY++;
}
}
else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
/* upside-down */
GLint row;
for (row=0; row<drawHeight; row++) {
destY--;
(*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[4]) src, NULL);
src += rowLength * 4;
}
}
else {
/* with zooming */
GLint row;
for (row=0; row<drawHeight; row++) {
span.x = destX;
span.y = destY;
span.end = drawWidth;
_mesa_write_zoomed_rgba_span(ctx, &span,
(CONST GLchan (*)[4]) src, zoomY0);
src += rowLength * 4;
destY++;
}
}
}
return GL_TRUE;
}
else if (format == GL_RGB && type == CHAN_TYPE
&& ctx->_ImageTransferState == 0) {
if (ctx->Visual.rgbMode) {
GLchan *src = (GLchan *) pixels
+ (skipRows * rowLength + skipPixels) * 3;
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
GLint row;
for (row=0; row<drawHeight; row++) {
(*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[3]) src, NULL);
src += rowLength * 3;
destY++;
}
}
else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
/* upside-down */
GLint row;
for (row=0; row<drawHeight; row++) {
destY--;
(*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[3]) src, NULL);
src += rowLength * 3;
}
}
else {
/* with zooming */
GLint row;
for (row=0; row<drawHeight; row++) {
span.x = destX;
span.y = destY;
span.end = drawWidth;
_mesa_write_zoomed_rgb_span(ctx, &span,
(CONST GLchan (*)[3]) src, zoomY0);
src += rowLength * 3;
destY++;
}
}
}
return GL_TRUE;
}
else if (format == GL_LUMINANCE && type == CHAN_TYPE
&& ctx->_ImageTransferState==0) {
if (ctx->Visual.rgbMode) {
GLchan *src = (GLchan *) pixels
+ (skipRows * rowLength + skipPixels);
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
/* no zooming */
GLint row;
ASSERT(drawWidth < MAX_WIDTH);
for (row=0; row<drawHeight; row++) {
GLint i;
for (i=0;i<drawWidth;i++) {
span.array->rgb[i][0] = src[i];
span.array->rgb[i][1] = src[i];
span.array->rgb[i][2] = src[i];
}
(*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[3]) span.array->rgb, NULL);
src += rowLength;
destY++;
}
}
else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
/* upside-down */
GLint row;
ASSERT(drawWidth < MAX_WIDTH);
for (row=0; row<drawHeight; row++) {
GLint i;
for (i=0;i<drawWidth;i++) {
span.array->rgb[i][0] = src[i];
span.array->rgb[i][1] = src[i];
span.array->rgb[i][2] = src[i];
}
destY--;
(*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[3]) span.array->rgb, NULL);
src += rowLength;
}
}
else {
/* with zooming */
GLint row;
ASSERT(drawWidth < MAX_WIDTH);
for (row=0; row<drawHeight; row++) {
GLint i;
for (i=0;i<drawWidth;i++) {
span.array->rgb[i][0] = src[i];
span.array->rgb[i][1] = src[i];
span.array->rgb[i][2] = src[i];
}
span.x = destX;
span.y = destY;
span.end = drawWidth;
_mesa_write_zoomed_rgb_span(ctx, &span,
(CONST GLchan (*)[3]) span.array->rgb, zoomY0);
src += rowLength;
destY++;
}
}
}
return GL_TRUE;
}
else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE
&& ctx->_ImageTransferState == 0) {
if (ctx->Visual.rgbMode) {
GLchan *src = (GLchan *) pixels
+ (skipRows * rowLength + skipPixels)*2;
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
/* no zooming */
GLint row;
ASSERT(drawWidth < MAX_WIDTH);
for (row=0; row<drawHeight; row++) {
GLint i;
GLchan *ptr = src;
for (i=0;i<drawWidth;i++) {
span.array->rgba[i][0] = *ptr;
span.array->rgba[i][1] = *ptr;
span.array->rgba[i][2] = *ptr++;
span.array->rgba[i][3] = *ptr++;
}
(*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[4]) span.array->rgba, NULL);
src += rowLength*2;
destY++;
}
}
else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
/* upside-down */
GLint row;
ASSERT(drawWidth < MAX_WIDTH);
for (row=0; row<drawHeight; row++) {
GLint i;
GLchan *ptr = src;
for (i=0;i<drawWidth;i++) {
span.array->rgba[i][0] = *ptr;
span.array->rgba[i][1] = *ptr;
span.array->rgba[i][2] = *ptr++;
span.array->rgba[i][3] = *ptr++;
}
destY--;
(*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[4]) span.array->rgba, NULL);
src += rowLength*2;
}
}
else {
/* with zooming */
GLint row;
ASSERT(drawWidth < MAX_WIDTH);
for (row=0; row<drawHeight; row++) {
GLchan *ptr = src;
GLint i;
for (i=0;i<drawWidth;i++) {
span.array->rgba[i][0] = *ptr;
span.array->rgba[i][1] = *ptr;
span.array->rgba[i][2] = *ptr++;
span.array->rgba[i][3] = *ptr++;
}
span.x = destX;
span.y = destY;
span.end = drawWidth;
_mesa_write_zoomed_rgba_span(ctx, &span,
(CONST GLchan (*)[4]) span.array->rgba, zoomY0);
src += rowLength*2;
destY++;
}
}
}
return GL_TRUE;
}
else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
if (ctx->Visual.rgbMode) {
/* convert CI data to RGBA */
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
/* no zooming */
GLint row;
for (row=0; row<drawHeight; row++) {
ASSERT(drawWidth < MAX_WIDTH);
_mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
(*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
(const GLchan (*)[4]) span.array->rgba, NULL);
src += rowLength;
destY++;
}
return GL_TRUE;
}
else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
/* upside-down */
GLint row;
for (row=0; row<drawHeight; row++) {
ASSERT(drawWidth < MAX_WIDTH);
_mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
destY--;
(*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
(CONST GLchan (*)[4]) span.array->rgba, NULL);
src += rowLength;
}
return GL_TRUE;
}
else {
/* with zooming */
GLint row;
for (row=0; row<drawHeight; row++) {
ASSERT(drawWidth < MAX_WIDTH);
_mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
span.x = destX;
span.y = destY;
span.end = drawWidth;
_mesa_write_zoomed_rgba_span(ctx, &span,
(CONST GLchan (*)[4]) span.array->rgba, zoomY0);
src += rowLength;
destY++;
}
return GL_TRUE;
}
}
else if (ctx->_ImageTransferState==0) {
/* write CI data to CI frame buffer */
GLint row;
if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
/* no zooming */
for (row=0; row<drawHeight; row++) {
(*swrast->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
src, NULL);
src += rowLength;
destY++;
}
return GL_TRUE;
}
else {
/* with zooming */
return GL_FALSE;
}
}
}
else {
/* can't handle this pixel format and/or data type here */
return GL_FALSE;
}
}
 
/* can't do a simple draw, have to use slow path */
return GL_FALSE;
}
 
 
 
/*
* Do glDrawPixels of index pixels.
*/
static void
draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum type, const GLvoid *pixels )
{
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
const GLint desty = y;
GLint row, drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
struct sw_span span;
 
INIT_SPAN(span, GL_BITMAP, drawWidth, 0, SPAN_INDEX);
 
if (ctx->Depth.Test)
_mesa_span_default_z(ctx, &span);
if (ctx->Fog.Enabled)
_mesa_span_default_fog(ctx, &span);
 
/*
* General solution
*/
for (row = 0; row < height; row++, y++) {
const GLvoid *source = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
_mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT,
span.array->index,
type, source, &ctx->Unpack,
ctx->_ImageTransferState);
span.x = x;
span.y = y;
span.end = drawWidth;
if (zoom)
_mesa_write_zoomed_index_span(ctx, &span, desty);
else
_mesa_write_index_span(ctx, &span);
}
}
 
 
 
/*
* Do glDrawPixels of stencil image. The image datatype may either
* be GLubyte or GLbitmap.
*/
static void
draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum type, const GLvoid *pixels )
{
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
const GLint desty = y;
GLint row, drawWidth;
 
if (type != GL_BYTE &&
type != GL_UNSIGNED_BYTE &&
type != GL_SHORT &&
type != GL_UNSIGNED_SHORT &&
type != GL_INT &&
type != GL_UNSIGNED_INT &&
type != GL_FLOAT &&
type != GL_BITMAP) {
_mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
return;
}
 
if (ctx->Visual.stencilBits == 0) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(no stencil buffer)");
return;
}
 
drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
 
for (row = 0; row < height; row++, y++) {
GLstencil values[MAX_WIDTH];
GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
const GLvoid *source = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
_mesa_unpack_index_span(ctx, drawWidth, destType, values,
type, source, &ctx->Unpack,
ctx->_ImageTransferState);
if (ctx->_ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
_mesa_shift_and_offset_stencil( ctx, drawWidth, values );
}
if (ctx->Pixel.MapStencilFlag) {
_mesa_map_stencil( ctx, drawWidth, values );
}
 
if (zoom) {
_mesa_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
values, desty );
}
else {
_mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
}
}
}
 
 
/*
* Do a glDrawPixels of depth values.
*/
static void
draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum type, const GLvoid *pixels )
{
const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
const GLint desty = y;
GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
struct sw_span span;
 
INIT_SPAN(span, GL_BITMAP, drawWidth, 0, SPAN_Z);
 
if (type != GL_BYTE
&& type != GL_UNSIGNED_BYTE
&& type != GL_SHORT
&& type != GL_UNSIGNED_SHORT
&& type != GL_INT
&& type != GL_UNSIGNED_INT
&& type != GL_FLOAT) {
_mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
return;
}
 
_mesa_span_default_color(ctx, &span);
 
if (ctx->Fog.Enabled)
_mesa_span_default_fog(ctx, &span);
if (ctx->Texture._EnabledUnits)
_mesa_span_default_texcoords(ctx, &span);
 
if (type==GL_UNSIGNED_SHORT && ctx->Visual.depthBits == 16
&& !bias_or_scale && !zoom && ctx->Visual.rgbMode) {
/* Special case: directly write 16-bit depth values */
GLint row;
span.x = x;
span.y = y;
span.end = drawWidth;
for (row = 0; row < height; row++, span.y++) {
const GLushort *zptr = (const GLushort *)
_mesa_image_address(&ctx->Unpack, pixels, width, height,
GL_DEPTH_COMPONENT, type, 0, row, 0);
GLint i;
for (i = 0; i < drawWidth; i++)
span.array->z[i] = zptr[i];
_mesa_write_rgba_span(ctx, &span);
}
}
else if (type==GL_UNSIGNED_INT && ctx->Visual.depthBits == 32
&& !bias_or_scale && !zoom && ctx->Visual.rgbMode) {
/* Special case: directly write 32-bit depth values */
GLint row;
span.x = x;
span.y = y;
span.end = drawWidth;
for (row = 0; row < height; row++, span.y++) {
const GLuint *zptr = (const GLuint *)
_mesa_image_address(&ctx->Unpack, pixels, width, height,
GL_DEPTH_COMPONENT, type, 0, row, 0);
MEMCPY(span.array->z, zptr, drawWidth * sizeof(GLdepth));
_mesa_write_rgba_span(ctx, &span);
}
}
else {
/* General case */
GLint row;
span.x = x;
span.y = y;
span.end = drawWidth;
for (row = 0; row < height; row++, span.y++) {
GLfloat fspan[MAX_WIDTH];
const GLvoid *src = _mesa_image_address(&ctx->Unpack,
pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
_mesa_unpack_depth_span( ctx, drawWidth, fspan, type, src,
&ctx->Unpack );
/* clamp depth values to [0,1] and convert from floats to integers */
{
const GLfloat zs = ctx->DepthMaxF;
GLint i;
for (i = 0; i < drawWidth; i++) {
span.array->z[i] = (GLdepth) (fspan[i] * zs + 0.5F);
}
}
if (ctx->Visual.rgbMode) {
if (zoom) {
_mesa_write_zoomed_rgba_span(ctx, &span,
(const GLchan (*)[4]) span.array->rgba, desty);
}
else
_mesa_write_rgba_span(ctx, &span);
}
else {
if (zoom)
_mesa_write_zoomed_index_span(ctx, &span, desty);
else
_mesa_write_index_span(ctx, &span);
}
}
}
}
 
 
/*
* Do glDrawPixels of RGBA pixels.
*/
static void
draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type, const GLvoid *pixels )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
const GLint desty = y;
GLboolean quickDraw;
GLfloat *convImage = NULL;
GLuint transferOps = ctx->_ImageTransferState;
struct sw_span span;
 
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
 
if (!_mesa_is_legal_format_and_type(format, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)");
return;
}
 
/* Try an optimized glDrawPixels first */
if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels))
return;
 
if (ctx->Depth.Test)
_mesa_span_default_z(ctx, &span);
if (ctx->Fog.Enabled)
_mesa_span_default_fog(ctx, &span);
if (ctx->Texture._EnabledUnits)
_mesa_span_default_texcoords(ctx, &span);
 
if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
&& x + width <= (GLint) ctx->DrawBuffer->Width
&& y + height <= (GLint) ctx->DrawBuffer->Height) {
quickDraw = GL_TRUE;
}
else {
quickDraw = GL_FALSE;
}
 
if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
/* Convolution has to be handled specially. We'll create an
* intermediate image, applying all pixel transfer operations
* up to convolution. Then we'll convolve the image. Then
* we'll proceed with the rest of the transfer operations and
* rasterize the image.
*/
GLint row;
GLfloat *dest, *tmpImage;
 
tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
if (!tmpImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
if (!convImage) {
FREE(tmpImage);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
 
/* Unpack the image and apply transfer ops up to convolution */
dest = tmpImage;
for (row = 0; row < height; row++) {
const GLvoid *source = _mesa_image_address(unpack,
pixels, width, height, format, type, 0, row, 0);
_mesa_unpack_float_color_span(ctx, width, GL_RGBA, (GLfloat *) dest,
format, type, source, unpack,
transferOps & IMAGE_PRE_CONVOLUTION_BITS,
GL_FALSE);
dest += width * 4;
}
 
/* do convolution */
if (ctx->Pixel.Convolution2DEnabled) {
_mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
}
else {
ASSERT(ctx->Pixel.Separable2DEnabled);
_mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
}
FREE(tmpImage);
 
/* continue transfer ops and draw the convolved image */
unpack = &_mesa_native_packing;
pixels = convImage;
format = GL_RGBA;
type = GL_FLOAT;
transferOps &= IMAGE_POST_CONVOLUTION_BITS;
}
 
/*
* General solution
*/
{
GLint row;
if (width > MAX_WIDTH)
width = MAX_WIDTH;
 
for (row = 0; row < height; row++, y++) {
const GLvoid *source = _mesa_image_address(unpack,
pixels, width, height, format, type, 0, row, 0);
 
_mesa_unpack_chan_color_span(ctx, width, GL_RGBA,
(GLchan *) span.array->rgba,
format, type, source, unpack,
transferOps);
 
if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
(ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
continue;
 
if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
span.end = width;
_swrast_pixel_texture(ctx, &span);
}
 
if (quickDraw) {
(*swrast->Driver.WriteRGBASpan)(ctx, width, x, y,
(CONST GLchan (*)[4]) span.array->rgba, NULL);
}
else if (zoom) {
span.x = x;
span.y = y;
span.end = width;
_mesa_write_zoomed_rgba_span(ctx, &span,
(CONST GLchan (*)[4]) span.array->rgba, desty);
}
else {
span.x = x;
span.y = y;
span.end = width;
_mesa_write_rgba_span(ctx, &span);
}
}
}
 
if (convImage) {
FREE(convImage);
}
}
 
 
 
/*
* Execute glDrawPixels
*/
void
_swrast_DrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
(void) unpack;
 
if (swrast->NewState)
_swrast_validate_derived( ctx );
 
RENDER_START(swrast,ctx);
 
switch (format) {
case GL_STENCIL_INDEX:
draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
break;
case GL_DEPTH_COMPONENT:
draw_depth_pixels( ctx, x, y, width, height, type, pixels );
break;
case GL_COLOR_INDEX:
if (ctx->Visual.rgbMode)
draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
else
draw_index_pixels(ctx, x, y, width, height, type, pixels);
break;
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RGB:
case GL_BGR:
case GL_RGBA:
case GL_BGRA:
case GL_ABGR_EXT:
draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
}
 
RENDER_FINISH(swrast,ctx);
}
 
 
 
#if 0 /* experimental */
/*
* Execute glDrawDepthPixelsMESA().
*/
void
_swrast_DrawDepthPixelsMESA( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum colorFormat, GLenum colorType,
const GLvoid *colors,
GLenum depthType, const GLvoid *depths,
const struct gl_pixelstore_attrib *unpack )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
(void) unpack;
 
if (swrast->NewState)
_swrast_validate_derived( ctx );
 
RENDER_START(swrast,ctx);
 
switch (colorFormat) {
case GL_COLOR_INDEX:
if (ctx->Visual.rgbMode)
draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType, colors);
else
draw_index_pixels(ctx, x, y, width, height, colorType, colors);
break;
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RGB:
case GL_BGR:
case GL_RGBA:
case GL_BGRA:
case GL_ABGR_EXT:
draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType, colors);
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM,
"glDrawDepthPixelsMESA(colorFormat)" );
}
 
RENDER_FINISH(swrast,ctx);
}
#endif
/shark/trunk/ports/mesa/src/swrast/s_points.h
0,0 → 1,40
/* $Id: s_points.h,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_POINTS_H
#define S_POINTS_H
 
#include "mtypes.h"
 
extern void
_swrast_choose_point( GLcontext *ctx );
 
extern void
_swrast_add_spec_terms_point( GLcontext *ctx,
const SWvertex *v0 );
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_linetemp.h
0,0 → 1,626
/* $Id: s_linetemp.h,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 5.0
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* Line Rasterizer Template
*
* This file is #include'd to generate custom line rasterizers.
*
* The following macros may be defined to indicate what auxillary information
* must be interplated along the line:
* INTERP_Z - if defined, interpolate Z values
* INTERP_FOG - if defined, interpolate FOG values
* INTERP_RGB - if defined, interpolate RGB values
* INTERP_SPEC - if defined, interpolate specular RGB values
* INTERP_ALPHA - if defined, interpolate Alpha values
* INTERP_INDEX - if defined, interpolate color index values
* INTERP_TEX - if defined, interpolate unit 0 texcoords
* INTERP_MULTITEX - if defined, interpolate multi-texcoords
*
* When one can directly address pixels in the color buffer the following
* macros can be defined and used to directly compute pixel addresses during
* rasterization (see pixelPtr):
* PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
* BYTES_PER_ROW - number of bytes per row in the color buffer
* PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
* Y==0 at bottom of screen and increases upward.
*
* Similarly, for direct depth buffer access, this type is used for depth
* buffer addressing:
* DEPTH_TYPE - either GLushort or GLuint
*
* Optionally, one may provide one-time setup code
* SETUP_CODE - code which is to be executed once per line
*
* To actually "plot" each pixel the PLOT macro must be defined...
* PLOT(X,Y) - code to plot a pixel. Example:
* if (Z < *zPtr) {
* *zPtr = Z;
* color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
* FixedToInt(b0) );
* put_pixel( X, Y, color );
* }
*
* This code was designed for the origin to be in the lower-left corner.
*
*/
 
 
/*void line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )*/
{
GLint x0 = (GLint) vert0->win[0];
GLint x1 = (GLint) vert1->win[0];
GLint y0 = (GLint) vert0->win[1];
GLint y1 = (GLint) vert1->win[1];
GLint dx, dy;
#ifdef INTERP_XY
GLint xstep, ystep;
#endif
#ifdef INTERP_Z
GLint z0, z1, dz;
const GLint depthBits = ctx->Visual.depthBits;
const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
# define FixedToDepth(F) ((F) >> fixedToDepthShift)
# ifdef DEPTH_TYPE
GLint zPtrXstep, zPtrYstep;
DEPTH_TYPE *zPtr;
# endif
#endif
#ifdef INTERP_FOG
GLfloat fog0 = vert0->fog;
GLfloat dfog = vert1->fog - fog0;
#endif
#ifdef INTERP_RGB
GLfixed r0 = ChanToFixed(vert0->color[0]);
GLfixed dr = ChanToFixed(vert1->color[0]) - r0;
GLfixed g0 = ChanToFixed(vert0->color[1]);
GLfixed dg = ChanToFixed(vert1->color[1]) - g0;
GLfixed b0 = ChanToFixed(vert0->color[2]);
GLfixed db = ChanToFixed(vert1->color[2]) - b0;
#endif
#ifdef INTERP_SPEC
GLfixed sr0 = ChanToFixed(vert0->specular[0]);
GLfixed dsr = ChanToFixed(vert1->specular[0]) - sr0;
GLfixed sg0 = ChanToFixed(vert0->specular[1]);
GLfixed dsg = ChanToFixed(vert1->specular[1]) - sg0;
GLfixed sb0 = ChanToFixed(vert0->specular[2]);
GLfixed dsb = ChanToFixed(vert1->specular[2]) - sb0;
#endif
#ifdef INTERP_ALPHA
GLfixed a0 = ChanToFixed(vert0->color[3]);
GLfixed da = ChanToFixed(vert1->color[3]) - a0;
#endif
#ifdef INTERP_INDEX
GLint i0 = vert0->index << 8;
GLint di = (GLint) (vert1->index << 8) - i0;
#endif
#ifdef INTERP_TEX
const GLfloat invw0 = vert0->win[3];
const GLfloat invw1 = vert1->win[3];
GLfloat tex[4];
GLfloat dtex[4];
GLfloat fragTexcoord[4];
#endif
#ifdef INTERP_MULTITEX
const GLfloat invw0 = vert0->win[3];
const GLfloat invw1 = vert1->win[3];
GLfloat tex[MAX_TEXTURE_UNITS][4];
GLfloat dtex[MAX_TEXTURE_UNITS][4];
GLfloat fragTexcoord[MAX_TEXTURE_UNITS][4];
#endif
#ifdef PIXEL_ADDRESS
PIXEL_TYPE *pixelPtr;
GLint pixelXstep, pixelYstep;
#endif
#ifdef INTERP_TEX
{
tex[0] = invw0 * vert0->texcoord[0][0];
dtex[0] = invw1 * vert1->texcoord[0][0] - tex[0];
tex[1] = invw0 * vert0->texcoord[0][1];
dtex[1] = invw1 * vert1->texcoord[0][1] - tex[1];
tex[2] = invw0 * vert0->texcoord[0][2];
dtex[2] = invw1 * vert1->texcoord[0][2] - tex[2];
tex[3] = invw0 * vert0->texcoord[0][3];
dtex[3] = invw1 * vert1->texcoord[0][3] - tex[3];
}
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
tex[u][0] = invw0 * vert0->texcoord[u][0];
dtex[u][0] = invw1 * vert1->texcoord[u][0] - tex[u][0];
tex[u][1] = invw0 * vert0->texcoord[u][1];
dtex[u][1] = invw1 * vert1->texcoord[u][1] - tex[u][1];
tex[u][2] = invw0 * vert0->texcoord[u][2];
dtex[u][2] = invw1 * vert1->texcoord[u][2] - tex[u][2];
tex[u][3] = invw0 * vert0->texcoord[u][3];
dtex[u][3] = invw1 * vert1->texcoord[u][3] - tex[u][3];
}
}
}
#endif
 
/* Cull primitives with malformed coordinates.
*/
{
float tmp = vert0->win[0] + vert0->win[1] + vert1->win[0] + vert1->win[1];
if (IS_INF_OR_NAN(tmp))
return;
}
 
/*
printf("%s():\n", __FUNCTION__);
printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
vert0->win[0], vert0->win[1], vert0->win[2],
vert1->win[0], vert1->win[1], vert1->win[2]);
printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
vert0->color[0], vert0->color[1], vert0->color[2],
vert1->color[0], vert1->color[1], vert1->color[2]);
printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
vert0->specular[0], vert0->specular[1], vert0->specular[2],
vert1->specular[0], vert1->specular[1], vert1->specular[2]);
*/
 
/*
* Despite being clipped to the view volume, the line's window coordinates
* may just lie outside the window bounds. That is, if the legal window
* coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
* This quick and dirty code nudges the endpoints inside the window if
* necessary.
*/
#ifdef CLIP_HACK
{
GLint w = ctx->DrawBuffer->Width;
GLint h = ctx->DrawBuffer->Height;
if ((x0==w) | (x1==w)) {
if ((x0==w) & (x1==w))
return;
x0 -= x0==w;
x1 -= x1==w;
}
if ((y0==h) | (y1==h)) {
if ((y0==h) & (y1==h))
return;
y0 -= y0==h;
y1 -= y1==h;
}
}
#endif
dx = x1 - x0;
dy = y1 - y0;
if (dx==0 && dy==0) {
return;
}
 
/*
* Setup
*/
#ifdef SETUP_CODE
SETUP_CODE
#endif
 
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) _mesa_zbuffer_address(ctx, x0, y0);
# endif
if (depthBits <= 16) {
z0 = FloatToFixed(vert0->win[2]) + FIXED_HALF;
z1 = FloatToFixed(vert1->win[2]) + FIXED_HALF;
}
else {
z0 = (int) vert0->win[2];
z1 = (int) vert1->win[2];
}
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
#endif
 
if (dx<0) {
dx = -dx; /* make positive */
#ifdef INTERP_XY
xstep = -1;
#endif
#if defined(INTERP_Z) && defined(DEPTH_TYPE)
zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
#endif
#ifdef PIXEL_ADDRESS
pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
#endif
}
else {
#ifdef INTERP_XY
xstep = 1;
#endif
#if defined(INTERP_Z) && defined(DEPTH_TYPE)
zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
#endif
#ifdef PIXEL_ADDRESS
pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
#endif
}
 
if (dy<0) {
dy = -dy; /* make positive */
#ifdef INTERP_XY
ystep = -1;
#endif
#if defined(INTERP_Z) && defined(DEPTH_TYPE)
zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
#endif
#ifdef PIXEL_ADDRESS
pixelYstep = BYTES_PER_ROW;
#endif
}
else {
#ifdef INTERP_XY
ystep = 1;
#endif
#if defined(INTERP_Z) && defined(DEPTH_TYPE)
zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
#endif
#ifdef PIXEL_ADDRESS
pixelYstep = -(BYTES_PER_ROW);
#endif
}
 
/*
* Draw
*/
 
if (dx>dy) {
/*** X-major line ***/
GLint i;
GLint errorInc = dy+dy;
GLint error = errorInc-dx;
GLint errorDec = error-dx;
#ifdef SET_XMAJOR
xMajor = GL_TRUE;
#endif
#ifdef INTERP_Z
dz = (z1-z0) / dx;
#endif
#ifdef INTERP_FOG
dfog /= dx;
#endif
#ifdef INTERP_RGB
dr /= dx; /* convert from whole line delta to per-pixel delta */
dg /= dx;
db /= dx;
#endif
#ifdef INTERP_SPEC
dsr /= dx; /* convert from whole line delta to per-pixel delta */
dsg /= dx;
dsb /= dx;
#endif
#ifdef INTERP_ALPHA
da /= dx;
#endif
#ifdef INTERP_INDEX
di /= dx;
#endif
#ifdef INTERP_TEX
{
const GLfloat invDx = 1.0F / (GLfloat) dx;
dtex[0] *= invDx;
dtex[1] *= invDx;
dtex[2] *= invDx;
dtex[3] *= invDx;
}
#endif
#ifdef INTERP_MULTITEX
{
const GLfloat invDx = 1.0F / (GLfloat) dx;
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
dtex[u][0] *= invDx;
dtex[u][1] *= invDx;
dtex[u][2] *= invDx;
dtex[u][3] *= invDx;
}
}
}
#endif
 
for (i=0;i<dx;i++) {
#ifdef INTERP_Z
GLdepth Z = FixedToDepth(z0);
#endif
#ifdef INTERP_INDEX
GLint I = i0 >> 8;
#endif
#ifdef INTERP_TEX
{
const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F;
fragTexcoord[0] = tex[0] * invQ;
fragTexcoord[1] = tex[1] * invQ;
fragTexcoord[2] = tex[2] * invQ;
fragTexcoord[3] = tex[3];
}
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
const GLfloat invQ = 1.0F / tex[u][3];
fragTexcoord[u][0] = tex[u][0] * invQ;
fragTexcoord[u][1] = tex[u][1] * invQ;
fragTexcoord[u][2] = tex[u][2] * invQ;
fragTexcoord[u][3] = tex[u][3];
}
}
}
#endif
 
PLOT( x0, y0 );
 
#ifdef INTERP_XY
x0 += xstep;
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
# endif
z0 += dz;
#endif
#ifdef INTERP_FOG
fog0 += dfog;
#endif
#ifdef INTERP_RGB
r0 += dr;
g0 += dg;
b0 += db;
#endif
#ifdef INTERP_SPEC
sr0 += dsr;
sg0 += dsg;
sb0 += dsb;
#endif
#ifdef INTERP_ALPHA
a0 += da;
#endif
#ifdef INTERP_INDEX
i0 += di;
#endif
#ifdef INTERP_TEX
tex[0] += dtex[0];
tex[1] += dtex[1];
tex[2] += dtex[2];
tex[3] += dtex[3];
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
tex[u][0] += dtex[u][0];
tex[u][1] += dtex[u][1];
tex[u][2] += dtex[u][2];
tex[u][3] += dtex[u][3];
}
}
}
#endif
 
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
#endif
if (error<0) {
error += errorInc;
}
else {
error += errorDec;
#ifdef INTERP_XY
y0 += ystep;
#endif
#if defined(INTERP_Z) && defined(DEPTH_TYPE)
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
#endif
}
}
}
else {
/*** Y-major line ***/
GLint i;
GLint errorInc = dx+dx;
GLint error = errorInc-dy;
GLint errorDec = error-dy;
#ifdef INTERP_Z
dz = (z1-z0) / dy;
#endif
#ifdef INTERP_FOG
dfog /= dy;
#endif
#ifdef INTERP_RGB
dr /= dy; /* convert from whole line delta to per-pixel delta */
dg /= dy;
db /= dy;
#endif
#ifdef INTERP_SPEC
dsr /= dy; /* convert from whole line delta to per-pixel delta */
dsg /= dy;
dsb /= dy;
#endif
#ifdef INTERP_ALPHA
da /= dy;
#endif
#ifdef INTERP_INDEX
di /= dy;
#endif
#ifdef INTERP_TEX
{
const GLfloat invDy = 1.0F / (GLfloat) dy;
dtex[0] *= invDy;
dtex[1] *= invDy;
dtex[2] *= invDy;
dtex[3] *= invDy;
}
#endif
#ifdef INTERP_MULTITEX
{
const GLfloat invDy = 1.0F / (GLfloat) dy;
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
dtex[u][0] *= invDy;
dtex[u][1] *= invDy;
dtex[u][2] *= invDy;
dtex[u][3] *= invDy;
}
}
}
#endif
 
for (i=0;i<dy;i++) {
#ifdef INTERP_Z
GLdepth Z = FixedToDepth(z0);
#endif
#ifdef INTERP_INDEX
GLint I = i0 >> 8;
#endif
#ifdef INTERP_TEX
{
const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F;
fragTexcoord[0] = tex[0] * invQ;
fragTexcoord[1] = tex[1] * invQ;
fragTexcoord[2] = tex[2] * invQ;
fragTexcoord[3] = tex[3];
}
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
const GLfloat invQ = 1.0F / tex[u][3];
fragTexcoord[u][0] = tex[u][0] * invQ;
fragTexcoord[u][1] = tex[u][1] * invQ;
fragTexcoord[u][2] = tex[u][2] * invQ;
fragTexcoord[u][3] = tex[u][3];
}
}
}
#endif
 
PLOT( x0, y0 );
 
#ifdef INTERP_XY
y0 += ystep;
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
# endif
z0 += dz;
#endif
#ifdef INTERP_FOG
fog0 += dfog;
#endif
#ifdef INTERP_RGB
r0 += dr;
g0 += dg;
b0 += db;
#endif
#ifdef INTERP_SPEC
sr0 += dsr;
sg0 += dsg;
sb0 += dsb;
#endif
#ifdef INTERP_ALPHA
a0 += da;
#endif
#ifdef INTERP_INDEX
i0 += di;
#endif
#ifdef INTERP_TEX
tex[0] += dtex[0];
tex[1] += dtex[1];
tex[2] += dtex[2];
tex[3] += dtex[3];
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
tex[u][0] += dtex[u][0];
tex[u][1] += dtex[u][1];
tex[u][2] += dtex[u][2];
tex[u][3] += dtex[u][3];
}
}
}
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
#endif
if (error<0) {
error += errorInc;
}
else {
error += errorDec;
#ifdef INTERP_XY
x0 += xstep;
#endif
#if defined(INTERP_Z) && defined(DEPTH_TYPE)
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
#endif
}
}
}
 
}
 
 
#undef INTERP_XY
#undef INTERP_Z
#undef INTERP_FOG
#undef INTERP_RGB
#undef INTERP_SPEC
#undef INTERP_ALPHA
#undef INTERP_TEX
#undef INTERP_MULTITEX
#undef INTERP_INDEX
#undef PIXEL_ADDRESS
#undef PIXEL_TYPE
#undef DEPTH_TYPE
#undef BYTES_PER_ROW
#undef SETUP_CODE
#undef PLOT
#undef CLIP_HACK
#undef FixedToDepth
#undef SET_XMAJOR
/shark/trunk/ports/mesa/src/swrast/s_drawpix.h
0,0 → 1,42
/* $Id: s_drawpix.h,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_DRAWPIXELS_H
#define S_DRAWPIXELS_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern GLboolean
_mesa_clip_pixelrect(const GLcontext *ctx,
GLint *destX, GLint *destY,
GLsizei *width, GLsizei *height,
GLint *skipPixels, GLint *skipRows);
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_blend.c
0,0 → 1,807
/* $Id: s_blend.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
 
#include "glheader.h"
#include "context.h"
#include "colormac.h"
#include "macros.h"
 
#include "s_alphabuf.h"
#include "s_blend.h"
#include "s_context.h"
#include "s_span.h"
 
 
#if defined(USE_MMX_ASM)
#include "X86/mmx.h"
#include "X86/common_x86_asm.h"
#define _BLENDAPI _ASMAPI
#else
#define _BLENDAPI
#endif
 
 
/*
* Special case for glBlendFunc(GL_ZERO, GL_ONE)
*/
static void _BLENDAPI
blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
ASSERT(ctx->Color.BlendSrcRGB==GL_ZERO);
ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
(void) ctx;
 
for (i = 0; i < n; i++) {
if (mask[i]) {
COPY_CHAN4( rgba[i], dest[i] );
}
}
}
 
 
/*
* Special case for glBlendFunc(GL_ONE, GL_ZERO)
*/
static void _BLENDAPI
blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
ASSERT(ctx->Color.BlendDstRGB==GL_ZERO);
(void) ctx;
(void) n;
(void) mask;
(void) rgba;
(void) dest;
}
 
 
/*
* Common transparency blending mode.
*/
static void _BLENDAPI
blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
(void) ctx;
 
for (i=0;i<n;i++) {
if (mask[i]) {
const GLchan t = rgba[i][ACOMP]; /* t in [0, CHAN_MAX] */
if (t == 0) {
/* 0% alpha */
rgba[i][RCOMP] = dest[i][RCOMP];
rgba[i][GCOMP] = dest[i][GCOMP];
rgba[i][BCOMP] = dest[i][BCOMP];
rgba[i][ACOMP] = dest[i][ACOMP];
}
else if (t == CHAN_MAX) {
/* 100% alpha, no-op */
}
else {
#if 0
/* This is pretty close, but Glean complains */
const GLint s = CHAN_MAX - t;
const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s + 1) >> 8;
const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s + 1) >> 8;
const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s + 1) >> 8;
const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s + 1) >> 8;
#elif 0
/* This is slower but satisfies Glean */
const GLint s = CHAN_MAX - t;
const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) / 255;
const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) / 255;
const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) / 255;
const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) / 255;
#else
#if CHAN_BITS == 8
/* This satisfies Glean and should be reasonably fast */
/* Contributed by Nathan Hand */
#if 0
#define DIV255(X) (((X) << 8) + (X) + 256) >> 16
#else
GLint temp;
#define DIV255(X) (temp = (X), ((temp << 8) + temp + 256) >> 16)
#endif
const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP];
 
#undef DIV255
#elif CHAN_BITS == 16
const GLfloat tt = (GLfloat) t / CHAN_MAXF;
const GLint r = (GLint) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
const GLint g = (GLint) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
const GLint b = (GLint) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
const GLint a = (GLint) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
#else /* CHAN_BITS == 32 */
const GLfloat tt = (GLfloat) t / CHAN_MAXF;
const GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP];
const GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP];
const GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP];
const GLfloat a = CLAMP( rgba[i][ACOMP], 0.0F, CHAN_MAXF ) * t +
CLAMP( dest[i][ACOMP], 0.0F, CHAN_MAXF ) * (1.0F - t);
#endif
#endif
ASSERT(r <= CHAN_MAX);
ASSERT(g <= CHAN_MAX);
ASSERT(b <= CHAN_MAX);
ASSERT(a <= CHAN_MAX);
rgba[i][RCOMP] = (GLchan) r;
rgba[i][GCOMP] = (GLchan) g;
rgba[i][BCOMP] = (GLchan) b;
rgba[i][ACOMP] = (GLchan) a;
}
}
}
}
 
 
 
/*
* Add src and dest.
*/
static void _BLENDAPI
blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
(void) ctx;
 
for (i=0;i<n;i++) {
if (mask[i]) {
#if CHAN_TYPE == GL_FLOAT
/* don't RGB clamp to max */
GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF) + dest[i][ACOMP];
rgba[i][RCOMP] += dest[i][RCOMP];
rgba[i][GCOMP] += dest[i][GCOMP];
rgba[i][BCOMP] += dest[i][BCOMP];
rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAXF );
#else
GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
rgba[i][RCOMP] = (GLchan) MIN2( r, CHAN_MAX );
rgba[i][GCOMP] = (GLchan) MIN2( g, CHAN_MAX );
rgba[i][BCOMP] = (GLchan) MIN2( b, CHAN_MAX );
rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAX );
#endif
}
}
}
 
 
 
/*
* Blend min function (for GL_EXT_blend_minmax)
*/
static void _BLENDAPI
blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
(void) ctx;
 
for (i=0;i<n;i++) {
if (mask[i]) {
rgba[i][RCOMP] = (GLchan) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
rgba[i][GCOMP] = (GLchan) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
rgba[i][BCOMP] = (GLchan) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
#if CHAN_TYPE == GL_FLOAT
rgba[i][ACOMP] = (GLchan) MIN2(CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF),
dest[i][ACOMP]);
#else
rgba[i][ACOMP] = (GLchan) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
#endif
}
}
}
 
 
 
/*
* Blend max function (for GL_EXT_blend_minmax)
*/
static void _BLENDAPI
blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
(void) ctx;
 
for (i=0;i<n;i++) {
if (mask[i]) {
rgba[i][RCOMP] = (GLchan) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
rgba[i][GCOMP] = (GLchan) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
rgba[i][BCOMP] = (GLchan) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
#if CHAN_TYPE == GL_FLOAT
rgba[i][ACOMP] = (GLchan) MAX2(CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF),
dest[i][ACOMP]);
#else
rgba[i][ACOMP] = (GLchan) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
#endif
}
}
}
 
 
 
/*
* Modulate: result = src * dest
*/
static void _BLENDAPI
blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
GLuint i;
(void) ctx;
 
for (i=0;i<n;i++) {
if (mask[i]) {
#if CHAN_TYPE == GL_FLOAT
rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
GLint r = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
GLint g = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
GLint b = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
GLint a = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
rgba[i][RCOMP] = (GLchan) r;
rgba[i][GCOMP] = (GLchan) g;
rgba[i][BCOMP] = (GLchan) b;
rgba[i][ACOMP] = (GLchan) a;
#else
GLint r = (rgba[i][RCOMP] * dest[i][RCOMP] + 255) >> 8;
GLint g = (rgba[i][GCOMP] * dest[i][GCOMP] + 255) >> 8;
GLint b = (rgba[i][BCOMP] * dest[i][BCOMP] + 255) >> 8;
GLint a = (rgba[i][ACOMP] * dest[i][ACOMP] + 255) >> 8;
rgba[i][RCOMP] = (GLchan) r;
rgba[i][GCOMP] = (GLchan) g;
rgba[i][BCOMP] = (GLchan) b;
rgba[i][ACOMP] = (GLchan) a;
#endif
}
}
}
 
 
 
/*
* General case blend pixels.
* Input: n - number of pixels
* mask - the usual write mask
* In/Out: rgba - the incoming and modified pixels
* Input: dest - the pixels from the dest color buffer
*/
static void _BLENDAPI
blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan rgba[][4], CONST GLchan dest[][4] )
{
const GLfloat rscale = 1.0F / CHAN_MAXF;
const GLfloat gscale = 1.0F / CHAN_MAXF;
const GLfloat bscale = 1.0F / CHAN_MAXF;
const GLfloat ascale = 1.0F / CHAN_MAXF;
GLuint i;
 
for (i=0;i<n;i++) {
if (mask[i]) {
#if CHAN_TYPE == GL_FLOAT
GLfloat Rs, Gs, Bs, As; /* Source colors */
GLfloat Rd, Gd, Bd, Ad; /* Dest colors */
#else
GLint Rs, Gs, Bs, As; /* Source colors */
GLint Rd, Gd, Bd, Ad; /* Dest colors */
#endif
GLfloat sR, sG, sB, sA; /* Source scaling */
GLfloat dR, dG, dB, dA; /* Dest scaling */
GLfloat r, g, b, a; /* result color */
 
/* Incoming/source Color */
Rs = rgba[i][RCOMP];
Gs = rgba[i][GCOMP];
Bs = rgba[i][BCOMP];
As = rgba[i][ACOMP];
#if CHAN_TYPE == GL_FLOAT
/* clamp */
Rs = MIN2(Rs, CHAN_MAXF);
Gs = MIN2(Gs, CHAN_MAXF);
Bs = MIN2(Bs, CHAN_MAXF);
As = MIN2(As, CHAN_MAXF);
#endif
 
/* Frame buffer/dest color */
Rd = dest[i][RCOMP];
Gd = dest[i][GCOMP];
Bd = dest[i][BCOMP];
Ad = dest[i][ACOMP];
#if CHAN_TYPE == GL_FLOAT
/* clamp */
Rd = MIN2(Rd, CHAN_MAXF);
Gd = MIN2(Gd, CHAN_MAXF);
Bd = MIN2(Bd, CHAN_MAXF);
Ad = MIN2(Ad, CHAN_MAXF);
#endif
 
/* Source RGB factor */
switch (ctx->Color.BlendSrcRGB) {
case GL_ZERO:
sR = sG = sB = 0.0F;
break;
case GL_ONE:
sR = sG = sB = 1.0F;
break;
case GL_DST_COLOR:
sR = (GLfloat) Rd * rscale;
sG = (GLfloat) Gd * gscale;
sB = (GLfloat) Bd * bscale;
break;
case GL_ONE_MINUS_DST_COLOR:
sR = 1.0F - (GLfloat) Rd * rscale;
sG = 1.0F - (GLfloat) Gd * gscale;
sB = 1.0F - (GLfloat) Bd * bscale;
break;
case GL_SRC_ALPHA:
sR = sG = sB = (GLfloat) As * ascale;
break;
case GL_ONE_MINUS_SRC_ALPHA:
sR = sG = sB = 1.0F - (GLfloat) As * ascale;
break;
case GL_DST_ALPHA:
sR = sG = sB = (GLfloat) Ad * ascale;
break;
case GL_ONE_MINUS_DST_ALPHA:
sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
break;
case GL_SRC_ALPHA_SATURATE:
if (As < CHAN_MAX - Ad) {
sR = sG = sB = (GLfloat) As * ascale;
}
else {
sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
}
break;
case GL_CONSTANT_COLOR:
sR = ctx->Color.BlendColor[0];
sG = ctx->Color.BlendColor[1];
sB = ctx->Color.BlendColor[2];
break;
case GL_ONE_MINUS_CONSTANT_COLOR:
sR = 1.0F - ctx->Color.BlendColor[0];
sG = 1.0F - ctx->Color.BlendColor[1];
sB = 1.0F - ctx->Color.BlendColor[2];
break;
case GL_CONSTANT_ALPHA:
sR = sG = sB = ctx->Color.BlendColor[3];
break;
case GL_ONE_MINUS_CONSTANT_ALPHA:
sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
break;
case GL_SRC_COLOR: /* GL_NV_blend_square */
sR = (GLfloat) Rs * rscale;
sG = (GLfloat) Gs * gscale;
sB = (GLfloat) Bs * bscale;
break;
case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
sR = 1.0F - (GLfloat) Rs * rscale;
sG = 1.0F - (GLfloat) Gs * gscale;
sB = 1.0F - (GLfloat) Bs * bscale;
break;
default:
/* this should never happen */
_mesa_problem(ctx, "Bad blend source RGB factor in do_blend");
return;
}
 
/* Source Alpha factor */
switch (ctx->Color.BlendSrcA) {
case GL_ZERO:
sA = 0.0F;
break;
case GL_ONE:
sA = 1.0F;
break;
case GL_DST_COLOR:
sA = (GLfloat) Ad * ascale;
break;
case GL_ONE_MINUS_DST_COLOR:
sA = 1.0F - (GLfloat) Ad * ascale;
break;
case GL_SRC_ALPHA:
sA = (GLfloat) As * ascale;
break;
case GL_ONE_MINUS_SRC_ALPHA:
sA = 1.0F - (GLfloat) As * ascale;
break;
case GL_DST_ALPHA:
sA =(GLfloat) Ad * ascale;
break;
case GL_ONE_MINUS_DST_ALPHA:
sA = 1.0F - (GLfloat) Ad * ascale;
break;
case GL_SRC_ALPHA_SATURATE:
sA = 1.0;
break;
case GL_CONSTANT_COLOR:
sA = ctx->Color.BlendColor[3];
break;
case GL_ONE_MINUS_CONSTANT_COLOR:
sA = 1.0F - ctx->Color.BlendColor[3];
break;
case GL_CONSTANT_ALPHA:
sA = ctx->Color.BlendColor[3];
break;
case GL_ONE_MINUS_CONSTANT_ALPHA:
sA = 1.0F - ctx->Color.BlendColor[3];
break;
case GL_SRC_COLOR: /* GL_NV_blend_square */
sA = (GLfloat) As * ascale;
break;
case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
sA = 1.0F - (GLfloat) As * ascale;
break;
default:
/* this should never happen */
sA = 0.0F;
_mesa_problem(ctx, "Bad blend source A factor in do_blend");
}
 
/* Dest RGB factor */
switch (ctx->Color.BlendDstRGB) {
case GL_ZERO:
dR = dG = dB = 0.0F;
break;
case GL_ONE:
dR = dG = dB = 1.0F;
break;
case GL_SRC_COLOR:
dR = (GLfloat) Rs * rscale;
dG = (GLfloat) Gs * gscale;
dB = (GLfloat) Bs * bscale;
break;
case GL_ONE_MINUS_SRC_COLOR:
dR = 1.0F - (GLfloat) Rs * rscale;
dG = 1.0F - (GLfloat) Gs * gscale;
dB = 1.0F - (GLfloat) Bs * bscale;
break;
case GL_SRC_ALPHA:
dR = dG = dB = (GLfloat) As * ascale;
break;
case GL_ONE_MINUS_SRC_ALPHA:
dR = dG = dB = 1.0F - (GLfloat) As * ascale;
break;
case GL_DST_ALPHA:
dR = dG = dB = (GLfloat) Ad * ascale;
break;
case GL_ONE_MINUS_DST_ALPHA:
dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
break;
case GL_CONSTANT_COLOR:
dR = ctx->Color.BlendColor[0];
dG = ctx->Color.BlendColor[1];
dB = ctx->Color.BlendColor[2];
break;
case GL_ONE_MINUS_CONSTANT_COLOR:
dR = 1.0F - ctx->Color.BlendColor[0];
dG = 1.0F - ctx->Color.BlendColor[1];
dB = 1.0F - ctx->Color.BlendColor[2];
break;
case GL_CONSTANT_ALPHA:
dR = dG = dB = ctx->Color.BlendColor[3];
break;
case GL_ONE_MINUS_CONSTANT_ALPHA:
dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
break;
case GL_DST_COLOR: /* GL_NV_blend_square */
dR = (GLfloat) Rd * rscale;
dG = (GLfloat) Gd * gscale;
dB = (GLfloat) Bd * bscale;
break;
case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
dR = 1.0F - (GLfloat) Rd * rscale;
dG = 1.0F - (GLfloat) Gd * gscale;
dB = 1.0F - (GLfloat) Bd * bscale;
break;
default:
/* this should never happen */
dR = dG = dB = 0.0F;
_mesa_problem(ctx, "Bad blend dest RGB factor in do_blend");
}
 
/* Dest Alpha factor */
switch (ctx->Color.BlendDstA) {
case GL_ZERO:
dA = 0.0F;
break;
case GL_ONE:
dA = 1.0F;
break;
case GL_SRC_COLOR:
dA = (GLfloat) As * ascale;
break;
case GL_ONE_MINUS_SRC_COLOR:
dA = 1.0F - (GLfloat) As * ascale;
break;
case GL_SRC_ALPHA:
dA = (GLfloat) As * ascale;
break;
case GL_ONE_MINUS_SRC_ALPHA:
dA = 1.0F - (GLfloat) As * ascale;
break;
case GL_DST_ALPHA:
dA = (GLfloat) Ad * ascale;
break;
case GL_ONE_MINUS_DST_ALPHA:
dA = 1.0F - (GLfloat) Ad * ascale;
break;
case GL_CONSTANT_COLOR:
dA = ctx->Color.BlendColor[3];
break;
case GL_ONE_MINUS_CONSTANT_COLOR:
dA = 1.0F - ctx->Color.BlendColor[3];
break;
case GL_CONSTANT_ALPHA:
dA = ctx->Color.BlendColor[3];
break;
case GL_ONE_MINUS_CONSTANT_ALPHA:
dA = 1.0F - ctx->Color.BlendColor[3];
break;
case GL_DST_COLOR: /* GL_NV_blend_square */
dA = (GLfloat) Ad * ascale;
break;
case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
dA = 1.0F - (GLfloat) Ad * ascale;
break;
default:
/* this should never happen */
dA = 0.0F;
_mesa_problem(ctx, "Bad blend dest A factor in do_blend");
return;
}
 
/* Due to round-off problems we have to clamp against zero. */
/* Optimization: we don't have to do this for all src & dst factors */
if (dA < 0.0F) dA = 0.0F;
if (dR < 0.0F) dR = 0.0F;
if (dG < 0.0F) dG = 0.0F;
if (dB < 0.0F) dB = 0.0F;
if (sA < 0.0F) sA = 0.0F;
if (sR < 0.0F) sR = 0.0F;
if (sG < 0.0F) sG = 0.0F;
if (sB < 0.0F) sB = 0.0F;
 
ASSERT( sR <= 1.0 );
ASSERT( sG <= 1.0 );
ASSERT( sB <= 1.0 );
ASSERT( sA <= 1.0 );
ASSERT( dR <= 1.0 );
ASSERT( dG <= 1.0 );
ASSERT( dB <= 1.0 );
ASSERT( dA <= 1.0 );
 
/* compute blended color */
#if CHAN_TYPE == GL_FLOAT
if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
r = Rs * sR + Rd * dR;
g = Gs * sG + Gd * dG;
b = Bs * sB + Bd * dB;
a = As * sA + Ad * dA;
}
else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
r = Rs * sR - Rd * dR;
g = Gs * sG - Gd * dG;
b = Bs * sB - Bd * dB;
a = As * sA - Ad * dA;
}
else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
r = Rd * dR - Rs * sR;
g = Gd * dG - Gs * sG;
b = Bd * dB - Bs * sB;
a = Ad * dA - As * sA;
}
else {
/* should never get here */
r = g = b = a = 0.0F; /* silence uninitialized var warning */
_mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
}
 
/* final clamping */
rgba[i][RCOMP] = MAX2( r, 0.0F );
rgba[i][GCOMP] = MAX2( g, 0.0F );
rgba[i][BCOMP] = MAX2( b, 0.0F );
rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF );
#else
if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
r = Rs * sR + Rd * dR + 0.5F;
g = Gs * sG + Gd * dG + 0.5F;
b = Bs * sB + Bd * dB + 0.5F;
a = As * sA + Ad * dA + 0.5F;
}
else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
r = Rs * sR - Rd * dR + 0.5F;
g = Gs * sG - Gd * dG + 0.5F;
b = Bs * sB - Bd * dB + 0.5F;
a = As * sA - Ad * dA + 0.5F;
}
else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
r = Rd * dR - Rs * sR + 0.5F;
g = Gd * dG - Gs * sG + 0.5F;
b = Bd * dB - Bs * sB + 0.5F;
a = Ad * dA - As * sA + 0.5F;
}
else {
/* should never get here */
r = g = b = a = 0.0F; /* silence uninitialized var warning */
_mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
}
 
/* final clamping */
rgba[i][RCOMP] = (GLchan) (GLint) CLAMP( r, 0.0F, CHAN_MAXF );
rgba[i][GCOMP] = (GLchan) (GLint) CLAMP( g, 0.0F, CHAN_MAXF );
rgba[i][BCOMP] = (GLchan) (GLint) CLAMP( b, 0.0F, CHAN_MAXF );
rgba[i][ACOMP] = (GLchan) (GLint) CLAMP( a, 0.0F, CHAN_MAXF );
#endif
}
}
}
 
 
 
 
 
/*
* Analyze current blending parameters to pick fastest blending function.
* Result: the ctx->Color.BlendFunc pointer is updated.
*/
void _swrast_choose_blend_func( GLcontext *ctx )
{
const GLenum eq = ctx->Color.BlendEquation;
const GLenum srcRGB = ctx->Color.BlendSrcRGB;
const GLenum dstRGB = ctx->Color.BlendDstRGB;
const GLenum srcA = ctx->Color.BlendSrcA;
const GLenum dstA = ctx->Color.BlendDstA;
 
if (srcRGB != srcA || dstRGB != dstA) {
SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
}
else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
&& dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency;
}
else
#endif
SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency;
}
else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_add;
}
else
#endif
SWRAST_CONTEXT(ctx)->BlendFunc = blend_add;
}
else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
&& (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
||
((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
&& (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_modulate;
}
else
#endif
SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate;
}
else if (eq==GL_MIN_EXT) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_min;
}
else
#endif
SWRAST_CONTEXT(ctx)->BlendFunc = blend_min;
}
else if (eq==GL_MAX_EXT) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_max;
}
else
#endif
SWRAST_CONTEXT(ctx)->BlendFunc = blend_max;
}
else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop;
}
else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace;
}
else {
SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
}
}
 
 
 
/*
* Apply the blending operator to a span of pixels.
* We can handle horizontal runs of pixels (spans) or arrays of x/y
* pixel coordinates.
*/
void
_mesa_blend_span( GLcontext *ctx, const struct sw_span *span,
GLchan rgba[][4] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLchan framebuffer[MAX_WIDTH][4];
 
ASSERT(span->end <= MAX_WIDTH);
ASSERT(span->arrayMask & SPAN_RGBA);
ASSERT(!ctx->Color.ColorLogicOpEnabled);
 
/* Read span of current frame buffer pixels */
if (span->arrayMask & SPAN_XY) {
/* array of x/y pixel coords */
(*swrast->Driver.ReadRGBAPixels)( ctx, span->end,
span->array->x, span->array->y,
framebuffer, span->array->mask );
if (swrast->_RasterMask & ALPHABUF_BIT) {
_mesa_read_alpha_pixels( ctx, span->end,
span->array->x, span->array->y,
framebuffer, span->array->mask );
}
}
else {
/* horizontal run of pixels */
_mesa_read_rgba_span( ctx, ctx->DrawBuffer, span->end,
span->x, span->y, framebuffer );
}
 
SWRAST_CONTEXT(ctx)->BlendFunc( ctx, span->end, span->array->mask, rgba,
(const GLchan (*)[4]) framebuffer );
}
/shark/trunk/ports/mesa/src/swrast/s_alpha.c
0,0 → 1,226
/* $Id: s_alpha.c,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file swrast/s_alpha.c
* \brief Functions to apply alpha test.
*/
 
#include "glheader.h"
#include "context.h"
#include "colormac.h"
#include "macros.h"
#include "mmath.h"
 
#include "s_alpha.h"
#include "s_context.h"
 
 
/**
* \fn GLint _mesa_alpha_test( const GLcontext *ctx, struct sw_span *span )
* \brief Apply the alpha test to a span of pixels.
* \return
* - "0" = all pixels in the span failed the alpha test.
* - "1" = one or more pixels passed the alpha test.
*/
GLint
_mesa_alpha_test( const GLcontext *ctx, struct sw_span *span )
{
const GLchan (*rgba)[4] = (const GLchan (*)[4]) span->array->rgba;
GLchan ref;
const GLuint n = span->end;
GLubyte *mask = span->array->mask;
GLuint i;
 
CLAMPED_FLOAT_TO_CHAN(ref, ctx->Color.AlphaRef);
 
if (span->arrayMask & SPAN_RGBA) {
/* Use the array values */
switch (ctx->Color.AlphaFunc) {
case GL_LESS:
for (i = 0; i < n; i++)
mask[i] &= (rgba[i][ACOMP] < ref);
break;
case GL_LEQUAL:
for (i = 0; i < n; i++)
mask[i] &= (rgba[i][ACOMP] <= ref);
break;
case GL_GEQUAL:
for (i = 0; i < n; i++)
mask[i] &= (rgba[i][ACOMP] >= ref);
break;
case GL_GREATER:
for (i = 0; i < n; i++)
mask[i] &= (rgba[i][ACOMP] > ref);
break;
case GL_NOTEQUAL:
for (i = 0; i < n; i++)
mask[i] &= (rgba[i][ACOMP] != ref);
break;
case GL_EQUAL:
for (i = 0; i < n; i++)
mask[i] &= (rgba[i][ACOMP] == ref);
break;
case GL_ALWAYS:
/* do nothing */
return 1;
case GL_NEVER:
/* caller should check for zero! */
span->writeAll = GL_FALSE;
return 0;
default:
_mesa_problem( ctx, "Invalid alpha test in _mesa_alpha_test" );
return 0;
}
}
else {
/* Use the interpolation values */
#if CHAN_TYPE == GL_FLOAT
const GLfloat alphaStep = span->alphaStep;
GLfloat alpha = span->alpha;
ASSERT(span->interpMask & SPAN_RGBA);
switch (ctx->Color.AlphaFunc) {
case GL_LESS:
for (i = 0; i < n; i++) {
mask[i] &= (alpha < ref);
alpha += alphaStep;
}
break;
case GL_LEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (alpha <= ref);
alpha += alphaStep;
}
break;
case GL_GEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (alpha >= ref);
alpha += alphaStep;
}
break;
case GL_GREATER:
for (i = 0; i < n; i++) {
mask[i] &= (alpha > ref);
alpha += alphaStep;
}
break;
case GL_NOTEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (alpha != ref);
alpha += alphaStep;
}
break;
case GL_EQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (alpha == ref);
alpha += alphaStep;
}
break;
case GL_ALWAYS:
/* do nothing */
return 1;
case GL_NEVER:
/* caller should check for zero! */
span->writeAll = GL_FALSE;
return 0;
default:
_mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
return 0;
}
#else
/* 8 or 16-bit channel interpolation */
const GLfixed alphaStep = span->alphaStep;
GLfixed alpha = span->alpha;
ASSERT(span->interpMask & SPAN_RGBA);
switch (ctx->Color.AlphaFunc) {
case GL_LESS:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) < ref);
alpha += alphaStep;
}
break;
case GL_LEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) <= ref);
alpha += alphaStep;
}
break;
case GL_GEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) >= ref);
alpha += alphaStep;
}
break;
case GL_GREATER:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) > ref);
alpha += alphaStep;
}
break;
case GL_NOTEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) != ref);
alpha += alphaStep;
}
break;
case GL_EQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) == ref);
alpha += alphaStep;
}
break;
case GL_ALWAYS:
/* do nothing */
return 1;
case GL_NEVER:
/* caller should check for zero! */
span->writeAll = GL_FALSE;
return 0;
default:
_mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
return 0;
}
#endif /* CHAN_TYPE */
}
 
#if 0
/* XXXX This causes conformance failures!!!! */
while ((span->start <= span->end) &&
(mask[span->start] == 0))
span->start ++;
 
while ((span->end >= span->start) &&
(mask[span->end] == 0))
span->end --;
#endif
 
span->writeAll = GL_FALSE;
 
if (span->start >= span->end)
return 0;
else
return 1;
}
/shark/trunk/ports/mesa/src/swrast/s_trispan.h
0,0 → 1,32
/* $Id: s_trispan.h,v 1.1 2003-02-28 11:49:43 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_TRISPAN_H
#define S_TRISPAN_H
 
 
#endif /* S_TRISPAN_H */
/shark/trunk/ports/mesa/src/swrast/s_accum.c
0,0 → 1,529
/* $Id: s_accum.c,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "mmath.h"
#include "imports.h"
 
#include "s_accum.h"
#include "s_alphabuf.h"
#include "s_context.h"
#include "s_masking.h"
#include "s_span.h"
 
 
/*
* Accumulation buffer notes
*
* Normally, accumulation buffer values are GLshorts with values in
* [-32767, 32767] which represent floating point colors in [-1, 1],
* as suggested by the OpenGL specification.
*
* We optimize for the common case used for full-scene antialiasing:
* // start with accum buffer cleared to zero
* glAccum(GL_LOAD, w); // or GL_ACCUM the first image
* glAccum(GL_ACCUM, w);
* ...
* glAccum(GL_ACCUM, w);
* glAccum(GL_RETURN, 1.0);
* That is, we start with an empty accumulation buffer and accumulate
* n images, each with weight w = 1/n.
* In this scenario, we can simply store unscaled integer values in
* the accum buffer instead of scaled integers. We'll also keep track
* of the w value so when we do GL_RETURN we simply divide the accumulated
* values by n (=1/w).
* This lets us avoid _many_ int->float->int conversions.
*/
 
 
#if CHAN_BITS == 8 && ACCUM_BITS < 32
#define USE_OPTIMIZED_ACCUM /* enable the optimization */
#endif
 
 
void
_mesa_alloc_accum_buffer( GLframebuffer *buffer )
{
GET_CURRENT_CONTEXT(ctx);
GLint n;
 
if (buffer->Accum) {
MESA_PBUFFER_FREE( buffer->Accum );
buffer->Accum = NULL;
}
 
/* allocate accumulation buffer if not already present */
n = buffer->Width * buffer->Height * 4 * sizeof(GLaccum);
buffer->Accum = (GLaccum *) MESA_PBUFFER_ALLOC( n );
if (!buffer->Accum) {
/* unable to setup accumulation buffer */
_mesa_error( NULL, GL_OUT_OF_MEMORY, "glAccum" );
}
 
if (ctx) {
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* XXX these fields should probably be in the GLframebuffer */
#ifdef USE_OPTIMIZED_ACCUM
swrast->_IntegerAccumMode = GL_TRUE;
#else
swrast->_IntegerAccumMode = GL_FALSE;
#endif
swrast->_IntegerAccumScaler = 0.0;
}
}
 
 
/*
* This is called when we fall out of optimized/unscaled accum buffer mode.
* That is, we convert each unscaled accum buffer value into a scaled value
* representing the range[-1, 1].
*/
static void rescale_accum( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height * 4;
const GLfloat s = swrast->_IntegerAccumScaler * (32767.0F / CHAN_MAXF);
GLaccum *accum = ctx->DrawBuffer->Accum;
GLuint i;
 
assert(swrast->_IntegerAccumMode);
assert(accum);
 
for (i = 0; i < n; i++) {
accum[i] = (GLaccum) (accum[i] * s);
}
 
swrast->_IntegerAccumMode = GL_FALSE;
}
 
 
 
 
 
 
/*
* Clear the accumulation Buffer.
*/
void
_mesa_clear_accum_buffer( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint buffersize;
GLfloat acc_scale;
 
if (ctx->Visual.accumRedBits==0) {
/* No accumulation buffer! */
return;
}
 
if (sizeof(GLaccum)==1) {
acc_scale = 127.0;
}
else if (sizeof(GLaccum)==2) {
acc_scale = 32767.0;
}
else {
acc_scale = 1.0F;
}
 
/* number of pixels */
buffersize = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
 
if (!ctx->DrawBuffer->Accum) {
/* try to alloc accumulation buffer */
ctx->DrawBuffer->Accum = (GLaccum *)
MALLOC( buffersize * 4 * sizeof(GLaccum) );
}
 
if (ctx->DrawBuffer->Accum) {
if (ctx->Scissor.Enabled) {
/* Limit clear to scissor box */
const GLaccum r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
const GLaccum g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
const GLaccum b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
const GLaccum a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
GLint i, j;
GLint width, height;
GLaccum *row;
/* size of region to clear */
width = 4 * (ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin);
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
/* ptr to first element to clear */
row = ctx->DrawBuffer->Accum
+ 4 * (ctx->DrawBuffer->_Ymin * ctx->DrawBuffer->Width
+ ctx->DrawBuffer->_Xmin);
for (j=0;j<height;j++) {
for (i=0;i<width;i+=4) {
row[i+0] = r;
row[i+1] = g;
row[i+2] = b;
row[i+3] = a;
}
row += 4 * ctx->DrawBuffer->Width;
}
}
else {
/* clear whole buffer */
if (ctx->Accum.ClearColor[0]==0.0 &&
ctx->Accum.ClearColor[1]==0.0 &&
ctx->Accum.ClearColor[2]==0.0 &&
ctx->Accum.ClearColor[3]==0.0) {
/* Black */
_mesa_bzero( ctx->DrawBuffer->Accum,
buffersize * 4 * sizeof(GLaccum) );
}
else {
/* Not black */
const GLaccum r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
const GLaccum g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
const GLaccum b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
const GLaccum a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
GLaccum *acc = ctx->DrawBuffer->Accum;
GLuint i;
for (i=0;i<buffersize;i++) {
*acc++ = r;
*acc++ = g;
*acc++ = b;
*acc++ = a;
}
}
}
 
/* update optimized accum state vars */
if (ctx->Accum.ClearColor[0] == 0.0 && ctx->Accum.ClearColor[1] == 0.0 &&
ctx->Accum.ClearColor[2] == 0.0 && ctx->Accum.ClearColor[3] == 0.0) {
#ifdef USE_OPTIMIZED_ACCUM
swrast->_IntegerAccumMode = GL_TRUE;
#else
swrast->_IntegerAccumMode = GL_FALSE;
#endif
swrast->_IntegerAccumScaler = 0.0; /* denotes empty accum buffer */
}
else {
swrast->_IntegerAccumMode = GL_FALSE;
}
}
}
 
 
void
_swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value,
GLint xpos, GLint ypos,
GLint width, GLint height )
 
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint width4;
GLfloat acc_scale;
GLchan rgba[MAX_WIDTH][4];
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
 
 
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived( ctx );
 
if (!ctx->DrawBuffer->Accum) {
_mesa_warning(ctx,
"Calling glAccum() without an accumulation "
"buffer (low memory?)");
return;
}
 
if (sizeof(GLaccum)==1) {
acc_scale = 127.0;
}
else if (sizeof(GLaccum)==2) {
acc_scale = 32767.0;
}
else {
acc_scale = 1.0F;
}
 
width4 = 4 * width;
 
switch (op) {
case GL_ADD:
if (value != 0.0F) {
const GLaccum val = (GLaccum) (value * acc_scale);
GLint j;
/* Leave optimized accum buffer mode */
if (swrast->_IntegerAccumMode)
rescale_accum(ctx);
for (j = 0; j < height; j++) {
GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + 4*xpos;
GLuint i;
for (i = 0; i < width4; i++) {
acc[i] += val;
}
ypos++;
}
}
break;
 
case GL_MULT:
if (value != 1.0F) {
GLint j;
/* Leave optimized accum buffer mode */
if (swrast->_IntegerAccumMode)
rescale_accum(ctx);
for (j = 0; j < height; j++) {
GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + 4 * xpos;
GLuint i;
for (i = 0; i < width4; i++) {
acc[i] = (GLaccum) ( (GLfloat) acc[i] * value );
}
ypos++;
}
}
break;
 
case GL_ACCUM:
if (value == 0.0F)
return;
 
_swrast_use_read_buffer(ctx);
 
/* May have to leave optimized accum buffer mode */
if (swrast->_IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0)
swrast->_IntegerAccumScaler = value;
if (swrast->_IntegerAccumMode && value != swrast->_IntegerAccumScaler)
rescale_accum(ctx);
 
RENDER_START(swrast,ctx);
 
if (swrast->_IntegerAccumMode) {
/* simply add integer color values into accum buffer */
GLint j;
GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
assert(swrast->_IntegerAccumScaler > 0.0);
assert(swrast->_IntegerAccumScaler <= 1.0);
for (j = 0; j < height; j++) {
 
GLint i, i4;
_mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
for (i = i4 = 0; i < width; i++, i4+=4) {
acc[i4+0] += rgba[i][RCOMP];
acc[i4+1] += rgba[i][GCOMP];
acc[i4+2] += rgba[i][BCOMP];
acc[i4+3] += rgba[i][ACOMP];
}
acc += width4;
ypos++;
}
}
else {
/* scaled integer (or float) accum buffer */
const GLfloat rscale = value * acc_scale / CHAN_MAXF;
const GLfloat gscale = value * acc_scale / CHAN_MAXF;
const GLfloat bscale = value * acc_scale / CHAN_MAXF;
const GLfloat ascale = value * acc_scale / CHAN_MAXF;
GLint j;
for (j=0;j<height;j++) {
GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
GLint i;
_mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
for (i=0;i<width;i++) {
acc[0] += (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale );
acc[1] += (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale );
acc[2] += (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale );
acc[3] += (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale );
acc += 4;
}
ypos++;
}
}
/* restore read buffer = draw buffer (the default) */
_swrast_use_draw_buffer(ctx);
 
RENDER_FINISH(swrast,ctx);
break;
 
case GL_LOAD:
_swrast_use_read_buffer(ctx);
 
/* This is a change to go into optimized accum buffer mode */
if (value > 0.0 && value <= 1.0) {
#ifdef USE_OPTIMIZED_ACCUM
swrast->_IntegerAccumMode = GL_TRUE;
#else
swrast->_IntegerAccumMode = GL_FALSE;
#endif
swrast->_IntegerAccumScaler = value;
}
else {
swrast->_IntegerAccumMode = GL_FALSE;
swrast->_IntegerAccumScaler = 0.0;
}
 
RENDER_START(swrast,ctx);
if (swrast->_IntegerAccumMode) {
/* just copy values into accum buffer */
GLint j;
GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
assert(swrast->_IntegerAccumScaler > 0.0);
assert(swrast->_IntegerAccumScaler <= 1.0);
for (j = 0; j < height; j++) {
GLint i, i4;
_mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
for (i = i4 = 0; i < width; i++, i4 += 4) {
acc[i4+0] = rgba[i][RCOMP];
acc[i4+1] = rgba[i][GCOMP];
acc[i4+2] = rgba[i][BCOMP];
acc[i4+3] = rgba[i][ACOMP];
}
acc += width4;
ypos++;
}
}
else {
/* scaled integer (or float) accum buffer */
const GLfloat rscale = value * acc_scale / CHAN_MAXF;
const GLfloat gscale = value * acc_scale / CHAN_MAXF;
const GLfloat bscale = value * acc_scale / CHAN_MAXF;
const GLfloat ascale = value * acc_scale / CHAN_MAXF;
#if 0
const GLfloat d = 3.0 / acc_scale; /* XXX what's this? */
#endif
GLint i, j;
for (j = 0; j < height; j++) {
GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
_mesa_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
for (i=0;i<width;i++) {
#if 0
*acc++ = (GLaccum) ((GLfloat) rgba[i][RCOMP] * rscale + d);
*acc++ = (GLaccum) ((GLfloat) rgba[i][GCOMP] * gscale + d);
*acc++ = (GLaccum) ((GLfloat) rgba[i][BCOMP] * bscale + d);
*acc++ = (GLaccum) ((GLfloat) rgba[i][ACOMP] * ascale + d);
#else
*acc++ = (GLaccum) ((GLfloat) rgba[i][RCOMP] * rscale);
*acc++ = (GLaccum) ((GLfloat) rgba[i][GCOMP] * gscale);
*acc++ = (GLaccum) ((GLfloat) rgba[i][BCOMP] * bscale);
*acc++ = (GLaccum) ((GLfloat) rgba[i][ACOMP] * ascale);
#endif
}
ypos++;
}
}
 
/* restore read buffer = draw buffer (the default) */
_swrast_use_draw_buffer(ctx);
 
RENDER_FINISH(swrast,ctx);
break;
 
case GL_RETURN:
/* May have to leave optimized accum buffer mode */
if (swrast->_IntegerAccumMode && value != 1.0)
rescale_accum(ctx);
 
RENDER_START(swrast,ctx);
#ifdef USE_OPTIMIZED_ACCUM
if (swrast->_IntegerAccumMode && swrast->_IntegerAccumScaler > 0) {
/* build lookup table to avoid many floating point multiplies */
static GLchan multTable[32768];
static GLfloat prevMult = 0.0;
const GLfloat mult = swrast->_IntegerAccumScaler;
const GLint max = MIN2((GLint) (256 / mult), 32767);
GLint j;
if (mult != prevMult) {
for (j = 0; j < max; j++)
multTable[j] = IROUND((GLfloat) j * mult);
prevMult = mult;
}
 
assert(swrast->_IntegerAccumScaler > 0.0);
assert(swrast->_IntegerAccumScaler <= 1.0);
for (j = 0; j < height; j++) {
const GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos*4;
GLint i, i4;
for (i = i4 = 0; i < width; i++, i4 += 4) {
ASSERT(acc[i4+0] < max);
ASSERT(acc[i4+1] < max);
ASSERT(acc[i4+2] < max);
ASSERT(acc[i4+3] < max);
rgba[i][RCOMP] = multTable[acc[i4+0]];
rgba[i][GCOMP] = multTable[acc[i4+1]];
rgba[i][BCOMP] = multTable[acc[i4+2]];
rgba[i][ACOMP] = multTable[acc[i4+3]];
}
if (colorMask != 0xffffffff) {
_mesa_mask_rgba_array( ctx, width, xpos, ypos, rgba );
}
(*swrast->Driver.WriteRGBASpan)( ctx, width, xpos, ypos,
(const GLchan (*)[4])rgba, NULL );
if (ctx->DrawBuffer->UseSoftwareAlphaBuffers
&& ctx->Color.ColorMask[ACOMP]) {
_mesa_write_alpha_span(ctx, width, xpos, ypos,
(CONST GLchan (*)[4]) rgba, NULL);
}
ypos++;
}
}
else
#endif /* USE_OPTIMIZED_ACCUM */
{
/* scaled integer (or float) accum buffer */
const GLfloat rscale = value / acc_scale * CHAN_MAXF;
const GLfloat gscale = value / acc_scale * CHAN_MAXF;
const GLfloat bscale = value / acc_scale * CHAN_MAXF;
const GLfloat ascale = value / acc_scale * CHAN_MAXF;
GLint i, j;
for (j=0;j<height;j++) {
const GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos*4;
for (i=0;i<width;i++) {
GLint r = IROUND( (GLfloat) (acc[0]) * rscale );
GLint g = IROUND( (GLfloat) (acc[1]) * gscale );
GLint b = IROUND( (GLfloat) (acc[2]) * bscale );
GLint a = IROUND( (GLfloat) (acc[3]) * ascale );
acc += 4;
rgba[i][RCOMP] = CLAMP( r, 0, CHAN_MAX );
rgba[i][GCOMP] = CLAMP( g, 0, CHAN_MAX );
rgba[i][BCOMP] = CLAMP( b, 0, CHAN_MAX );
rgba[i][ACOMP] = CLAMP( a, 0, CHAN_MAX );
}
if (colorMask != 0xffffffff) {
_mesa_mask_rgba_array( ctx, width, xpos, ypos, rgba );
}
(*swrast->Driver.WriteRGBASpan)( ctx, width, xpos, ypos,
(const GLchan (*)[4])rgba, NULL );
if (ctx->DrawBuffer->UseSoftwareAlphaBuffers
&& ctx->Color.ColorMask[ACOMP]) {
_mesa_write_alpha_span(ctx, width, xpos, ypos,
(CONST GLchan (*)[4]) rgba, NULL);
}
ypos++;
}
}
RENDER_FINISH(swrast,ctx);
break;
 
default:
_mesa_error( ctx, GL_INVALID_ENUM, "glAccum" );
}
}
/shark/trunk/ports/mesa/src/swrast/s_blend.h
0,0 → 1,46
/* $Id: s_blend.h,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_BLEND_H
#define S_BLEND_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
 
extern void
_mesa_blend_span( GLcontext *ctx, const struct sw_span *span,
GLchan rgba[][4] );
 
 
extern void
_swrast_choose_blend_func( GLcontext *ctx );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_aaline.c
0,0 → 1,537
/* $Id: s_aaline.c,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "swrast/s_aaline.h"
#include "swrast/s_context.h"
#include "swrast/s_span.h"
#include "swrast/swrast.h"
#include "mtypes.h"
#include "mmath.h"
 
 
#define SUB_PIXEL 4
 
 
/*
* Info about the AA line we're rendering
*/
struct LineInfo
{
GLfloat x0, y0; /* start */
GLfloat x1, y1; /* end */
GLfloat dx, dy; /* direction vector */
GLfloat len; /* length */
GLfloat halfWidth; /* half of line width */
GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */
/* for coverage computation */
GLfloat qx0, qy0; /* quad vertices */
GLfloat qx1, qy1;
GLfloat qx2, qy2;
GLfloat qx3, qy3;
GLfloat ex0, ey0; /* quad edge vectors */
GLfloat ex1, ey1;
GLfloat ex2, ey2;
GLfloat ex3, ey3;
 
/* DO_Z */
GLfloat zPlane[4];
/* DO_FOG */
GLfloat fPlane[4];
/* DO_RGBA */
GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
/* DO_INDEX */
GLfloat iPlane[4];
/* DO_SPEC */
GLfloat srPlane[4], sgPlane[4], sbPlane[4];
/* DO_TEX or DO_MULTITEX */
GLfloat sPlane[MAX_TEXTURE_UNITS][4];
GLfloat tPlane[MAX_TEXTURE_UNITS][4];
GLfloat uPlane[MAX_TEXTURE_UNITS][4];
GLfloat vPlane[MAX_TEXTURE_UNITS][4];
GLfloat lambda[MAX_TEXTURE_UNITS];
GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS];
 
struct sw_span span;
};
 
 
 
/*
* Compute the equation of a plane used to interpolate line fragment data
* such as color, Z, texture coords, etc.
* Input: (x0, y0) and (x1,y1) are the endpoints of the line.
* z0, and z1 are the end point values to interpolate.
* Output: plane - the plane equation.
*
* Note: we don't really have enough parameters to specify a plane.
* We take the endpoints of the line and compute a plane such that
* the cross product of the line vector and the plane normal is
* parallel to the projection plane.
*/
static void
compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
GLfloat z0, GLfloat z1, GLfloat plane[4])
{
#if 0
/* original */
const GLfloat px = x1 - x0;
const GLfloat py = y1 - y0;
const GLfloat pz = z1 - z0;
const GLfloat qx = -py;
const GLfloat qy = px;
const GLfloat qz = 0;
const GLfloat a = py * qz - pz * qy;
const GLfloat b = pz * qx - px * qz;
const GLfloat c = px * qy - py * qx;
const GLfloat d = -(a * x0 + b * y0 + c * z0);
plane[0] = a;
plane[1] = b;
plane[2] = c;
plane[3] = d;
#else
/* simplified */
const GLfloat px = x1 - x0;
const GLfloat py = y1 - y0;
const GLfloat pz = z0 - z1;
const GLfloat a = pz * px;
const GLfloat b = pz * py;
const GLfloat c = px * px + py * py;
const GLfloat d = -(a * x0 + b * y0 + c * z0);
if (a == 0.0 && b == 0.0 && c == 0.0 && d == 0.0) {
plane[0] = 0.0;
plane[1] = 0.0;
plane[2] = 1.0;
plane[3] = 0.0;
}
else {
plane[0] = a;
plane[1] = b;
plane[2] = c;
plane[3] = d;
}
#endif
}
 
 
static INLINE void
constant_plane(GLfloat value, GLfloat plane[4])
{
plane[0] = 0.0;
plane[1] = 0.0;
plane[2] = -1.0;
plane[3] = value;
}
 
 
static INLINE GLfloat
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
{
const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
return z;
}
 
#define SOLVE_PLANE(X, Y, PLANE) \
((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
 
 
/*
* Return 1 / solve_plane().
*/
static INLINE GLfloat
solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
{
const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y;
if (denom == 0.0)
return 0.0;
else
return -plane[2] / denom;
}
 
 
/*
* Solve plane and return clamped GLchan value.
*/
static INLINE GLchan
solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
{
GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2] + 0.5F;
if (z < 0.0F)
return 0;
else if (z > CHAN_MAXF)
return (GLchan) CHAN_MAXF;
return (GLchan) (GLint) z;
}
 
 
/*
* Compute mipmap level of detail.
*/
static INLINE GLfloat
compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
GLfloat invQ, GLfloat width, GLfloat height)
{
GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width;
GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width;
GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height;
GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height;
GLfloat r1 = dudx * dudx + dudy * dudy;
GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
GLfloat rho2 = r1 + r2;
/* return log base 2 of rho */
if (rho2 == 0.0F)
return 0.0;
else
return (GLfloat) (log(rho2) * 1.442695 * 0.5);/* 1.442695 = 1/log(2) */
}
 
 
 
 
/*
* Fill in the samples[] array with the (x,y) subpixel positions of
* xSamples * ySamples sample positions.
* Note that the four corner samples are put into the first four
* positions of the array. This allows us to optimize for the common
* case of all samples being inside the polygon.
*/
static void
make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2])
{
const GLfloat dx = 1.0F / (GLfloat) xSamples;
const GLfloat dy = 1.0F / (GLfloat) ySamples;
GLint x, y;
GLint i;
 
i = 4;
for (x = 0; x < xSamples; x++) {
for (y = 0; y < ySamples; y++) {
GLint j;
if (x == 0 && y == 0) {
/* lower left */
j = 0;
}
else if (x == xSamples - 1 && y == 0) {
/* lower right */
j = 1;
}
else if (x == 0 && y == ySamples - 1) {
/* upper left */
j = 2;
}
else if (x == xSamples - 1 && y == ySamples - 1) {
/* upper right */
j = 3;
}
else {
j = i++;
}
samples[j][0] = x * dx + 0.5F * dx;
samples[j][1] = y * dy + 0.5F * dy;
}
}
}
 
 
 
/*
* Compute how much of the given pixel's area is inside the rectangle
* defined by vertices v0, v1, v2, v3.
* Vertices MUST be specified in counter-clockwise order.
* Return: coverage in [0, 1].
*/
static GLfloat
compute_coveragef(const struct LineInfo *info,
GLint winx, GLint winy)
{
static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2];
static GLboolean haveSamples = GL_FALSE;
const GLfloat x = (GLfloat) winx;
const GLfloat y = (GLfloat) winy;
GLint stop = 4, i;
GLfloat insideCount = SUB_PIXEL * SUB_PIXEL;
 
if (!haveSamples) {
make_sample_table(SUB_PIXEL, SUB_PIXEL, samples);
haveSamples = GL_TRUE;
}
 
#if 0 /*DEBUG*/
{
const GLfloat area = dx0 * dy1 - dx1 * dy0;
assert(area >= 0.0);
}
#endif
 
for (i = 0; i < stop; i++) {
const GLfloat sx = x + samples[i][0];
const GLfloat sy = y + samples[i][1];
const GLfloat fx0 = sx - info->qx0;
const GLfloat fy0 = sy - info->qy0;
const GLfloat fx1 = sx - info->qx1;
const GLfloat fy1 = sy - info->qy1;
const GLfloat fx2 = sx - info->qx2;
const GLfloat fy2 = sy - info->qy2;
const GLfloat fx3 = sx - info->qx3;
const GLfloat fy3 = sy - info->qy3;
/* cross product determines if sample is inside or outside each edge */
GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0);
GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1);
GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2);
GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3);
/* Check if the sample is exactly on an edge. If so, let cross be a
* positive or negative value depending on the direction of the edge.
*/
if (cross0 == 0.0F)
cross0 = info->ex0 + info->ey0;
if (cross1 == 0.0F)
cross1 = info->ex1 + info->ey1;
if (cross2 == 0.0F)
cross2 = info->ex2 + info->ey2;
if (cross3 == 0.0F)
cross3 = info->ex3 + info->ey3;
if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) {
/* point is outside quadrilateral */
insideCount -= 1.0F;
stop = SUB_PIXEL * SUB_PIXEL;
}
}
if (stop == 4)
return 1.0F;
else
return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL));
}
 
 
 
typedef void (*plot_func)(GLcontext *ctx, struct LineInfo *line,
int ix, int iy);
 
 
/*
* Draw an AA line segment (called many times per line when stippling)
*/
static void
segment(GLcontext *ctx,
struct LineInfo *line,
plot_func plot,
GLfloat t0, GLfloat t1)
{
const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx;
const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy;
/* compute the actual segment's endpoints */
const GLfloat x0 = line->x0 + t0 * line->dx;
const GLfloat y0 = line->y0 + t0 * line->dy;
const GLfloat x1 = line->x0 + t1 * line->dx;
const GLfloat y1 = line->y0 + t1 * line->dy;
 
/* compute vertices of the line-aligned quadrilateral */
line->qx0 = x0 - line->yAdj;
line->qy0 = y0 + line->xAdj;
line->qx1 = x0 + line->yAdj;
line->qy1 = y0 - line->xAdj;
line->qx2 = x1 + line->yAdj;
line->qy2 = y1 - line->xAdj;
line->qx3 = x1 - line->yAdj;
line->qy3 = y1 + line->xAdj;
/* compute the quad's edge vectors (for coverage calc) */
line->ex0 = line->qx1 - line->qx0;
line->ey0 = line->qy1 - line->qy0;
line->ex1 = line->qx2 - line->qx1;
line->ey1 = line->qy2 - line->qy1;
line->ex2 = line->qx3 - line->qx2;
line->ey2 = line->qy3 - line->qy2;
line->ex3 = line->qx0 - line->qx3;
line->ey3 = line->qy0 - line->qy3;
 
if (absDx > absDy) {
/* X-major line */
GLfloat dydx = line->dy / line->dx;
GLfloat xLeft, xRight, yBot, yTop;
GLint ix, ixRight;
if (x0 < x1) {
xLeft = x0 - line->halfWidth;
xRight = x1 + line->halfWidth;
if (line->dy >= 0.0) {
yBot = y0 - 3.0F * line->halfWidth;
yTop = y0 + line->halfWidth;
}
else {
yBot = y0 - line->halfWidth;
yTop = y0 + 3.0F * line->halfWidth;
}
}
else {
xLeft = x1 - line->halfWidth;
xRight = x0 + line->halfWidth;
if (line->dy <= 0.0) {
yBot = y1 - 3.0F * line->halfWidth;
yTop = y1 + line->halfWidth;
}
else {
yBot = y1 - line->halfWidth;
yTop = y1 + 3.0F * line->halfWidth;
}
}
 
/* scan along the line, left-to-right */
ixRight = (GLint) (xRight + 1.0F);
 
/*printf("avg span height: %g\n", yTop - yBot);*/
for (ix = (GLint) xLeft; ix < ixRight; ix++) {
const GLint iyBot = (GLint) yBot;
const GLint iyTop = (GLint) (yTop + 1.0F);
GLint iy;
/* scan across the line, bottom-to-top */
for (iy = iyBot; iy < iyTop; iy++) {
(*plot)(ctx, line, ix, iy);
}
yBot += dydx;
yTop += dydx;
}
}
else {
/* Y-major line */
GLfloat dxdy = line->dx / line->dy;
GLfloat yBot, yTop, xLeft, xRight;
GLint iy, iyTop;
if (y0 < y1) {
yBot = y0 - line->halfWidth;
yTop = y1 + line->halfWidth;
if (line->dx >= 0.0) {
xLeft = x0 - 3.0F * line->halfWidth;
xRight = x0 + line->halfWidth;
}
else {
xLeft = x0 - line->halfWidth;
xRight = x0 + 3.0F * line->halfWidth;
}
}
else {
yBot = y1 - line->halfWidth;
yTop = y0 + line->halfWidth;
if (line->dx <= 0.0) {
xLeft = x1 - 3.0F * line->halfWidth;
xRight = x1 + line->halfWidth;
}
else {
xLeft = x1 - line->halfWidth;
xRight = x1 + 3.0F * line->halfWidth;
}
}
 
/* scan along the line, bottom-to-top */
iyTop = (GLint) (yTop + 1.0F);
 
/*printf("avg span width: %g\n", xRight - xLeft);*/
for (iy = (GLint) yBot; iy < iyTop; iy++) {
const GLint ixLeft = (GLint) xLeft;
const GLint ixRight = (GLint) (xRight + 1.0F);
GLint ix;
/* scan across the line, left-to-right */
for (ix = ixLeft; ix < ixRight; ix++) {
(*plot)(ctx, line, ix, iy);
}
xLeft += dxdy;
xRight += dxdy;
}
}
}
 
 
#define NAME(x) aa_ci_##x
#define DO_Z
#define DO_FOG
#define DO_INDEX
#include "s_aalinetemp.h"
 
 
#define NAME(x) aa_rgba_##x
#define DO_Z
#define DO_FOG
#define DO_RGBA
#include "s_aalinetemp.h"
 
 
#define NAME(x) aa_tex_rgba_##x
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_TEX
#include "s_aalinetemp.h"
 
 
#define NAME(x) aa_multitex_rgba_##x
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_MULTITEX
#include "s_aalinetemp.h"
 
 
#define NAME(x) aa_multitex_spec_##x
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_MULTITEX
#define DO_SPEC
#include "s_aalinetemp.h"
 
 
 
void
_swrast_choose_aa_line_function(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
ASSERT(ctx->Line.SmoothFlag);
 
if (ctx->Visual.rgbMode) {
/* RGBA */
if (ctx->Texture._EnabledUnits != 0) {
if (ctx->Texture._EnabledUnits > 1) {
/* Multitextured! */
if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR ||
ctx->Fog.ColorSumEnabled)
swrast->Line = aa_multitex_spec_line;
else
swrast->Line = aa_multitex_rgba_line;
}
else {
swrast->Line = aa_tex_rgba_line;
}
}
else {
swrast->Line = aa_rgba_line;
}
}
else {
/* Color Index */
swrast->Line = aa_ci_line;
}
}
/shark/trunk/ports/mesa/src/swrast/s_alpha.h
0,0 → 1,40
/* $Id: s_alpha.h,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_ALPHA_H
#define S_ALPHA_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern GLint
_mesa_alpha_test( const GLcontext *ctx, struct sw_span *span );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_aatritemp.h
0,0 → 1,554
/* $Id: s_aatritemp.h,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* Antialiased Triangle Rasterizer Template
*
* This file is #include'd to generate custom AA triangle rasterizers.
* NOTE: this code hasn't been optimized yet. That'll come after it
* works correctly.
*
* The following macros may be defined to indicate what auxillary information
* must be copmuted across the triangle:
* DO_Z - if defined, compute Z values
* DO_RGBA - if defined, compute RGBA values
* DO_INDEX - if defined, compute color index values
* DO_SPEC - if defined, compute specular RGB values
* DO_TEX - if defined, compute unit 0 STRQ texcoords
* DO_MULTITEX - if defined, compute all unit's STRQ texcoords
*/
 
/*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
{
const GLfloat *p0 = v0->win;
const GLfloat *p1 = v1->win;
const GLfloat *p2 = v2->win;
const SWvertex *vMin, *vMid, *vMax;
GLint iyMin, iyMax;
GLfloat yMin, yMax;
GLboolean ltor;
GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */
struct sw_span span;
#ifdef DO_Z
GLfloat zPlane[4];
#endif
#ifdef DO_FOG
GLfloat fogPlane[4];
#else
GLfloat *fog = NULL;
#endif
#ifdef DO_RGBA
GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
#endif
#ifdef DO_INDEX
GLfloat iPlane[4];
#endif
#ifdef DO_SPEC
GLfloat srPlane[4], sgPlane[4], sbPlane[4];
#endif
#ifdef DO_TEX
GLfloat sPlane[4], tPlane[4], uPlane[4], vPlane[4];
GLfloat texWidth, texHeight;
#elif defined(DO_MULTITEX)
GLfloat sPlane[MAX_TEXTURE_UNITS][4]; /* texture S */
GLfloat tPlane[MAX_TEXTURE_UNITS][4]; /* texture T */
GLfloat uPlane[MAX_TEXTURE_UNITS][4]; /* texture R */
GLfloat vPlane[MAX_TEXTURE_UNITS][4]; /* texture Q */
GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS];
#endif
GLfloat bf = SWRAST_CONTEXT(ctx)->_backface_sign;
INIT_SPAN(span, GL_POLYGON, 0, 0, SPAN_COVERAGE);
 
/* determine bottom to top order of vertices */
{
GLfloat y0 = v0->win[1];
GLfloat y1 = v1->win[1];
GLfloat y2 = v2->win[1];
if (y0 <= y1) {
if (y1 <= y2) {
vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */
}
else if (y2 <= y0) {
vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */
}
else {
vMin = v0; vMid = v2; vMax = v1; bf = -bf; /* y0<=y2<=y1 */
}
}
else {
if (y0 <= y2) {
vMin = v1; vMid = v0; vMax = v2; bf = -bf; /* y1<=y0<=y2 */
}
else if (y2 <= y1) {
vMin = v2; vMid = v1; vMax = v0; bf = -bf; /* y2<=y1<=y0 */
}
else {
vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */
}
}
}
 
majDx = vMax->win[0] - vMin->win[0];
majDy = vMax->win[1] - vMin->win[1];
 
{
const GLfloat botDx = vMid->win[0] - vMin->win[0];
const GLfloat botDy = vMid->win[1] - vMin->win[1];
const GLfloat area = majDx * botDy - botDx * majDy;
ltor = (GLboolean) (area < 0.0F);
/* Do backface culling */
if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area))
return;
}
 
#ifndef DO_OCCLUSION_TEST
ctx->OcclusionResult = GL_TRUE;
#endif
 
/* Plane equation setup:
* We evaluate plane equations at window (x,y) coordinates in order
* to compute color, Z, fog, texcoords, etc. This isn't terribly
* efficient but it's easy and reliable.
*/
#ifdef DO_Z
compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
span.arrayMask |= SPAN_Z;
#endif
#ifdef DO_FOG
compute_plane(p0, p1, p2, v0->fog, v1->fog, v2->fog, fogPlane);
span.arrayMask |= SPAN_FOG;
#endif
#ifdef DO_RGBA
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(p0, p1, p2, v0->color[0], v1->color[0], v2->color[0], rPlane);
compute_plane(p0, p1, p2, v0->color[1], v1->color[1], v2->color[1], gPlane);
compute_plane(p0, p1, p2, v0->color[2], v1->color[2], v2->color[2], bPlane);
compute_plane(p0, p1, p2, v0->color[3], v1->color[3], v2->color[3], aPlane);
}
else {
constant_plane(v2->color[RCOMP], rPlane);
constant_plane(v2->color[GCOMP], gPlane);
constant_plane(v2->color[BCOMP], bPlane);
constant_plane(v2->color[ACOMP], aPlane);
}
span.arrayMask |= SPAN_RGBA;
#endif
#ifdef DO_INDEX
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(p0, p1, p2, (GLfloat) v0->index,
(GLfloat) v1->index, (GLfloat) v2->index, iPlane);
}
else {
constant_plane((GLfloat) v2->index, iPlane);
}
span.arrayMask |= SPAN_INDEX;
#endif
#ifdef DO_SPEC
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(p0, p1, p2, v0->specular[0], v1->specular[0], v2->specular[0],srPlane);
compute_plane(p0, p1, p2, v0->specular[1], v1->specular[1], v2->specular[1],sgPlane);
compute_plane(p0, p1, p2, v0->specular[2], v1->specular[2], v2->specular[2],sbPlane);
}
else {
constant_plane(v2->specular[RCOMP], srPlane);
constant_plane(v2->specular[GCOMP], sgPlane);
constant_plane(v2->specular[BCOMP], sbPlane);
}
span.arrayMask |= SPAN_SPEC;
#endif
#ifdef DO_TEX
{
const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
const GLfloat invW0 = v0->win[3];
const GLfloat invW1 = v1->win[3];
const GLfloat invW2 = v2->win[3];
const GLfloat s0 = v0->texcoord[0][0] * invW0;
const GLfloat s1 = v1->texcoord[0][0] * invW1;
const GLfloat s2 = v2->texcoord[0][0] * invW2;
const GLfloat t0 = v0->texcoord[0][1] * invW0;
const GLfloat t1 = v1->texcoord[0][1] * invW1;
const GLfloat t2 = v2->texcoord[0][1] * invW2;
const GLfloat r0 = v0->texcoord[0][2] * invW0;
const GLfloat r1 = v1->texcoord[0][2] * invW1;
const GLfloat r2 = v2->texcoord[0][2] * invW2;
const GLfloat q0 = v0->texcoord[0][3] * invW0;
const GLfloat q1 = v1->texcoord[0][3] * invW1;
const GLfloat q2 = v2->texcoord[0][3] * invW2;
compute_plane(p0, p1, p2, s0, s1, s2, sPlane);
compute_plane(p0, p1, p2, t0, t1, t2, tPlane);
compute_plane(p0, p1, p2, r0, r1, r2, uPlane);
compute_plane(p0, p1, p2, q0, q1, q2, vPlane);
texWidth = (GLfloat) texImage->Width;
texHeight = (GLfloat) texImage->Height;
}
span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
#elif defined(DO_MULTITEX)
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
const GLfloat invW0 = v0->win[3];
const GLfloat invW1 = v1->win[3];
const GLfloat invW2 = v2->win[3];
const GLfloat s0 = v0->texcoord[u][0] * invW0;
const GLfloat s1 = v1->texcoord[u][0] * invW1;
const GLfloat s2 = v2->texcoord[u][0] * invW2;
const GLfloat t0 = v0->texcoord[u][1] * invW0;
const GLfloat t1 = v1->texcoord[u][1] * invW1;
const GLfloat t2 = v2->texcoord[u][1] * invW2;
const GLfloat r0 = v0->texcoord[u][2] * invW0;
const GLfloat r1 = v1->texcoord[u][2] * invW1;
const GLfloat r2 = v2->texcoord[u][2] * invW2;
const GLfloat q0 = v0->texcoord[u][3] * invW0;
const GLfloat q1 = v1->texcoord[u][3] * invW1;
const GLfloat q2 = v2->texcoord[u][3] * invW2;
compute_plane(p0, p1, p2, s0, s1, s2, sPlane[u]);
compute_plane(p0, p1, p2, t0, t1, t2, tPlane[u]);
compute_plane(p0, p1, p2, r0, r1, r2, uPlane[u]);
compute_plane(p0, p1, p2, q0, q1, q2, vPlane[u]);
texWidth[u] = (GLfloat) texImage->Width;
texHeight[u] = (GLfloat) texImage->Height;
}
}
}
span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
#endif
 
/* Begin bottom-to-top scan over the triangle.
* The long edge will either be on the left or right side of the
* triangle. We always scan from the long edge toward the shorter
* edges, stopping when we find that coverage = 0. If the long edge
* is on the left we scan left-to-right. Else, we scan right-to-left.
*/
yMin = vMin->win[1];
yMax = vMax->win[1];
iyMin = (GLint) yMin;
iyMax = (GLint) yMax + 1;
 
if (ltor) {
/* scan left to right */
const GLfloat *pMin = vMin->win;
const GLfloat *pMid = vMid->win;
const GLfloat *pMax = vMax->win;
const GLfloat dxdy = majDx / majDy;
const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
GLint iy;
for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
GLint ix, startX = (GLint) (x - xAdj);
GLuint count;
GLfloat coverage = 0.0F;
 
/* skip over fragments with zero coverage */
while (startX < MAX_WIDTH) {
coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
if (coverage > 0.0F)
break;
startX++;
}
 
/* enter interior of triangle */
ix = startX;
count = 0;
while (coverage > 0.0F) {
/* (cx,cy) = center of fragment */
const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
struct span_arrays *array = span.array;
#ifdef DO_INDEX
array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy);
#else
array->coverage[count] = coverage;
#endif
#ifdef DO_Z
array->z[count] = (GLdepth) solve_plane(cx, cy, zPlane);
#endif
#ifdef DO_FOG
array->fog[count] = solve_plane(cx, cy, fogPlane);
#endif
#ifdef DO_RGBA
array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
#endif
#ifdef DO_INDEX
array->index[count] = (GLint) solve_plane(cx, cy, iPlane);
#endif
#ifdef DO_SPEC
array->spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane);
array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
#endif
#ifdef DO_TEX
{
const GLfloat invQ = solve_plane_recip(cx, cy, vPlane);
array->texcoords[0][count][0] = solve_plane(cx, cy, sPlane) * invQ;
array->texcoords[0][count][1] = solve_plane(cx, cy, tPlane) * invQ;
array->texcoords[0][count][2] = solve_plane(cx, cy, uPlane) * invQ;
array->lambda[0][count] = compute_lambda(sPlane, tPlane, vPlane,
cx, cy, invQ,
texWidth, texHeight);
}
#elif defined(DO_MULTITEX)
{
GLuint unit;
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]);
array->texcoords[unit][count][0] = solve_plane(cx, cy, sPlane[unit]) * invQ;
array->texcoords[unit][count][1] = solve_plane(cx, cy, tPlane[unit]) * invQ;
array->texcoords[unit][count][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
array->lambda[unit][count] = compute_lambda(sPlane[unit],
tPlane[unit], vPlane[unit], cx, cy, invQ,
texWidth[unit], texHeight[unit]);
}
}
}
#endif
ix++;
count++;
coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
}
if (ix <= startX)
continue;
span.x = startX;
span.y = iy;
span.end = (GLuint) ix - (GLuint) startX;
ASSERT(span.interpMask == 0);
#if defined(DO_MULTITEX) || defined(DO_TEX)
_mesa_write_texture_span(ctx, &span);
#elif defined(DO_RGBA)
_mesa_write_rgba_span(ctx, &span);
#elif defined(DO_INDEX)
_mesa_write_index_span(ctx, &span);
#endif
}
}
else {
/* scan right to left */
const GLfloat *pMin = vMin->win;
const GLfloat *pMid = vMid->win;
const GLfloat *pMax = vMax->win;
const GLfloat dxdy = majDx / majDy;
const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
GLint iy;
for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
GLint ix, left, startX = (GLint) (x + xAdj);
GLuint count, n;
GLfloat coverage = 0.0F;
/* make sure we're not past the window edge */
if (startX >= ctx->DrawBuffer->_Xmax) {
startX = ctx->DrawBuffer->_Xmax - 1;
}
 
/* skip fragments with zero coverage */
while (startX >= 0) {
coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
if (coverage > 0.0F)
break;
startX--;
}
/* enter interior of triangle */
ix = startX;
count = 0;
while (coverage > 0.0F) {
/* (cx,cy) = center of fragment */
const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
struct span_arrays *array = span.array;
#ifdef DO_INDEX
array->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy);
#else
array->coverage[ix] = coverage;
#endif
#ifdef DO_Z
array->z[ix] = (GLdepth) solve_plane(cx, cy, zPlane);
#endif
#ifdef DO_FOG
array->fog[ix] = solve_plane(cx, cy, fogPlane);
#endif
#ifdef DO_RGBA
array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
#endif
#ifdef DO_INDEX
array->index[ix] = (GLint) solve_plane(cx, cy, iPlane);
#endif
#ifdef DO_SPEC
array->spec[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane);
array->spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
array->spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
#endif
#ifdef DO_TEX
{
const GLfloat invQ = solve_plane_recip(cx, cy, vPlane);
array->texcoords[0][ix][0] = solve_plane(cx, cy, sPlane) * invQ;
array->texcoords[0][ix][1] = solve_plane(cx, cy, tPlane) * invQ;
array->texcoords[0][ix][2] = solve_plane(cx, cy, uPlane) * invQ;
array->lambda[0][ix] = compute_lambda(sPlane, tPlane, vPlane,
cx, cy, invQ, texWidth, texHeight);
}
#elif defined(DO_MULTITEX)
{
GLuint unit;
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]);
array->texcoords[unit][ix][0] = solve_plane(cx, cy, sPlane[unit]) * invQ;
array->texcoords[unit][ix][1] = solve_plane(cx, cy, tPlane[unit]) * invQ;
array->texcoords[unit][ix][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
array->lambda[unit][ix] = compute_lambda(sPlane[unit],
tPlane[unit],
vPlane[unit],
cx, cy, invQ,
texWidth[unit],
texHeight[unit]);
}
}
}
#endif
ix--;
count++;
coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
}
if (startX <= ix)
continue;
 
n = (GLuint) startX - (GLuint) ix;
 
left = ix + 1;
 
/* shift all values to the left */
/* XXX this is temporary */
{
struct span_arrays *array = span.array;
GLint j;
for (j = 0; j < (GLint) n; j++) {
#ifdef DO_RGBA
COPY_4V(array->rgba[j], array->rgba[j + left]);
#endif
#ifdef DO_SPEC
COPY_4V(array->spec[j], array->spec[j + left]);
#endif
#ifdef DO_INDEX
array->index[j] = array->index[j + left];
#endif
#ifdef DO_Z
array->z[j] = array->z[j + left];
#endif
#ifdef DO_FOG
array->fog[j] = array->fog[j + left];
#endif
#ifdef DO_TEX
COPY_4V(array->texcoords[0][j], array->texcoords[0][j + left]);
#endif
#if defined(DO_MULTITEX) || defined(DO_TEX)
array->lambda[0][j] = array->lambda[0][j + left];
#endif
array->coverage[j] = array->coverage[j + left];
}
}
#ifdef DO_MULTITEX
/* shift texcoords */
{
struct span_arrays *array = span.array;
GLuint unit;
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
GLint j;
for (j = 0; j < (GLint) n; j++) {
array->texcoords[unit][j][0] = array->texcoords[unit][j + left][0];
array->texcoords[unit][j][1] = array->texcoords[unit][j + left][1];
array->texcoords[unit][j][2] = array->texcoords[unit][j + left][2];
array->lambda[unit][j] = array->lambda[unit][j + left];
}
}
}
}
#endif
 
span.x = left;
span.y = iy;
span.end = n;
ASSERT(span.interpMask == 0);
#if defined(DO_MULTITEX) || defined(DO_TEX)
_mesa_write_texture_span(ctx, &span);
#elif defined(DO_RGBA)
_mesa_write_rgba_span(ctx, &span);
#elif defined(DO_INDEX)
_mesa_write_index_span(ctx, &span);
#endif
}
}
}
 
 
#ifdef DO_Z
#undef DO_Z
#endif
 
#ifdef DO_FOG
#undef DO_FOG
#endif
 
#ifdef DO_RGBA
#undef DO_RGBA
#endif
 
#ifdef DO_INDEX
#undef DO_INDEX
#endif
 
#ifdef DO_SPEC
#undef DO_SPEC
#endif
 
#ifdef DO_TEX
#undef DO_TEX
#endif
 
#ifdef DO_MULTITEX
#undef DO_MULTITEX
#endif
 
#ifdef DO_OCCLUSION_TEST
#undef DO_OCCLUSION_TEST
#endif
/shark/trunk/ports/mesa/src/swrast/s_buffers.c
0,0 → 1,305
/* $Id: s_buffers.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "macros.h"
#include "imports.h"
 
#include "s_accum.h"
#include "s_alphabuf.h"
#include "s_context.h"
#include "s_depth.h"
#include "s_masking.h"
#include "s_stencil.h"
 
 
 
 
/*
* Clear the color buffer when glColorMask or glIndexMask is in effect.
*/
static void
clear_color_buffer_with_masking( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLint x = ctx->DrawBuffer->_Xmin;
const GLint y = ctx->DrawBuffer->_Ymin;
const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
 
if (ctx->Visual.rgbMode) {
/* RGBA mode */
GLchan clearColor[4];
GLint i;
CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
for (i = 0; i < height; i++) {
GLchan rgba[MAX_WIDTH][4];
GLint j;
for (j = 0; j < width; j++) {
COPY_CHAN4(rgba[j], clearColor);
}
_mesa_mask_rgba_array( ctx, width, x, y + i, rgba );
(*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i,
(CONST GLchan (*)[4]) rgba, NULL );
}
}
else {
/* Color index mode */
GLuint span[MAX_WIDTH];
GLubyte mask[MAX_WIDTH];
GLint i, j;
MEMSET( mask, 1, width );
for (i=0;i<height;i++) {
for (j=0;j<width;j++) {
span[j] = ctx->Color.ClearIndex;
}
_mesa_mask_index_array( ctx, width, x, y + i, span );
(*swrast->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask );
}
}
}
 
 
 
/*
* Clear a color buffer without index/channel masking.
*/
static void
clear_color_buffer(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLint x = ctx->DrawBuffer->_Xmin;
const GLint y = ctx->DrawBuffer->_Ymin;
const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
 
if (ctx->Visual.rgbMode) {
/* RGBA mode */
GLchan clearColor[4];
GLchan span[MAX_WIDTH][4];
GLint i;
 
CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]);
CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]);
CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]);
CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]);
 
ASSERT(*((GLuint *) &ctx->Color.ColorMask) == 0xffffffff);
 
for (i = 0; i < width; i++) {
COPY_CHAN4(span[i], clearColor);
}
for (i = 0; i < height; i++) {
(*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i,
(CONST GLchan (*)[4]) span, NULL );
}
}
else {
/* Color index mode */
ASSERT((ctx->Color.IndexMask & ((1 << ctx->Visual.indexBits) - 1))
== (GLuint) ((1 << ctx->Visual.indexBits) - 1));
if (ctx->Visual.indexBits == 8) {
/* 8-bit clear */
GLubyte span[MAX_WIDTH];
GLint i;
MEMSET(span, ctx->Color.ClearIndex, width);
for (i = 0; i < height; i++) {
(*swrast->Driver.WriteCI8Span)( ctx, width, x, y + i, span, NULL );
}
}
else {
/* non 8-bit clear */
GLuint span[MAX_WIDTH];
GLint i;
for (i = 0; i < width; i++) {
span[i] = ctx->Color.ClearIndex;
}
for (i = 0; i < height; i++) {
(*swrast->Driver.WriteCI32Span)( ctx, width, x, y + i, span, NULL );
}
}
}
}
 
 
 
/*
* Clear the front/back/left/right color buffers.
* This function is usually only called if we need to clear the
* buffers with masking.
*/
static void
clear_color_buffers(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
GLuint bufferBit;
 
/* loop over four possible dest color buffers */
for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
if (bufferBit & ctx->Color._DrawDestMask) {
(*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
 
if (colorMask != 0xffffffff) {
clear_color_buffer_with_masking(ctx);
}
else {
clear_color_buffer(ctx);
}
}
}
 
/* restore default read/draw buffer */
_swrast_use_draw_buffer(ctx);
}
 
 
 
void
_swrast_Clear( GLcontext *ctx, GLbitfield mask,
GLboolean all,
GLint x, GLint y, GLint width, GLint height )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
#ifdef DEBUG
{
GLbitfield legalBits = DD_FRONT_LEFT_BIT |
DD_FRONT_RIGHT_BIT |
DD_BACK_LEFT_BIT |
DD_BACK_RIGHT_BIT |
DD_DEPTH_BIT |
DD_STENCIL_BIT |
DD_ACCUM_BIT;
assert((mask & (~legalBits)) == 0);
}
#endif
 
RENDER_START(swrast,ctx);
 
/* do software clearing here */
if (mask) {
if (mask & ctx->Color._DrawDestMask) clear_color_buffers(ctx);
if (mask & GL_DEPTH_BUFFER_BIT) _mesa_clear_depth_buffer(ctx);
if (mask & GL_ACCUM_BUFFER_BIT) _mesa_clear_accum_buffer(ctx);
if (mask & GL_STENCIL_BUFFER_BIT) _mesa_clear_stencil_buffer(ctx);
}
 
/* clear software-based alpha buffer(s) */
if ( (mask & GL_COLOR_BUFFER_BIT)
&& ctx->DrawBuffer->UseSoftwareAlphaBuffers
&& ctx->Color.ColorMask[ACOMP]) {
_mesa_clear_alpha_buffers( ctx );
}
 
RENDER_FINISH(swrast,ctx);
}
 
 
void
_swrast_alloc_buffers( GLframebuffer *buffer )
{
/* Reallocate other buffers if needed. */
if (buffer->UseSoftwareDepthBuffer) {
_mesa_alloc_depth_buffer( buffer );
}
if (buffer->UseSoftwareStencilBuffer) {
_mesa_alloc_stencil_buffer( buffer );
}
if (buffer->UseSoftwareAccumBuffer) {
_mesa_alloc_accum_buffer( buffer );
}
if (buffer->UseSoftwareAlphaBuffers) {
_mesa_alloc_alpha_buffers( buffer );
}
}
 
 
/*
* Fallback for ctx->Driver.DrawBuffer()
*/
void
_swrast_DrawBuffer( GLcontext *ctx, GLenum mode )
{
_swrast_use_draw_buffer(ctx);
}
 
 
/*
* Setup things so that we read/write spans from the user-designated
* read buffer (set via glReadPixels). We usually just have to call
* this for glReadPixels, glCopyPixels, etc.
*/
void
_swrast_use_read_buffer( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
/* Do this so the software-emulated alpha plane span functions work! */
swrast->CurrentBuffer = ctx->Pixel._ReadSrcMask;
/* Tell the device driver where to read/write spans */
(*swrast->Driver.SetBuffer)( ctx, ctx->ReadBuffer, swrast->CurrentBuffer );
}
 
 
/*
* Setup things so that we read/write spans from the default draw buffer.
* This is the usual mode that Mesa's software rasterizer operates in.
*/
void
_swrast_use_draw_buffer( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
/* The user can specify rendering to zero, one, two, or four color
* buffers simultaneously with glDrawBuffer()!
* We don't expect the span/point/line/triangle functions to deal with
* that mess so we'll iterate over the multiple buffers as needed.
* But usually we only render to one color buffer at a time.
* We set ctx->Color._DriverDrawBuffer to that buffer and tell the
* device driver to use that buffer.
* Look in s_span.c's multi_write_rgba_span() function to see how
* we loop over multiple color buffers when needed.
*/
 
if (ctx->Color._DrawDestMask & FRONT_LEFT_BIT)
swrast->CurrentBuffer = FRONT_LEFT_BIT;
else if (ctx->Color._DrawDestMask & BACK_LEFT_BIT)
swrast->CurrentBuffer = BACK_LEFT_BIT;
else if (ctx->Color._DrawDestMask & FRONT_RIGHT_BIT)
swrast->CurrentBuffer = FRONT_RIGHT_BIT;
else if (ctx->Color._DrawDestMask & BACK_RIGHT_BIT)
swrast->CurrentBuffer = BACK_RIGHT_BIT;
else
/* glDrawBuffer(GL_NONE) */
swrast->CurrentBuffer = FRONT_LEFT_BIT; /* we always have this buffer */
 
(*swrast->Driver.SetBuffer)( ctx, ctx->DrawBuffer, swrast->CurrentBuffer );
}
/shark/trunk/ports/mesa/src/swrast/s_logic.c
0,0 → 1,498
/* $Id: s_logic.c,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "context.h"
#include "imports.h"
#include "macros.h"
 
#include "s_alphabuf.h"
#include "s_context.h"
#include "s_logic.h"
#include "s_span.h"
 
 
 
/*
* Apply logic op to array of CI pixels.
*/
static void
index_logicop( GLcontext *ctx, GLuint n, GLuint index[], const GLuint dest[],
const GLubyte mask[] )
{
GLuint i;
switch (ctx->Color.LogicOp) {
case GL_CLEAR:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = 0;
}
}
break;
case GL_SET:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~0;
}
}
break;
case GL_COPY:
/* do nothing */
break;
case GL_COPY_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~index[i];
}
}
break;
case GL_NOOP:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = dest[i];
}
}
break;
case GL_INVERT:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~dest[i];
}
}
break;
case GL_AND:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] &= dest[i];
}
}
break;
case GL_NAND:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~(index[i] & dest[i]);
}
}
break;
case GL_OR:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] |= dest[i];
}
}
break;
case GL_NOR:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~(index[i] | dest[i]);
}
}
break;
case GL_XOR:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] ^= dest[i];
}
}
break;
case GL_EQUIV:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~(index[i] ^ dest[i]);
}
}
break;
case GL_AND_REVERSE:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = index[i] & ~dest[i];
}
}
break;
case GL_AND_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~index[i] & dest[i];
}
}
break;
case GL_OR_REVERSE:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = index[i] | ~dest[i];
}
}
break;
case GL_OR_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
index[i] = ~index[i] | dest[i];
}
}
break;
default:
_mesa_problem(ctx, "bad mode in index_logic()");
}
}
 
 
 
/*
* Apply the current logic operator to a span of CI pixels. This is only
* used if the device driver can't do logic ops.
*/
void
_mesa_logicop_ci_span( GLcontext *ctx, const struct sw_span *span,
GLuint index[] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint dest[MAX_WIDTH];
 
ASSERT(span->end < MAX_WIDTH);
 
/* Read dest values from frame buffer */
if (span->arrayMask & SPAN_XY) {
(*swrast->Driver.ReadCI32Pixels)( ctx, span->end,
span->array->x, span->array->y,
dest, span->array->mask );
}
else {
(*swrast->Driver.ReadCI32Span)( ctx, span->end, span->x, span->y, dest );
}
 
index_logicop( ctx, span->end, index, dest, span->array->mask );
}
 
 
 
/*
* Apply logic operator to rgba pixels.
* Input: ctx - the context
* n - number of pixels
* mask - pixel mask array
* In/Out: src - incoming pixels which will be modified
* Input: dest - frame buffer values
*
* Note: Since the R, G, B, and A channels are all treated the same we
* process them as 4-byte GLuints instead of four GLubytes.
*/
static void
rgba_logicop_ui( const GLcontext *ctx, GLuint n, const GLubyte mask[],
GLuint src[], const GLuint dest[] )
{
GLuint i;
switch (ctx->Color.LogicOp) {
case GL_CLEAR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = 0;
}
}
break;
case GL_SET:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~0;
}
}
break;
case GL_COPY:
/* do nothing */
break;
case GL_COPY_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~src[i];
}
}
break;
case GL_NOOP:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = dest[i];
}
}
break;
case GL_INVERT:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~dest[i];
}
}
break;
case GL_AND:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] &= dest[i];
}
}
break;
case GL_NAND:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~(src[i] & dest[i]);
}
}
break;
case GL_OR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i]|= dest[i];
}
}
break;
case GL_NOR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~(src[i] | dest[i]);
}
}
break;
case GL_XOR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] ^= dest[i];
}
}
break;
case GL_EQUIV:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~(src[i] ^ dest[i]);
}
}
break;
case GL_AND_REVERSE:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = src[i] & ~dest[i];
}
}
break;
case GL_AND_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~src[i] & dest[i];
}
}
break;
case GL_OR_REVERSE:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = src[i] | ~dest[i];
}
}
break;
case GL_OR_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~src[i] | dest[i];
}
}
break;
default:
/* should never happen */
_mesa_problem(ctx, "Bad function in rgba_logicop");
}
}
 
 
/*
* As above, but operate on GLchan values
* Note: need to pass n = numPixels * 4.
*/
static void
rgba_logicop_chan( const GLcontext *ctx, GLuint n, const GLubyte mask[],
GLchan srcPtr[], const GLchan destPtr[] )
{
#if CHAN_TYPE == GL_FLOAT
GLuint *src = (GLuint *) srcPtr;
const GLuint *dest = (const GLuint *) destPtr;
GLuint i;
ASSERT(sizeof(GLfloat) == sizeof(GLuint));
#else
GLchan *src = srcPtr;
const GLchan *dest = destPtr;
GLuint i;
#endif
 
switch (ctx->Color.LogicOp) {
case GL_CLEAR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = 0;
}
}
break;
case GL_SET:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~0;
}
}
break;
case GL_COPY:
/* do nothing */
break;
case GL_COPY_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~src[i];
}
}
break;
case GL_NOOP:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = dest[i];
}
}
break;
case GL_INVERT:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~dest[i];
}
}
break;
case GL_AND:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] &= dest[i];
}
}
break;
case GL_NAND:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~(src[i] & dest[i]);
}
}
break;
case GL_OR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i]|= dest[i];
}
}
break;
case GL_NOR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~(src[i] | dest[i]);
}
}
break;
case GL_XOR:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] ^= dest[i];
}
}
break;
case GL_EQUIV:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~(src[i] ^ dest[i]);
}
}
break;
case GL_AND_REVERSE:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = src[i] & ~dest[i];
}
}
break;
case GL_AND_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~src[i] & dest[i];
}
}
break;
case GL_OR_REVERSE:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = src[i] | ~dest[i];
}
}
break;
case GL_OR_INVERTED:
for (i=0;i<n;i++) {
if (mask[i]) {
src[i] = ~src[i] | dest[i];
}
}
break;
default:
/* should never happen */
_mesa_problem(ctx, "Bad function in rgba_logicop");
}
}
 
 
 
/*
* Apply the current logic operator to a span of RGBA pixels.
* We can handle horizontal runs of pixels (spans) or arrays of x/y
* pixel coordinates.
*/
void
_mesa_logicop_rgba_span( GLcontext *ctx, const struct sw_span *span,
GLchan rgba[][4] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLchan dest[MAX_WIDTH][4];
 
ASSERT(span->end < MAX_WIDTH);
ASSERT(span->arrayMask & SPAN_RGBA);
 
if (span->arrayMask & SPAN_XY) {
(*swrast->Driver.ReadRGBAPixels)(ctx, span->end,
span->array->x, span->array->y,
dest, span->array->mask);
if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
_mesa_read_alpha_pixels(ctx, span->end,
span->array->x, span->array->y,
dest, span->array->mask);
}
}
else {
_mesa_read_rgba_span(ctx, ctx->DrawBuffer, span->end,
span->x, span->y, dest);
}
 
if (sizeof(GLchan) * 4 == sizeof(GLuint)) {
rgba_logicop_ui(ctx, span->end, span->array->mask,
(GLuint *) rgba, (const GLuint *) dest);
}
else {
rgba_logicop_chan(ctx, 4 * span->end, span->array->mask,
(GLchan *) rgba, (const GLchan *) dest);
}
}
/shark/trunk/ports/mesa/src/swrast/s_accum.h
0,0 → 1,44
/* $Id: s_accum.h,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.0.2
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_ACCUM_H
#define S_ACCUM_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern void
_mesa_alloc_accum_buffer( GLframebuffer *buffer );
 
 
extern void
_mesa_clear_accum_buffer( GLcontext *ctx );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_aaline.h
0,0 → 1,40
/* $Id: s_aaline.h,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_AALINE_H
#define S_AALINE_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern void
_swrast_choose_aa_line_function(GLcontext *ctx);
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_stencil.c
0,0 → 1,1327
/* $Id: s_stencil.c,v 1.1 2003-02-28 11:49:43 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
 
#include "s_context.h"
#include "s_depth.h"
#include "s_stencil.h"
 
 
 
/* Stencil Logic:
 
IF stencil test fails THEN
Apply fail-op to stencil value
Don't write the pixel (RGBA,Z)
ELSE
IF doing depth test && depth test fails THEN
Apply zfail-op to stencil value
Write RGBA and Z to appropriate buffers
ELSE
Apply zpass-op to stencil value
ENDIF
 
*/
 
 
/*
* Return the address of a stencil buffer value given the window coords:
*/
#define STENCIL_ADDRESS(X,Y) \
(ctx->DrawBuffer->Stencil + ctx->DrawBuffer->Width * (Y) + (X))
 
 
 
/**
* Apply the given stencil operator to the array of stencil values.
* Don't touch stencil[i] if mask[i] is zero.
* Input: n - size of stencil array
* oper - the stencil buffer operator
* face - 0 or 1 for front or back face operation
* stencil - array of stencil values
* mask - array [n] of flag: 1=apply operator, 0=don't apply operator
* Output: stencil - modified values
*/
static void
apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,
GLuint n, GLstencil stencil[], const GLubyte mask[] )
{
const GLstencil ref = ctx->Stencil.Ref[face];
const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
const GLstencil invmask = (GLstencil) (~wrtmask);
GLuint i;
 
switch (oper) {
case GL_KEEP:
/* do nothing */
break;
case GL_ZERO:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
stencil[i] = 0;
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
stencil[i] = (GLstencil) (stencil[i] & invmask);
}
}
}
break;
case GL_REPLACE:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
stencil[i] = ref;
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil s = stencil[i];
stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
}
}
}
break;
case GL_INCR:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil s = stencil[i];
if (s < STENCIL_MAX) {
stencil[i] = (GLstencil) (s+1);
}
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
/* VERIFY logic of adding 1 to a write-masked value */
GLstencil s = stencil[i];
if (s < STENCIL_MAX) {
stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
}
}
}
}
break;
case GL_DECR:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil s = stencil[i];
if (s>0) {
stencil[i] = (GLstencil) (s-1);
}
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
/* VERIFY logic of subtracting 1 to a write-masked value */
GLstencil s = stencil[i];
if (s>0) {
stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
}
}
}
}
break;
case GL_INCR_WRAP_EXT:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
stencil[i]++;
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil s = stencil[i];
stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
}
}
}
break;
case GL_DECR_WRAP_EXT:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
stencil[i]--;
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil s = stencil[i];
stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
}
}
}
break;
case GL_INVERT:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil s = stencil[i];
stencil[i] = (GLstencil) ~s;
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil s = stencil[i];
stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
}
}
}
break;
default:
_mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
}
}
 
 
 
 
/**
* Apply stencil test to an array of stencil values (before depth buffering).
* Input: face - 0 or 1 for front or back-face polygons
* n - number of pixels in the array
* stencil - array of [n] stencil values
* mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
* Output: mask - pixels which fail the stencil test will have their
* mask flag set to 0.
* stencil - updated stencil values (where the test passed)
* Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
*/
static GLboolean
do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
GLubyte mask[] )
{
GLubyte fail[MAX_WIDTH];
GLboolean allfail = GL_FALSE;
GLuint i;
GLstencil r, s;
const GLuint valueMask = ctx->Stencil.ValueMask[face];
 
ASSERT(n <= MAX_WIDTH);
 
/*
* Perform stencil test. The results of this operation are stored
* in the fail[] array:
* IF fail[i] is non-zero THEN
* the stencil fail operator is to be applied
* ELSE
* the stencil fail operator is not to be applied
* ENDIF
*/
switch (ctx->Stencil.Function[face]) {
case GL_NEVER:
/* never pass; always fail */
for (i=0;i<n;i++) {
if (mask[i]) {
mask[i] = 0;
fail[i] = 1;
}
else {
fail[i] = 0;
}
}
allfail = GL_TRUE;
break;
case GL_LESS:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
if (r < s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_LEQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
if (r <= s) {
/* pass */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_GREATER:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
if (r > s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_GEQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
if (r >= s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_EQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
if (r == s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_NOTEQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
if (r != s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_ALWAYS:
/* always pass */
for (i=0;i<n;i++) {
fail[i] = 0;
}
break;
default:
_mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
return 0;
}
 
if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
}
 
return !allfail;
}
 
 
 
/**
* Apply stencil and depth testing to the span of pixels.
* Both software and hardware stencil buffers are acceptable.
* Input: n - number of pixels in the span
* x, y - location of leftmost pixel in span
* z - array [n] of z values
* mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
* Output: mask - array [n] of flags (1=stencil and depth test passed)
* Return: GL_FALSE - all fragments failed the testing
* GL_TRUE - one or more fragments passed the testing
*
*/
static GLboolean
stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLstencil stencilRow[MAX_WIDTH];
GLstencil *stencil;
const GLuint n = span->end;
const GLint x = span->x;
const GLint y = span->y;
GLubyte *mask = span->array->mask;
 
ASSERT((span->arrayMask & SPAN_XY) == 0);
ASSERT(ctx->Stencil.Enabled);
ASSERT(n <= MAX_WIDTH);
#ifdef DEBUG
if (ctx->Depth.Test) {
ASSERT(span->arrayMask & SPAN_Z);
}
#endif
/* Get initial stencil values */
if (swrast->Driver.WriteStencilSpan) {
/* Get stencil values from the hardware stencil buffer */
ASSERT(swrast->Driver.ReadStencilSpan);
(*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
stencil = stencilRow;
}
else {
/* Get pointer into software stencil buffer */
stencil = STENCIL_ADDRESS(x, y);
}
/*
* Apply the stencil test to the fragments.
* failMask[i] is 1 if the stencil test failed.
*/
if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
/* all fragments failed the stencil test, we're done. */
span->writeAll = GL_FALSE;
return GL_FALSE;
}
 
/*
* Some fragments passed the stencil test, apply depth test to them
* and apply Zpass and Zfail stencil ops.
*/
if (ctx->Depth.Test == GL_FALSE) {
/*
* No depth buffer, just apply zpass stencil function to active pixels.
*/
apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
}
else {
/*
* Perform depth buffering, then apply zpass or zfail stencil function.
*/
GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
GLuint i;
 
/* save the current mask bits */
MEMCPY(oldmask, mask, n * sizeof(GLubyte));
 
/* apply the depth test */
_mesa_depth_test_span(ctx, span);
 
/* Set the stencil pass/fail flags according to result of depth testing.
* if oldmask[i] == 0 then
* Don't touch the stencil value
* else if oldmask[i] and newmask[i] then
* Depth test passed
* else
* assert(oldmask[i] && !newmask[i])
* Depth test failed
* endif
*/
for (i=0;i<n;i++) {
ASSERT(mask[i] == 0 || mask[i] == 1);
passmask[i] = oldmask[i] & mask[i];
failmask[i] = oldmask[i] & (mask[i] ^ 1);
}
 
/* apply the pass and fail operations */
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
n, stencil, failmask );
}
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
n, stencil, passmask );
}
}
 
/*
* Write updated stencil values back into hardware stencil buffer.
*/
if (swrast->Driver.WriteStencilSpan) {
ASSERT(stencil == stencilRow);
(swrast->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
}
span->writeAll = GL_FALSE;
return GL_TRUE; /* one or more fragments passed both tests */
}
 
 
 
 
/**
* Apply the given stencil operator for each pixel in the array whose
* mask flag is set.
* \note This is for software stencil buffers only.
* Input: n - number of pixels in the span
* x, y - array of [n] pixels
* operator - the stencil buffer operator
* mask - array [n] of flag: 1=apply operator, 0=don't apply operator
*/
static void
apply_stencil_op_to_pixels( const GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
GLenum oper, GLuint face, const GLubyte mask[] )
{
const GLstencil ref = ctx->Stencil.Ref[face];
const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
const GLstencil invmask = (GLstencil) (~wrtmask);
GLuint i;
 
ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* software stencil buffer only! */
 
switch (oper) {
case GL_KEEP:
/* do nothing */
break;
case GL_ZERO:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = 0;
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) (invmask & *sptr);
}
}
}
break;
case GL_REPLACE:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = ref;
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
}
}
}
break;
case GL_INCR:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
if (*sptr < STENCIL_MAX) {
*sptr = (GLstencil) (*sptr + 1);
}
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
if (*sptr < STENCIL_MAX) {
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
}
}
}
}
break;
case GL_DECR:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
if (*sptr>0) {
*sptr = (GLstencil) (*sptr - 1);
}
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
if (*sptr>0) {
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
}
}
}
}
break;
case GL_INCR_WRAP_EXT:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) (*sptr + 1);
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
}
}
}
break;
case GL_DECR_WRAP_EXT:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) (*sptr - 1);
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
}
}
}
break;
case GL_INVERT:
if (invmask==0) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) (~*sptr);
}
}
}
else {
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
}
}
}
break;
default:
_mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
}
}
 
 
 
/**
* Apply stencil test to an array of pixels before depth buffering.
*
* \note Used for software stencil buffer only.
* Input: n - number of pixels in the span
* x, y - array of [n] pixels to stencil
* mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
* Output: mask - pixels which fail the stencil test will have their
* mask flag set to 0.
* \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
*/
static GLboolean
stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
const GLint x[], const GLint y[], GLubyte mask[] )
{
GLubyte fail[MAX_WIDTH];
GLstencil r, s;
GLuint i;
GLboolean allfail = GL_FALSE;
const GLuint valueMask = ctx->Stencil.ValueMask[face];
 
/* software stencil buffer only! */
ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);
ASSERT(!SWRAST_CONTEXT(ctx)->Driver.ReadStencilSpan);
ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan);
 
/*
* Perform stencil test. The results of this operation are stored
* in the fail[] array:
* IF fail[i] is non-zero THEN
* the stencil fail operator is to be applied
* ELSE
* the stencil fail operator is not to be applied
* ENDIF
*/
 
switch (ctx->Stencil.Function[face]) {
case GL_NEVER:
/* always fail */
for (i=0;i<n;i++) {
if (mask[i]) {
mask[i] = 0;
fail[i] = 1;
}
else {
fail[i] = 0;
}
}
allfail = GL_TRUE;
break;
case GL_LESS:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
s = (GLstencil) (*sptr & valueMask);
if (r < s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_LEQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
s = (GLstencil) (*sptr & valueMask);
if (r <= s) {
/* pass */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_GREATER:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
s = (GLstencil) (*sptr & valueMask);
if (r > s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_GEQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
s = (GLstencil) (*sptr & valueMask);
if (r >= s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_EQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
s = (GLstencil) (*sptr & valueMask);
if (r == s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_NOTEQUAL:
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
s = (GLstencil) (*sptr & valueMask);
if (r != s) {
/* passed */
fail[i] = 0;
}
else {
fail[i] = 1;
mask[i] = 0;
}
}
else {
fail[i] = 0;
}
}
break;
case GL_ALWAYS:
/* always pass */
for (i=0;i<n;i++) {
fail[i] = 0;
}
break;
default:
_mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
return 0;
}
 
if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
face, fail );
}
 
return !allfail;
}
 
 
 
 
/**
* Apply stencil and depth testing to an array of pixels.
* This is used both for software and hardware stencil buffers.
*
* The comments in this function are a bit sparse but the code is
* almost identical to stencil_and_ztest_span(), which is well
* commented.
*
* Input: n - number of pixels in the array
* x, y - array of [n] pixel positions
* z - array [n] of z values
* mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
* Output: mask - array [n] of flags (1=stencil and depth test passed)
* Return: GL_FALSE - all fragments failed the testing
* GL_TRUE - one or more fragments passed the testing
*/
static GLboolean
stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face )
{
const GLuint n = span->end;
const GLint *x = span->array->x;
const GLint *y = span->array->y;
GLubyte *mask = span->array->mask;
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
ASSERT(span->arrayMask & SPAN_XY);
ASSERT(ctx->Stencil.Enabled);
ASSERT(n <= MAX_WIDTH);
 
if (swrast->Driver.WriteStencilPixels) {
/*** Hardware stencil buffer ***/
GLstencil stencil[MAX_WIDTH];
GLubyte origMask[MAX_WIDTH];
 
ASSERT(!ctx->DrawBuffer->UseSoftwareStencilBuffer);
ASSERT(swrast->Driver.ReadStencilPixels);
(*swrast->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);
 
MEMCPY(origMask, mask, n * sizeof(GLubyte));
 
(void) do_stencil_test(ctx, face, n, stencil, mask);
 
if (ctx->Depth.Test == GL_FALSE) {
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
n, stencil, mask);
}
else {
_mesa_depth_test_span(ctx, span);
 
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
GLubyte failmask[MAX_WIDTH];
GLuint i;
for (i = 0; i < n; i++) {
ASSERT(mask[i] == 0 || mask[i] == 1);
failmask[i] = origMask[i] & (mask[i] ^ 1);
}
apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
n, stencil, failmask);
}
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
GLubyte passmask[MAX_WIDTH];
GLuint i;
for (i = 0; i < n; i++) {
ASSERT(mask[i] == 0 || mask[i] == 1);
passmask[i] = origMask[i] & mask[i];
}
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
n, stencil, passmask);
}
}
 
/* Write updated stencil values into hardware stencil buffer */
(swrast->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, origMask);
 
return GL_TRUE;
}
else {
/*** Software stencil buffer ***/
 
ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer);
 
if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
/* all fragments failed the stencil test, we're done. */
return GL_FALSE;
}
 
if (ctx->Depth.Test==GL_FALSE) {
apply_stencil_op_to_pixels(ctx, n, x, y,
ctx->Stencil.ZPassFunc[face], face, mask);
}
else {
GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
GLuint i;
 
MEMCPY(oldmask, mask, n * sizeof(GLubyte));
 
_mesa_depth_test_span(ctx, span);
 
for (i=0;i<n;i++) {
ASSERT(mask[i] == 0 || mask[i] == 1);
passmask[i] = oldmask[i] & mask[i];
failmask[i] = oldmask[i] & (mask[i] ^ 1);
}
 
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
apply_stencil_op_to_pixels(ctx, n, x, y,
ctx->Stencil.ZFailFunc[face],
face, failmask);
}
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
apply_stencil_op_to_pixels(ctx, n, x, y,
ctx->Stencil.ZPassFunc[face],
face, passmask);
}
}
 
return GL_TRUE; /* one or more fragments passed both tests */
}
}
 
 
/**
* /return GL_TRUE = one or more fragments passed,
* GL_FALSE = all fragments failed.
*/
GLboolean
_mesa_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span)
{
/* span->facing can only be non-zero if using two-sided stencil */
ASSERT(ctx->Stencil.TestTwoSide || span->facing == 0);
if (span->arrayMask & SPAN_XY)
return stencil_and_ztest_pixels(ctx, span, span->facing);
else
return stencil_and_ztest_span(ctx, span, span->facing);
}
 
 
/**
* Return a span of stencil values from the stencil buffer.
* Used for glRead/CopyPixels
* Input: n - how many pixels
* x,y - location of first pixel
* Output: stencil - the array of stencil values
*/
void
_mesa_read_stencil_span( GLcontext *ctx,
GLint n, GLint x, GLint y, GLstencil stencil[] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLint bufWidth = (GLint) ctx->DrawBuffer->Width;
const GLint bufHeight = (GLint) ctx->DrawBuffer->Height;
 
if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) {
/* span is completely outside framebuffer */
return; /* undefined values OK */
}
 
if (x < 0) {
GLint dx = -x;
x = 0;
n -= dx;
stencil += dx;
}
if (x + n > bufWidth) {
GLint dx = x + n - bufWidth;
n -= dx;
}
if (n <= 0) {
return;
}
 
 
ASSERT(n >= 0);
if (swrast->Driver.ReadStencilSpan) {
(*swrast->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil );
}
else if (ctx->DrawBuffer->Stencil) {
const GLstencil *s = STENCIL_ADDRESS( x, y );
#if STENCIL_BITS == 8
MEMCPY( stencil, s, n * sizeof(GLstencil) );
#else
GLuint i;
for (i=0;i<n;i++)
stencil[i] = s[i];
#endif
}
}
 
 
 
/**
* Write a span of stencil values to the stencil buffer.
* Used for glDraw/CopyPixels
* Input: n - how many pixels
* x, y - location of first pixel
* stencil - the array of stencil values
*/
void
_mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
const GLstencil stencil[] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLstencil *ssrc = stencil;
const GLint bufWidth = (GLint) ctx->DrawBuffer->Width;
const GLint bufHeight = (GLint) ctx->DrawBuffer->Height;
 
if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) {
/* span is completely outside framebuffer */
return; /* undefined values OK */
}
 
if (x < 0) {
GLint dx = -x;
x = 0;
n -= dx;
ssrc += dx;
}
if (x + n > bufWidth) {
GLint dx = x + n - bufWidth;
n -= dx;
}
if (n <= 0) {
return;
}
 
if (swrast->Driver.WriteStencilSpan) {
(*swrast->Driver.WriteStencilSpan)( ctx, n, x, y, ssrc, NULL );
}
else if (ctx->DrawBuffer->Stencil) {
GLstencil *s = STENCIL_ADDRESS( x, y );
#if STENCIL_BITS == 8
MEMCPY( s, ssrc, n * sizeof(GLstencil) );
#else
GLuint i;
for (i=0;i<n;i++)
s[i] = ssrc[i];
#endif
}
}
 
 
 
/**
* Allocate a new stencil buffer. If there's an old one it will be
* deallocated first. The new stencil buffer will be uninitialized.
*/
void
_mesa_alloc_stencil_buffer( GLframebuffer *buffer )
{
/* deallocate current stencil buffer if present */
if (buffer->Stencil) {
MESA_PBUFFER_FREE(buffer->Stencil);
buffer->Stencil = NULL;
}
 
/* allocate new stencil buffer */
buffer->Stencil = (GLstencil *)
MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height * sizeof(GLstencil));
if (!buffer->Stencil) {
/* out of memory */
_mesa_error( NULL, GL_OUT_OF_MEMORY, "_mesa_alloc_stencil_buffer" );
}
}
 
 
 
/**
* Clear the software (malloc'd) stencil buffer.
*/
static void
clear_software_stencil_buffer( GLcontext *ctx )
{
if (ctx->Visual.stencilBits==0 || !ctx->DrawBuffer->Stencil) {
/* no stencil buffer */
return;
}
 
if (ctx->Scissor.Enabled) {
/* clear scissor region only */
const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
/* must apply mask to the clear */
GLint y;
for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
const GLstencil mask = ctx->Stencil.WriteMask[0];
const GLstencil invMask = ~mask;
const GLstencil clearVal = (ctx->Stencil.Clear & mask);
GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y );
GLint i;
for (i = 0; i < width; i++) {
stencil[i] = (stencil[i] & invMask) | clearVal;
}
}
}
else {
/* no masking */
GLint y;
for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y );
#if STENCIL_BITS==8
MEMSET( stencil, ctx->Stencil.Clear, width * sizeof(GLstencil) );
#else
GLint i;
for (i = 0; i < width; i++)
stencil[x] = ctx->Stencil.Clear;
#endif
}
}
}
else {
/* clear whole stencil buffer */
if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
/* must apply mask to the clear */
const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
GLstencil *stencil = ctx->DrawBuffer->Stencil;
const GLstencil mask = ctx->Stencil.WriteMask[0];
const GLstencil invMask = ~mask;
const GLstencil clearVal = (ctx->Stencil.Clear & mask);
GLuint i;
for (i = 0; i < n; i++) {
stencil[i] = (stencil[i] & invMask) | clearVal;
}
}
else {
/* clear whole buffer without masking */
const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
GLstencil *stencil = ctx->DrawBuffer->Stencil;
 
#if STENCIL_BITS==8
MEMSET(stencil, ctx->Stencil.Clear, n * sizeof(GLstencil) );
#else
GLuint i;
for (i = 0; i < n; i++) {
stencil[i] = ctx->Stencil.Clear;
}
#endif
}
}
}
 
 
 
/**
* Clear the hardware (in graphics card) stencil buffer.
* This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan()
* functions.
* Actually, if there is a hardware stencil buffer it really should have
* been cleared in Driver.Clear()! However, if the hardware does not
* support scissored clears or masked clears (i.e. glStencilMask) then
* we have to use the span-based functions.
*/
static void
clear_hardware_stencil_buffer( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
ASSERT(swrast->Driver.WriteStencilSpan);
ASSERT(swrast->Driver.ReadStencilSpan);
 
if (ctx->Scissor.Enabled) {
/* clear scissor region only */
const GLint x = ctx->DrawBuffer->_Xmin;
const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
/* must apply mask to the clear */
GLint y;
for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
const GLstencil mask = ctx->Stencil.WriteMask[0];
const GLstencil invMask = ~mask;
const GLstencil clearVal = (ctx->Stencil.Clear & mask);
GLstencil stencil[MAX_WIDTH];
GLint i;
(*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
for (i = 0; i < width; i++) {
stencil[i] = (stencil[i] & invMask) | clearVal;
}
(*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
else {
/* no masking */
GLstencil stencil[MAX_WIDTH];
GLint y, i;
for (i = 0; i < width; i++) {
stencil[i] = ctx->Stencil.Clear;
}
for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
(*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
}
else {
/* clear whole stencil buffer */
if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) {
/* must apply mask to the clear */
const GLstencil mask = ctx->Stencil.WriteMask[0];
const GLstencil invMask = ~mask;
const GLstencil clearVal = (ctx->Stencil.Clear & mask);
const GLint width = ctx->DrawBuffer->Width;
const GLint height = ctx->DrawBuffer->Height;
const GLint x = ctx->DrawBuffer->_Xmin;
GLint y;
for (y = 0; y < height; y++) {
GLstencil stencil[MAX_WIDTH];
GLint i;
(*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
for (i = 0; i < width; i++) {
stencil[i] = (stencil[i] & invMask) | clearVal;
}
(*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
else {
/* clear whole buffer without masking */
const GLint width = ctx->DrawBuffer->Width;
const GLint height = ctx->DrawBuffer->Height;
const GLint x = ctx->DrawBuffer->_Xmin;
GLstencil stencil[MAX_WIDTH];
GLint y, i;
for (i = 0; i < width; i++) {
stencil[i] = ctx->Stencil.Clear;
}
for (y = 0; y < height; y++) {
(*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
}
}
 
 
 
/**
* Clear the stencil buffer (hardware or software).
*/
void
_mesa_clear_stencil_buffer( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.WriteStencilSpan) {
ASSERT(swrast->Driver.ReadStencilSpan);
clear_hardware_stencil_buffer(ctx);
}
else {
clear_software_stencil_buffer(ctx);
}
}
/shark/trunk/ports/mesa/src/swrast/s_pixeltex.c
0,0 → 1,118
/* $Id: s_pixeltex.c,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* This file implements both the GL_SGIX_pixel_texture and
* GL_SIGS_pixel_texture extensions. Luckily, they pretty much
* overlap in functionality so we use the same state variables
* and execution code for both.
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "imports.h"
 
#include "s_context.h"
#include "s_pixeltex.h"
#include "s_texture.h"
 
 
/*
* Convert RGBA values into strq texture coordinates.
*/
static void
pixeltexgen(GLcontext *ctx, GLuint n, const GLchan rgba[][4],
GLfloat texcoord[][4])
{
if (ctx->Pixel.FragmentRgbSource == GL_CURRENT_RASTER_COLOR) {
GLuint i;
for (i = 0; i < n; i++) {
texcoord[i][0] = ctx->Current.RasterColor[RCOMP];
texcoord[i][1] = ctx->Current.RasterColor[GCOMP];
texcoord[i][2] = ctx->Current.RasterColor[BCOMP];
}
}
else {
GLuint i;
ASSERT(ctx->Pixel.FragmentRgbSource == GL_PIXEL_GROUP_COLOR_SGIS);
for (i = 0; i < n; i++) {
texcoord[i][0] = CHAN_TO_FLOAT(rgba[i][RCOMP]);
texcoord[i][1] = CHAN_TO_FLOAT(rgba[i][GCOMP]);
texcoord[i][2] = CHAN_TO_FLOAT(rgba[i][BCOMP]);
}
}
 
if (ctx->Pixel.FragmentAlphaSource == GL_CURRENT_RASTER_COLOR) {
GLuint i;
for (i = 0; i < n; i++) {
texcoord[i][3] = ctx->Current.RasterColor[ACOMP];
}
}
else {
GLuint i;
ASSERT(ctx->Pixel.FragmentAlphaSource == GL_PIXEL_GROUP_COLOR_SGIS);
for (i = 0; i < n; i++) {
texcoord[i][3] = CHAN_TO_FLOAT(rgba[i][ACOMP]);
}
}
}
 
 
 
/*
* Used by glDraw/CopyPixels: the incoming image colors are treated
* as texture coordinates. Use those coords to texture the image.
* This is for GL_SGIS_pixel_texture / GL_SGIX_pixel_texture.
*/
void
_swrast_pixel_texture(GLcontext *ctx, struct sw_span *span)
{
GLuint unit;
 
ASSERT(!(span->arrayMask & SPAN_TEXTURE));
span->arrayMask |= SPAN_TEXTURE;
 
/* convert colors into texture coordinates */
pixeltexgen( ctx, span->end,
(const GLchan (*)[4]) span->array->rgba,
span->array->texcoords[0] );
 
/* copy the new texture units for all enabled units */
for (unit = 1; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
MEMCPY( span->array->texcoords[unit], span->array->texcoords[0],
span->end * 4 * sizeof(GLfloat) );
}
}
 
/* apply texture mapping */
_swrast_texture_span( ctx, span );
 
/* this is a work-around to be fixed by initializing again span */
span->arrayMask &= ~SPAN_TEXTURE;
}
/shark/trunk/ports/mesa/src/swrast/s_logic.h
0,0 → 1,46
/* $Id: s_logic.h,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_LOGIC_H
#define S_LOGIC_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern void
_mesa_logicop_ci_span( GLcontext *ctx, const struct sw_span *span,
GLuint index[] );
 
 
extern void
_mesa_logicop_rgba_span( GLcontext *ctx, const struct sw_span *span,
GLchan rgba[][4] );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_stencil.h
0,0 → 1,60
/* $Id: s_stencil.h,v 1.1 2003-02-28 11:49:43 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_STENCIL_H
#define S_STENCIL_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
 
extern GLboolean
_mesa_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span);
 
 
 
extern void
_mesa_read_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
GLstencil stencil[] );
 
 
extern void
_mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
const GLstencil stencil[] );
 
 
extern void
_mesa_alloc_stencil_buffer( GLframebuffer *buffer );
 
 
extern void
_mesa_clear_stencil_buffer( GLcontext *ctx );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_aatriangle.c
0,0 → 1,480
/* $Id: s_aatriangle.c,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* Antialiased Triangle rasterizers
*/
 
 
#include "glheader.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "s_aatriangle.h"
#include "s_context.h"
#include "s_span.h"
 
 
/*
* Compute coefficients of a plane using the X,Y coords of the v0, v1, v2
* vertices and the given Z values.
* A point (x,y,z) lies on plane iff a*x+b*y+c*z+d = 0.
*/
static INLINE void
compute_plane(const GLfloat v0[], const GLfloat v1[], const GLfloat v2[],
GLfloat z0, GLfloat z1, GLfloat z2, GLfloat plane[4])
{
const GLfloat px = v1[0] - v0[0];
const GLfloat py = v1[1] - v0[1];
const GLfloat pz = z1 - z0;
 
const GLfloat qx = v2[0] - v0[0];
const GLfloat qy = v2[1] - v0[1];
const GLfloat qz = z2 - z0;
 
/* Crossproduct "(a,b,c):= dv1 x dv2" is orthogonal to plane. */
const GLfloat a = py * qz - pz * qy;
const GLfloat b = pz * qx - px * qz;
const GLfloat c = px * qy - py * qx;
/* Point on the plane = "r*(a,b,c) + w", with fixed "r" depending
on the distance of plane from origin and arbitrary "w" parallel
to the plane. */
/* The scalar product "(r*(a,b,c)+w)*(a,b,c)" is "r*(a^2+b^2+c^2)",
which is equal to "-d" below. */
const GLfloat d = -(a * v0[0] + b * v0[1] + c * z0);
 
plane[0] = a;
plane[1] = b;
plane[2] = c;
plane[3] = d;
}
 
 
/*
* Compute coefficients of a plane with a constant Z value.
*/
static INLINE void
constant_plane(GLfloat value, GLfloat plane[4])
{
plane[0] = 0.0;
plane[1] = 0.0;
plane[2] = -1.0;
plane[3] = value;
}
 
#define CONSTANT_PLANE(VALUE, PLANE) \
do { \
PLANE[0] = 0.0F; \
PLANE[1] = 0.0F; \
PLANE[2] = -1.0F; \
PLANE[3] = VALUE; \
} while (0)
 
 
 
/*
* Solve plane equation for Z at (X,Y).
*/
static INLINE GLfloat
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
{
ASSERT(plane[2] != 0.0F);
return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
}
 
 
#define SOLVE_PLANE(X, Y, PLANE) \
((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
 
 
/*
* Return 1 / solve_plane().
*/
static INLINE GLfloat
solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
{
const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y;
if (denom == 0.0F)
return 0.0F;
else
return -plane[2] / denom;
}
 
 
/*
* Solve plane and return clamped GLchan value.
*/
static INLINE GLchan
solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
{
GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2] + 0.5F;
if (z < 0.0F)
return 0;
else if (z > CHAN_MAXF)
return (GLchan) CHAN_MAXF;
return (GLchan) (GLint) z;
}
 
 
 
/*
* Compute how much (area) of the given pixel is inside the triangle.
* Vertices MUST be specified in counter-clockwise order.
* Return: coverage in [0, 1].
*/
static GLfloat
compute_coveragef(const GLfloat v0[3], const GLfloat v1[3],
const GLfloat v2[3], GLint winx, GLint winy)
{
/* Given a position [0,3]x[0,3] return the sub-pixel sample position.
* Contributed by Ray Tice.
*
* Jitter sample positions -
* - average should be .5 in x & y for each column
* - each of the 16 rows and columns should be used once
* - the rectangle formed by the first four points
* should contain the other points
* - the distrubition should be fairly even in any given direction
*
* The pattern drawn below isn't optimal, but it's better than a regular
* grid. In the drawing, the center of each subpixel is surrounded by
* four dots. The "x" marks the jittered position relative to the
* subpixel center.
*/
#define POS(a, b) (0.5+a*4+b)/16
static const GLfloat samples[16][2] = {
/* start with the four corners */
{ POS(0, 2), POS(0, 0) },
{ POS(3, 3), POS(0, 2) },
{ POS(0, 0), POS(3, 1) },
{ POS(3, 1), POS(3, 3) },
/* continue with interior samples */
{ POS(1, 1), POS(0, 1) },
{ POS(2, 0), POS(0, 3) },
{ POS(0, 3), POS(1, 3) },
{ POS(1, 2), POS(1, 0) },
{ POS(2, 3), POS(1, 2) },
{ POS(3, 2), POS(1, 1) },
{ POS(0, 1), POS(2, 2) },
{ POS(1, 0), POS(2, 1) },
{ POS(2, 1), POS(2, 3) },
{ POS(3, 0), POS(2, 0) },
{ POS(1, 3), POS(3, 0) },
{ POS(2, 2), POS(3, 2) }
};
 
const GLfloat x = (GLfloat) winx;
const GLfloat y = (GLfloat) winy;
const GLfloat dx0 = v1[0] - v0[0];
const GLfloat dy0 = v1[1] - v0[1];
const GLfloat dx1 = v2[0] - v1[0];
const GLfloat dy1 = v2[1] - v1[1];
const GLfloat dx2 = v0[0] - v2[0];
const GLfloat dy2 = v0[1] - v2[1];
GLint stop = 4, i;
GLfloat insideCount = 16.0F;
 
#ifdef DEBUG
{
const GLfloat area = dx0 * dy1 - dx1 * dy0;
ASSERT(area >= 0.0);
}
#endif
 
for (i = 0; i < stop; i++) {
const GLfloat sx = x + samples[i][0];
const GLfloat sy = y + samples[i][1];
const GLfloat fx0 = sx - v0[0];
const GLfloat fy0 = sy - v0[1];
const GLfloat fx1 = sx - v1[0];
const GLfloat fy1 = sy - v1[1];
const GLfloat fx2 = sx - v2[0];
const GLfloat fy2 = sy - v2[1];
/* cross product determines if sample is inside or outside each edge */
GLfloat cross0 = (dx0 * fy0 - dy0 * fx0);
GLfloat cross1 = (dx1 * fy1 - dy1 * fx1);
GLfloat cross2 = (dx2 * fy2 - dy2 * fx2);
/* Check if the sample is exactly on an edge. If so, let cross be a
* positive or negative value depending on the direction of the edge.
*/
if (cross0 == 0.0F)
cross0 = dx0 + dy0;
if (cross1 == 0.0F)
cross1 = dx1 + dy1;
if (cross2 == 0.0F)
cross2 = dx2 + dy2;
if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F) {
/* point is outside triangle */
insideCount -= 1.0F;
stop = 16;
}
}
if (stop == 4)
return 1.0F;
else
return insideCount * (1.0F / 16.0F);
}
 
 
 
/*
* Compute how much (area) of the given pixel is inside the triangle.
* Vertices MUST be specified in counter-clockwise order.
* Return: coverage in [0, 15].
*/
static GLint
compute_coveragei(const GLfloat v0[3], const GLfloat v1[3],
const GLfloat v2[3], GLint winx, GLint winy)
{
/* NOTE: 15 samples instead of 16. */
static const GLfloat samples[15][2] = {
/* start with the four corners */
{ POS(0, 2), POS(0, 0) },
{ POS(3, 3), POS(0, 2) },
{ POS(0, 0), POS(3, 1) },
{ POS(3, 1), POS(3, 3) },
/* continue with interior samples */
{ POS(1, 1), POS(0, 1) },
{ POS(2, 0), POS(0, 3) },
{ POS(0, 3), POS(1, 3) },
{ POS(1, 2), POS(1, 0) },
{ POS(2, 3), POS(1, 2) },
{ POS(3, 2), POS(1, 1) },
{ POS(0, 1), POS(2, 2) },
{ POS(1, 0), POS(2, 1) },
{ POS(2, 1), POS(2, 3) },
{ POS(3, 0), POS(2, 0) },
{ POS(1, 3), POS(3, 0) }
};
const GLfloat x = (GLfloat) winx;
const GLfloat y = (GLfloat) winy;
const GLfloat dx0 = v1[0] - v0[0];
const GLfloat dy0 = v1[1] - v0[1];
const GLfloat dx1 = v2[0] - v1[0];
const GLfloat dy1 = v2[1] - v1[1];
const GLfloat dx2 = v0[0] - v2[0];
const GLfloat dy2 = v0[1] - v2[1];
GLint stop = 4, i;
GLint insideCount = 15;
 
#ifdef DEBUG
{
const GLfloat area = dx0 * dy1 - dx1 * dy0;
ASSERT(area >= 0.0);
}
#endif
 
for (i = 0; i < stop; i++) {
const GLfloat sx = x + samples[i][0];
const GLfloat sy = y + samples[i][1];
const GLfloat fx0 = sx - v0[0];
const GLfloat fy0 = sy - v0[1];
const GLfloat fx1 = sx - v1[0];
const GLfloat fy1 = sy - v1[1];
const GLfloat fx2 = sx - v2[0];
const GLfloat fy2 = sy - v2[1];
/* cross product determines if sample is inside or outside each edge */
GLfloat cross0 = (dx0 * fy0 - dy0 * fx0);
GLfloat cross1 = (dx1 * fy1 - dy1 * fx1);
GLfloat cross2 = (dx2 * fy2 - dy2 * fx2);
/* Check if the sample is exactly on an edge. If so, let cross be a
* positive or negative value depending on the direction of the edge.
*/
if (cross0 == 0.0F)
cross0 = dx0 + dy0;
if (cross1 == 0.0F)
cross1 = dx1 + dy1;
if (cross2 == 0.0F)
cross2 = dx2 + dy2;
if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F) {
/* point is outside triangle */
insideCount--;
stop = 15;
}
}
if (stop == 4)
return 15;
else
return insideCount;
}
 
 
 
static void
rgba_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#include "s_aatritemp.h"
}
 
 
static void
index_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_INDEX
#include "s_aatritemp.h"
}
 
 
/*
* Compute mipmap level of detail.
* XXX we should really include the R coordinate in this computation
* in order to do 3-D texture mipmapping.
*/
static INLINE GLfloat
compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
const GLfloat qPlane[4], GLfloat cx, GLfloat cy,
GLfloat invQ, GLfloat texWidth, GLfloat texHeight)
{
const GLfloat s = solve_plane(cx, cy, sPlane);
const GLfloat t = solve_plane(cx, cy, tPlane);
const GLfloat invQ_x1 = solve_plane_recip(cx+1.0F, cy, qPlane);
const GLfloat invQ_y1 = solve_plane_recip(cx, cy+1.0F, qPlane);
const GLfloat s_x1 = s - sPlane[0] / sPlane[2];
const GLfloat s_y1 = s - sPlane[1] / sPlane[2];
const GLfloat t_x1 = t - tPlane[0] / tPlane[2];
const GLfloat t_y1 = t - tPlane[1] / tPlane[2];
GLfloat dsdx = s_x1 * invQ_x1 - s * invQ;
GLfloat dsdy = s_y1 * invQ_y1 - s * invQ;
GLfloat dtdx = t_x1 * invQ_x1 - t * invQ;
GLfloat dtdy = t_y1 * invQ_y1 - t * invQ;
GLfloat maxU, maxV, rho, lambda;
dsdx = FABSF(dsdx);
dsdy = FABSF(dsdy);
dtdx = FABSF(dtdx);
dtdy = FABSF(dtdy);
maxU = MAX2(dsdx, dsdy) * texWidth;
maxV = MAX2(dtdx, dtdy) * texHeight;
rho = MAX2(maxU, maxV);
lambda = LOG2(rho);
return lambda;
}
 
 
static void
tex_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_TEX
#include "s_aatritemp.h"
}
 
 
static void
spec_tex_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_TEX
#define DO_SPEC
#include "s_aatritemp.h"
}
 
 
static void
multitex_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_MULTITEX
#include "s_aatritemp.h"
}
 
static void
spec_multitex_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_MULTITEX
#define DO_SPEC
#include "s_aatritemp.h"
}
 
 
/*
* Examine GL state and set swrast->Triangle to an
* appropriate antialiased triangle rasterizer function.
*/
void
_mesa_set_aa_triangle_function(GLcontext *ctx)
{
ASSERT(ctx->Polygon.SmoothFlag);
 
if (ctx->Texture._EnabledUnits != 0) {
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
if (ctx->Texture._EnabledUnits > 1) {
SWRAST_CONTEXT(ctx)->Triangle = spec_multitex_aa_tri;
}
else {
SWRAST_CONTEXT(ctx)->Triangle = spec_tex_aa_tri;
}
}
else {
if (ctx->Texture._EnabledUnits > 1) {
SWRAST_CONTEXT(ctx)->Triangle = multitex_aa_tri;
}
else {
SWRAST_CONTEXT(ctx)->Triangle = tex_aa_tri;
}
}
}
else if (ctx->Visual.rgbMode) {
SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri;
}
else {
SWRAST_CONTEXT(ctx)->Triangle = index_aa_tri;
}
 
ASSERT(SWRAST_CONTEXT(ctx)->Triangle);
}
/shark/trunk/ports/mesa/src/swrast/s_pixeltex.h
0,0 → 1,39
/* $Id: s_pixeltex.h,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_PIXELTEX_H
#define S_PIXELTEX_H
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern void
_swrast_pixel_texture(GLcontext *ctx, struct sw_span *span);
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_lines.c
0,0 → 1,884
/* $Id: s_lines.c,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 5.0
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "macros.h"
#include "mmath.h"
#include "s_aaline.h"
#include "s_context.h"
#include "s_depth.h"
#include "s_feedback.h"
#include "s_lines.h"
#include "s_span.h"
 
 
/*
* Init the mask[] array to implement a line stipple.
*/
static void
compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
 
for (i = 0; i < len; i++) {
GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
if ((1 << bit) & ctx->Line.StipplePattern) {
mask[i] = GL_TRUE;
}
else {
mask[i] = GL_FALSE;
}
swrast->StippleCounter++;
}
}
 
 
/*
* To draw a wide line we can simply redraw the span N times, side by side.
*/
static void
draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor )
{
GLint width, start;
 
ASSERT(span->end < MAX_WIDTH);
 
width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
 
if (width & 1)
start = width / 2;
else
start = width / 2 - 1;
 
if (xMajor) {
GLint *y = span->array->y;
GLuint i;
GLint w;
for (w = 0; w < width; w++) {
if (w == 0) {
for (i = 0; i < span->end; i++)
y[i] -= start;
}
else {
for (i = 0; i < span->end; i++)
y[i]++;
}
if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
_mesa_write_texture_span(ctx, span);
else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
_mesa_write_rgba_span(ctx, span);
else
_mesa_write_index_span(ctx, span);
}
}
else {
GLint *x = span->array->x;
GLuint i;
GLint w;
for (w = 0; w < width; w++) {
if (w == 0) {
for (i = 0; i < span->end; i++)
x[i] -= start;
}
else {
for (i = 0; i < span->end; i++)
x[i]++;
}
if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
_mesa_write_texture_span(ctx, span);
else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
_mesa_write_rgba_span(ctx, span);
else
_mesa_write_index_span(ctx, span);
}
}
}
 
 
 
/**********************************************************************/
/***** Rasterization *****/
/**********************************************************************/
 
 
/* Flat, color index line */
static void flat_ci_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLint *x, *y;
struct sw_span span;
 
ASSERT(ctx->Light.ShadeModel == GL_FLAT);
ASSERT(!ctx->Line.StippleFlag);
ASSERT(ctx->Line.Width == 1.0F);
 
INIT_SPAN(span, GL_LINE, 0, SPAN_INDEX, SPAN_XY);
span.index = IntToFixed(vert1->index);
span.indexStep = 0;
x = span.array->x;
y = span.array->y;
 
#define INTERP_XY 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
span.end++; \
}
 
#include "s_linetemp.h"
 
_mesa_write_index_span(ctx, &span);
}
 
 
/* Flat-shaded, RGBA line */
static void flat_rgba_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
struct sw_span span;
GLint *x, *y;
 
ASSERT(ctx->Light.ShadeModel == GL_FLAT);
ASSERT(!ctx->Line.StippleFlag);
ASSERT(ctx->Line.Width == 1.0F);
 
INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA, SPAN_XY);
span.red = ChanToFixed(vert1->color[0]);
span.green = ChanToFixed(vert1->color[1]);
span.blue = ChanToFixed(vert1->color[2]);
span.alpha = ChanToFixed(vert1->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
x = span.array->x;
y = span.array->y;
 
#define INTERP_XY 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
span.end++; \
}
 
#include "s_linetemp.h"
 
_mesa_write_rgba_span(ctx, &span);
}
 
 
/* Smooth shaded, color index line */
static void smooth_ci_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
struct sw_span span;
GLint *x, *y;
GLuint *index;
 
ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
ASSERT(!ctx->Line.StippleFlag);
ASSERT(ctx->Line.Width == 1.0F);
 
INIT_SPAN(span, GL_LINE, 0, 0, SPAN_XY | SPAN_INDEX);
x = span.array->x;
y = span.array->y;
index = span.array->index;
 
#define INTERP_XY 1
#define INTERP_INDEX 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
index[span.end] = I; \
span.end++; \
}
 
#include "s_linetemp.h"
 
_mesa_write_index_span(ctx, &span);
}
 
 
/* Smooth-shaded, RGBA line */
static void smooth_rgba_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
struct sw_span span;
GLint *x, *y;
GLchan (*rgba)[4];
 
ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
ASSERT(!ctx->Line.StippleFlag);
ASSERT(ctx->Line.Width == 1.0F);
 
INIT_SPAN(span, GL_LINE, 0, 0, SPAN_XY | SPAN_RGBA);
x = span.array->x;
y = span.array->y;
rgba = span.array->rgba;
 
#define INTERP_XY 1
#define INTERP_RGB 1
#define INTERP_ALPHA 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
rgba[span.end][RCOMP] = FixedToInt(r0); \
rgba[span.end][GCOMP] = FixedToInt(g0); \
rgba[span.end][BCOMP] = FixedToInt(b0); \
rgba[span.end][ACOMP] = FixedToInt(a0); \
span.end++; \
}
 
#include "s_linetemp.h"
 
_mesa_write_rgba_span(ctx, &span);
}
 
 
/* Smooth shaded, color index, any width, maybe stippled */
static void general_smooth_ci_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
GLint *x, *y;
GLdepth *z;
GLfloat *fog;
GLuint *index;
 
ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
 
INIT_SPAN(span, GL_LINE, 0, 0,
SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_INDEX);
x = span.array->x;
y = span.array->y;
z = span.array->z;
fog = span.array->fog;
index = span.array->index;
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define INTERP_INDEX 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
z[span.end] = Z; \
fog[span.end] = fog0; \
index[span.end] = I; \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_index_span(ctx, &span);
}
}
 
 
/* Flat shaded, color index, any width, maybe stippled */
static void general_flat_ci_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
GLint *x, *y;
GLdepth *z;
GLfloat *fog;
 
ASSERT(ctx->Light.ShadeModel == GL_FLAT);
 
INIT_SPAN(span, GL_LINE, 0, SPAN_INDEX,
SPAN_XY | SPAN_Z | SPAN_FOG);
span.index = IntToFixed(vert1->index);
span.indexStep = 0;
x = span.array->x;
y = span.array->y;
z = span.array->z;
fog = span.array->fog;
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
z[span.end] = Z; \
fog[span.end] = fog0; \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_index_span(ctx, &span);
}
}
 
 
 
static void general_smooth_rgba_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
GLint *x, *y;
GLdepth *z;
GLchan (*rgba)[4];
GLfloat *fog;
 
ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
 
INIT_SPAN(span, GL_LINE, 0, 0,
SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA);
x = span.array->x;
y = span.array->y;
z = span.array->z;
rgba = span.array->rgba;
fog = span.array->fog;
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define INTERP_RGB 1
#define INTERP_ALPHA 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
z[span.end] = Z; \
rgba[span.end][RCOMP] = FixedToInt(r0); \
rgba[span.end][GCOMP] = FixedToInt(g0); \
rgba[span.end][BCOMP] = FixedToInt(b0); \
rgba[span.end][ACOMP] = FixedToInt(a0); \
fog[span.end] = fog0; \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_rgba_span(ctx, &span);
}
}
 
 
static void general_flat_rgba_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
GLint *x, *y;
GLdepth *z;
GLfloat *fog;
 
ASSERT(ctx->Light.ShadeModel == GL_FLAT);
 
INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA,
SPAN_XY | SPAN_Z | SPAN_FOG);
span.red = ChanToFixed(vert1->color[0]);
span.green = ChanToFixed(vert1->color[1]);
span.blue = ChanToFixed(vert1->color[2]);
span.alpha = ChanToFixed(vert1->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
x = span.array->x;
y = span.array->y;
z = span.array->z;
fog = span.array->fog;
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define PLOT(X,Y) \
{ \
x[span.end] = X; \
y[span.end] = Y; \
z[span.end] = Z; \
fog[span.end] = fog0; \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_rgba_span(ctx, &span);
}
}
 
 
/* Flat-shaded, textured, any width, maybe stippled */
static void flat_textured_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
 
ASSERT(ctx->Light.ShadeModel == GL_FLAT);
 
INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA | SPAN_SPEC,
SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA);
span.red = ChanToFixed(vert1->color[0]);
span.green = ChanToFixed(vert1->color[1]);
span.blue = ChanToFixed(vert1->color[2]);
span.alpha = ChanToFixed(vert1->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
span.specRed = ChanToFixed(vert1->specular[0]);
span.specGreen = ChanToFixed(vert1->specular[1]);
span.specBlue = ChanToFixed(vert1->specular[2]);
span.specRedStep = 0;
span.specGreenStep = 0;
span.specBlueStep = 0;
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define INTERP_TEX 1
#define PLOT(X,Y) \
{ \
span.array->x[span.end] = X; \
span.array->y[span.end] = Y; \
span.array->z[span.end] = Z; \
span.array->fog[span.end] = fog0; \
span.array->texcoords[0][span.end][0] = fragTexcoord[0]; \
span.array->texcoords[0][span.end][1] = fragTexcoord[1]; \
span.array->texcoords[0][span.end][2] = fragTexcoord[2]; \
span.array->lambda[0][span.end] = 0.0; \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_texture_span(ctx, &span);
}
}
 
 
 
/* Smooth-shaded, textured, any width, maybe stippled */
static void smooth_textured_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
 
ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
 
INIT_SPAN(span, GL_LINE, 0, 0,
SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_TEXTURE | SPAN_LAMBDA);
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define INTERP_RGB 1
#define INTERP_ALPHA 1
#define INTERP_TEX 1
#define PLOT(X,Y) \
{ \
span.array->x[span.end] = X; \
span.array->y[span.end] = Y; \
span.array->z[span.end] = Z; \
span.array->fog[span.end] = fog0; \
span.array->rgba[span.end][RCOMP] = FixedToInt(r0); \
span.array->rgba[span.end][GCOMP] = FixedToInt(g0); \
span.array->rgba[span.end][BCOMP] = FixedToInt(b0); \
span.array->rgba[span.end][ACOMP] = FixedToInt(a0); \
span.array->texcoords[0][span.end][0] = fragTexcoord[0]; \
span.array->texcoords[0][span.end][1] = fragTexcoord[1]; \
span.array->texcoords[0][span.end][2] = fragTexcoord[2]; \
span.array->lambda[0][span.end] = 0.0; \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_texture_span(ctx, &span);
}
}
 
 
/* Smooth-shaded, multitextured, any width, maybe stippled, separate specular
* color interpolation.
*/
static void smooth_multitextured_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
GLuint u;
 
ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
 
INIT_SPAN(span, GL_LINE, 0, 0,
SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_SPEC | SPAN_TEXTURE | SPAN_LAMBDA);
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define INTERP_RGB 1
#define INTERP_SPEC 1
#define INTERP_ALPHA 1
#define INTERP_MULTITEX 1
#define PLOT(X,Y) \
{ \
span.array->x[span.end] = X; \
span.array->y[span.end] = Y; \
span.array->z[span.end] = Z; \
span.array->fog[span.end] = fog0; \
span.array->rgba[span.end][RCOMP] = FixedToInt(r0); \
span.array->rgba[span.end][GCOMP] = FixedToInt(g0); \
span.array->rgba[span.end][BCOMP] = FixedToInt(b0); \
span.array->rgba[span.end][ACOMP] = FixedToInt(a0); \
span.array->spec[span.end][RCOMP] = FixedToInt(sr0); \
span.array->spec[span.end][GCOMP] = FixedToInt(sg0); \
span.array->spec[span.end][BCOMP] = FixedToInt(sb0); \
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
if (ctx->Texture.Unit[u]._ReallyEnabled) { \
span.array->texcoords[u][span.end][0] = fragTexcoord[u][0]; \
span.array->texcoords[u][span.end][1] = fragTexcoord[u][1]; \
span.array->texcoords[u][span.end][2] = fragTexcoord[u][2]; \
span.array->lambda[u][span.end] = 0.0; \
} \
} \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_texture_span(ctx, &span);
}
}
 
 
/* Flat-shaded, multitextured, any width, maybe stippled, separate specular
* color interpolation.
*/
static void flat_multitextured_line( GLcontext *ctx,
const SWvertex *vert0,
const SWvertex *vert1 )
{
GLboolean xMajor = GL_FALSE;
struct sw_span span;
GLuint u;
 
ASSERT(ctx->Light.ShadeModel == GL_FLAT);
 
INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA | SPAN_SPEC,
SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA);
span.red = ChanToFixed(vert1->color[0]);
span.green = ChanToFixed(vert1->color[1]);
span.blue = ChanToFixed(vert1->color[2]);
span.alpha = ChanToFixed(vert1->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
span.specRed = ChanToFixed(vert1->specular[0]);
span.specGreen = ChanToFixed(vert1->specular[1]);
span.specBlue = ChanToFixed(vert1->specular[2]);
span.specRedStep = 0;
span.specGreenStep = 0;
span.specBlueStep = 0;
 
#define SET_XMAJOR 1
#define INTERP_XY 1
#define INTERP_Z 1
#define INTERP_FOG 1
#define INTERP_MULTITEX 1
#define PLOT(X,Y) \
{ \
span.array->x[span.end] = X; \
span.array->y[span.end] = Y; \
span.array->z[span.end] = Z; \
span.array->fog[span.end] = fog0; \
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
if (ctx->Texture.Unit[u]._ReallyEnabled) { \
span.array->texcoords[u][span.end][0] = fragTexcoord[u][0]; \
span.array->texcoords[u][span.end][1] = fragTexcoord[u][1]; \
span.array->texcoords[u][span.end][2] = fragTexcoord[u][2]; \
span.array->lambda[u][span.end] = 0.0; \
} \
} \
span.end++; \
}
#include "s_linetemp.h"
 
if (ctx->Line.StippleFlag) {
span.arrayMask |= SPAN_MASK;
compute_stipple_mask(ctx, span.end, span.array->mask);
}
 
if (ctx->Line.Width > 1.0) {
draw_wide_line(ctx, &span, xMajor);
}
else {
_mesa_write_texture_span(ctx, &span);
}
}
 
 
void _swrast_add_spec_terms_line( GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1 )
{
SWvertex *ncv0 = (SWvertex *)v0;
SWvertex *ncv1 = (SWvertex *)v1;
GLchan c[2][4];
COPY_CHAN4( c[0], ncv0->color );
COPY_CHAN4( c[1], ncv1->color );
ACC_3V( ncv0->color, ncv0->specular );
ACC_3V( ncv1->color, ncv1->specular );
SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
COPY_CHAN4( ncv0->color, c[0] );
COPY_CHAN4( ncv1->color, c[1] );
}
 
 
#ifdef DEBUG
extern void
_mesa_print_line_function(GLcontext *ctx); /* silence compiler warning */
void
_mesa_print_line_function(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
_mesa_printf("Line Func == ");
if (swrast->Line == flat_ci_line)
_mesa_printf("flat_ci_line\n");
else if (swrast->Line == flat_rgba_line)
_mesa_printf("flat_rgba_line\n");
else if (swrast->Line == smooth_ci_line)
_mesa_printf("smooth_ci_line\n");
else if (swrast->Line == smooth_rgba_line)
_mesa_printf("smooth_rgba_line\n");
else if (swrast->Line == general_smooth_ci_line)
_mesa_printf("general_smooth_ci_line\n");
else if (swrast->Line == general_flat_ci_line)
_mesa_printf("general_flat_ci_line\n");
else if (swrast->Line == general_smooth_rgba_line)
_mesa_printf("general_smooth_rgba_line\n");
else if (swrast->Line == general_flat_rgba_line)
_mesa_printf("general_flat_rgba_line\n");
else if (swrast->Line == flat_textured_line)
_mesa_printf("flat_textured_line\n");
else if (swrast->Line == smooth_textured_line)
_mesa_printf("smooth_textured_line\n");
else if (swrast->Line == smooth_multitextured_line)
_mesa_printf("smooth_multitextured_line\n");
else if (swrast->Line == flat_multitextured_line)
_mesa_printf("flat_multitextured_line\n");
else
_mesa_printf("Driver func %p\n", (void *) swrast->Line);
}
#endif
 
 
 
#ifdef DEBUG
 
/* record the current line function name */
static const char *lineFuncName = NULL;
 
#define USE(lineFunc) \
do { \
lineFuncName = #lineFunc; \
/*_mesa_printf("%s\n", lineFuncName);*/ \
swrast->Line = lineFunc; \
} while (0)
 
#else
 
#define USE(lineFunc) swrast->Line = lineFunc
 
#endif
 
 
 
/*
* Determine which line drawing function to use given the current
* rendering context.
*
* Please update the summary flag _SWRAST_NEW_LINE if you add or remove
* tests to this code.
*/
void
_swrast_choose_line( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLboolean rgbmode = ctx->Visual.rgbMode;
 
if (ctx->RenderMode == GL_RENDER) {
if (ctx->Line.SmoothFlag) {
/* antialiased lines */
_swrast_choose_aa_line_function(ctx);
ASSERT(swrast->Triangle);
}
else if (ctx->Texture._EnabledUnits) {
if (ctx->Texture._EnabledUnits > 1 ||
(ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) {
/* multi-texture and/or separate specular color */
if (ctx->Light.ShadeModel == GL_SMOOTH)
USE(smooth_multitextured_line);
else
USE(flat_multitextured_line);
}
else {
if (ctx->Light.ShadeModel == GL_SMOOTH) {
USE(smooth_textured_line);
}
else {
USE(flat_textured_line);
}
}
}
else {
if (ctx->Light.ShadeModel == GL_SMOOTH) {
if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
|| ctx->Line.StippleFlag) {
if (rgbmode)
USE(general_smooth_rgba_line);
else
USE(general_smooth_ci_line);
}
else {
if (rgbmode)
USE(smooth_rgba_line);
else
USE(smooth_ci_line);
}
}
else {
if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
|| ctx->Line.StippleFlag) {
if (rgbmode)
USE(general_flat_rgba_line);
else
USE(general_flat_ci_line);
}
else {
if (rgbmode)
USE(flat_rgba_line);
else
USE(flat_ci_line);
}
}
}
}
else if (ctx->RenderMode == GL_FEEDBACK) {
USE(_mesa_feedback_line);
}
else {
ASSERT(ctx->RenderMode == GL_SELECT);
USE(_mesa_select_line);
}
 
/*_mesa_print_line_function(ctx);*/
}
/shark/trunk/ports/mesa/src/swrast/s_fog.c
0,0 → 1,315
/* $Id: s_fog.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "mmath.h"
 
#include "s_context.h"
#include "s_fog.h"
#include "s_span.h"
 
 
 
 
/**
* Used to convert current raster distance to a fog factor in [0,1].
*/
GLfloat
_mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z)
{
GLfloat d, f;
 
switch (ctx->Fog.Mode) {
case GL_LINEAR:
if (ctx->Fog.Start == ctx->Fog.End)
d = 1.0F;
else
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
f = (ctx->Fog.End - z) * d;
return CLAMP(f, 0.0F, 1.0F);
case GL_EXP:
d = ctx->Fog.Density;
f = (GLfloat) exp(-d * z);
return f;
case GL_EXP2:
d = ctx->Fog.Density;
f = (GLfloat) exp(-(d * d * z * z));
return f;
default:
_mesa_problem(ctx, "Bad fog mode in _mesa_z_to_fogfactor");
return 0.0;
}
}
 
 
 
/**
* Calculate fog factors (in [0,1]) from window z values
* Input: n - number of pixels
* z - array of integer depth values
* red, green, blue, alpha - pixel colors
* Output: red, green, blue, alpha - fogged pixel colors
*
* Use lookup table & interpolation?
*/
static void
compute_fog_factors_from_z( const GLcontext *ctx,
GLuint n,
const GLdepth z[],
GLfloat fogFact[] )
{
const GLfloat *proj = ctx->ProjectionMatrixStack.Top->m;
const GLboolean ortho = (proj[15] != 0.0F);
const GLfloat p10 = proj[10];
const GLfloat p14 = proj[14];
const GLfloat tz = ctx->Viewport._WindowMap.m[MAT_TZ];
GLfloat szInv;
GLuint i;
 
if (ctx->Viewport._WindowMap.m[MAT_SZ] == 0.0)
szInv = 1.0F;
else
szInv = 1.0F / ctx->Viewport._WindowMap.m[MAT_SZ];
 
/*
* Note: to compute eyeZ from the ndcZ we have to solve the following:
*
* p[10] * eyeZ + p[14] * eyeW
* ndcZ = ---------------------------
* p[11] * eyeZ + p[15] * eyeW
*
* Thus:
*
* p[14] * eyeW - p[15] * eyeW * ndcZ
* eyeZ = ----------------------------------
* p[11] * ndcZ - p[10]
*
* If we note:
* a) if using an orthographic projection, p[11] = 0 and p[15] = 1.
* b) if using a perspective projection, p[11] = -1 and p[15] = 0.
* c) we assume eyeW = 1 (not always true- glVertex4)
*
* Then we can simplify the calculation of eyeZ quite a bit. We do
* separate calculations for the orthographic and perspective cases below.
* Note that we drop a negative sign or two since they don't matter.
*/
 
switch (ctx->Fog.Mode) {
case GL_LINEAR:
{
GLfloat fogEnd = ctx->Fog.End;
GLfloat fogScale;
if (ctx->Fog.Start == ctx->Fog.End)
fogScale = 1.0;
else
fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
if (ortho) {
for (i=0;i<n;i++) {
GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
GLfloat eyez = (ndcz - p14) / p10;
GLfloat f;
if (eyez < 0.0)
eyez = -eyez;
f = (fogEnd - eyez) * fogScale;
fogFact[i] = CLAMP(f, 0.0F, 1.0F);
}
}
else {
/* perspective */
for (i=0;i<n;i++) {
GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
GLfloat eyez = p14 / (ndcz + p10);
GLfloat f;
if (eyez < 0.0)
eyez = -eyez;
f = (fogEnd - eyez) * fogScale;
fogFact[i] = CLAMP(f, 0.0F, 1.0F);
}
}
}
break;
case GL_EXP:
if (ortho) {
for (i=0;i<n;i++) {
GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
GLfloat eyez = (ndcz - p14) / p10;
if (eyez < 0.0)
eyez = -eyez;
fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez );
}
}
else {
/* perspective */
for (i=0;i<n;i++) {
GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
GLfloat eyez = p14 / (ndcz + p10);
if (eyez < 0.0)
eyez = -eyez;
fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez );
}
}
break;
case GL_EXP2:
{
GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
if (ortho) {
for (i=0;i<n;i++) {
GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
GLfloat eyez = (ndcz - p14) / p10;
GLfloat tmp = negDensitySquared * eyez * eyez;
#if defined(__alpha__) || defined(__alpha)
/* XXX this underflow check may be needed for other systems*/
if (tmp < FLT_MIN_10_EXP)
tmp = FLT_MIN_10_EXP;
#endif
fogFact[i] = (GLfloat) exp( tmp );
}
}
else {
/* perspective */
for (i=0;i<n;i++) {
GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
GLfloat eyez = p14 / (ndcz + p10);
GLfloat tmp = negDensitySquared * eyez * eyez;
#if defined(__alpha__) || defined(__alpha)
/* XXX this underflow check may be needed for other systems*/
if (tmp < FLT_MIN_10_EXP)
tmp = FLT_MIN_10_EXP;
#endif
fogFact[i] = (GLfloat) exp( tmp );
}
}
}
break;
default:
_mesa_problem(ctx, "Bad fog mode in compute_fog_factors_from_z");
return;
}
}
 
 
 
/**
* Apply fog to a span of RGBA pixels.
* The fog factors are either in the span->array->fog or stored as base/step.
* These are fog _factors_, not fog coords. Fog coords were converted to
* fog factors per vertex.
*/
void
_mesa_fog_rgba_span( const GLcontext *ctx, struct sw_span *span )
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLuint n = span->end;
GLchan (*rgba)[4] = (GLchan (*)[4]) span->array->rgba;
GLchan rFog, gFog, bFog;
 
ASSERT(ctx->Fog.Enabled);
ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
ASSERT(span->arrayMask & SPAN_RGBA);
 
UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
 
if (swrast->_PreferPixelFog) {
/* compute fog factor from each fragment's Z value */
if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0)
_mesa_span_interpolate_z(ctx, span);
compute_fog_factors_from_z(ctx, n, span->array->z, span->array->fog);
span->arrayMask |= SPAN_FOG;
}
 
if (span->arrayMask & SPAN_FOG) {
/* use fog array in span */
GLuint i;
for (i = 0; i < n; i++) {
const GLfloat fog = span->array->fog[i];
const GLfloat oneMinusFog = 1.0F - fog;
rgba[i][RCOMP] = (GLchan) (fog * rgba[i][RCOMP] + oneMinusFog * rFog);
rgba[i][GCOMP] = (GLchan) (fog * rgba[i][GCOMP] + oneMinusFog * gFog);
rgba[i][BCOMP] = (GLchan) (fog * rgba[i][BCOMP] + oneMinusFog * bFog);
}
}
else {
/* interpolate fog factors */
GLfloat fog = span->fog, dFog = span->fogStep;
GLuint i;
for (i = 0; i < n; i++) {
const GLfloat oneMinusFog = 1.0F - fog;
rgba[i][RCOMP] = (GLchan) (fog * rgba[i][RCOMP] + oneMinusFog * rFog);
rgba[i][GCOMP] = (GLchan) (fog * rgba[i][GCOMP] + oneMinusFog * gFog);
rgba[i][BCOMP] = (GLchan) (fog * rgba[i][BCOMP] + oneMinusFog * bFog);
fog += dFog;
}
}
}
 
 
/**
* As above, but color index mode.
*/
void
_mesa_fog_ci_span( const GLcontext *ctx, struct sw_span *span )
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLuint n = span->end;
GLuint *index = span->array->index;
 
ASSERT(ctx->Fog.Enabled);
ASSERT(span->arrayMask & SPAN_INDEX);
ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
 
if (swrast->_PreferPixelFog) {
/* compute fog factor from each fragment's Z value */
if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0)
_mesa_span_interpolate_z(ctx, span);
compute_fog_factors_from_z(ctx, n, span->array->z, span->array->fog);
span->arrayMask |= SPAN_FOG;
}
 
if (span->arrayMask & SPAN_FOG) {
const GLuint idx = (GLuint) ctx->Fog.Index;
GLuint i;
for (i = 0; i < n; i++) {
const GLfloat f = CLAMP(span->array->fog[i], 0.0F, 1.0F);
index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx);
}
}
else {
GLfloat fog = span->fog, dFog = span->fogStep;
const GLuint idx = (GLuint) ctx->Fog.Index;
GLuint i;
for (i = 0; i < n; i++) {
const GLfloat f = CLAMP(fog, 0.0F, 1.0F);
index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx);
fog += dFog;
}
}
}
/shark/trunk/ports/mesa/src/swrast/s_imaging.c
0,0 → 1,156
/* $Id: s_imaging.c,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/* KW: Moved these here to remove knowledge of swrast from core mesa.
* Should probably pull the entire software implementation of these
* extensions into either swrast or a sister module.
*/
 
#include "s_context.h"
#include "s_span.h"
 
void
_swrast_CopyColorTable( GLcontext *ctx,
GLenum target, GLenum internalformat,
GLint x, GLint y, GLsizei width)
{
GLchan data[MAX_WIDTH][4];
 
/* Select buffer to read from */
_swrast_use_read_buffer(ctx);
 
if (width > MAX_WIDTH)
width = MAX_WIDTH;
 
/* read the data from framebuffer */
_mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y, data );
 
/* Restore reading from draw buffer (the default) */
_swrast_use_draw_buffer(ctx);
 
glColorTable(target, internalformat, width, GL_RGBA, CHAN_TYPE, data);
}
 
void
_swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
GLint x, GLint y, GLsizei width)
{
GLchan data[MAX_WIDTH][4];
 
/* Select buffer to read from */
_swrast_use_read_buffer(ctx);
 
if (width > MAX_WIDTH)
width = MAX_WIDTH;
 
/* read the data from framebuffer */
_mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y, data );
 
/* Restore reading from draw buffer (the default) */
_swrast_use_draw_buffer(ctx);
 
glColorSubTable(target, start, width, GL_RGBA, CHAN_TYPE, data);
}
 
 
void
_swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
GLenum internalFormat,
GLint x, GLint y, GLsizei width)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLchan rgba[MAX_CONVOLUTION_WIDTH][4];
 
/* Select buffer to read from */
_swrast_use_read_buffer(ctx);
 
RENDER_START( swrast, ctx );
 
/* read the data from framebuffer */
_mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y,
(GLchan (*)[4]) rgba );
RENDER_FINISH( swrast, ctx );
 
/* Restore reading from draw buffer (the default) */
_swrast_use_draw_buffer(ctx);
 
/* store as convolution filter */
glConvolutionFilter1D(target, internalFormat, width,
GL_RGBA, CHAN_TYPE, rgba);
}
 
 
void
_swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_pixelstore_attrib packSave;
GLchan rgba[MAX_CONVOLUTION_HEIGHT][MAX_CONVOLUTION_WIDTH][4];
GLint i;
 
/* Select buffer to read from */
_swrast_use_read_buffer(ctx);
 
RENDER_START(swrast,ctx);
/* read pixels from framebuffer */
for (i = 0; i < height; i++) {
_mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
(GLchan (*)[4]) rgba[i] );
}
 
RENDER_FINISH(swrast,ctx);
 
/* Restore reading from draw buffer (the default) */
_swrast_use_draw_buffer(ctx);
 
/*
* HACK: save & restore context state so we can store this as a
* convolution filter via the GL api. Doesn't call any callbacks
* hanging off ctx->Unpack statechanges.
*/
 
packSave = ctx->Unpack; /* save pixel packing params */
 
ctx->Unpack.Alignment = 1;
ctx->Unpack.RowLength = MAX_CONVOLUTION_WIDTH;
ctx->Unpack.SkipPixels = 0;
ctx->Unpack.SkipRows = 0;
ctx->Unpack.ImageHeight = 0;
ctx->Unpack.SkipImages = 0;
ctx->Unpack.SwapBytes = GL_FALSE;
ctx->Unpack.LsbFirst = GL_FALSE;
ctx->NewState |= _NEW_PACKUNPACK;
 
glConvolutionFilter2D(target, internalFormat, width, height,
GL_RGBA, CHAN_TYPE, rgba);
 
ctx->Unpack = packSave; /* restore pixel packing params */
ctx->NewState |= _NEW_PACKUNPACK;
}
/shark/trunk/ports/mesa/src/swrast/s_bitmap.c
0,0 → 1,255
/* $Id: s_bitmap.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file swrast/s_bitmap.c
* \brief glBitmap rendering.
* \author Brian Paul
*/
 
#include "glheader.h"
#include "image.h"
#include "macros.h"
#include "mmath.h"
#include "pixel.h"
 
#include "s_context.h"
#include "s_span.h"
 
 
 
/*
* Render a bitmap.
*/
void
_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLint row, col;
GLuint count = 0;
struct sw_span span;
 
ASSERT(ctx->RenderMode == GL_RENDER);
ASSERT(bitmap);
 
RENDER_START(swrast,ctx);
 
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived( ctx );
 
INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_XY);
 
if (ctx->Visual.rgbMode) {
span.interpMask |= SPAN_RGBA;
span.red = FloatToFixed(ctx->Current.RasterColor[0] * CHAN_MAXF);
span.green = FloatToFixed(ctx->Current.RasterColor[1] * CHAN_MAXF);
span.blue = FloatToFixed(ctx->Current.RasterColor[2] * CHAN_MAXF);
span.alpha = FloatToFixed(ctx->Current.RasterColor[3] * CHAN_MAXF);
span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0;
}
else {
span.interpMask |= SPAN_INDEX;
span.index = ChanToFixed(ctx->Current.RasterIndex);
span.indexStep = 0;
}
 
if (ctx->Depth.Test)
_mesa_span_default_z(ctx, &span);
if (ctx->Fog.Enabled)
_mesa_span_default_fog(ctx, &span);
 
for (row = 0; row < height; row++, span.y++) {
const GLubyte *src = (const GLubyte *) _mesa_image_address( unpack,
bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
 
if (unpack->LsbFirst) {
/* Lsb first */
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
for (col = 0; col < width; col++) {
if (*src & mask) {
span.array->x[count] = px + col;
span.array->y[count] = py + row;
count++;
}
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
 
/* get ready for next row */
if (mask != 1)
src++;
}
else {
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col = 0; col < width; col++) {
if (*src & mask) {
span.array->x[count] = px + col;
span.array->y[count] = py + row;
count++;
}
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
 
/* get ready for next row */
if (mask != 128)
src++;
}
 
if (count + width >= MAX_WIDTH || row + 1 == height) {
/* flush the span */
span.end = count;
if (ctx->Visual.rgbMode)
_mesa_write_rgba_span(ctx, &span);
else
_mesa_write_index_span(ctx, &span);
span.end = 0;
count = 0;
}
}
 
RENDER_FINISH(swrast,ctx);
}
 
 
#if 0
/*
* XXX this is another way to implement Bitmap. Use horizontal runs of
* fragments, initializing the mask array to indicate which fragmens to
* draw or skip.
*/
void
_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLint row, col;
struct sw_span span;
 
ASSERT(ctx->RenderMode == GL_RENDER);
ASSERT(bitmap);
 
RENDER_START(swrast,ctx);
 
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived( ctx );
 
INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_MASK);
 
/*span.arrayMask |= SPAN_MASK;*/ /* we'll init span.mask[] */
span.x = px;
span.y = py;
/*span.end = width;*/
if (ctx->Visual.rgbMode) {
span.interpMask |= SPAN_RGBA;
span.red = FloatToFixed(ctx->Current.RasterColor[0] * CHAN_MAXF);
span.green = FloatToFixed(ctx->Current.RasterColor[1] * CHAN_MAXF);
span.blue = FloatToFixed(ctx->Current.RasterColor[2] * CHAN_MAXF);
span.alpha = FloatToFixed(ctx->Current.RasterColor[3] * CHAN_MAXF);
span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0;
}
else {
span.interpMask |= SPAN_INDEX;
span.index = ChanToFixed(ctx->Current.RasterIndex);
span.indexStep = 0;
}
 
if (ctx->Depth.Test)
_mesa_span_default_z(ctx, &span);
if (ctx->Fog.Enabled)
_mesa_span_default_fog(ctx, &span);
 
for (row=0; row<height; row++, span.y++) {
const GLubyte *src = (const GLubyte *) _mesa_image_address( unpack,
bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
 
if (unpack->LsbFirst) {
/* Lsb first */
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
 
if (ctx->Visual.rgbMode)
_mesa_write_rgba_span(ctx, &span);
else
_mesa_write_index_span(ctx, &span);
 
/* get ready for next row */
if (mask != 1)
src++;
}
else {
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
 
if (ctx->Visual.rgbMode)
_mesa_write_rgba_span(ctx, &span);
else
_mesa_write_index_span(ctx, &span);
 
/* get ready for next row */
if (mask != 128)
src++;
}
}
 
RENDER_FINISH(swrast,ctx);
}
#endif
/shark/trunk/ports/mesa/src/swrast/s_aatriangle.h
0,0 → 1,40
/* $Id: s_aatriangle.h,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_AATRIANGLE_H
#define S_AATRIANGLE_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern void
_mesa_set_aa_triangle_function(GLcontext *ctx);
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_lines.h
0,0 → 1,42
/* $Id: s_lines.h,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_LINES_H
#define S_LINES_H
 
#include "mtypes.h"
 
void
_swrast_choose_line( GLcontext *ctx );
 
void
_swrast_add_spec_terms_line( GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1 );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_fog.h
0,0 → 1,46
/* $Id: s_fog.h,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_FOG_H
#define S_FOG_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern GLfloat
_mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z);
 
extern void
_mesa_fog_rgba_span( const GLcontext *ctx, struct sw_span *span );
 
extern void
_mesa_fog_ci_span( const GLcontext *ctx, struct sw_span *span );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_alphabuf.c
0,0 → 1,335
/* $Id: s_alphabuf.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* Software alpha planes. Many frame buffers don't have alpha bits so
* we simulate them in software.
*/
 
 
#include "glheader.h"
#include "context.h"
#include "imports.h"
 
#include "s_context.h"
#include "s_alphabuf.h"
 
 
/*
* Allocate a new front and back alpha buffer.
*/
void
_mesa_alloc_alpha_buffers( GLframebuffer *buffer )
{
const GLint bytes = buffer->Width * buffer->Height * sizeof(GLchan);
 
ASSERT(buffer->UseSoftwareAlphaBuffers);
 
if (buffer->FrontLeftAlpha) {
MESA_PBUFFER_FREE( buffer->FrontLeftAlpha );
}
buffer->FrontLeftAlpha = MESA_PBUFFER_ALLOC( bytes );
if (!buffer->FrontLeftAlpha) {
/* out of memory */
_mesa_error( NULL, GL_OUT_OF_MEMORY,
"Couldn't allocate front-left alpha buffer" );
}
 
if (buffer->Visual.doubleBufferMode) {
if (buffer->BackLeftAlpha) {
MESA_PBUFFER_FREE( buffer->BackLeftAlpha );
}
buffer->BackLeftAlpha = MESA_PBUFFER_ALLOC( bytes );
if (!buffer->BackLeftAlpha) {
/* out of memory */
_mesa_error( NULL, GL_OUT_OF_MEMORY,
"Couldn't allocate back-left alpha buffer" );
}
}
 
if (buffer->Visual.stereoMode) {
if (buffer->FrontRightAlpha) {
MESA_PBUFFER_FREE( buffer->FrontRightAlpha );
}
buffer->FrontRightAlpha = MESA_PBUFFER_ALLOC( bytes );
if (!buffer->FrontRightAlpha) {
/* out of memory */
_mesa_error( NULL, GL_OUT_OF_MEMORY,
"Couldn't allocate front-right alpha buffer" );
}
 
if (buffer->Visual.doubleBufferMode) {
if (buffer->BackRightAlpha) {
MESA_PBUFFER_FREE( buffer->BackRightAlpha );
}
buffer->BackRightAlpha = MESA_PBUFFER_ALLOC( bytes );
if (!buffer->BackRightAlpha) {
/* out of memory */
_mesa_error( NULL, GL_OUT_OF_MEMORY,
"Couldn't allocate back-right alpha buffer" );
}
}
}
}
 
 
/*
* Clear all the alpha buffers
*/
void
_mesa_clear_alpha_buffers( GLcontext *ctx )
{
const GLchan aclear = (GLchan) ctx->Color.ClearColor[3];
GLuint bufferBit;
 
ASSERT(ctx->DrawBuffer->UseSoftwareAlphaBuffers);
ASSERT(ctx->Color.ColorMask[ACOMP]);
 
/* loop over four possible alpha buffers */
for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
if (bufferBit & ctx->Color._DrawDestMask) {
GLchan *buffer;
if (bufferBit == FRONT_LEFT_BIT) {
buffer = (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
}
else if (bufferBit == FRONT_RIGHT_BIT) {
buffer = (GLchan *) ctx->DrawBuffer->FrontRightAlpha;
}
else if (bufferBit == BACK_LEFT_BIT) {
buffer = (GLchan *) ctx->DrawBuffer->BackLeftAlpha;
}
else {
buffer = (GLchan *) ctx->DrawBuffer->BackRightAlpha;
}
 
if (ctx->Scissor.Enabled) {
/* clear scissor region */
GLint j;
GLint rowLen = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
GLint width = ctx->DrawBuffer->Width;
GLchan *aptr = buffer
+ ctx->DrawBuffer->_Ymin * ctx->DrawBuffer->Width
+ ctx->DrawBuffer->_Xmin;
for (j = 0; j < rows; j++) {
#if CHAN_BITS == 8
MEMSET( aptr, aclear, rowLen );
#elif CHAN_BITS == 16
MEMSET16( aptr, aclear, rowLen );
#else
GLint i;
for (i = 0; i < rowLen; i++) {
aptr[i] = aclear;
}
#endif
aptr += width;
}
}
else {
/* clear whole buffer */
GLuint pixels = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
#if CHAN_BITS == 8
MEMSET(buffer, aclear, pixels);
#elif CHAN_BITS == 16
MEMSET16(buffer, aclear, pixels);
#else
GLuint i;
for (i = 0; i < pixels; i++) {
buffer[i] = aclear;
}
#endif
}
}
}
}
 
 
 
static INLINE
GLchan *get_alpha_buffer( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
switch (swrast->CurrentBuffer) {
case FRONT_LEFT_BIT:
return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
break;
case BACK_LEFT_BIT:
return (GLchan *) ctx->DrawBuffer->BackLeftAlpha;
break;
case FRONT_RIGHT_BIT:
return (GLchan *) ctx->DrawBuffer->FrontRightAlpha;
break;
case BACK_RIGHT_BIT:
return (GLchan *) ctx->DrawBuffer->BackRightAlpha;
break;
default:
_mesa_problem(ctx, "Bad CurrentBuffer in get_alpha_buffer()");
return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha;
}
}
 
 
void
_mesa_write_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
CONST GLchan rgba[][4], const GLubyte mask[] )
{
GLchan *buffer, *aptr;
GLuint i;
 
buffer = get_alpha_buffer(ctx);
aptr = buffer + y * ctx->DrawBuffer->Width + x;
 
if (mask) {
for (i=0;i<n;i++) {
if (mask[i]) {
*aptr = rgba[i][ACOMP];
}
aptr++;
}
}
else {
for (i=0;i<n;i++) {
*aptr++ = rgba[i][ACOMP];
}
}
}
 
 
void
_mesa_write_mono_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
GLchan alpha, const GLubyte mask[] )
{
GLchan *buffer, *aptr;
GLuint i;
 
buffer = get_alpha_buffer(ctx);
aptr = buffer + y * ctx->DrawBuffer->Width + x;
 
if (mask) {
for (i=0;i<n;i++) {
if (mask[i]) {
*aptr = alpha;
}
aptr++;
}
}
else {
for (i=0;i<n;i++) {
*aptr++ = alpha;
}
}
}
 
 
void
_mesa_write_alpha_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
CONST GLchan rgba[][4], const GLubyte mask[] )
{
GLchan *buffer;
GLuint i;
 
buffer = get_alpha_buffer(ctx);
 
if (mask) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
*aptr = rgba[i][ACOMP];
}
}
}
else {
for (i=0;i<n;i++) {
GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
*aptr = rgba[i][ACOMP];
}
}
}
 
 
void
_mesa_write_mono_alpha_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
GLchan alpha, const GLubyte mask[] )
{
GLchan *buffer;
GLuint i;
 
buffer = get_alpha_buffer(ctx);
 
if (mask) {
for (i=0;i<n;i++) {
if (mask[i]) {
GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
*aptr = alpha;
}
}
}
else {
for (i=0;i<n;i++) {
GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
*aptr = alpha;
}
}
}
 
 
 
void
_mesa_read_alpha_span( GLcontext *ctx,
GLuint n, GLint x, GLint y, GLchan rgba[][4] )
{
const GLchan *buffer, *aptr;
GLuint i;
 
buffer = get_alpha_buffer(ctx);
aptr = buffer + y * ctx->DrawBuffer->Width + x;
 
for (i = 0; i < n; i++)
rgba[i][ACOMP] = *aptr++;
}
 
 
void
_mesa_read_alpha_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
GLchan rgba[][4], const GLubyte mask[] )
{
const GLchan *buffer;
GLuint i;
 
buffer = get_alpha_buffer(ctx);
 
for (i = 0; i < n; i++) {
if (mask[i]) {
const GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i];
rgba[i][ACOMP] = *aptr;
}
}
}
/shark/trunk/ports/mesa/src/swrast/s_zoom.c
0,0 → 1,346
/* $Id: s_zoom.c,v 1.1 2003-02-28 11:49:43 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#include "glheader.h"
#include "macros.h"
#include "imports.h"
#include "colormac.h"
 
#include "s_context.h"
#include "s_span.h"
#include "s_stencil.h"
#include "s_zoom.h"
 
 
/*
* Helper function called from _mesa_write_zoomed_rgba/rgb/index_span().
*/
static void
zoom_span( GLcontext *ctx, const struct sw_span *span,
const GLvoid *src, GLint y0, GLenum format )
{
GLint r0, r1, row;
GLint c0, c1, skipCol;
GLint i, j;
const GLuint maxWidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
GLchan rgbaSave[MAX_WIDTH][4];
GLuint indexSave[MAX_WIDTH];
const GLchan (*rgba)[4] = (const GLchan (*)[4]) src;
const GLchan (*rgb)[3] = (const GLchan (*)[3]) src;
const GLuint *indexes = (const GLuint *) src;
struct sw_span zoomed;
struct span_arrays zoomed_arrays; /* this is big! */
 
/* no pixel arrays! */
ASSERT((span->arrayMask & SPAN_XY) == 0);
ASSERT(span->primitive == GL_BITMAP);
 
INIT_SPAN(zoomed, GL_BITMAP, 0, 0, 0);
zoomed.array = &zoomed_arrays;
 
if (format == GL_RGBA || format == GL_RGB) {
zoomed.z = span->z;
zoomed.zStep = span->z;
zoomed.fog = span->fog;
zoomed.fogStep = span->fogStep;
zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
zoomed.arrayMask |= SPAN_RGBA;
}
else if (format == GL_COLOR_INDEX) {
zoomed.z = span->z;
zoomed.zStep = span->z;
zoomed.fog = span->fog;
zoomed.fogStep = span->fogStep;
zoomed.interpMask = span->interpMask & ~SPAN_INDEX;
zoomed.arrayMask |= SPAN_INDEX;
}
 
/*
* Compute which columns to draw: [c0, c1)
*/
c0 = (GLint) span->x;
c1 = (GLint) (span->x + span->end * ctx->Pixel.ZoomX);
if (c0 == c1) {
return;
}
else if (c1 < c0) {
/* swap */
GLint ctmp = c1;
c1 = c0;
c0 = ctmp;
}
if (c0 < 0) {
zoomed.x = 0;
zoomed.start = 0;
zoomed.end = c1;
skipCol = -c0;
}
else {
zoomed.x = c0;
zoomed.start = 0;
zoomed.end = c1 - c0;
skipCol = 0;
}
if (zoomed.end > maxWidth)
zoomed.end = maxWidth;
 
/*
* Compute which rows to draw: [r0, r1)
*/
row = span->y - y0;
r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
if (r0 == r1) {
return;
}
else if (r1 < r0) {
/* swap */
GLint rtmp = r1;
r1 = r0;
r0 = rtmp;
}
 
ASSERT(r0 < r1);
ASSERT(c0 < c1);
 
/*
* Trivial clip rejection testing.
*/
if (r1 < 0) /* below window */
return;
if (r0 >= (GLint) ctx->DrawBuffer->Height) /* above window */
return;
if (c1 < 0) /* left of window */
return;
if (c0 >= (GLint) ctx->DrawBuffer->Width) /* right of window */
return;
 
/* zoom the span horizontally */
if (format == GL_RGBA) {
if (ctx->Pixel.ZoomX == -1.0F) {
/* common case */
for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
i = span->end - (j + skipCol) - 1;
COPY_CHAN4(zoomed.array->rgba[j], rgba[i]);
}
}
else {
/* general solution */
const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
i = (GLint) ((j + skipCol) * xscale);
if (i < 0)
i = span->end + i - 1;
COPY_CHAN4(zoomed.array->rgba[j], rgba[i]);
}
}
}
else if (format == GL_RGB) {
if (ctx->Pixel.ZoomX == -1.0F) {
/* common case */
for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
i = span->end - (j + skipCol) - 1;
zoomed.array->rgba[j][0] = rgb[i][0];
zoomed.array->rgba[j][1] = rgb[i][1];
zoomed.array->rgba[j][2] = rgb[i][2];
zoomed.array->rgba[j][3] = CHAN_MAX;
}
}
else {
/* general solution */
const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
i = (GLint) ((j + skipCol) * xscale);
if (i < 0)
i = span->end + i - 1;
zoomed.array->rgba[j][0] = rgb[i][0];
zoomed.array->rgba[j][1] = rgb[i][1];
zoomed.array->rgba[j][2] = rgb[i][2];
zoomed.array->rgba[j][3] = CHAN_MAX;
}
}
}
else if (format == GL_COLOR_INDEX) {
if (ctx->Pixel.ZoomX == -1.0F) {
/* common case */
for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
i = span->end - (j + skipCol) - 1;
zoomed.array->index[j] = indexes[i];
}
}
else {
/* general solution */
const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
i = (GLint) ((j + skipCol) * xscale);
if (i < 0)
i = span->end + i - 1;
zoomed.array->index[j] = indexes[i];
}
}
}
 
/* write the span in rows [r0, r1) */
if (format == GL_RGBA || format == GL_RGB) {
/* Writing the span may modify the colors, so make a backup now if we're
* going to call _mesa_write_zoomed_span() more than once.
*/
if (r1 - r0 > 1) {
MEMCPY(rgbaSave, zoomed.array->rgba, zoomed.end * 4 * sizeof(GLchan));
}
for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) {
_mesa_write_rgba_span(ctx, &zoomed);
if (r1 - r0 > 1) {
/* restore the colors */
MEMCPY(zoomed.array->rgba, rgbaSave, zoomed.end*4 * sizeof(GLchan));
}
}
}
else if (format == GL_COLOR_INDEX) {
if (r1 - r0 > 1) {
MEMCPY(indexSave, zoomed.array->index, zoomed.end * sizeof(GLuint));
}
for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) {
_mesa_write_index_span(ctx, &zoomed);
if (r1 - r0 > 1) {
/* restore the colors */
MEMCPY(zoomed.array->index, indexSave, zoomed.end * sizeof(GLuint));
}
}
}
}
 
 
void
_mesa_write_zoomed_rgba_span( GLcontext *ctx, const struct sw_span *span,
CONST GLchan rgba[][4], GLint y0 )
{
zoom_span(ctx, span, (const GLvoid *) rgba, y0, GL_RGBA);
}
 
 
void
_mesa_write_zoomed_rgb_span( GLcontext *ctx, const struct sw_span *span,
CONST GLchan rgb[][3], GLint y0 )
{
zoom_span(ctx, span, (const GLvoid *) rgb, y0, GL_RGB);
}
 
 
void
_mesa_write_zoomed_index_span( GLcontext *ctx, const struct sw_span *span,
GLint y0 )
{
zoom_span(ctx, span, (const GLvoid *) span->array->index, y0, GL_COLOR_INDEX);
}
 
 
/*
* As above, but write stencil values.
*/
void
_mesa_write_zoomed_stencil_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLstencil stencil[], GLint y0 )
{
GLint m;
GLint r0, r1, row, r;
GLint i, j, skipcol;
GLstencil zstencil[MAX_WIDTH]; /* zoomed stencil values */
GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
 
/* compute width of output row */
m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
if (m==0) {
return;
}
if (ctx->Pixel.ZoomX<0.0) {
/* adjust x coordinate for left/right mirroring */
x = x - m;
}
 
/* compute which rows to draw */
row = y-y0;
r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
if (r0==r1) {
return;
}
else if (r1<r0) {
GLint rtmp = r1;
r1 = r0;
r0 = rtmp;
}
 
/* return early if r0...r1 is above or below window */
if (r0<0 && r1<0) {
/* below window */
return;
}
if (r0 >= (GLint) ctx->DrawBuffer->Height &&
r1 >= (GLint) ctx->DrawBuffer->Height) {
/* above window */
return;
}
 
/* check if left edge is outside window */
skipcol = 0;
if (x<0) {
skipcol = -x;
m += x;
}
/* make sure span isn't too long or short */
if (m>maxwidth) {
m = maxwidth;
}
else if (m<=0) {
return;
}
 
ASSERT( m <= MAX_WIDTH );
 
/* zoom the span horizontally */
if (ctx->Pixel.ZoomX==-1.0F) {
/* n==m */
for (j=0;j<m;j++) {
i = n - (j+skipcol) - 1;
zstencil[j] = stencil[i];
}
}
else {
GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
for (j=0;j<m;j++) {
i = (GLint) ((j+skipcol) * xscale);
if (i<0) i = n + i - 1;
zstencil[j] = stencil[i];
}
}
 
/* write the span */
for (r=r0; r<r1; r++) {
_mesa_write_stencil_span( ctx, m, x+skipcol, r, zstencil );
}
}
/shark/trunk/ports/mesa/src/swrast/s_aalinetemp.h
0,0 → 1,315
/* $Id: s_aalinetemp.h,v 1.1 2003-02-28 11:49:40 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* Antialiased line template.
*/
 
 
/*
* Function to render each fragment in the AA line.
*/
static void
NAME(plot)(GLcontext *ctx, struct LineInfo *line, int ix, int iy)
{
const GLfloat fx = (GLfloat) ix;
const GLfloat fy = (GLfloat) iy;
const GLfloat coverage = compute_coveragef(line, ix, iy);
const GLuint i = line->span.end;
 
if (coverage == 0.0)
return;
 
line->span.end++;
line->span.array->coverage[i] = coverage;
line->span.array->x[i] = ix;
line->span.array->y[i] = iy;
 
/*
* Compute Z, color, texture coords, fog for the fragment by
* solving the plane equations at (ix,iy).
*/
#ifdef DO_Z
line->span.array->z[i] = (GLdepth) solve_plane(fx, fy, line->zPlane);
#endif
#ifdef DO_FOG
line->span.array->fog[i] = solve_plane(fx, fy, line->fPlane);
#endif
#ifdef DO_RGBA
line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane);
line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane);
line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane);
line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane);
#endif
#ifdef DO_INDEX
line->span.array->index[i] = (GLint) solve_plane(fx, fy, line->iPlane);
#endif
#ifdef DO_SPEC
line->span.array->spec[i][RCOMP] = solve_plane_chan(fx, fy, line->srPlane);
line->span.array->spec[i][GCOMP] = solve_plane_chan(fx, fy, line->sgPlane);
line->span.array->spec[i][BCOMP] = solve_plane_chan(fx, fy, line->sbPlane);
#endif
#ifdef DO_TEX
{
const GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[0]);
line->span.array->texcoords[0][i][0] = solve_plane(fx, fy, line->sPlane[0]) * invQ;
line->span.array->texcoords[0][i][1] = solve_plane(fx, fy, line->tPlane[0]) * invQ;
line->span.array->texcoords[0][i][2] = solve_plane(fx, fy, line->uPlane[0]) * invQ;
line->span.array->lambda[0][i] = compute_lambda(line->sPlane[0], line->tPlane[0], invQ,
line->texWidth[0], line->texHeight[0]);
}
#elif defined(DO_MULTITEX)
{
GLuint unit;
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
const GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[unit]);
line->span.array->texcoords[unit][i][0] = solve_plane(fx, fy, line->sPlane[unit]) * invQ;
line->span.array->texcoords[unit][i][1] = solve_plane(fx, fy, line->tPlane[unit]) * invQ;
line->span.array->texcoords[unit][i][2] = solve_plane(fx, fy, line->uPlane[unit]) * invQ;
line->span.array->lambda[unit][i] = compute_lambda(line->sPlane[unit],
line->tPlane[unit], invQ,
line->texWidth[unit], line->texHeight[unit]);
}
}
}
#endif
 
if (line->span.end == MAX_WIDTH) {
#if defined(DO_TEX) || defined(DO_MULTITEX)
_mesa_write_texture_span(ctx, &(line->span));
#elif defined(DO_RGBA)
_mesa_write_rgba_span(ctx, &(line->span));
#else
_mesa_write_index_span(ctx, &(line->span));
#endif
line->span.end = 0; /* reset counter */
}
}
 
 
 
/*
* Line setup
*/
static void
NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat tStart, tEnd; /* segment start, end along line length */
GLboolean inSegment;
GLint iLen, i;
 
/* Init the LineInfo struct */
struct LineInfo line;
line.x0 = v0->win[0];
line.y0 = v0->win[1];
line.x1 = v1->win[0];
line.y1 = v1->win[1];
line.dx = line.x1 - line.x0;
line.dy = line.y1 - line.y0;
line.len = (GLfloat) sqrt(line.dx * line.dx + line.dy * line.dy);
line.halfWidth = 0.5F * ctx->Line.Width;
 
if (line.len == 0.0 || IS_INF_OR_NAN(line.len))
return;
 
INIT_SPAN(line.span, GL_LINE, 0, 0, SPAN_XY | SPAN_COVERAGE);
 
line.xAdj = line.dx / line.len * line.halfWidth;
line.yAdj = line.dy / line.len * line.halfWidth;
 
#ifdef DO_Z
line.span.arrayMask |= SPAN_Z;
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->win[2], v1->win[2], line.zPlane);
#endif
#ifdef DO_FOG
line.span.arrayMask |= SPAN_FOG;
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->fog, v1->fog, line.fPlane);
#endif
#ifdef DO_RGBA
line.span.arrayMask |= SPAN_RGBA;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[RCOMP], v1->color[RCOMP], line.rPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[GCOMP], v1->color[GCOMP], line.gPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[BCOMP], v1->color[BCOMP], line.bPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[ACOMP], v1->color[ACOMP], line.aPlane);
}
else {
constant_plane(v1->color[RCOMP], line.rPlane);
constant_plane(v1->color[GCOMP], line.gPlane);
constant_plane(v1->color[BCOMP], line.bPlane);
constant_plane(v1->color[ACOMP], line.aPlane);
}
#endif
#ifdef DO_SPEC
line.span.arrayMask |= SPAN_SPEC;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->specular[RCOMP], v1->specular[RCOMP], line.srPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->specular[GCOMP], v1->specular[GCOMP], line.sgPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->specular[BCOMP], v1->specular[BCOMP], line.sbPlane);
}
else {
constant_plane(v1->specular[RCOMP], line.srPlane);
constant_plane(v1->specular[GCOMP], line.sgPlane);
constant_plane(v1->specular[BCOMP], line.sbPlane);
}
#endif
#ifdef DO_INDEX
line.span.arrayMask |= SPAN_INDEX;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(line.x0, line.y0, line.x1, line.y1,
(GLfloat) v0->index, (GLfloat) v1->index, line.iPlane);
}
else {
constant_plane((GLfloat) v1->index, line.iPlane);
}
#endif
#ifdef DO_TEX
{
const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
const GLfloat invW0 = v0->win[3];
const GLfloat invW1 = v1->win[3];
const GLfloat s0 = v0->texcoord[0][0] * invW0;
const GLfloat s1 = v1->texcoord[0][0] * invW1;
const GLfloat t0 = v0->texcoord[0][1] * invW0;
const GLfloat t1 = v1->texcoord[0][1] * invW0;
const GLfloat r0 = v0->texcoord[0][2] * invW0;
const GLfloat r1 = v1->texcoord[0][2] * invW0;
const GLfloat q0 = v0->texcoord[0][3] * invW0;
const GLfloat q1 = v1->texcoord[0][3] * invW0;
line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[0]);
compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[0]);
compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[0]);
compute_plane(line.x0, line.y0, line.x1, line.y1, q0, q1, line.vPlane[0]);
line.texWidth[0] = (GLfloat) texImage->Width;
line.texHeight[0] = (GLfloat) texImage->Height;
}
#elif defined(DO_MULTITEX)
{
GLuint u;
line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
const GLfloat invW0 = v0->win[3];
const GLfloat invW1 = v1->win[3];
const GLfloat s0 = v0->texcoord[u][0] * invW0;
const GLfloat s1 = v1->texcoord[u][0] * invW1;
const GLfloat t0 = v0->texcoord[u][1] * invW0;
const GLfloat t1 = v1->texcoord[u][1] * invW0;
const GLfloat r0 = v0->texcoord[u][2] * invW0;
const GLfloat r1 = v1->texcoord[u][2] * invW0;
const GLfloat q0 = v0->texcoord[u][3] * invW0;
const GLfloat q1 = v1->texcoord[u][3] * invW0;
compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[u]);
compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[u]);
compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[u]);
compute_plane(line.x0, line.y0, line.x1, line.y1, q0, q1, line.vPlane[u]);
line.texWidth[u] = (GLfloat) texImage->Width;
line.texHeight[u] = (GLfloat) texImage->Height;
}
}
}
#endif
 
tStart = tEnd = 0.0;
inSegment = GL_FALSE;
iLen = (GLint) line.len;
 
if (ctx->Line.StippleFlag) {
for (i = 0; i < iLen; i++) {
const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
if ((1 << bit) & ctx->Line.StipplePattern) {
/* stipple bit is on */
const GLfloat t = (GLfloat) i / (GLfloat) line.len;
if (!inSegment) {
/* start new segment */
inSegment = GL_TRUE;
tStart = t;
}
else {
/* still in the segment, extend it */
tEnd = t;
}
}
else {
/* stipple bit is off */
if (inSegment && (tEnd > tStart)) {
/* draw the segment */
segment(ctx, &line, NAME(plot), tStart, tEnd);
inSegment = GL_FALSE;
}
else {
/* still between segments, do nothing */
}
}
swrast->StippleCounter++;
}
 
if (inSegment) {
/* draw the final segment of the line */
segment(ctx, &line, NAME(plot), tStart, 1.0F);
}
}
else {
/* non-stippled */
segment(ctx, &line, NAME(plot), 0.0, 1.0);
}
 
#if defined(DO_TEX) || defined(DO_MULTITEX)
_mesa_write_texture_span(ctx, &(line.span));
#elif defined(DO_RGBA)
_mesa_write_rgba_span(ctx, &(line.span));
#else
_mesa_write_index_span(ctx, &(line.span));
#endif
}
 
 
 
 
#undef DO_Z
#undef DO_FOG
#undef DO_RGBA
#undef DO_INDEX
#undef DO_SPEC
#undef DO_TEX
#undef DO_MULTITEX
#undef NAME
/shark/trunk/ports/mesa/src/swrast/s_context.c
0,0 → 1,660
/* $Id: s_context.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "glheader.h"
#include "context.h"
#include "mtypes.h"
#include "imports.h"
 
#include "swrast.h"
#include "s_blend.h"
#include "s_context.h"
#include "s_lines.h"
#include "s_points.h"
#include "s_span.h"
#include "s_triangle.h"
#include "s_texture.h"
 
 
/*
* Recompute the value of swrast->_RasterMask, etc. according to
* the current context.
*/
static void
_swrast_update_rasterflags( GLcontext *ctx )
{
GLuint RasterMask = 0;
 
if (ctx->Color.AlphaEnabled) RasterMask |= ALPHATEST_BIT;
if (ctx->Color.BlendEnabled) RasterMask |= BLEND_BIT;
if (ctx->Depth.Test) RasterMask |= DEPTH_BIT;
if (ctx->Fog.Enabled) RasterMask |= FOG_BIT;
if (ctx->Scissor.Enabled) RasterMask |= CLIP_BIT;
if (ctx->Stencil.Enabled) RasterMask |= STENCIL_BIT;
if (ctx->Visual.rgbMode) {
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
if (colorMask != 0xffffffff) RasterMask |= MASKING_BIT;
if (ctx->Color.ColorLogicOpEnabled) RasterMask |= LOGIC_OP_BIT;
if (ctx->Texture._EnabledUnits) RasterMask |= TEXTURE_BIT;
}
else {
if (ctx->Color.IndexMask != 0xffffffff) RasterMask |= MASKING_BIT;
if (ctx->Color.IndexLogicOpEnabled) RasterMask |= LOGIC_OP_BIT;
}
 
if (ctx->DrawBuffer->UseSoftwareAlphaBuffers
&& ctx->Color.ColorMask[ACOMP]
&& ctx->Color.DrawBuffer != GL_NONE)
RasterMask |= ALPHABUF_BIT;
 
if ( ctx->Viewport.X < 0
|| ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width
|| ctx->Viewport.Y < 0
|| ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) {
RasterMask |= CLIP_BIT;
}
 
if (ctx->Depth.OcclusionTest)
RasterMask |= OCCLUSION_BIT;
 
 
/* If we're not drawing to exactly one color buffer set the
* MULTI_DRAW_BIT flag. Also set it if we're drawing to no
* buffers or the RGBA or CI mask disables all writes.
*/
if (ctx->Color._DrawDestMask != FRONT_LEFT_BIT &&
ctx->Color._DrawDestMask != BACK_LEFT_BIT &&
ctx->Color._DrawDestMask != FRONT_RIGHT_BIT &&
ctx->Color._DrawDestMask != BACK_RIGHT_BIT) {
/* more than one color buffer designated for writing (or zero buffers) */
RasterMask |= MULTI_DRAW_BIT;
}
else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) {
RasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
}
else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) {
RasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */
}
 
SWRAST_CONTEXT(ctx)->_RasterMask = RasterMask;
}
 
 
static void
_swrast_update_polygon( GLcontext *ctx )
{
GLfloat backface_sign = 1;
 
if (ctx->Polygon.CullFlag) {
backface_sign = 1;
switch(ctx->Polygon.CullFaceMode) {
case GL_BACK:
if(ctx->Polygon.FrontFace==GL_CCW)
backface_sign = -1;
break;
case GL_FRONT:
if(ctx->Polygon.FrontFace!=GL_CCW)
backface_sign = -1;
break;
default:
case GL_FRONT_AND_BACK:
backface_sign = 0;
break;
}
}
else {
backface_sign = 0;
}
 
SWRAST_CONTEXT(ctx)->_backface_sign = backface_sign;
}
 
 
static void
_swrast_update_hint( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
(ctx->Hint.Fog == GL_NICEST &&
swrast->AllowPixelFog));
}
 
 
/*
* Update the swrast->_AnyTextureCombine flag.
*/
static void
_swrast_update_texture_env( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
swrast->_AnyTextureCombine = GL_FALSE;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT ||
ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) {
swrast->_AnyTextureCombine = GL_TRUE;
return;
}
}
}
 
 
#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \
_NEW_TEXTURE | \
_NEW_HINT | \
_NEW_POLYGON )
 
/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
*/
#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \
_NEW_RENDERMODE| \
_NEW_POLYGON| \
_NEW_DEPTH| \
_NEW_STENCIL| \
_NEW_COLOR| \
_NEW_TEXTURE| \
_SWRAST_NEW_RASTERMASK| \
_NEW_LIGHT| \
_NEW_FOG | \
_DD_NEW_SEPARATE_SPECULAR)
 
#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \
_NEW_RENDERMODE| \
_NEW_LINE| \
_NEW_TEXTURE| \
_NEW_LIGHT| \
_NEW_FOG| \
_NEW_DEPTH | \
_DD_NEW_SEPARATE_SPECULAR)
 
#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \
_NEW_RENDERMODE | \
_NEW_POINT | \
_NEW_TEXTURE | \
_NEW_LIGHT | \
_NEW_FOG | \
_DD_NEW_SEPARATE_SPECULAR)
 
#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
 
#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
 
#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
 
 
 
/* Stub for swrast->Triangle to select a true triangle function
* after a state change.
*/
static void
_swrast_validate_triangle( GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2 )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
_swrast_validate_derived( ctx );
swrast->choose_triangle( ctx );
 
if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) &&
ctx->Texture._EnabledUnits == 0) {
swrast->SpecTriangle = swrast->Triangle;
swrast->Triangle = _swrast_add_spec_terms_triangle;
}
 
swrast->Triangle( ctx, v0, v1, v2 );
}
 
static void
_swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
_swrast_validate_derived( ctx );
swrast->choose_line( ctx );
 
if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) &&
ctx->Texture._EnabledUnits == 0) {
swrast->SpecLine = swrast->Line;
swrast->Line = _swrast_add_spec_terms_line;
}
 
 
swrast->Line( ctx, v0, v1 );
}
 
static void
_swrast_validate_point( GLcontext *ctx, const SWvertex *v0 )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
_swrast_validate_derived( ctx );
swrast->choose_point( ctx );
 
if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) &&
ctx->Texture._EnabledUnits == 0) {
swrast->SpecPoint = swrast->Point;
swrast->Point = _swrast_add_spec_terms_point;
}
 
swrast->Point( ctx, v0 );
}
 
static void
_swrast_validate_blend_func( GLcontext *ctx, GLuint n,
const GLubyte mask[],
GLchan src[][4],
CONST GLchan dst[][4] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
_swrast_validate_derived( ctx );
_swrast_choose_blend_func( ctx );
 
swrast->BlendFunc( ctx, n, mask, src, dst );
}
 
 
static void
_swrast_validate_texture_sample( GLcontext *ctx, GLuint texUnit,
const struct gl_texture_object *tObj,
GLuint n, GLfloat texcoords[][4],
const GLfloat lambda[], GLchan rgba[][4] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
_swrast_validate_derived( ctx );
_swrast_choose_texture_sample_func( ctx, texUnit, tObj );
 
swrast->TextureSample[texUnit]( ctx, texUnit, tObj, n, texcoords,
lambda, rgba );
}
 
 
static void
_swrast_sleep( GLcontext *ctx, GLuint new_state )
{
}
 
 
static void
_swrast_invalidate_state( GLcontext *ctx, GLuint new_state )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
 
swrast->NewState |= new_state;
 
/* After 10 statechanges without any swrast functions being called,
* put the module to sleep.
*/
if (++swrast->StateChanges > 10) {
swrast->InvalidateState = _swrast_sleep;
swrast->NewState = ~0;
new_state = ~0;
}
 
if (new_state & swrast->invalidate_triangle)
swrast->Triangle = _swrast_validate_triangle;
 
if (new_state & swrast->invalidate_line)
swrast->Line = _swrast_validate_line;
 
if (new_state & swrast->invalidate_point)
swrast->Point = _swrast_validate_point;
 
if (new_state & _SWRAST_NEW_BLEND_FUNC)
swrast->BlendFunc = _swrast_validate_blend_func;
 
if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
swrast->TextureSample[i] = _swrast_validate_texture_sample;
 
if (ctx->Visual.rgbMode) {
ASSERT(swrast->Driver.WriteRGBASpan);
ASSERT(swrast->Driver.WriteRGBSpan);
ASSERT(swrast->Driver.WriteMonoRGBASpan);
ASSERT(swrast->Driver.WriteRGBAPixels);
ASSERT(swrast->Driver.WriteMonoRGBAPixels);
ASSERT(swrast->Driver.ReadRGBASpan);
ASSERT(swrast->Driver.ReadRGBAPixels);
}
else {
ASSERT(swrast->Driver.WriteCI32Span);
ASSERT(swrast->Driver.WriteCI8Span);
ASSERT(swrast->Driver.WriteMonoCISpan);
ASSERT(swrast->Driver.WriteCI32Pixels);
ASSERT(swrast->Driver.WriteMonoCIPixels);
ASSERT(swrast->Driver.ReadCI32Span);
ASSERT(swrast->Driver.ReadCI32Pixels);
}
}
 
 
void
_swrast_validate_derived( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
if (swrast->NewState) {
if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
_swrast_update_rasterflags( ctx );
 
if (swrast->NewState & _NEW_POLYGON)
_swrast_update_polygon( ctx );
 
if (swrast->NewState & _NEW_HINT)
_swrast_update_hint( ctx );
 
if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
_swrast_update_texture_env( ctx );
 
swrast->NewState = 0;
swrast->StateChanges = 0;
swrast->InvalidateState = _swrast_invalidate_state;
}
}
 
#define SWRAST_DEBUG 0
 
/* Public entrypoints: See also s_accum.c, s_bitmap.c, etc.
*/
void
_swrast_Quad( GLcontext *ctx,
const SWvertex *v0, const SWvertex *v1,
const SWvertex *v2, const SWvertex *v3 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Quad\n");
_swrast_print_vertex( ctx, v0 );
_swrast_print_vertex( ctx, v1 );
_swrast_print_vertex( ctx, v2 );
_swrast_print_vertex( ctx, v3 );
}
SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
}
 
void
_swrast_Triangle( GLcontext *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Triangle\n");
_swrast_print_vertex( ctx, v0 );
_swrast_print_vertex( ctx, v1 );
_swrast_print_vertex( ctx, v2 );
}
SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
}
 
void
_swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Line\n");
_swrast_print_vertex( ctx, v0 );
_swrast_print_vertex( ctx, v1 );
}
SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
}
 
void
_swrast_Point( GLcontext *ctx, const SWvertex *v0 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Point\n");
_swrast_print_vertex( ctx, v0 );
}
SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
}
 
void
_swrast_InvalidateState( GLcontext *ctx, GLuint new_state )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_InvalidateState\n");
}
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
}
 
void
_swrast_ResetLineStipple( GLcontext *ctx )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_ResetLineStipple\n");
}
SWRAST_CONTEXT(ctx)->StippleCounter = 0;
}
 
void
_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
}
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
}
 
void
_swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
}
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
}
 
 
GLboolean
_swrast_CreateContext( GLcontext *ctx )
{
GLuint i;
SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext));
 
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_CreateContext\n");
}
 
if (!swrast)
return GL_FALSE;
 
swrast->NewState = ~0;
 
swrast->choose_point = _swrast_choose_point;
swrast->choose_line = _swrast_choose_line;
swrast->choose_triangle = _swrast_choose_triangle;
 
swrast->invalidate_point = _SWRAST_NEW_POINT;
swrast->invalidate_line = _SWRAST_NEW_LINE;
swrast->invalidate_triangle = _SWRAST_NEW_TRIANGLE;
 
swrast->Point = _swrast_validate_point;
swrast->Line = _swrast_validate_line;
swrast->Triangle = _swrast_validate_triangle;
swrast->InvalidateState = _swrast_sleep;
swrast->BlendFunc = _swrast_validate_blend_func;
 
swrast->AllowVertexFog = GL_TRUE;
swrast->AllowPixelFog = GL_TRUE;
 
if (ctx->Visual.doubleBufferMode)
swrast->CurrentBuffer = BACK_LEFT_BIT;
else
swrast->CurrentBuffer = FRONT_LEFT_BIT;
 
/* Optimized Accum buffer */
swrast->_IntegerAccumMode = GL_TRUE;
swrast->_IntegerAccumScaler = 0.0;
 
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
swrast->TextureSample[i] = _swrast_validate_texture_sample;
 
swrast->SpanArrays = MALLOC_STRUCT(span_arrays);
if (!swrast->SpanArrays) {
FREE(swrast);
return GL_FALSE;
}
 
/* init point span buffer */
swrast->PointSpan.primitive = GL_POINT;
swrast->PointSpan.start = 0;
swrast->PointSpan.end = 0;
swrast->PointSpan.facing = 0;
swrast->PointSpan.array = swrast->SpanArrays;
 
assert(ctx->Const.MaxTextureUnits > 0);
assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_UNITS);
 
swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureUnits *
MAX_WIDTH * 4 * sizeof(GLchan));
if (!swrast->TexelBuffer) {
FREE(swrast->SpanArrays);
FREE(swrast);
return GL_FALSE;
}
 
ctx->swrast_context = swrast;
 
return GL_TRUE;
}
 
void
_swrast_DestroyContext( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_DestroyContext\n");
}
 
FREE( swrast->SpanArrays );
FREE( swrast->TexelBuffer );
FREE( swrast );
 
ctx->swrast_context = 0;
}
 
 
struct swrast_device_driver *
_swrast_GetDeviceDriverReference( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
return &swrast->Driver;
}
 
void
_swrast_flush( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* flush any pending fragments from rendering points */
if (swrast->PointSpan.end > 0) {
if (ctx->Visual.rgbMode) {
if (ctx->Texture._EnabledUnits)
_mesa_write_texture_span(ctx, &(swrast->PointSpan));
else
_mesa_write_rgba_span(ctx, &(swrast->PointSpan));
}
else {
_mesa_write_index_span(ctx, &(swrast->PointSpan));
}
swrast->PointSpan.end = 0;
}
}
 
void
_swrast_render_primitive( GLcontext *ctx, GLenum prim )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
_swrast_flush(ctx);
}
swrast->Primitive = prim;
}
 
 
void
_swrast_render_start( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.SpanRenderStart)
swrast->Driver.SpanRenderStart( ctx );
swrast->PointSpan.end = 0;
}
void
_swrast_render_finish( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.SpanRenderFinish)
swrast->Driver.SpanRenderFinish( ctx );
 
_swrast_flush(ctx);
}
 
 
#define SWRAST_DEBUG_VERTICES 0
 
void
_swrast_print_vertex( GLcontext *ctx, const SWvertex *v )
{
GLuint i;
 
if (SWRAST_DEBUG_VERTICES) {
_mesa_debug(ctx, "win %f %f %f %f\n",
v->win[0], v->win[1], v->win[2], v->win[3]);
 
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
if (ctx->Texture.Unit[i]._ReallyEnabled)
_mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
v->texcoord[i][0], v->texcoord[i][1],
v->texcoord[i][2], v->texcoord[i][3]);
 
#if CHAN_TYPE == GL_FLOAT
_mesa_debug(ctx, "color %f %f %f %f\n",
v->color[0], v->color[1], v->color[2], v->color[3]);
_mesa_debug(ctx, "spec %f %f %f %f\n",
v->specular[0], v->specular[1],
v->specular[2], v->specular[3]);
#else
_mesa_debug(ctx, "color %d %d %d %d\n",
v->color[0], v->color[1], v->color[2], v->color[3]);
_mesa_debug(ctx, "spec %d %d %d %d\n",
v->specular[0], v->specular[1],
v->specular[2], v->specular[3]);
#endif
_mesa_debug(ctx, "fog %f\n", v->fog);
_mesa_debug(ctx, "index %d\n", v->index);
_mesa_debug(ctx, "pointsize %f\n", v->pointSize);
_mesa_debug(ctx, "\n");
}
}
/shark/trunk/ports/mesa/src/swrast/s_pointtemp.h
0,0 → 1,373
/* $Id: s_pointtemp.h,v 1.1 2003-02-28 11:49:42 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 5.0
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* Point rendering template code.
*
* Set FLAGS = bitwise-OR of the following tokens:
*
* RGBA = do rgba instead of color index
* SMOOTH = do antialiasing
* TEXTURE = do texture coords
* SPECULAR = do separate specular color
* LARGE = do points with diameter > 1 pixel
* ATTENUATE = compute point size attenuation
* SPRITE = GL_NV_point_sprite
*
* Notes: LARGE and ATTENUATE are exclusive of each other.
* TEXTURE requires RGBA
* SPECULAR requires TEXTURE
*/
 
 
/*
* NOTES on antialiased point rasterization:
*
* Let d = distance of fragment center from vertex.
* if d < rmin2 then
* fragment has 100% coverage
* else if d > rmax2 then
* fragment has 0% coverage
* else
* fragment has % coverage = (d - rmin2) / (rmax2 - rmin2)
*/
 
 
 
static void
NAME ( GLcontext *ctx, const SWvertex *vert )
{
#if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
GLfloat size;
#endif
#if FLAGS & ATTENUATE
GLfloat alphaAtten;
#endif
#if FLAGS & RGBA
const GLchan red = vert->color[0];
const GLchan green = vert->color[1];
const GLchan blue = vert->color[2];
const GLchan alpha = vert->color[3];
#endif
#if FLAGS & SPECULAR
const GLchan specRed = vert->specular[0];
const GLchan specGreen = vert->specular[1];
const GLchan specBlue = vert->specular[2];
#endif
#if FLAGS & INDEX
const GLuint colorIndex = vert->index;
#endif
#if FLAGS & TEXTURE
GLfloat texcoord[MAX_TEXTURE_UNITS][4];
GLuint u;
#endif
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct sw_span *span = &(swrast->PointSpan);
 
/* Cull primitives with malformed coordinates.
*/
{
float tmp = vert->win[0] + vert->win[1];
if (IS_INF_OR_NAN(tmp))
return;
}
 
/*
* Span init
*/
span->interpMask = SPAN_FOG;
span->arrayMask = SPAN_XY | SPAN_Z;
span->fog = vert->fog;
span->fogStep = 0.0;
#if FLAGS & RGBA
span->arrayMask |= SPAN_RGBA;
#endif
#if FLAGS & SPECULAR
span->arrayMask |= SPAN_SPEC;
#endif
#if FLAGS & INDEX
span->arrayMask |= SPAN_INDEX;
#endif
#if FLAGS & TEXTURE
span->arrayMask |= SPAN_TEXTURE;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
const GLfloat q = vert->texcoord[u][3];
const GLfloat invQ = (q == 0.0F || q == 1.0F) ? 1.0F : (1.0F / q);
texcoord[u][0] = vert->texcoord[u][0] * invQ;
texcoord[u][1] = vert->texcoord[u][1] * invQ;
texcoord[u][2] = vert->texcoord[u][2] * invQ;
texcoord[u][3] = q;
}
}
#endif
#if FLAGS & SMOOTH
span->arrayMask |= SPAN_COVERAGE;
#endif
#if FLAGS & SPRITE
span->arrayMask |= SPAN_TEXTURE;
#endif
 
#if FLAGS & ATTENUATE
if (vert->pointSize >= ctx->Point.Threshold) {
size = MIN2(vert->pointSize, ctx->Point.MaxSize);
alphaAtten = 1.0F;
}
else {
GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
size = MAX2(ctx->Point.Threshold, ctx->Point.MinSize);
alphaAtten = dsize * dsize;
}
#elif FLAGS & (LARGE | SMOOTH | SPRITE)
size = ctx->Point._Size;
#endif
 
#if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
/*
* Multi-pixel points
*/
{{
GLint x, y;
const GLfloat radius = 0.5F * size;
const GLint z = (GLint) (vert->win[2] + 0.5F);
GLuint count;
#if FLAGS & SMOOTH
const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
const GLfloat rmax = radius + 0.7071F;
const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
const GLfloat rmax2 = rmax * rmax;
const GLfloat cscale = 1.0F / (rmax2 - rmin2);
const GLint xmin = (GLint) (vert->win[0] - radius);
const GLint xmax = (GLint) (vert->win[0] + radius);
const GLint ymin = (GLint) (vert->win[1] - radius);
const GLint ymax = (GLint) (vert->win[1] + radius);
#else
/* non-smooth */
GLint xmin, xmax, ymin, ymax;
GLint iSize = (GLint) (size + 0.5F);
GLint iRadius;
iSize = MAX2(1, iSize);
iRadius = iSize / 2;
if (iSize & 1) {
/* odd size */
xmin = (GLint) (vert->win[0] - iRadius);
xmax = (GLint) (vert->win[0] + iRadius);
ymin = (GLint) (vert->win[1] - iRadius);
ymax = (GLint) (vert->win[1] + iRadius);
}
else {
/* even size */
xmin = (GLint) vert->win[0] - iRadius + 1;
xmax = xmin + iSize - 1;
ymin = (GLint) vert->win[1] - iRadius + 1;
ymax = ymin + iSize - 1;
}
#endif /*SMOOTH*/
 
/* check if we need to flush */
if (span->end + (xmax-xmin+1) * (ymax-ymin+1) >= MAX_WIDTH ||
(swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
#if FLAGS & (TEXTURE | SPRITE)
if (ctx->Texture._EnabledUnits)
_mesa_write_texture_span(ctx, span);
else
_mesa_write_rgba_span(ctx, span);
#elif FLAGS & RGBA
_mesa_write_rgba_span(ctx, span);
#else
_mesa_write_index_span(ctx, span);
#endif
span->end = 0;
}
 
/*
* OK, generate fragments
*/
count = span->end;
(void) radius;
for (y = ymin; y <= ymax; y++) {
for (x = xmin; x <= xmax; x++) {
#if FLAGS & (SPRITE | TEXTURE)
GLuint u;
#endif
 
#if FLAGS & RGBA
span->array->rgba[count][RCOMP] = red;
span->array->rgba[count][GCOMP] = green;
span->array->rgba[count][BCOMP] = blue;
span->array->rgba[count][ACOMP] = alpha;
#endif
#if FLAGS & SPECULAR
span->array->spec[count][RCOMP] = specRed;
span->array->spec[count][GCOMP] = specGreen;
span->array->spec[count][BCOMP] = specBlue;
#endif
#if FLAGS & INDEX
span->array->index[count] = colorIndex;
#endif
#if FLAGS & TEXTURE
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
COPY_4V(span->array->texcoords[u][count], texcoord[u]);
}
}
#endif
 
#if FLAGS & SMOOTH
/* compute coverage */
{
const GLfloat dx = x - vert->win[0] + 0.5F;
const GLfloat dy = y - vert->win[1] + 0.5F;
const GLfloat dist2 = dx * dx + dy * dy;
if (dist2 < rmax2) {
if (dist2 >= rmin2) {
/* compute partial coverage */
span->array->coverage[count] = 1.0F - (dist2 - rmin2) * cscale;
#if FLAGS & INDEX
/* coverage in [0,15] */
span->array->coverage[count] *= 15.0;
#endif
}
else {
/* full coverage */
span->array->coverage[count] = 1.0F;
}
 
span->array->x[count] = x;
span->array->y[count] = y;
span->array->z[count] = z;
 
#if (FLAGS & ATTENUATE) && (FLAGS & RGBA)
span->array->rgba[count][ACOMP] = (GLchan) (alpha * alphaAtten);
#elif FLAGS & RGBA
span->array->rgba[count][ACOMP] = alpha;
#endif /*ATTENUATE*/
count++;
} /*if*/
}
 
#else /*SMOOTH*/
 
/* not smooth (square points) */
span->array->x[count] = x;
span->array->y[count] = y;
span->array->z[count] = z;
 
#if FLAGS & SPRITE
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
if (ctx->Point.CoordReplace[u]) {
GLfloat s = 0.5F + (x + 0.5F - vert->win[0]) / size;
GLfloat t = 0.5F - (y + 0.5F - vert->win[1]) / size;
span->array->texcoords[u][count][0] = s;
span->array->texcoords[u][count][1] = t;
span->array->texcoords[u][count][3] = 1.0F;
if (ctx->Point.SpriteRMode == GL_ZERO)
span->array->texcoords[u][count][2] = 0.0F;
else if (ctx->Point.SpriteRMode == GL_S)
span->array->texcoords[u][count][2] = vert->texcoord[u][0];
else /* GL_R */
span->array->texcoords[u][count][2] = vert->texcoord[u][2];
}
else {
COPY_4V(span->array->texcoords[u][count], vert->texcoord[u]);
}
}
}
#endif /*SPRITE*/
 
count++; /* square point */
 
#endif /*SMOOTH*/
 
} /*for x*/
} /*for y*/
span->end = count;
}}
 
#else /* LARGE | ATTENUATE | SMOOTH | SPRITE */
 
/*
* Single-pixel points
*/
{{
GLuint count;
 
/* check if we need to flush */
if (span->end >= MAX_WIDTH ||
(swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
#if FLAGS & (TEXTURE | SPRITE)
if (ctx->Texture._EnabledUnits)
_mesa_write_texture_span(ctx, span);
else
_mesa_write_rgba_span(ctx, span);
#elif FLAGS & RGBA
_mesa_write_rgba_span(ctx, span);
#else
_mesa_write_index_span(ctx, span);
#endif
span->end = 0;
}
 
count = span->end;
 
#if FLAGS & RGBA
span->array->rgba[count][RCOMP] = red;
span->array->rgba[count][GCOMP] = green;
span->array->rgba[count][BCOMP] = blue;
span->array->rgba[count][ACOMP] = alpha;
#endif
#if FLAGS & SPECULAR
span->array->spec[count][RCOMP] = specRed;
span->array->spec[count][GCOMP] = specGreen;
span->array->spec[count][BCOMP] = specBlue;
#endif
#if FLAGS & INDEX
span->array->index[count] = colorIndex;
#endif
#if FLAGS & TEXTURE
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
COPY_4V(span->array->texcoords[u][count], texcoord[u]);
}
}
#endif
 
span->array->x[count] = (GLint) vert->win[0];
span->array->y[count] = (GLint) vert->win[1];
span->array->z[count] = (GLint) (vert->win[2] + 0.5F);
span->end = count + 1;
}}
 
#endif /* LARGE || ATTENUATE || SMOOTH */
 
ASSERT(span->end <= MAX_WIDTH);
}
 
 
#undef FLAGS
#undef NAME
/shark/trunk/ports/mesa/src/swrast/s_feedback.c
0,0 → 1,167
/* $Id: s_feedback.c,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "feedback.h"
#include "macros.h"
#include "mmath.h"
 
#include "s_context.h"
#include "s_feedback.h"
#include "s_triangle.h"
 
 
#define FB_3D 0x01
#define FB_4D 0x02
#define FB_INDEX 0x04
#define FB_COLOR 0x08
#define FB_TEXTURE 0X10
 
 
 
 
static void feedback_vertex( GLcontext *ctx,
const SWvertex *v, const SWvertex *pv )
{
const GLuint texUnit = 0; /* See section 5.3 of 1.2.1 spec */
GLfloat win[4];
GLfloat color[4];
GLfloat tc[4];
GLuint index;
 
win[0] = v->win[0];
win[1] = v->win[1];
win[2] = v->win[2] / ctx->DepthMaxF;
win[3] = 1.0F / v->win[3];
 
color[0] = CHAN_TO_FLOAT(pv->color[0]);
color[1] = CHAN_TO_FLOAT(pv->color[1]);
color[2] = CHAN_TO_FLOAT(pv->color[2]);
color[3] = CHAN_TO_FLOAT(pv->color[3]);
 
if (v->texcoord[texUnit][3] != 1.0 &&
v->texcoord[texUnit][3] != 0.0) {
GLfloat invq = 1.0F / v->texcoord[texUnit][3];
tc[0] = v->texcoord[texUnit][0] * invq;
tc[1] = v->texcoord[texUnit][1] * invq;
tc[2] = v->texcoord[texUnit][2] * invq;
tc[3] = v->texcoord[texUnit][3];
}
else {
COPY_4V(tc, v->texcoord[texUnit]);
}
 
index = v->index;
 
_mesa_feedback_vertex( ctx, win, color, index, tc );
}
 
 
/*
* Put triangle in feedback buffer.
*/
void _mesa_feedback_triangle( GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
if (_mesa_cull_triangle( ctx, v0, v1, v2 )) {
FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN );
FEEDBACK_TOKEN( ctx, (GLfloat) 3 ); /* three vertices */
 
if (ctx->Light.ShadeModel == GL_SMOOTH) {
feedback_vertex( ctx, v0, v0 );
feedback_vertex( ctx, v1, v1 );
feedback_vertex( ctx, v2, v2 );
} else {
feedback_vertex( ctx, v0, v2 );
feedback_vertex( ctx, v1, v2 );
feedback_vertex( ctx, v2, v2 );
}
}
}
 
 
void _mesa_feedback_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
{
GLenum token = GL_LINE_TOKEN;
SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
if (swrast->StippleCounter==0)
token = GL_LINE_RESET_TOKEN;
 
FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) token );
 
if (ctx->Light.ShadeModel == GL_SMOOTH) {
feedback_vertex( ctx, v0, v0 );
feedback_vertex( ctx, v1, v1 );
} else {
feedback_vertex( ctx, v0, v1 );
feedback_vertex( ctx, v1, v1 );
}
 
swrast->StippleCounter++;
}
 
 
void _mesa_feedback_point( GLcontext *ctx, const SWvertex *v )
{
FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POINT_TOKEN );
feedback_vertex( ctx, v, v );
}
 
 
void _mesa_select_triangle( GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
if (_mesa_cull_triangle( ctx, v0, v1, v2 )) {
const GLfloat zs = 1.0F / ctx->DepthMaxF;
 
_mesa_update_hitflag( ctx, v0->win[2] * zs );
_mesa_update_hitflag( ctx, v1->win[2] * zs );
_mesa_update_hitflag( ctx, v2->win[2] * zs );
}
}
 
 
void _mesa_select_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
{
const GLfloat zs = 1.0F / ctx->DepthMaxF;
_mesa_update_hitflag( ctx, v0->win[2] * zs );
_mesa_update_hitflag( ctx, v1->win[2] * zs );
}
 
 
void _mesa_select_point( GLcontext *ctx, const SWvertex *v )
{
const GLfloat zs = 1.0F / ctx->DepthMaxF;
_mesa_update_hitflag( ctx, v->win[2] * zs );
}
/shark/trunk/ports/mesa/src/swrast/s_alphabuf.h
0,0 → 1,81
/* $Id: s_alphabuf.h,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.0.2
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef S_ALPHABUF_H
#define S_ALPHABUF_H
 
 
#include "mtypes.h"
#include "swrast.h"
 
 
extern void
_mesa_alloc_alpha_buffers( GLframebuffer *buffer );
 
 
extern void
_mesa_clear_alpha_buffers( GLcontext *ctx );
 
 
extern void
_mesa_write_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
CONST GLchan rgba[][4], const GLubyte mask[] );
 
 
extern void
_mesa_write_mono_alpha_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
GLchan alpha, const GLubyte mask[] );
 
 
 
extern void
_mesa_write_alpha_pixels( GLcontext* ctx,
GLuint n, const GLint x[], const GLint y[],
CONST GLchan rgba[][4],
const GLubyte mask[] );
 
 
extern void
_mesa_write_mono_alpha_pixels( GLcontext* ctx,
GLuint n, const GLint x[],
const GLint y[], GLchan alpha,
const GLubyte mask[] );
 
 
extern void
_mesa_read_alpha_span( GLcontext* ctx,
GLuint n, GLint x, GLint y, GLchan rgba[][4] );
 
 
extern void
_mesa_read_alpha_pixels( GLcontext* ctx,
GLuint n, const GLint x[], const GLint y[],
GLchan rgba[][4], const GLubyte mask[] );
 
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_zoom.h
0,0 → 1,49
/* $Id: s_zoom.h,v 1.1 2003-02-28 11:49:44 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#ifndef S_ZOOM_H
#define S_ZOOM_H
 
#include "mtypes.h"
#include "swrast.h"
 
extern void
_mesa_write_zoomed_rgba_span( GLcontext *ctx, const struct sw_span *span,
CONST GLchan rgb[][4], GLint y0 );
 
extern void
_mesa_write_zoomed_rgb_span( GLcontext *ctx, const struct sw_span *span,
CONST GLchan rgb[][3], GLint y0 );
 
extern void
_mesa_write_zoomed_index_span( GLcontext *ctx, const struct sw_span *span,
GLint y0 );
 
extern void
_mesa_write_zoomed_stencil_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
const GLstencil stencil[], GLint y0 );
 
#endif
/shark/trunk/ports/mesa/src/swrast/s_tritemp.h
0,0 → 1,1406
/* $Id: s_tritemp.h,v 1.1 2003-02-28 11:49:43 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* $XFree86: xc/extras/Mesa/src/swrast/s_tritemp.h,v 1.2 2002/02/27 21:07:54 tsi Exp $ */
 
/*
* Triangle Rasterizer Template
*
* This file is #include'd to generate custom triangle rasterizers.
*
* The following macros may be defined to indicate what auxillary information
* must be interplated across the triangle:
* INTERP_Z - if defined, interpolate Z values
* INTERP_FOG - if defined, interpolate fog values
* INTERP_RGB - if defined, interpolate RGB values
* INTERP_ALPHA - if defined, interpolate Alpha values (req's INTERP_RGB)
* INTERP_SPEC - if defined, interpolate specular RGB values
* INTERP_INDEX - if defined, interpolate color index values
* INTERP_INT_TEX - if defined, interpolate integer ST texcoords
* (fast, simple 2-D texture mapping)
* INTERP_TEX - if defined, interpolate set 0 float STRQ texcoords
* NOTE: OpenGL STRQ = Mesa STUV (R was taken for red)
* INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords
* INTERP_FLOAT_RGBA - if defined, interpolate RGBA with floating point
* INTERP_FLOAT_SPEC - if defined, interpolate specular with floating point
*
* When one can directly address pixels in the color buffer the following
* macros can be defined and used to compute pixel addresses during
* rasterization (see pRow):
* PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
* BYTES_PER_ROW - number of bytes per row in the color buffer
* PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
* Y==0 at bottom of screen and increases upward.
*
* Similarly, for direct depth buffer access, this type is used for depth
* buffer addressing:
* DEPTH_TYPE - either GLushort or GLuint
*
* Optionally, one may provide one-time setup code per triangle:
* SETUP_CODE - code which is to be executed once per triangle
* CLEANUP_CODE - code to execute at end of triangle
*
* The following macro MUST be defined:
* RENDER_SPAN(span) - code to write a span of pixels.
*
* This code was designed for the origin to be in the lower-left corner.
*
* Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen!
*/
 
 
/*
* This is a bit of a hack, but it's a centralized place to enable floating-
* point color interpolation when GLchan is actually floating point.
*/
#if CHAN_TYPE == GL_FLOAT
 
#if defined(INTERP_RGB)
#undef INTERP_RGB
#undef INTERP_ALPHA
#define INTERP_FLOAT_RGBA
#endif
 
#if defined(INTERP_SPEC)
#undef INTERP_SPEC
#define INTERP_FLOAT_SPEC
#endif
 
#endif
 
 
/*void triangle( GLcontext *ctx, SWvertex *v0, SWvertex *v1, SWvertex *v2 )*/
{
typedef struct {
const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */
GLfloat dx; /* X(v1) - X(v0) */
GLfloat dy; /* Y(v1) - Y(v0) */
GLfixed fdxdy; /* dx/dy in fixed-point */
GLfixed fsx; /* first sample point x coord */
GLfixed fsy;
GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */
GLint lines; /* number of lines to be sampled on this edge */
GLfixed fx0; /* fixed pt X of lower endpoint */
} EdgeT;
 
#ifdef INTERP_Z
const GLint depthBits = ctx->Visual.depthBits;
const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
const GLfloat maxDepth = ctx->DepthMaxF;
#define FixedToDepth(F) ((F) >> fixedToDepthShift)
#endif
EdgeT eMaj, eTop, eBot;
GLfloat oneOverArea;
const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */
float bf = SWRAST_CONTEXT(ctx)->_backface_sign;
const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
 
struct sw_span span;
 
INIT_SPAN(span, GL_POLYGON, 0, 0, 0);
 
#ifdef INTERP_Z
(void) fixedToDepthShift;
#endif
 
/*
printf("%s()\n", __FUNCTION__);
printf(" %g, %g, %g\n", v0->win[0], v0->win[1], v0->win[2]);
printf(" %g, %g, %g\n", v1->win[0], v1->win[1], v1->win[2]);
printf(" %g, %g, %g\n", v2->win[0], v2->win[1], v2->win[2]);
*/
 
/* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
* And find the order of the 3 vertices along the Y axis.
*/
{
const GLfixed fy0 = FloatToFixed(v0->win[1] - 0.5F) & snapMask;
const GLfixed fy1 = FloatToFixed(v1->win[1] - 0.5F) & snapMask;
const GLfixed fy2 = FloatToFixed(v2->win[1] - 0.5F) & snapMask;
 
if (fy0 <= fy1) {
if (fy1 <= fy2) {
/* y0 <= y1 <= y2 */
vMin = v0; vMid = v1; vMax = v2;
vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2;
}
else if (fy2 <= fy0) {
/* y2 <= y0 <= y1 */
vMin = v2; vMid = v0; vMax = v1;
vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1;
}
else {
/* y0 <= y2 <= y1 */
vMin = v0; vMid = v2; vMax = v1;
vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1;
bf = -bf;
}
}
else {
if (fy0 <= fy2) {
/* y1 <= y0 <= y2 */
vMin = v1; vMid = v0; vMax = v2;
vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2;
bf = -bf;
}
else if (fy2 <= fy1) {
/* y2 <= y1 <= y0 */
vMin = v2; vMid = v1; vMax = v0;
vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0;
bf = -bf;
}
else {
/* y1 <= y2 <= y0 */
vMin = v1; vMid = v2; vMax = v0;
vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0;
}
}
 
/* fixed point X coords */
vMin_fx = FloatToFixed(vMin->win[0] + 0.5F) & snapMask;
vMid_fx = FloatToFixed(vMid->win[0] + 0.5F) & snapMask;
vMax_fx = FloatToFixed(vMax->win[0] + 0.5F) & snapMask;
}
 
/* vertex/edge relationship */
eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */
eTop.v0 = vMid; eTop.v1 = vMax;
eBot.v0 = vMin; eBot.v1 = vMid;
 
/* compute deltas for each edge: vertex[upper] - vertex[lower] */
eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
 
/* compute area, oneOverArea and perform backface culling */
{
const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
 
/* Do backface culling */
if (area * bf < 0.0)
return;
 
if (IS_INF_OR_NAN(area) || area == 0.0F)
return;
 
oneOverArea = 1.0F / area;
}
 
#ifndef DO_OCCLUSION_TEST
ctx->OcclusionResult = GL_TRUE;
#endif
span.facing = ctx->_Facing; /* for 2-sided stencil test */
 
/* Edge setup. For a triangle strip these could be reused... */
{
eMaj.fsy = FixedCeil(vMin_fy);
eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
if (eMaj.lines > 0) {
GLfloat dxdy = eMaj.dx / eMaj.dy;
eMaj.fdxdy = SignedFloatToFixed(dxdy);
eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */
eMaj.fx0 = vMin_fx;
eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * dxdy);
}
else {
return; /*CULLED*/
}
 
eTop.fsy = FixedCeil(vMid_fy);
eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
if (eTop.lines > 0) {
GLfloat dxdy = eTop.dx / eTop.dy;
eTop.fdxdy = SignedFloatToFixed(dxdy);
eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
eTop.fx0 = vMid_fx;
eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * dxdy);
}
 
eBot.fsy = FixedCeil(vMin_fy);
eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
if (eBot.lines > 0) {
GLfloat dxdy = eBot.dx / eBot.dy;
eBot.fdxdy = SignedFloatToFixed(dxdy);
eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */
eBot.fx0 = vMin_fx;
eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * dxdy);
}
}
 
/*
* Conceptually, we view a triangle as two subtriangles
* separated by a perfectly horizontal line. The edge that is
* intersected by this line is one with maximal absolute dy; we
* call it a ``major'' edge. The other two edges are the
* ``top'' edge (for the upper subtriangle) and the ``bottom''
* edge (for the lower subtriangle). If either of these two
* edges is horizontal or very close to horizontal, the
* corresponding subtriangle might cover zero sample points;
* we take care to handle such cases, for performance as well
* as correctness.
*
* By stepping rasterization parameters along the major edge,
* we can avoid recomputing them at the discontinuity where
* the top and bottom edges meet. However, this forces us to
* be able to scan both left-to-right and right-to-left.
* Also, we must determine whether the major edge is at the
* left or right side of the triangle. We do this by
* computing the magnitude of the cross-product of the major
* and top edges. Since this magnitude depends on the sine of
* the angle between the two edges, its sign tells us whether
* we turn to the left or to the right when travelling along
* the major edge to the top edge, and from this we infer
* whether the major edge is on the left or the right.
*
* Serendipitously, this cross-product magnitude is also a
* value we need to compute the iteration parameter
* derivatives for the triangle, and it can be used to perform
* backface culling because its sign tells us whether the
* triangle is clockwise or counterclockwise. In this code we
* refer to it as ``area'' because it's also proportional to
* the pixel area of the triangle.
*/
 
{
GLint scan_from_left_to_right; /* true if scanning left-to-right */
#ifdef INTERP_Z
GLfloat dzdx, dzdy;
#endif
#ifdef INTERP_FOG
GLfloat dfogdy;
#endif
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
GLfloat drdx, drdy;
GLfloat dgdx, dgdy;
GLfloat dbdx, dbdy;
#endif
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
GLfloat dadx, dady;
#endif
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
GLfloat dsrdx, dsrdy;
GLfloat dsgdx, dsgdy;
GLfloat dsbdx, dsbdy;
#endif
#ifdef INTERP_INDEX
GLfloat didx, didy;
#endif
#ifdef INTERP_INT_TEX
GLfloat dsdx, dsdy;
GLfloat dtdx, dtdy;
#endif
#ifdef INTERP_TEX
GLfloat dsdx, dsdy;
GLfloat dtdx, dtdy;
GLfloat dudx, dudy;
GLfloat dvdx, dvdy;
#endif
#ifdef INTERP_MULTITEX
GLfloat dsdx[MAX_TEXTURE_UNITS], dsdy[MAX_TEXTURE_UNITS];
GLfloat dtdx[MAX_TEXTURE_UNITS], dtdy[MAX_TEXTURE_UNITS];
GLfloat dudx[MAX_TEXTURE_UNITS], dudy[MAX_TEXTURE_UNITS];
GLfloat dvdx[MAX_TEXTURE_UNITS], dvdy[MAX_TEXTURE_UNITS];
#endif
 
/*
* Execute user-supplied setup code
*/
#ifdef SETUP_CODE
SETUP_CODE
#endif
 
scan_from_left_to_right = (oneOverArea < 0.0F);
 
 
/* compute d?/dx and d?/dy derivatives */
#ifdef INTERP_Z
span.interpMask |= SPAN_Z;
{
GLfloat eMaj_dz, eBot_dz;
eMaj_dz = vMax->win[2] - vMin->win[2];
eBot_dz = vMid->win[2] - vMin->win[2];
dzdx = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
if (dzdx > maxDepth || dzdx < -maxDepth) {
/* probably a sliver triangle */
dzdx = 0.0;
dzdy = 0.0;
}
else {
dzdy = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
}
if (depthBits <= 16)
span.zStep = SignedFloatToFixed(dzdx);
else
span.zStep = (GLint) dzdx;
}
#endif
#ifdef INTERP_FOG
span.interpMask |= SPAN_FOG;
{
const GLfloat eMaj_dfog = vMax->fog - vMin->fog;
const GLfloat eBot_dfog = vMid->fog - vMin->fog;
span.fogStep = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog);
dfogdy = oneOverArea * (eMaj.dx * eBot_dfog - eMaj_dfog * eBot.dx);
}
#endif
#ifdef INTERP_RGB
span.interpMask |= SPAN_RGBA;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
GLfloat eMaj_dr, eBot_dr;
GLfloat eMaj_dg, eBot_dg;
GLfloat eMaj_db, eBot_db;
# ifdef INTERP_ALPHA
GLfloat eMaj_da, eBot_da;
# endif
eMaj_dr = (GLfloat) ((GLint) vMax->color[RCOMP] -
(GLint) vMin->color[RCOMP]);
eBot_dr = (GLfloat) ((GLint) vMid->color[RCOMP] -
(GLint) vMin->color[RCOMP]);
drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
span.redStep = SignedFloatToFixed(drdx);
drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
eMaj_dg = (GLfloat) ((GLint) vMax->color[GCOMP] -
(GLint) vMin->color[GCOMP]);
eBot_dg = (GLfloat) ((GLint) vMid->color[GCOMP] -
(GLint) vMin->color[GCOMP]);
dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
span.greenStep = SignedFloatToFixed(dgdx);
dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
eMaj_db = (GLfloat) ((GLint) vMax->color[BCOMP] -
(GLint) vMin->color[BCOMP]);
eBot_db = (GLfloat) ((GLint) vMid->color[BCOMP] -
(GLint) vMin->color[BCOMP]);
dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
span.blueStep = SignedFloatToFixed(dbdx);
dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
# ifdef INTERP_ALPHA
eMaj_da = (GLfloat) ((GLint) vMax->color[ACOMP] -
(GLint) vMin->color[ACOMP]);
eBot_da = (GLfloat) ((GLint) vMid->color[ACOMP] -
(GLint) vMin->color[ACOMP]);
dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
span.alphaStep = SignedFloatToFixed(dadx);
dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
# endif
}
else {
ASSERT (ctx->Light.ShadeModel == GL_FLAT);
span.interpMask |= SPAN_FLAT;
drdx = drdy = 0.0F;
dgdx = dgdy = 0.0F;
dbdx = dbdy = 0.0F;
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
# ifdef INTERP_ALPHA
dadx = dady = 0.0F;
span.alphaStep = 0;
# endif
}
#endif
#ifdef INTERP_FLOAT_RGBA
span.interpMask |= SPAN_RGBA;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
GLfloat eMaj_dr, eBot_dr;
GLfloat eMaj_dg, eBot_dg;
GLfloat eMaj_db, eBot_db;
GLfloat eMaj_da, eBot_da;
eMaj_dr = vMax->color[RCOMP] - vMin->color[RCOMP];
eBot_dr = vMid->color[RCOMP] - vMin->color[RCOMP];
drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
span.redStep = drdx;
drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
eMaj_dg = vMax->color[GCOMP] - vMin->color[GCOMP];
eBot_dg = vMid->color[GCOMP] - vMin->color[GCOMP];
dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
span.greenStep = dgdx;
dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
eMaj_db = vMax->color[BCOMP] - vMin->color[BCOMP];
eBot_db = vMid->color[BCOMP] - vMin->color[BCOMP];
dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
span.blueStep = dbdx;
dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
eMaj_da = vMax->color[ACOMP] - vMin->color[ACOMP];
eBot_da = vMid->color[ACOMP] - vMin->color[ACOMP];
dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
span.alphaStep = dadx;
dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
}
else {
drdx = drdy = span.redStep = 0.0F;
dgdx = dgdy = span.greenStep = 0.0F;
dbdx = dbdy = span.blueStep = 0.0F;
dadx = dady = span.alphaStep = 0.0F;
}
#endif
#ifdef INTERP_SPEC
span.interpMask |= SPAN_SPEC;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
GLfloat eMaj_dsr, eBot_dsr;
GLfloat eMaj_dsg, eBot_dsg;
GLfloat eMaj_dsb, eBot_dsb;
eMaj_dsr = (GLfloat) ((GLint) vMax->specular[RCOMP] -
(GLint) vMin->specular[RCOMP]);
eBot_dsr = (GLfloat) ((GLint) vMid->specular[RCOMP] -
(GLint) vMin->specular[RCOMP]);
dsrdx = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
span.specRedStep = SignedFloatToFixed(dsrdx);
dsrdy = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
eMaj_dsg = (GLfloat) ((GLint) vMax->specular[GCOMP] -
(GLint) vMin->specular[GCOMP]);
eBot_dsg = (GLfloat) ((GLint) vMid->specular[GCOMP] -
(GLint) vMin->specular[GCOMP]);
dsgdx = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
span.specGreenStep = SignedFloatToFixed(dsgdx);
dsgdy = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
eMaj_dsb = (GLfloat) ((GLint) vMax->specular[BCOMP] -
(GLint) vMin->specular[BCOMP]);
eBot_dsb = (GLfloat) ((GLint) vMid->specular[BCOMP] -
(GLint) vMin->specular[BCOMP]);
dsbdx = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
span.specBlueStep = SignedFloatToFixed(dsbdx);
dsbdy = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
}
else {
dsrdx = dsrdy = 0.0F;
dsgdx = dsgdy = 0.0F;
dsbdx = dsbdy = 0.0F;
span.specRedStep = 0;
span.specGreenStep = 0;
span.specBlueStep = 0;
}
#endif
#ifdef INTERP_FLOAT_SPEC
span.interpMask |= SPAN_SPEC;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
GLfloat eMaj_dsr, eBot_dsr;
GLfloat eMaj_dsg, eBot_dsg;
GLfloat eMaj_dsb, eBot_dsb;
eMaj_dsr = vMax->specular[RCOMP] - vMin->specular[RCOMP];
eBot_dsr = vMid->specular[RCOMP] - vMin->specular[RCOMP];
dsrdx = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
span.specRedStep = dsrdx;
dsrdy = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
eMaj_dsg = vMax->specular[GCOMP] - vMin->specular[GCOMP];
eBot_dsg = vMid->specular[GCOMP] - vMin->specular[GCOMP];
dsgdx = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
span.specGreenStep = dsgdx;
dsgdy = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
eMaj_dsb = vMax->specular[BCOMP] - vMin->specular[BCOMP];
eBot_dsb = vMid->specular[BCOMP] - vMin->specular[BCOMP];
dsbdx = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
span.specBlueStep = dsbdx;
dsbdy = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
}
else {
dsrdx = dsrdy = span.specRedStep = 0;
dsgdx = dsgdy = span.specGreenStep = 0;
dsbdx = dsbdy = span.specBlueStep = 0;
}
#endif
#ifdef INTERP_INDEX
span.interpMask |= SPAN_INDEX;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
GLfloat eMaj_di, eBot_di;
eMaj_di = (GLfloat) ((GLint) vMax->index - (GLint) vMin->index);
eBot_di = (GLfloat) ((GLint) vMid->index - (GLint) vMin->index);
didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
span.indexStep = SignedFloatToFixed(didx);
didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
}
else {
span.interpMask |= SPAN_FLAT;
didx = didy = 0.0F;
span.indexStep = 0;
}
#endif
#ifdef INTERP_INT_TEX
span.interpMask |= SPAN_INT_TEXTURE;
{
GLfloat eMaj_ds, eBot_ds;
eMaj_ds = (vMax->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
eBot_ds = (vMid->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
span.intTexStep[0] = SignedFloatToFixed(dsdx);
dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
}
{
GLfloat eMaj_dt, eBot_dt;
eMaj_dt = (vMax->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
eBot_dt = (vMid->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
span.intTexStep[1] = SignedFloatToFixed(dtdx);
dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
}
 
#endif
#ifdef INTERP_TEX
span.interpMask |= SPAN_TEXTURE;
{
GLfloat wMax = vMax->win[3];
GLfloat wMin = vMin->win[3];
GLfloat wMid = vMid->win[3];
GLfloat eMaj_ds, eBot_ds;
GLfloat eMaj_dt, eBot_dt;
GLfloat eMaj_du, eBot_du;
GLfloat eMaj_dv, eBot_dv;
 
eMaj_ds = vMax->texcoord[0][0] * wMax - vMin->texcoord[0][0] * wMin;
eBot_ds = vMid->texcoord[0][0] * wMid - vMin->texcoord[0][0] * wMin;
dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
span.texStepX[0][0] = dsdx;
span.texStepY[0][0] = dsdy;
 
eMaj_dt = vMax->texcoord[0][1] * wMax - vMin->texcoord[0][1] * wMin;
eBot_dt = vMid->texcoord[0][1] * wMid - vMin->texcoord[0][1] * wMin;
dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
span.texStepX[0][1] = dtdx;
span.texStepY[0][1] = dtdy;
 
eMaj_du = vMax->texcoord[0][2] * wMax - vMin->texcoord[0][2] * wMin;
eBot_du = vMid->texcoord[0][2] * wMid - vMin->texcoord[0][2] * wMin;
dudx = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
dudy = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
span.texStepX[0][2] = dudx;
span.texStepY[0][2] = dudy;
 
eMaj_dv = vMax->texcoord[0][3] * wMax - vMin->texcoord[0][3] * wMin;
eBot_dv = vMid->texcoord[0][3] * wMid - vMin->texcoord[0][3] * wMin;
dvdx = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
dvdy = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
span.texStepX[0][3] = dvdx;
span.texStepY[0][3] = dvdy;
}
#endif
#ifdef INTERP_MULTITEX
span.interpMask |= SPAN_TEXTURE;
{
GLfloat wMax = vMax->win[3];
GLfloat wMin = vMin->win[3];
GLfloat wMid = vMid->win[3];
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
GLfloat eMaj_ds, eBot_ds;
GLfloat eMaj_dt, eBot_dt;
GLfloat eMaj_du, eBot_du;
GLfloat eMaj_dv, eBot_dv;
eMaj_ds = vMax->texcoord[u][0] * wMax
- vMin->texcoord[u][0] * wMin;
eBot_ds = vMid->texcoord[u][0] * wMid
- vMin->texcoord[u][0] * wMin;
dsdx[u] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
dsdy[u] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
span.texStepX[u][0] = dsdx[u];
span.texStepY[u][0] = dsdy[u];
 
eMaj_dt = vMax->texcoord[u][1] * wMax
- vMin->texcoord[u][1] * wMin;
eBot_dt = vMid->texcoord[u][1] * wMid
- vMin->texcoord[u][1] * wMin;
dtdx[u] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
dtdy[u] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
span.texStepX[u][1] = dtdx[u];
span.texStepY[u][1] = dtdy[u];
 
eMaj_du = vMax->texcoord[u][2] * wMax
- vMin->texcoord[u][2] * wMin;
eBot_du = vMid->texcoord[u][2] * wMid
- vMin->texcoord[u][2] * wMin;
dudx[u] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
dudy[u] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
span.texStepX[u][2] = dudx[u];
span.texStepY[u][2] = dudy[u];
 
eMaj_dv = vMax->texcoord[u][3] * wMax
- vMin->texcoord[u][3] * wMin;
eBot_dv = vMid->texcoord[u][3] * wMid
- vMin->texcoord[u][3] * wMin;
dvdx[u] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
dvdy[u] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
span.texStepX[u][3] = dvdx[u];
span.texStepY[u][3] = dvdy[u];
}
}
}
#endif
 
/*
* We always sample at pixel centers. However, we avoid
* explicit half-pixel offsets in this code by incorporating
* the proper offset in each of x and y during the
* transformation to window coordinates.
*
* We also apply the usual rasterization rules to prevent
* cracks and overlaps. A pixel is considered inside a
* subtriangle if it meets all of four conditions: it is on or
* to the right of the left edge, strictly to the left of the
* right edge, on or below the top edge, and strictly above
* the bottom edge. (Some edges may be degenerate.)
*
* The following discussion assumes left-to-right scanning
* (that is, the major edge is on the left); the right-to-left
* case is a straightforward variation.
*
* We start by finding the half-integral y coordinate that is
* at or below the top of the triangle. This gives us the
* first scan line that could possibly contain pixels that are
* inside the triangle.
*
* Next we creep down the major edge until we reach that y,
* and compute the corresponding x coordinate on the edge.
* Then we find the half-integral x that lies on or just
* inside the edge. This is the first pixel that might lie in
* the interior of the triangle. (We won't know for sure
* until we check the other edges.)
*
* As we rasterize the triangle, we'll step down the major
* edge. For each step in y, we'll move an integer number
* of steps in x. There are two possible x step sizes, which
* we'll call the ``inner'' step (guaranteed to land on the
* edge or inside it) and the ``outer'' step (guaranteed to
* land on the edge or outside it). The inner and outer steps
* differ by one. During rasterization we maintain an error
* term that indicates our distance from the true edge, and
* select either the inner step or the outer step, whichever
* gets us to the first pixel that falls inside the triangle.
*
* All parameters (z, red, etc.) as well as the buffer
* addresses for color and z have inner and outer step values,
* so that we can increment them appropriately. This method
* eliminates the need to adjust parameters by creeping a
* sub-pixel amount into the triangle at each scanline.
*/
 
{
int subTriangle;
GLfixed fx;
GLfixed fxLeftEdge = 0, fxRightEdge = 0;
GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
GLfixed fdxOuter;
int idxOuter;
float dxOuter;
GLfixed fError = 0, fdError = 0;
float adjx, adjy;
GLfixed fy;
#ifdef PIXEL_ADDRESS
PIXEL_TYPE *pRow = NULL;
int dPRowOuter = 0, dPRowInner; /* offset in bytes */
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
DEPTH_TYPE *zRow = NULL;
int dZRowOuter = 0, dZRowInner; /* offset in bytes */
# endif
GLfixed fz = 0, fdzOuter = 0, fdzInner;
#endif
#ifdef INTERP_FOG
GLfloat fogLeft = 0, dfogOuter = 0, dfogInner;
#endif
#ifdef INTERP_RGB
GLfixed fr = 0, fdrOuter = 0, fdrInner;
GLfixed fg = 0, fdgOuter = 0, fdgInner;
GLfixed fb = 0, fdbOuter = 0, fdbInner;
#endif
#ifdef INTERP_ALPHA
GLfixed fa = 0, fdaOuter = 0, fdaInner;
#endif
#ifdef INTERP_FLOAT_RGBA
GLfloat fr, fdrOuter, fdrInner;
GLfloat fg, fdgOuter, fdgInner;
GLfloat fb, fdbOuter, fdbInner;
GLfloat fa, fdaOuter, fdaInner;
#endif
#ifdef INTERP_SPEC
GLfixed fsr=0, fdsrOuter=0, fdsrInner;
GLfixed fsg=0, fdsgOuter=0, fdsgInner;
GLfixed fsb=0, fdsbOuter=0, fdsbInner;
#endif
#ifdef INTERP_FLOAT_SPEC
GLfloat fsr=0, fdsrOuter=0, fdsrInner;
GLfloat fsg=0, fdsgOuter=0, fdsgInner;
GLfloat fsb=0, fdsbOuter=0, fdsbInner;
#endif
#ifdef INTERP_INDEX
GLfixed fi=0, fdiOuter=0, fdiInner;
#endif
#ifdef INTERP_INT_TEX
GLfixed fs=0, fdsOuter=0, fdsInner;
GLfixed ft=0, fdtOuter=0, fdtInner;
#endif
#ifdef INTERP_TEX
GLfloat sLeft=0, dsOuter=0, dsInner;
GLfloat tLeft=0, dtOuter=0, dtInner;
GLfloat uLeft=0, duOuter=0, duInner;
GLfloat vLeft=0, dvOuter=0, dvInner;
#endif
#ifdef INTERP_MULTITEX
GLfloat sLeft[MAX_TEXTURE_UNITS];
GLfloat tLeft[MAX_TEXTURE_UNITS];
GLfloat uLeft[MAX_TEXTURE_UNITS];
GLfloat vLeft[MAX_TEXTURE_UNITS];
GLfloat dsOuter[MAX_TEXTURE_UNITS], dsInner[MAX_TEXTURE_UNITS];
GLfloat dtOuter[MAX_TEXTURE_UNITS], dtInner[MAX_TEXTURE_UNITS];
GLfloat duOuter[MAX_TEXTURE_UNITS], duInner[MAX_TEXTURE_UNITS];
GLfloat dvOuter[MAX_TEXTURE_UNITS], dvInner[MAX_TEXTURE_UNITS];
#endif
 
for (subTriangle=0; subTriangle<=1; subTriangle++) {
EdgeT *eLeft, *eRight;
int setupLeft, setupRight;
int lines;
 
if (subTriangle==0) {
/* bottom half */
if (scan_from_left_to_right) {
eLeft = &eMaj;
eRight = &eBot;
lines = eRight->lines;
setupLeft = 1;
setupRight = 1;
}
else {
eLeft = &eBot;
eRight = &eMaj;
lines = eLeft->lines;
setupLeft = 1;
setupRight = 1;
}
}
else {
/* top half */
if (scan_from_left_to_right) {
eLeft = &eMaj;
eRight = &eTop;
lines = eRight->lines;
setupLeft = 0;
setupRight = 1;
}
else {
eLeft = &eTop;
eRight = &eMaj;
lines = eLeft->lines;
setupLeft = 1;
setupRight = 0;
}
if (lines == 0)
return;
}
 
if (setupLeft && eLeft->lines > 0) {
const SWvertex *vLower;
GLfixed fsx = eLeft->fsx;
fx = FixedCeil(fsx);
fError = fx - fsx - FIXED_ONE;
fxLeftEdge = fsx - FIXED_EPSILON;
fdxLeftEdge = eLeft->fdxdy;
fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
idxOuter = FixedToInt(fdxOuter);
dxOuter = (float) idxOuter;
(void) dxOuter;
 
fy = eLeft->fsy;
span.y = FixedToInt(fy);
 
adjx = (float)(fx - eLeft->fx0); /* SCALED! */
adjy = eLeft->adjy; /* SCALED! */
(void) adjx; /* silence compiler warnings */
(void) adjy; /* silence compiler warnings */
 
vLower = eLeft->v0;
(void) vLower; /* silence compiler warnings */
 
#ifdef PIXEL_ADDRESS
{
pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
/* negative because Y=0 at bottom and increases upward */
}
#endif
/*
* Now we need the set of parameter (z, color, etc.) values at
* the point (fx, fy). This gives us properly-sampled parameter
* values that we can step from pixel to pixel. Furthermore,
* although we might have intermediate results that overflow
* the normal parameter range when we step temporarily outside
* the triangle, we shouldn't overflow or underflow for any
* pixel that's actually inside the triangle.
*/
 
#ifdef INTERP_Z
{
GLfloat z0 = vLower->win[2];
if (depthBits <= 16) {
/* interpolate fixed-pt values */
GLfloat tmp = (z0 * FIXED_SCALE +
dzdx * adjx + dzdy * adjy) + FIXED_HALF;
if (tmp < MAX_GLUINT / 2)
fz = (GLfixed) tmp;
else
fz = MAX_GLUINT / 2;
fdzOuter = SignedFloatToFixed(dzdy + dxOuter * dzdx);
}
else {
/* interpolate depth values exactly */
fz = (GLint) (z0 + dzdx * FixedToFloat(adjx)
+ dzdy * FixedToFloat(adjy));
fdzOuter = (GLint) (dzdy + dxOuter * dzdx);
}
# ifdef DEPTH_TYPE
zRow = (DEPTH_TYPE *)
_mesa_zbuffer_address(ctx, FixedToInt(fxLeftEdge), span.y);
dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
# endif
}
#endif
#ifdef INTERP_FOG
fogLeft = vLower->fog + (span.fogStep * adjx + dfogdy * adjy)
* (1.0F/FIXED_SCALE);
dfogOuter = dfogdy + dxOuter * span.fogStep;
#endif
#ifdef INTERP_RGB
if (ctx->Light.ShadeModel == GL_SMOOTH) {
fr = (GLfixed) (ChanToFixed(vLower->color[RCOMP])
+ drdx * adjx + drdy * adjy) + FIXED_HALF;
fdrOuter = SignedFloatToFixed(drdy + dxOuter * drdx);
fg = (GLfixed) (ChanToFixed(vLower->color[GCOMP])
+ dgdx * adjx + dgdy * adjy) + FIXED_HALF;
fdgOuter = SignedFloatToFixed(dgdy + dxOuter * dgdx);
fb = (GLfixed) (ChanToFixed(vLower->color[BCOMP])
+ dbdx * adjx + dbdy * adjy) + FIXED_HALF;
fdbOuter = SignedFloatToFixed(dbdy + dxOuter * dbdx);
# ifdef INTERP_ALPHA
fa = (GLfixed) (ChanToFixed(vLower->color[ACOMP])
+ dadx * adjx + dady * adjy) + FIXED_HALF;
fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
# endif
}
else {
ASSERT (ctx->Light.ShadeModel == GL_FLAT);
fr = ChanToFixed(v2->color[RCOMP]);
fg = ChanToFixed(v2->color[GCOMP]);
fb = ChanToFixed(v2->color[BCOMP]);
fdrOuter = fdgOuter = fdbOuter = 0;
# ifdef INTERP_ALPHA
fa = ChanToFixed(v2->color[ACOMP]);
fdaOuter = 0;
# endif
}
#endif
#ifdef INTERP_FLOAT_RGBA
if (ctx->Light.ShadeModel == GL_SMOOTH) {
fr = vLower->color[RCOMP]
+ (drdx * adjx + drdy * adjy) * (1.0F / FIXED_SCALE);
fdrOuter = drdy + dxOuter * drdx;
fg = vLower->color[GCOMP]
+ (dgdx * adjx + dgdy * adjy) * (1.0F / FIXED_SCALE);
fdgOuter = dgdy + dxOuter * dgdx;
fb = vLower->color[BCOMP]
+ (dbdx * adjx + dbdy * adjy) * (1.0F / FIXED_SCALE);
fdbOuter = dbdy + dxOuter * dbdx;
fa = vLower->color[ACOMP]
+ (dadx * adjx + dady * adjy) * (1.0F / FIXED_SCALE);
fdaOuter = dady + dxOuter * dadx;
}
else {
fr = v2->color[RCOMP];
fg = v2->color[GCOMP];
fb = v2->color[BCOMP];
fa = v2->color[ACOMP];
fdrOuter = fdgOuter = fdbOuter = fdaOuter = 0.0F;
}
#endif
#ifdef INTERP_SPEC
if (ctx->Light.ShadeModel == GL_SMOOTH) {
fsr = (GLfixed) (ChanToFixed(vLower->specular[RCOMP])
+ dsrdx * adjx + dsrdy * adjy) + FIXED_HALF;
fdsrOuter = SignedFloatToFixed(dsrdy + dxOuter * dsrdx);
fsg = (GLfixed) (ChanToFixed(vLower->specular[GCOMP])
+ dsgdx * adjx + dsgdy * adjy) + FIXED_HALF;
fdsgOuter = SignedFloatToFixed(dsgdy + dxOuter * dsgdx);
fsb = (GLfixed) (ChanToFixed(vLower->specular[BCOMP])
+ dsbdx * adjx + dsbdy * adjy) + FIXED_HALF;
fdsbOuter = SignedFloatToFixed(dsbdy + dxOuter * dsbdx);
}
else {
fsr = ChanToFixed(v2->specular[RCOMP]);
fsg = ChanToFixed(v2->specular[GCOMP]);
fsb = ChanToFixed(v2->specular[BCOMP]);
fdsrOuter = fdsgOuter = fdsbOuter = 0;
}
#endif
#ifdef INTERP_FLOAT_SPEC
if (ctx->Light.ShadeModel == GL_SMOOTH) {
fsr = vLower->specular[RCOMP]
+ (dsrdx * adjx + dsrdy * adjy) * (1.0F / FIXED_SCALE);
fdsrOuter = dsrdy + dxOuter * dsrdx;
fsg = vLower->specular[GCOMP]
+ (dsgdx * adjx + dsgdy * adjy) * (1.0F / FIXED_SCALE);
fdsgOuter = dsgdy + dxOuter * dsgdx;
fsb = vLower->specular[BCOMP]
+ (dsbdx * adjx + dsbdy * adjy) * (1.0F / FIXED_SCALE);
fdsbOuter = dsbdy + dxOuter * dsbdx;
}
else {
fsr = v2->specular[RCOMP];
fsg = v2->specular[GCOMP];
fsb = v2->specular[BCOMP];
fdsrOuter = fdsgOuter = fdsbOuter = 0.0F;
}
#endif
#ifdef INTERP_INDEX
if (ctx->Light.ShadeModel == GL_SMOOTH) {
fi = (GLfixed)(vLower->index * FIXED_SCALE
+ didx * adjx + didy * adjy) + FIXED_HALF;
fdiOuter = SignedFloatToFixed(didy + dxOuter * didx);
}
else {
fi = (GLfixed) (v2->index * FIXED_SCALE);
fdiOuter = 0;
}
#endif
#ifdef INTERP_INT_TEX
{
GLfloat s0, t0;
s0 = vLower->texcoord[0][0] * S_SCALE;
fs = (GLfixed)(s0 * FIXED_SCALE + dsdx * adjx
+ dsdy * adjy) + FIXED_HALF;
fdsOuter = SignedFloatToFixed(dsdy + dxOuter * dsdx);
 
t0 = vLower->texcoord[0][1] * T_SCALE;
ft = (GLfixed)(t0 * FIXED_SCALE + dtdx * adjx
+ dtdy * adjy) + FIXED_HALF;
fdtOuter = SignedFloatToFixed(dtdy + dxOuter * dtdx);
}
#endif
#ifdef INTERP_TEX
{
GLfloat invW = vLower->win[3];
GLfloat s0, t0, u0, v0;
s0 = vLower->texcoord[0][0] * invW;
sLeft = s0 + (span.texStepX[0][0] * adjx + dsdy * adjy)
* (1.0F/FIXED_SCALE);
dsOuter = dsdy + dxOuter * span.texStepX[0][0];
t0 = vLower->texcoord[0][1] * invW;
tLeft = t0 + (span.texStepX[0][1] * adjx + dtdy * adjy)
* (1.0F/FIXED_SCALE);
dtOuter = dtdy + dxOuter * span.texStepX[0][1];
u0 = vLower->texcoord[0][2] * invW;
uLeft = u0 + (span.texStepX[0][2] * adjx + dudy * adjy)
* (1.0F/FIXED_SCALE);
duOuter = dudy + dxOuter * span.texStepX[0][2];
v0 = vLower->texcoord[0][3] * invW;
vLeft = v0 + (span.texStepX[0][3] * adjx + dvdy * adjy)
* (1.0F/FIXED_SCALE);
dvOuter = dvdy + dxOuter * span.texStepX[0][3];
}
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
GLfloat invW = vLower->win[3];
GLfloat s0, t0, u0, v0;
s0 = vLower->texcoord[u][0] * invW;
sLeft[u] = s0 + (span.texStepX[u][0] * adjx + dsdy[u]
* adjy) * (1.0F/FIXED_SCALE);
dsOuter[u] = dsdy[u] + dxOuter * span.texStepX[u][0];
t0 = vLower->texcoord[u][1] * invW;
tLeft[u] = t0 + (span.texStepX[u][1] * adjx + dtdy[u]
* adjy) * (1.0F/FIXED_SCALE);
dtOuter[u] = dtdy[u] + dxOuter * span.texStepX[u][1];
u0 = vLower->texcoord[u][2] * invW;
uLeft[u] = u0 + (span.texStepX[u][2] * adjx + dudy[u]
* adjy) * (1.0F/FIXED_SCALE);
duOuter[u] = dudy[u] + dxOuter * span.texStepX[u][2];
v0 = vLower->texcoord[u][3] * invW;
vLeft[u] = v0 + (span.texStepX[u][3] * adjx + dvdy[u]
* adjy) * (1.0F/FIXED_SCALE);
dvOuter[u] = dvdy[u] + dxOuter * span.texStepX[u][3];
}
}
}
#endif
 
} /*if setupLeft*/
 
 
if (setupRight && eRight->lines>0) {
fxRightEdge = eRight->fsx - FIXED_EPSILON;
fdxRightEdge = eRight->fdxdy;
}
 
if (lines==0) {
continue;
}
 
 
/* Rasterize setup */
#ifdef PIXEL_ADDRESS
dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
# endif
fdzInner = fdzOuter + span.zStep;
#endif
#ifdef INTERP_FOG
dfogInner = dfogOuter + span.fogStep;
#endif
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
fdrInner = fdrOuter + span.redStep;
fdgInner = fdgOuter + span.greenStep;
fdbInner = fdbOuter + span.blueStep;
#endif
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
fdaInner = fdaOuter + span.alphaStep;
#endif
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
fdsrInner = fdsrOuter + span.specRedStep;
fdsgInner = fdsgOuter + span.specGreenStep;
fdsbInner = fdsbOuter + span.specBlueStep;
#endif
#ifdef INTERP_INDEX
fdiInner = fdiOuter + span.indexStep;
#endif
#ifdef INTERP_INT_TEX
fdsInner = fdsOuter + span.intTexStep[0];
fdtInner = fdtOuter + span.intTexStep[1];
#endif
#ifdef INTERP_TEX
dsInner = dsOuter + span.texStepX[0][0];
dtInner = dtOuter + span.texStepX[0][1];
duInner = duOuter + span.texStepX[0][2];
dvInner = dvOuter + span.texStepX[0][3];
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
dsInner[u] = dsOuter[u] + span.texStepX[u][0];
dtInner[u] = dtOuter[u] + span.texStepX[u][1];
duInner[u] = duOuter[u] + span.texStepX[u][2];
dvInner[u] = dvOuter[u] + span.texStepX[u][3];
}
}
}
#endif
 
while (lines > 0) {
/* initialize the span interpolants to the leftmost value */
/* ff = fixed-pt fragment */
const GLint right = FixedToInt(fxRightEdge);
 
span.x = FixedToInt(fxLeftEdge);
 
if (right <= span.x)
span.end = 0;
else
span.end = right - span.x;
 
#ifdef INTERP_Z
span.z = fz;
#endif
#ifdef INTERP_FOG
span.fog = fogLeft;
#endif
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
span.red = fr;
span.green = fg;
span.blue = fb;
#endif
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
span.alpha = fa;
#endif
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
span.specRed = fsr;
span.specGreen = fsg;
span.specBlue = fsb;
#endif
#ifdef INTERP_INDEX
span.index = fi;
#endif
#ifdef INTERP_INT_TEX
span.intTex[0] = fs;
span.intTex[1] = ft;
#endif
 
#ifdef INTERP_TEX
span.tex[0][0] = sLeft;
span.tex[0][1] = tLeft;
span.tex[0][2] = uLeft;
span.tex[0][3] = vLeft;
#endif
 
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
span.tex[u][0] = sLeft[u];
span.tex[u][1] = tLeft[u];
span.tex[u][2] = uLeft[u];
span.tex[u][3] = vLeft[u];
}
}
}
#endif
 
#ifdef INTERP_RGB
{
/* need this to accomodate round-off errors */
const GLint len = right - span.x - 1;
GLfixed ffrend = span.red + len * span.redStep;
GLfixed ffgend = span.green + len * span.greenStep;
GLfixed ffbend = span.blue + len * span.blueStep;
if (ffrend < 0) {
span.red -= ffrend;
if (span.red < 0)
span.red = 0;
}
if (ffgend < 0) {
span.green -= ffgend;
if (span.green < 0)
span.green = 0;
}
if (ffbend < 0) {
span.blue -= ffbend;
if (span.blue < 0)
span.blue = 0;
}
}
#endif
#ifdef INTERP_ALPHA
{
const GLint len = right - span.x - 1;
GLfixed ffaend = span.alpha + len * span.alphaStep;
if (ffaend < 0) {
span.alpha -= ffaend;
if (span.alpha < 0)
span.alpha = 0;
}
}
#endif
#ifdef INTERP_SPEC
{
/* need this to accomodate round-off errors */
const GLint len = right - span.x - 1;
GLfixed ffsrend = span.specRed + len * span.specRedStep;
GLfixed ffsgend = span.specGreen + len * span.specGreenStep;
GLfixed ffsbend = span.specBlue + len * span.specBlueStep;
if (ffsrend < 0) {
span.specRed -= ffsrend;
if (span.specRed < 0)
span.specRed = 0;
}
if (ffsgend < 0) {
span.specGreen -= ffsgend;
if (span.specGreen < 0)
span.specGreen = 0;
}
if (ffsbend < 0) {
span.specBlue -= ffsbend;
if (span.specBlue < 0)
span.specBlue = 0;
}
}
#endif
#ifdef INTERP_INDEX
if (span.index < 0) span.index = 0;
#endif
 
/* This is where we actually generate fragments */
if (span.end > 0) {
RENDER_SPAN( span );
}
 
/*
* Advance to the next scan line. Compute the
* new edge coordinates, and adjust the
* pixel-center x coordinate so that it stays
* on or inside the major edge.
*/
(span.y)++;
lines--;
 
fxLeftEdge += fdxLeftEdge;
fxRightEdge += fdxRightEdge;
 
 
fError += fdError;
if (fError >= 0) {
fError -= FIXED_ONE;
#ifdef PIXEL_ADDRESS
pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
# endif
fz += fdzOuter;
#endif
#ifdef INTERP_FOG
fogLeft += dfogOuter;
#endif
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
fr += fdrOuter;
fg += fdgOuter;
fb += fdbOuter;
#endif
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
fa += fdaOuter;
#endif
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
fsr += fdsrOuter;
fsg += fdsgOuter;
fsb += fdsbOuter;
#endif
#ifdef INTERP_INDEX
fi += fdiOuter;
#endif
#ifdef INTERP_INT_TEX
fs += fdsOuter;
ft += fdtOuter;
#endif
#ifdef INTERP_TEX
sLeft += dsOuter;
tLeft += dtOuter;
uLeft += duOuter;
vLeft += dvOuter;
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
sLeft[u] += dsOuter[u];
tLeft[u] += dtOuter[u];
uLeft[u] += duOuter[u];
vLeft[u] += dvOuter[u];
}
}
}
#endif
}
else {
#ifdef PIXEL_ADDRESS
pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
# endif
fz += fdzInner;
#endif
#ifdef INTERP_FOG
fogLeft += dfogInner;
#endif
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
fr += fdrInner;
fg += fdgInner;
fb += fdbInner;
#endif
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
fa += fdaInner;
#endif
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
fsr += fdsrInner;
fsg += fdsgInner;
fsb += fdsbInner;
#endif
#ifdef INTERP_INDEX
fi += fdiInner;
#endif
#ifdef INTERP_INT_TEX
fs += fdsInner;
ft += fdtInner;
#endif
#ifdef INTERP_TEX
sLeft += dsInner;
tLeft += dtInner;
uLeft += duInner;
vLeft += dvInner;
#endif
#ifdef INTERP_MULTITEX
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
sLeft[u] += dsInner[u];
tLeft[u] += dtInner[u];
uLeft[u] += duInner[u];
vLeft[u] += dvInner[u];
}
}
}
#endif
}
} /*while lines>0*/
 
} /* for subTriangle */
 
}
#ifdef CLEANUP_CODE
CLEANUP_CODE
#endif
}
}
 
#undef SETUP_CODE
#undef CLEANUP_CODE
#undef RENDER_SPAN
 
#undef PIXEL_TYPE
#undef BYTES_PER_ROW
#undef PIXEL_ADDRESS
 
#undef INTERP_Z
#undef INTERP_FOG
#undef INTERP_RGB
#undef INTERP_ALPHA
#undef INTERP_SPEC
#undef INTERP_INDEX
#undef INTERP_INT_TEX
#undef INTERP_TEX
#undef INTERP_MULTITEX
#undef INTERP_FLOAT_RGBA
#undef INTERP_FLOAT_SPEC
 
#undef S_SCALE
#undef T_SCALE
 
#undef FixedToDepth
 
#undef DO_OCCLUSION_TEST
/shark/trunk/ports/mesa/src/swrast/s_context.h
0,0 → 1,236
/* $Id: s_context.h,v 1.1 2003-02-28 11:49:41 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EV