diff options
Diffstat (limited to 'src/mesa/main')
70 files changed, 39633 insertions, 0 deletions
diff --git a/src/mesa/main/Imakefile b/src/mesa/main/Imakefile new file mode 100644 index 00000000000..115f16c8c35 --- /dev/null +++ b/src/mesa/main/Imakefile @@ -0,0 +1,127 @@ +#define DoNormalLib NO
+#define DoSharedLib YES
+#define DoDebugLib NO
+#define DoProfileLib NO
+#define LibName MESAGL
+#define SoRev SOX11REV
+#define LibHeaders NO
+
+#include <Threads.tmpl>
+
+REQUIREDLIBS = $(X11ROOT)\\XFree86\\lib\\ Xext X11
+BUILDLIBDIR = $(TOP)\\lib
+
+INCLUDES = -I$(TOP)\\include
+
+SRCS = \
+accum.c \
+alpha.c \
+alphabuf.c \
+api1.c \
+api2.c \
+attrib.c \
+bitmap.c \
+blend.c \
+bresenhm.c \
+clip.c \
+context.c \
+copypix.c \
+dd.c \
+depth.c \
+draw.c \
+drawpix.c \
+enable.c \
+eval2.c \
+feedback.c \
+fog.c \
+fortran.c \
+get.c \
+hash.c \
+glx.c \
+interp.c \
+light.c \
+lines.c \
+list.c \
+logic.c \
+masking.c \
+misc.c \
+osmesa.c \
+pb.c \
+pixel.c \
+points.c \
+polygons.c \
+readpix.c \
+scissor.c \
+span.c \
+stencil.c \
+svgamesa.c \
+texture.c \
+varray.c \
+vb.c \
+vertex.c \
+xfonts.c \
+xform.c \
+xmesa1.c \
+xmesa2.c \
+xmesa3.c
+
+OBJS = \
+accum.o \
+alpha.o \
+alphabuf.o \
+api1.o \
+api2.o \
+attrib.o \
+bitmap.o \
+blend.o \
+bresenhm.o \
+clip.o \
+context.o \
+copypix.o \
+dd.o \
+depth.o \
+draw.o \
+drawpix.o \
+enable.o \
+eval2.o \
+feedback.o \
+fog.o \
+fortran.o \
+get.o \
+hash.o \
+glx.o \
+interp.o \
+light.o \
+lines.o \
+list.o \
+logic.o \
+masking.o \
+misc.o \
+osmesa.o \
+pb.o \
+pixel.o \
+points.o \
+polygons.o \
+readpix.o \
+scissor.o \
+span.o \
+stencil.o \
+svgamesa.o \
+texture.o \
+varray.o \
+vb.o \
+vertex.o \
+xfonts.o \
+xform.o \
+xmesa1.o \
+xmesa2.o \
+xmesa3.o
+xmesa4.o
+
+LINTLIBS =
+
+#include <Library.tmpl>
+
+DependTarget()
+
+
\ No newline at end of file diff --git a/src/mesa/main/KNOWN_BUGS b/src/mesa/main/KNOWN_BUGS new file mode 100644 index 00000000000..9c9076bfedc --- /dev/null +++ b/src/mesa/main/KNOWN_BUGS @@ -0,0 +1,20 @@ +$Id: KNOWN_BUGS,v 1.1 1999/08/19 00:55:41 jtg Exp $ + + +Performance issues with EXT_point_parameters & quake2 + + +Broken drivers: + + --> After integration of the changes in kw3, only the X and FX +drivers are known to work. Windows and D3D are known to be broken, +and all others are suspected to be broken. Please test your driver +and update this entry when more is known. + + + +Separate specular color interpolation isn't implemented for points and +lines. Also, will have to add specular color add to pb.c (pixel buffer +code). + + diff --git a/src/mesa/main/Makefile.DJ b/src/mesa/main/Makefile.DJ new file mode 100644 index 00000000000..27c3556ab9b --- /dev/null +++ b/src/mesa/main/Makefile.DJ @@ -0,0 +1,95 @@ +# $Id: Makefile.DJ,v 1.1 1999/08/19 00:55:41 jtg Exp $ + +# Makefile for core library for MS-DOS using djgpp + +# Mesa 3-D graphics library +# Version: 3.1 +# Copyright (C) 1995-1998 Brian Paul +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +# $Log: Makefile.DJ,v $ +# Revision 1.1 1999/08/19 00:55:41 jtg +# Initial revision +# +# Revision 1.1 1999/01/01 14:35:09 brianp +# Initial revision +# + + + +##### MACROS ##### + +VPATH = RCS + +INCDIR = ..\include +LIBDIR = ..\lib + +# Want UniVBE (Display Doctor) Support, Scitech Software www.scitechsoft.com +# Set -I to point to scitech include files. +# Haven`t finished doing univbe version for djgpp +#CFLAGS += -DUNIVBE -D__DOS__ -D__MSDOS32__ -IC:\scitech\include +CFLAGS += -D__DOS__ -D__MSDOS32__ + +CORE_SOURCES = accum.c alpha.c alphabuf.c api1.c api2.c apiext.c attrib.c \ + bitmap.c blend.c clip.c colortab.c context.c copypix.c depth.c \ + dlist.c drawpix.c enable.c eval.c feedback.c fog.c \ + get.c hash.c image.c light.c lines.c logic.c masking.c matrix.c \ + misc.c mmath.c mthreads.c pb.c pixel.c points.c pointers.c polygon.c \ + quads.c rastpos.c readpix.c rect.c scissor.c shade.c span.c \ + stencil.c teximage.c texobj.c texstate.c texture.c triangle.c \ + varray.c winpos.c vb.c vbfill.c vbrender.c vbxform.c xform.c \ + zoom.c + +DRIVER_SOURCES = DOS\dosmesa.c + +SOURCES = $(CORE_SOURCES) $(DRIVER_SOURCES) + +OBJECTS = $(SOURCES:.c=.o) + +#CFLAGS += -g + +##### RULES ##### + +.c.o: + gcc -c -DDOSVGA -I$(INCDIR) $(CFLAGS) $< + +##### TARGETS ##### + +GL_LIB = dosmesa.a + +default: $(LIBDIR)/$(GL_LIB) + +clean: + -del *.o + +MAKELIB = AR ruv +RANLIB = ls + +# Make the library +$(LIBDIR)/$(GL_LIB): $(OBJECTS) + $(MAKELIB) $(GL_LIB) $(OBJECTS) + copy $(GL_LIB) $(LIBDIR)\$(GL_LIB) + +include depend.dos +# + +# Run 'make depend' to update the dependencies if you change what's included +# by any source file. +# +dep: $(SOURCES) + makedep -fdepend -Y -I../include $(SOURCES) + diff --git a/src/mesa/main/Makefile.X11 b/src/mesa/main/Makefile.X11 new file mode 100644 index 00000000000..e6419b555ac --- /dev/null +++ b/src/mesa/main/Makefile.X11 @@ -0,0 +1,243 @@ +# $Id: Makefile.X11,v 1.1 1999/08/19 00:55:41 jtg Exp $ + +# Mesa 3-D graphics library +# Version: 3.1 +# Copyright (C) 1995-1999 Brian Paul + +# Makefile for core library + + +##### MACROS ##### + +VPATH = RCS + +INCDIR = ../include +LIBDIR = ../lib + +CORE_SOURCES = \ + accum.c \ + alpha.c \ + alphabuf.c \ + api1.c \ + api2.c \ + apiext.c \ + attrib.c \ + bbox.c \ + bitmap.c \ + blend.c \ + clip.c \ + colortab.c \ + config.c \ + context.c \ + copypix.c \ + cva.c \ + debug_xform.c \ + depth.c \ + dlist.c \ + drawpix.c \ + enable.c \ + enums.c \ + eval.c \ + extensions.c \ + feedback.c \ + fog.c \ + get.c \ + hash.c \ + image.c \ + light.c \ + lines.c \ + logic.c \ + masking.c \ + matrix.c \ + misc.c \ + mmath.c \ + mthreads.c \ + pb.c \ + pixel.c \ + pipeline.c \ + points.c \ + pointers.c \ + polygon.c \ + quads.c \ + rastpos.c \ + readpix.c \ + rect.c \ + scissor.c \ + shade.c \ + span.c \ + stages.c \ + stencil.c \ + teximage.c \ + texobj.c \ + texstate.c \ + texture.c \ + translate.c \ + triangle.c \ + varray.c \ + vb.c \ + vbcull.c \ + vbfill.c \ + vbindirect.c \ + vbrender.c \ + vbxform.c \ + vector.c \ + winpos.c \ + xform.c \ + zoom.c \ + X86/x86.c \ + X86/common_x86.c \ + X86/3dnow.c + +DRIVER_SOURCES = \ + X/glxapi.c \ + X/fakeglx.c \ + X/realglx.c \ + X/xfonts.c \ + X/xmesa1.c \ + X/xmesa2.c \ + X/xmesa3.c \ + X/xmesa4.c \ + OSmesa/osmesa.c \ + SVGA/svgamesa.c \ + FX/fxapi.c \ + FX/fxclip.c \ + FX/fxcva.c \ + FX/fxdd.c \ + FX/fxddspan.c \ + FX/fxddtex.c \ + FX/fxfastpath.c \ + FX/fxpipeline.c \ + FX/fxrender.c \ + FX/fxsanity.c \ + FX/fxsetup.c \ + FX/fxtexman.c \ + FX/fxtrifuncs.c \ + FX/fxvsetup.c \ + FX/fxglidew.c +# GGI/ggimesa.c + +ASM_SOURCES = + +ADDITIONAL_OBJ = + +OBJECTS = $(ASM_SOURCES:.S=.o) \ + $(CORE_SOURCES:.c=.o) \ + $(DRIVER_SOURCES:.c=.o) \ + $(ADDITIONAL_OBJ) + + +#who put these here!?! +#GL_LIB = libMesaGL.so +#GLU_LIB = libMesaGLU.so +#GLUT_LIB = libglut.so +#CC = gcc +#INCLUDES=-I. -I../include -I/usr/X11R6/include -I/usr/include/glide -I/usr/local/glide/include + + +##### RULES ##### + +.c.o: + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ + +.S.o: + $(CC) -c $(CFLAGS) $< -o $@ + + +# UGH! These rules shouldn't be needed but IRIX's make (and others?) needs them +X/glxapi.o: X/glxapi.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X/fakeglx.o: X/fakeglx.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X/realglx.o: X/realglx.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X/xfonts.o: X/xfonts.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X/xmesa1.o: X/xmesa1.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X/xmesa2.o: X/xmesa2.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X/xmesa3.o: X/xmesa3.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X/xmesa4.o: X/xmesa4.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +SVGA/svgamesa.o: SVGA/svgamesa.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +OSmesa/osmesa.o: OSmesa/osmesa.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxapi.o: FX/fxapi.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxclip.o: FX/fxclip.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxcva.o: FX/fxcva.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxdd.o: FX/fxdd.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxddspan.o: FX/fxddspan.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxddtex.o: FX/fxddtex.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxfastpath.o: FX/fxfastpath.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxpipeline.o: FX/fxpipeline.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxrender.o: FX/fxrender.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxsanity.o: FX/fxsanity.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxsetup.o: FX/fxsetup.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxtrifuncs.o: FX/fxtrifuncs.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxtexman.o: FX/fxtexman.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxvsetup.o: FX/fxvsetup.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/fxglidew.o: FX/fxglidew.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +FX/X86/fx_3dnow_fastpath.o: FX/X86/fx_3dnow_fastpath.S FX/X86/fx_regoff.h +FX/X86/fx_regoff.h: FX/X86/fx_gen_regoff + $< > $@ +FX/X86/fx_gen_regoff : FX/X86/fx_gen_regoff.c + $(CC) -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +GGI/ggimesa.o: GGI/ggimesa.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X86/x86.o: X86/x86.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X86/common_x86.o: X86/common_x86.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ +X86/3dnow.o: X86/3dnow.c + $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@ + + +##### TARGETS ##### + +#default: +# @echo "Specify a target configuration" + +clean: + -rm *.o *~ */*.o */*~ + +targets: $(LIBDIR)/$(GL_LIB) + +# Make the library +$(LIBDIR)/$(GL_LIB): $(OBJECTS) + $(MAKELIB) $(GL_LIB) $(MAJOR) $(MINOR) $(OBJECTS) + rm -f $(LIBDIR)/$(GL_LIB)* + mv $(GL_LIB)* $(LIBDIR) + + +include ../Make-config + +include depend + + + +# +# Run 'make dep' to update the dependencies if you change what's included +# by any source file. +# +dep: $(CORE_SOURCES) $(DRIVER_SOURCES) + makedepend -fdepend -Y -I../include -DGGI -DSVGA -DFX $(CORE_SOURCES) $(DRIVER_SOURCES) + +tags: + etags `find . -name \*.[ch]` `find ../include` diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c new file mode 100644 index 00000000000..29a8a134f2c --- /dev/null +++ b/src/mesa/main/accum.c @@ -0,0 +1,495 @@ +/* $Id: accum.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include "accum.h" +#include "context.h" +#include "macros.h" +#include "masking.h" +#include "span.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +/* + * 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. + */ + + + +void gl_alloc_accum_buffer( GLcontext *ctx ) +{ + GLint n; + + if (ctx->Buffer->Accum) { + free( ctx->Buffer->Accum ); + ctx->Buffer->Accum = NULL; + } + + /* allocate accumulation buffer if not already present */ + n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum); + ctx->Buffer->Accum = (GLaccum *) malloc( n ); + if (!ctx->Buffer->Accum) { + /* unable to setup accumulation buffer */ + gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" ); + } + ctx->IntegerAccumMode = GL_TRUE; + ctx->IntegerAccumScaler = 0.0; +} + + + +void gl_ClearAccum( GLcontext *ctx, + GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glAccum"); + + ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 ); + ctx->Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 ); + ctx->Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 ); + ctx->Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.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 ) +{ + const GLuint n = ctx->Buffer->Width * ctx->Buffer->Height * 4; + const GLfloat s = ctx->IntegerAccumScaler * (32767.0 / 255.0); + GLaccum *accum = ctx->Buffer->Accum; + GLuint i; + + assert(ctx->IntegerAccumMode); + assert(sizeof(GLchan) == 1); /* if not true, 255.0 above must be fixed */ + assert(accum); + + for (i = 0; i < n; i++) { + accum[i] = (GLaccum) (accum[i] * s); + } + + ctx->IntegerAccumMode = GL_FALSE; +} + + + +void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value ) +{ + GLuint xpos, ypos, width, height, width4; + GLfloat acc_scale; + GLubyte rgba[MAX_WIDTH][4]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glAccum"); + + if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) { + /* No accumulation buffer! */ + gl_warning(ctx, "Calling glAccum() without an accumulation buffer"); + return; + } + + if (sizeof(GLaccum)==1) { + acc_scale = 127.0; + } + else if (sizeof(GLaccum)==2) { + acc_scale = 32767.0; + } + else { + /* sizeof(GLaccum) > 2 (Cray) */ + acc_scale = (float) SHRT_MAX; + } + + if (ctx->NewState) + gl_update_state( ctx ); + + /* Determine region to operate upon. */ + if (ctx->Scissor.Enabled) { + xpos = ctx->Scissor.X; + ypos = ctx->Scissor.Y; + width = ctx->Scissor.Width; + height = ctx->Scissor.Height; + } + else { + /* whole window */ + xpos = 0; + ypos = 0; + width = ctx->Buffer->Width; + height = ctx->Buffer->Height; + } + + width4 = 4 * width; + + switch (op) { + case GL_ADD: + { + const GLaccum intVal = (GLaccum) (value * acc_scale); + GLuint j; + /* May have to leave optimized accum buffer mode */ + if (ctx->IntegerAccumMode) + rescale_accum(ctx); + for (j = 0; j < height; j++) { + GLaccum * acc = ctx->Buffer->Accum + ypos * width4 + 4 * xpos; + GLuint i; + for (i = 0; i < width4; i++) { + acc[i] += intVal; + } + ypos++; + } + } + break; + + case GL_MULT: + { + GLuint j; + /* May have to leave optimized accum buffer mode */ + if (ctx->IntegerAccumMode) + rescale_accum(ctx); + for (j = 0; j < height; j++) { + GLaccum *acc = ctx->Buffer->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: + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); + + /* May have to leave optimized accum buffer mode */ + if (ctx->IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0) + ctx->IntegerAccumScaler = value; + if (ctx->IntegerAccumMode && value != ctx->IntegerAccumScaler) + rescale_accum(ctx); + + if (ctx->IntegerAccumMode) { + /* simply add integer color values into accum buffer */ + GLuint j; + GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4; + assert(ctx->IntegerAccumScaler > 0.0); + assert(ctx->IntegerAccumScaler <= 1.0); + for (j = 0; j < height; j++) { + + GLuint i, i4; + gl_read_rgba_span(ctx, 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 accum buffer */ + const GLfloat rscale = value * acc_scale / 255.0; + const GLfloat gscale = value * acc_scale / 255.0; + const GLfloat bscale = value * acc_scale / 255.0; + const GLfloat ascale = value * acc_scale / 255.0; + GLuint j; + for (j=0;j<height;j++) { + GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4; + GLuint i; + gl_read_rgba_span(ctx, width, xpos, ypos, rgba); + for (i=0;i<width;i++) { + *acc += (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale ); acc++; + *acc += (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale ); acc++; + *acc += (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale ); acc++; + *acc += (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale ); acc++; + } + ypos++; + } + } + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); + break; + + case GL_LOAD: + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); + + /* This is a change to go into optimized accum buffer mode */ + if (value > 0.0 && value <= 1.0) { + ctx->IntegerAccumMode = GL_TRUE; + ctx->IntegerAccumScaler = value; + } + else { + ctx->IntegerAccumMode = GL_FALSE; + ctx->IntegerAccumScaler = 0.0; + } + + if (ctx->IntegerAccumMode) { + /* just copy values into accum buffer */ + GLuint j; + GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4; + assert(ctx->IntegerAccumScaler > 0.0); + assert(ctx->IntegerAccumScaler <= 1.0); + for (j = 0; j < height; j++) { + GLuint i, i4; + gl_read_rgba_span(ctx, 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 accum buffer */ + const GLfloat rscale = value * acc_scale / 255.0; + const GLfloat gscale = value * acc_scale / 255.0; + const GLfloat bscale = value * acc_scale / 255.0; + const GLfloat ascale = value * acc_scale / 255.0; + GLuint i, j; + for (j = 0; j < height; j++) { + GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4; + gl_read_rgba_span(ctx, width, xpos, ypos, rgba); + for (i=0;i<width;i++) { + *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 ); + } + ypos++; + } + } + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); + break; + + case GL_RETURN: + /* May have to leave optimized accum buffer mode */ + if (ctx->IntegerAccumMode && value != 1.0) + rescale_accum(ctx); + + if (ctx->IntegerAccumMode) { + /* build lookup table to avoid integer divides */ + GLint divisor = (GLint) ((1.0F / ctx->IntegerAccumScaler) + 0.5F); + static GLubyte divTable[32768]; + static GLint prevDivisor = 0.0; + GLuint j; + if (divisor != prevDivisor) { + assert(divisor * 256 <= 32768); + for (j = 0; j < divisor * 256; j++) + divTable[j] = j / divisor; + prevDivisor = divisor; + } + + assert(ctx->IntegerAccumScaler > 0.0); + assert(ctx->IntegerAccumScaler <= 1.0); + for (j = 0; j < height; j++) { + const GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos*4; + GLuint i, i4; + for (i = i4 = 0; i < width; i++, i4 += 4) { + ASSERT(acc[i4+0] < divisor * 256); + ASSERT(acc[i4+1] < divisor * 256); + ASSERT(acc[i4+2] < divisor * 256); + ASSERT(acc[i4+3] < divisor * 256); + rgba[i][RCOMP] = divTable[acc[i4+0]]; + rgba[i][GCOMP] = divTable[acc[i4+1]]; + rgba[i][BCOMP] = divTable[acc[i4+2]]; + rgba[i][ACOMP] = divTable[acc[i4+3]]; + } + if (ctx->Color.SWmasking) { + gl_mask_rgba_span( ctx, width, xpos, ypos, rgba ); + } + (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, + (const GLubyte (*)[4])rgba, NULL ); + ypos++; + } + } + else { + const GLfloat rscale = value / acc_scale * 255.0F; + const GLfloat gscale = value / acc_scale * 255.0F; + const GLfloat bscale = value / acc_scale * 255.0F; + const GLfloat ascale = value / acc_scale * 255.0F; + GLuint i, j; + for (j=0;j<height;j++) { + const GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos*4; + for (i=0;i<width;i++) { + GLint r, g, b, a; + r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F ); + g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F ); + b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F ); + a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F ); + rgba[i][RCOMP] = CLAMP( r, 0, 255 ); + rgba[i][GCOMP] = CLAMP( g, 0, 255 ); + rgba[i][BCOMP] = CLAMP( b, 0, 255 ); + rgba[i][ACOMP] = CLAMP( a, 0, 255 ); + } + if (ctx->Color.SWmasking) { + gl_mask_rgba_span( ctx, width, xpos, ypos, rgba ); + } + (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, + (const GLubyte (*)[4])rgba, NULL ); + ypos++; + } + } + break; + + default: + gl_error( ctx, GL_INVALID_ENUM, "glAccum" ); + } +} + + + +/* + * Clear the accumulation Buffer. + */ +void gl_clear_accum_buffer( GLcontext *ctx ) +{ + GLuint buffersize; + GLfloat acc_scale; + + if (ctx->Visual->AccumBits==0) { + /* No accumulation buffer! */ + return; + } + + if (sizeof(GLaccum)==1) { + acc_scale = 127.0; + } + else if (sizeof(GLaccum)==2) { + acc_scale = 32767.0; + } + else { + /* sizeof(GLaccum) > 2 (Cray) */ + acc_scale = (float) SHRT_MAX; + } + + /* number of pixels */ + buffersize = ctx->Buffer->Width * ctx->Buffer->Height; + + if (!ctx->Buffer->Accum) { + /* try to alloc accumulation buffer */ + ctx->Buffer->Accum = (GLaccum *) + malloc( buffersize * 4 * sizeof(GLaccum) ); + } + + if (ctx->Buffer->Accum) { + if (ctx->Scissor.Enabled) { + /* Limit clear to scissor box */ + GLaccum r, g, b, a; + GLint i, j; + GLint width, height; + GLaccum *row; + r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale); + g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale); + b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale); + a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale); + /* size of region to clear */ + width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1); + height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1; + /* ptr to first element to clear */ + row = ctx->Buffer->Accum + + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width + + ctx->Buffer->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->Buffer->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 */ + MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) ); + } + else { + /* Not black */ + GLaccum *acc, r, g, b, a; + GLuint i; + + acc = ctx->Buffer->Accum; + r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale); + g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale); + b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale); + a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale); + 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) { + ctx->IntegerAccumMode = GL_TRUE; + ctx->IntegerAccumScaler = 0.0; /* denotes empty accum buffer */ + } + else { + ctx->IntegerAccumMode = GL_FALSE; + } + } +} diff --git a/src/mesa/main/accum.h b/src/mesa/main/accum.h new file mode 100644 index 00000000000..dd641da456a --- /dev/null +++ b/src/mesa/main/accum.h @@ -0,0 +1,51 @@ +/* $Id: accum.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 ACCUM_H +#define ACCUM_H + + +#include "types.h" + + +extern void gl_alloc_accum_buffer( GLcontext *ctx ); + + +extern void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value ); + + +extern void gl_ClearAccum( GLcontext *ctx, GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ); + + +extern void gl_clear_accum_buffer( GLcontext *ctx ); + + +#endif diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c new file mode 100644 index 00000000000..78f4d05b2c9 --- /dev/null +++ b/src/mesa/main/attrib.c @@ -0,0 +1,863 @@ +/* $Id: attrib.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "attrib.h" +#include "context.h" +#include "enable.h" +#include "enums.h" +#include "macros.h" +#include "misc.h" +#include "simple_list.h" +#include "texstate.h" +#include "types.h" +#ifdef XFree86Server +#undef MISC_H +#include "GL/xf86glx.h" +#endif +#endif + + +#define MALLOC_STRUCT(T) (struct T *) malloc( sizeof(struct T) ) + + + +/* + * Allocate a new attribute state node. These nodes have a + * "kind" value and a pointer to a struct of state data. + */ +static struct gl_attrib_node *new_attrib_node( GLbitfield kind ) +{ + struct gl_attrib_node *an; + + an = (struct gl_attrib_node *) malloc( sizeof(struct gl_attrib_node) ); + if (an) { + an->kind = kind; + } + return an; +} + + + +/* + * Copy texture object state from one texture object to another. + */ +static void copy_texobj_state( struct gl_texture_object *dest, + const struct gl_texture_object *src ) +{ + /* + dest->Name = src->Name; + dest->Dimensions = src->Dimensions; + */ + dest->Priority = src->Priority; + dest->BorderColor[0] = src->BorderColor[0]; + dest->BorderColor[1] = src->BorderColor[1]; + dest->BorderColor[2] = src->BorderColor[2]; + dest->BorderColor[3] = src->BorderColor[3]; + dest->WrapS = src->WrapS; + dest->WrapT = src->WrapT; + dest->WrapR = src->WrapR; + dest->MinFilter = src->MinFilter; + dest->MagFilter = src->MagFilter; + dest->MinLod = src->MinLod; + dest->MaxLod = src->MaxLod; + dest->BaseLevel = src->BaseLevel; + dest->MaxLevel = src->MaxLevel; + dest->P = src->P; + dest->M = src->M; + dest->MinMagThresh = src->MinMagThresh; + memcpy( dest->Palette, src->Palette, + sizeof(GLubyte) * MAX_TEXTURE_PALETTE_SIZE * 4 ); + dest->PaletteSize = src->PaletteSize; + dest->PaletteIntFormat = src->PaletteIntFormat; + dest->PaletteFormat = src->PaletteFormat; + dest->Complete = src->Complete; + dest->SampleFunc = src->SampleFunc; +} + + + +void gl_PushAttrib( GLcontext* ctx, GLbitfield mask ) +{ + struct gl_attrib_node *newnode; + struct gl_attrib_node *head; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushAttrib"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glPushAttrib %x\n", mask); + + if (ctx->AttribStackDepth>=MAX_ATTRIB_STACK_DEPTH) { + gl_error( ctx, GL_STACK_OVERFLOW, "glPushAttrib" ); + return; + } + + /* Build linked list of attribute nodes which save all attribute */ + /* groups specified by the mask. */ + head = NULL; + + if (mask & GL_ACCUM_BUFFER_BIT) { + struct gl_accum_attrib *attr; + attr = MALLOC_STRUCT( gl_accum_attrib ); + MEMCPY( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) ); + newnode = new_attrib_node( GL_ACCUM_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_COLOR_BUFFER_BIT) { + struct gl_colorbuffer_attrib *attr; + attr = MALLOC_STRUCT( gl_colorbuffer_attrib ); + MEMCPY( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) ); + newnode = new_attrib_node( GL_COLOR_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_CURRENT_BIT) { + struct gl_current_attrib *attr; + attr = MALLOC_STRUCT( gl_current_attrib ); + MEMCPY( attr, &ctx->Current, sizeof(struct gl_current_attrib) ); + newnode = new_attrib_node( GL_CURRENT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_DEPTH_BUFFER_BIT) { + struct gl_depthbuffer_attrib *attr; + attr = MALLOC_STRUCT( gl_depthbuffer_attrib ); + MEMCPY( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) ); + newnode = new_attrib_node( GL_DEPTH_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_ENABLE_BIT) { + struct gl_enable_attrib *attr; + GLuint i; + attr = MALLOC_STRUCT( gl_enable_attrib ); + /* Copy enable flags from all other attributes into the enable struct. */ + attr->AlphaTest = ctx->Color.AlphaEnabled; + attr->AutoNormal = ctx->Eval.AutoNormal; + attr->Blend = ctx->Color.BlendEnabled; + for (i=0;i<MAX_CLIP_PLANES;i++) { + attr->ClipPlane[i] = ctx->Transform.ClipEnabled[i]; + } + attr->ColorMaterial = ctx->Light.ColorMaterialEnabled; + attr->CullFace = ctx->Polygon.CullFlag; + attr->DepthTest = ctx->Depth.Test; + attr->Dither = ctx->Color.DitherFlag; + attr->Fog = ctx->Fog.Enabled; + for (i=0;i<MAX_LIGHTS;i++) { + attr->Light[i] = ctx->Light.Light[i].Enabled; + } + attr->Lighting = ctx->Light.Enabled; + attr->LineSmooth = ctx->Line.SmoothFlag; + attr->LineStipple = ctx->Line.StippleFlag; + attr->IndexLogicOp = ctx->Color.IndexLogicOpEnabled; + attr->ColorLogicOp = ctx->Color.ColorLogicOpEnabled; + attr->Map1Color4 = ctx->Eval.Map1Color4; + attr->Map1Index = ctx->Eval.Map1Index; + attr->Map1Normal = ctx->Eval.Map1Normal; + attr->Map1TextureCoord1 = ctx->Eval.Map1TextureCoord1; + attr->Map1TextureCoord2 = ctx->Eval.Map1TextureCoord2; + attr->Map1TextureCoord3 = ctx->Eval.Map1TextureCoord3; + attr->Map1TextureCoord4 = ctx->Eval.Map1TextureCoord4; + attr->Map1Vertex3 = ctx->Eval.Map1Vertex3; + attr->Map1Vertex4 = ctx->Eval.Map1Vertex4; + attr->Map2Color4 = ctx->Eval.Map2Color4; + attr->Map2Index = ctx->Eval.Map2Index; + attr->Map2Normal = ctx->Eval.Map2Normal; + attr->Map2TextureCoord1 = ctx->Eval.Map2TextureCoord1; + attr->Map2TextureCoord2 = ctx->Eval.Map2TextureCoord2; + attr->Map2TextureCoord3 = ctx->Eval.Map2TextureCoord3; + attr->Map2TextureCoord4 = ctx->Eval.Map2TextureCoord4; + attr->Map2Vertex3 = ctx->Eval.Map2Vertex3; + attr->Map2Vertex4 = ctx->Eval.Map2Vertex4; + attr->Normalize = ctx->Transform.Normalize; + attr->PointSmooth = ctx->Point.SmoothFlag; + attr->PolygonOffsetPoint = ctx->Polygon.OffsetPoint; + attr->PolygonOffsetLine = ctx->Polygon.OffsetLine; + attr->PolygonOffsetFill = ctx->Polygon.OffsetFill; + attr->PolygonSmooth = ctx->Polygon.SmoothFlag; + attr->PolygonStipple = ctx->Polygon.StippleFlag; + attr->RescaleNormals = ctx->Transform.RescaleNormals; + attr->Scissor = ctx->Scissor.Enabled; + attr->Stencil = ctx->Stencil.Enabled; + attr->Texture = ctx->Texture.Enabled; + for (i=0; i<MAX_TEXTURE_UNITS; i++) { + attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled; + } + newnode = new_attrib_node( GL_ENABLE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_EVAL_BIT) { + struct gl_eval_attrib *attr; + attr = MALLOC_STRUCT( gl_eval_attrib ); + MEMCPY( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) ); + newnode = new_attrib_node( GL_EVAL_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_FOG_BIT) { + struct gl_fog_attrib *attr; + attr = MALLOC_STRUCT( gl_fog_attrib ); + MEMCPY( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) ); + newnode = new_attrib_node( GL_FOG_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_HINT_BIT) { + struct gl_hint_attrib *attr; + attr = MALLOC_STRUCT( gl_hint_attrib ); + MEMCPY( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) ); + newnode = new_attrib_node( GL_HINT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_LIGHTING_BIT) { + struct gl_light_attrib *attr; + attr = MALLOC_STRUCT( gl_light_attrib ); + MEMCPY( attr, &ctx->Light, sizeof(struct gl_light_attrib) ); + newnode = new_attrib_node( GL_LIGHTING_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_LINE_BIT) { + struct gl_line_attrib *attr; + attr = MALLOC_STRUCT( gl_line_attrib ); + MEMCPY( attr, &ctx->Line, sizeof(struct gl_line_attrib) ); + newnode = new_attrib_node( GL_LINE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_LIST_BIT) { + struct gl_list_attrib *attr; + attr = MALLOC_STRUCT( gl_list_attrib ); + MEMCPY( attr, &ctx->List, sizeof(struct gl_list_attrib) ); + newnode = new_attrib_node( GL_LIST_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_PIXEL_MODE_BIT) { + struct gl_pixel_attrib *attr; + attr = MALLOC_STRUCT( gl_pixel_attrib ); + MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) ); + newnode = new_attrib_node( GL_PIXEL_MODE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_POINT_BIT) { + struct gl_point_attrib *attr; + attr = MALLOC_STRUCT( gl_point_attrib ); + MEMCPY( attr, &ctx->Point, sizeof(struct gl_point_attrib) ); + newnode = new_attrib_node( GL_POINT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_POLYGON_BIT) { + struct gl_polygon_attrib *attr; + attr = MALLOC_STRUCT( gl_polygon_attrib ); + MEMCPY( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) ); + newnode = new_attrib_node( GL_POLYGON_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_POLYGON_STIPPLE_BIT) { + GLuint *stipple; + stipple = (GLuint *) malloc( 32*sizeof(GLuint) ); + MEMCPY( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) ); + newnode = new_attrib_node( GL_POLYGON_STIPPLE_BIT ); + newnode->data = stipple; + newnode->next = head; + head = newnode; + } + + if (mask & GL_SCISSOR_BIT) { + struct gl_scissor_attrib *attr; + attr = MALLOC_STRUCT( gl_scissor_attrib ); + MEMCPY( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) ); + newnode = new_attrib_node( GL_SCISSOR_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_STENCIL_BUFFER_BIT) { + struct gl_stencil_attrib *attr; + attr = MALLOC_STRUCT( gl_stencil_attrib ); + MEMCPY( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) ); + newnode = new_attrib_node( GL_STENCIL_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_TEXTURE_BIT) { + struct gl_texture_attrib *attr; + GLuint u; + /* Take care of texture object reference counters */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + ctx->Texture.Unit[u].CurrentD[1]->RefCount++; + ctx->Texture.Unit[u].CurrentD[2]->RefCount++; + ctx->Texture.Unit[u].CurrentD[3]->RefCount++; + } + attr = MALLOC_STRUCT( gl_texture_attrib ); + MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) ); + /* copy state of the currently bound texture objects */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + copy_texobj_state(&attr->Unit[u].Saved1D, attr->Unit[u].CurrentD[1]); + copy_texobj_state(&attr->Unit[u].Saved2D, attr->Unit[u].CurrentD[2]); + copy_texobj_state(&attr->Unit[u].Saved3D, attr->Unit[u].CurrentD[3]); + } + newnode = new_attrib_node( GL_TEXTURE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_TRANSFORM_BIT) { + struct gl_transform_attrib *attr; + attr = MALLOC_STRUCT( gl_transform_attrib ); + MEMCPY( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) ); + newnode = new_attrib_node( GL_TRANSFORM_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_VIEWPORT_BIT) { + struct gl_viewport_attrib *attr; + attr = MALLOC_STRUCT( gl_viewport_attrib ); + MEMCPY( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) ); + newnode = new_attrib_node( GL_VIEWPORT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + ctx->AttribStack[ctx->AttribStackDepth] = head; + ctx->AttribStackDepth++; +} + + + +/* + * This function is kind of long just because we have to call a lot + * of device driver functions to update device driver state. + */ +void gl_PopAttrib( GLcontext* ctx ) +{ + struct gl_attrib_node *attr, *next; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopAttrib"); + + + if (ctx->AttribStackDepth==0) { + gl_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" ); + return; + } + + ctx->AttribStackDepth--; + attr = ctx->AttribStack[ctx->AttribStackDepth]; + + while (attr) { + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glPopAttrib %s\n", gl_lookup_enum_by_nr(attr->kind)); + + switch (attr->kind) { + case GL_ACCUM_BUFFER_BIT: + MEMCPY( &ctx->Accum, attr->data, sizeof(struct gl_accum_attrib) ); + break; + case GL_COLOR_BUFFER_BIT: + { + GLenum oldDrawBuffer = ctx->Color.DrawBuffer; + GLenum oldAlphaFunc = ctx->Color.AlphaFunc; + GLubyte oldAlphaRef = ctx->Color.AlphaRef; + GLenum oldBlendSrc = ctx->Color.BlendSrcRGB; + GLenum oldBlendDst = ctx->Color.BlendDstRGB; + MEMCPY( &ctx->Color, attr->data, + sizeof(struct gl_colorbuffer_attrib) ); + if (ctx->Color.DrawBuffer != oldDrawBuffer) { + gl_DrawBuffer(ctx, ctx->Color.DrawBuffer); + } + if ((ctx->Color.AlphaFunc != oldAlphaFunc || + ctx->Color.AlphaRef != oldAlphaRef) && + ctx->Driver.AlphaFunc) + (*ctx->Driver.AlphaFunc)( ctx, ctx->Color.AlphaFunc, + ctx->Color.AlphaRef / 255.0F); + if ((ctx->Color.BlendSrcRGB != oldBlendSrc || + ctx->Color.BlendSrcRGB != oldBlendDst) && + ctx->Driver.BlendFunc) + (*ctx->Driver.BlendFunc)( ctx, ctx->Color.BlendSrcRGB, + ctx->Color.BlendDstRGB); + } + break; + case GL_CURRENT_BIT: + MEMCPY( &ctx->Current, attr->data, + sizeof(struct gl_current_attrib) ); + break; + case GL_DEPTH_BUFFER_BIT: + { + GLenum oldDepthFunc = ctx->Depth.Func; + GLboolean oldDepthMask = ctx->Depth.Mask; + GLfloat oldDepthClear = ctx->Depth.Clear; + MEMCPY( &ctx->Depth, attr->data, + sizeof(struct gl_depthbuffer_attrib) ); + if (ctx->Depth.Func != oldDepthFunc && ctx->Driver.DepthFunc) + (*ctx->Driver.DepthFunc)( ctx, ctx->Depth.Func ); + if (ctx->Depth.Mask != oldDepthMask && ctx->Driver.DepthMask) + (*ctx->Driver.DepthMask)( ctx, ctx->Depth.Mask ); + if (ctx->Depth.Clear != oldDepthClear && ctx->Driver.ClearDepth) + (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear ); + } + break; + case GL_ENABLE_BIT: + { + const struct gl_enable_attrib *enable; + enable = (const struct gl_enable_attrib *) attr->data; + +#define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \ + if ((VALUE) != (NEWVALUE)) { \ + gl_set_enable( ctx, ENUM, (NEWVALUE) ); \ + } + + TEST_AND_UPDATE(ctx->Color.AlphaEnabled, enable->AlphaTest, GL_ALPHA_TEST); + TEST_AND_UPDATE(ctx->Transform.Normalize, enable->AutoNormal, GL_NORMALIZE); + TEST_AND_UPDATE(ctx->Color.BlendEnabled, enable->Blend, GL_BLEND); + { + GLuint i; + for (i=0;i<MAX_CLIP_PLANES;i++) { + if (ctx->Transform.ClipEnabled[i] != enable->ClipPlane[i]) + gl_set_enable( ctx, (GLenum) (GL_CLIP_PLANE0 + i), enable->ClipPlane[i] ); + } + } + TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial, GL_COLOR_MATERIAL); + TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE); + TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER); + TEST_AND_UPDATE(ctx->Fog.Enabled, enable->Fog, GL_FOG); + TEST_AND_UPDATE(ctx->Light.Enabled, enable->Lighting, GL_LIGHTING); + TEST_AND_UPDATE(ctx->Line.SmoothFlag, enable->LineSmooth, GL_LINE_SMOOTH); + TEST_AND_UPDATE(ctx->Line.StippleFlag, enable->LineStipple, GL_LINE_STIPPLE); + TEST_AND_UPDATE(ctx->Color.IndexLogicOpEnabled, enable->IndexLogicOp, GL_INDEX_LOGIC_OP); + TEST_AND_UPDATE(ctx->Color.ColorLogicOpEnabled, enable->ColorLogicOp, GL_COLOR_LOGIC_OP); + TEST_AND_UPDATE(ctx->Eval.Map1Color4, enable->Map1Color4, GL_MAP1_COLOR_4); + TEST_AND_UPDATE(ctx->Eval.Map1Index, enable->Map1Index, GL_MAP1_INDEX); + TEST_AND_UPDATE(ctx->Eval.Map1Normal, enable->Map1Normal, GL_MAP1_NORMAL); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord1, enable->Map1TextureCoord1, GL_MAP1_TEXTURE_COORD_1); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord2, enable->Map1TextureCoord2, GL_MAP1_TEXTURE_COORD_2); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord3, enable->Map1TextureCoord3, GL_MAP1_TEXTURE_COORD_3); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord4, enable->Map1TextureCoord4, GL_MAP1_TEXTURE_COORD_4); + TEST_AND_UPDATE(ctx->Eval.Map1Vertex3, enable->Map1Vertex3, GL_MAP1_VERTEX_3); + TEST_AND_UPDATE(ctx->Eval.Map1Vertex4, enable->Map1Vertex4, GL_MAP1_VERTEX_4); + TEST_AND_UPDATE(ctx->Eval.Map2Color4, enable->Map2Color4, GL_MAP2_COLOR_4); + TEST_AND_UPDATE(ctx->Eval.Map2Index, enable->Map2Index, GL_MAP2_INDEX); + TEST_AND_UPDATE(ctx->Eval.Map2Normal, enable->Map2Normal, GL_MAP2_NORMAL); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord1, enable->Map2TextureCoord1, GL_MAP2_TEXTURE_COORD_1); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord2, enable->Map2TextureCoord2, GL_MAP2_TEXTURE_COORD_2); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord3, enable->Map2TextureCoord3, GL_MAP2_TEXTURE_COORD_3); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord4, enable->Map2TextureCoord4, GL_MAP2_TEXTURE_COORD_4); + TEST_AND_UPDATE(ctx->Eval.Map2Vertex3, enable->Map2Vertex3, GL_MAP2_VERTEX_3); + TEST_AND_UPDATE(ctx->Eval.Map2Vertex4, enable->Map2Vertex4, GL_MAP2_VERTEX_4); + TEST_AND_UPDATE(ctx->Transform.Normalize, enable->Normalize, GL_NORMALIZE); + TEST_AND_UPDATE(ctx->Transform.RescaleNormals, enable->RescaleNormals, GL_RESCALE_NORMAL_EXT); + TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth, GL_POINT_SMOOTH); + TEST_AND_UPDATE(ctx->Polygon.OffsetPoint, enable->PolygonOffsetPoint, GL_POLYGON_OFFSET_POINT); + TEST_AND_UPDATE(ctx->Polygon.OffsetLine, enable->PolygonOffsetLine, GL_POLYGON_OFFSET_LINE); + TEST_AND_UPDATE(ctx->Polygon.OffsetFill, enable->PolygonOffsetFill, GL_POLYGON_OFFSET_FILL); + TEST_AND_UPDATE(ctx->Polygon.SmoothFlag, enable->PolygonSmooth, GL_POLYGON_SMOOTH); + TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple, GL_POLYGON_STIPPLE); + TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST); + TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST); + if (ctx->Texture.Enabled != enable->Texture) { + ctx->Texture.Enabled = enable->Texture; + if (ctx->Driver.Enable) { + if (ctx->Driver.ActiveTexture) + (*ctx->Driver.ActiveTexture)( ctx, 0 ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_1D, (GLboolean) (enable->Texture & TEXTURE0_1D) ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_2D, (GLboolean) (enable->Texture & TEXTURE0_2D) ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_3D, (GLboolean) (enable->Texture & TEXTURE0_3D) ); + if (ctx->Driver.ActiveTexture) + (*ctx->Driver.ActiveTexture)( ctx, 1 ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_1D, (GLboolean) (enable->Texture & TEXTURE1_1D) ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_2D, (GLboolean) (enable->Texture & TEXTURE1_2D) ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_3D, (GLboolean) (enable->Texture & TEXTURE1_3D) ); + if (ctx->Driver.ActiveTexture) + (*ctx->Driver.ActiveTexture)( ctx, ctx->Texture.CurrentUnit ); + } + } +#undef TEST_AND_UPDATE + { + GLuint i; + for (i=0; i<MAX_TEXTURE_UNITS; i++) { + if (ctx->Texture.Unit[i].TexGenEnabled != enable->TexGen[i]) { + ctx->Texture.Unit[i].TexGenEnabled = enable->TexGen[i]; + + /* ctx->Enabled recalculated in state change + processing */ + + if (ctx->Driver.Enable) { + if (ctx->Driver.ActiveTexture) + (*ctx->Driver.ActiveTexture)( ctx, i ); + if (enable->TexGen[i] & S_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_FALSE); + if (enable->TexGen[i] & T_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_FALSE); + if (enable->TexGen[i] & R_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_FALSE); + if (enable->TexGen[i] & Q_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_FALSE); + } + } + } + if (ctx->Driver.ActiveTexture) + (*ctx->Driver.ActiveTexture)( ctx, ctx->Texture.CurrentUnit ); + } + } + break; + case GL_EVAL_BIT: + MEMCPY( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) ); + break; + case GL_FOG_BIT: + { + GLboolean anyChange = (memcmp( &ctx->Fog, attr->data, sizeof(struct gl_fog_attrib) ) != 0); + MEMCPY( &ctx->Fog, attr->data, sizeof(struct gl_fog_attrib) ); + if (anyChange && ctx->Driver.Fogfv) { + const GLfloat mode = ctx->Fog.Mode; + const GLfloat density = ctx->Fog.Density; + const GLfloat start = ctx->Fog.Start; + const GLfloat end = ctx->Fog.End; + const GLfloat index = ctx->Fog.Index; + (*ctx->Driver.Fogfv)( ctx, GL_FOG_MODE, &mode); + (*ctx->Driver.Fogfv)( ctx, GL_FOG_DENSITY, &density ); + (*ctx->Driver.Fogfv)( ctx, GL_FOG_START, &start ); + (*ctx->Driver.Fogfv)( ctx, GL_FOG_END, &end ); + (*ctx->Driver.Fogfv)( ctx, GL_FOG_INDEX, &index ); + (*ctx->Driver.Fogfv)( ctx, GL_FOG_COLOR, ctx->Fog.Color ); + } + ctx->Enabled &= ENABLE_FOG; + if (ctx->Fog.Enabled) ctx->Enabled |= ENABLE_FOG; + } + break; + case GL_HINT_BIT: + MEMCPY( &ctx->Hint, attr->data, sizeof(struct gl_hint_attrib) ); + if (ctx->Driver.Hint) { + (*ctx->Driver.Hint)( ctx, GL_PERSPECTIVE_CORRECTION_HINT, + ctx->Hint.PerspectiveCorrection ); + (*ctx->Driver.Hint)( ctx, GL_POINT_SMOOTH_HINT, + ctx->Hint.PointSmooth); + (*ctx->Driver.Hint)( ctx, GL_LINE_SMOOTH_HINT, + ctx->Hint.LineSmooth ); + (*ctx->Driver.Hint)( ctx, GL_POLYGON_SMOOTH_HINT, + ctx->Hint.PolygonSmooth ); + (*ctx->Driver.Hint)( ctx, GL_FOG_HINT, ctx->Hint.Fog ); + } + break; + case GL_LIGHTING_BIT: + MEMCPY( &ctx->Light, attr->data, sizeof(struct gl_light_attrib) ); + if (ctx->Driver.Enable) { + GLuint i; + for (i = 0; i < MAX_LIGHTS; i++) { + GLenum light = (GLenum) (GL_LIGHT0 + i); + (*ctx->Driver.Enable)( ctx, light, ctx->Light.Light[i].Enabled ); + } + (*ctx->Driver.Enable)( ctx, GL_LIGHTING, ctx->Light.Enabled ); + } + ctx->Enabled &= ENABLE_LIGHT; + if (ctx->Light.Enabled && !is_empty_list(&ctx->Light.EnabledList)) + ctx->Enabled |= ENABLE_LIGHT; + break; + case GL_LINE_BIT: + MEMCPY( &ctx->Line, attr->data, sizeof(struct gl_line_attrib) ); + if (ctx->Driver.Enable) { + (*ctx->Driver.Enable)( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag ); + (*ctx->Driver.Enable)( ctx, GL_LINE_STIPPLE, ctx->Line.StippleFlag ); + } + break; + case GL_LIST_BIT: + MEMCPY( &ctx->List, attr->data, sizeof(struct gl_list_attrib) ); + break; + case GL_PIXEL_MODE_BIT: + MEMCPY( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) ); + break; + case GL_POINT_BIT: + MEMCPY( &ctx->Point, attr->data, sizeof(struct gl_point_attrib) ); + if (ctx->Driver.Enable) + (*ctx->Driver.Enable)( ctx, GL_POINT_SMOOTH, ctx->Point.SmoothFlag ); + break; + case GL_POLYGON_BIT: + { + GLenum oldFrontMode = ctx->Polygon.FrontMode; + GLenum oldBackMode = ctx->Polygon.BackMode; + MEMCPY( &ctx->Polygon, attr->data, + sizeof(struct gl_polygon_attrib) ); + if ((ctx->Polygon.FrontMode != oldFrontMode || + ctx->Polygon.BackMode != oldBackMode) && + ctx->Driver.PolygonMode) { + (*ctx->Driver.PolygonMode)( ctx, GL_FRONT, ctx->Polygon.FrontMode); + (*ctx->Driver.PolygonMode)( ctx, GL_BACK, ctx->Polygon.BackMode); + } + if (ctx->Driver.CullFace) + ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode ); + + if (ctx->Driver.FrontFace) + ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace ); + + if (ctx->Driver.Enable) + (*ctx->Driver.Enable)( ctx, GL_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag ); + } + break; + case GL_POLYGON_STIPPLE_BIT: + MEMCPY( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) ); + break; + case GL_SCISSOR_BIT: + MEMCPY( &ctx->Scissor, attr->data, + sizeof(struct gl_scissor_attrib) ); + if (ctx->Driver.Enable) + (*ctx->Driver.Enable)( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled ); + if (ctx->Driver.Scissor) + ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height ); + break; + case GL_STENCIL_BUFFER_BIT: + MEMCPY( &ctx->Stencil, attr->data, + sizeof(struct gl_stencil_attrib) ); + if (ctx->Driver.StencilFunc) + (*ctx->Driver.StencilFunc)( ctx, ctx->Stencil.Function, + ctx->Stencil.Ref, ctx->Stencil.ValueMask); + if (ctx->Driver.StencilMask) + (*ctx->Driver.StencilMask)( ctx, ctx->Stencil.WriteMask ); + if (ctx->Driver.StencilOp) + (*ctx->Driver.StencilOp)( ctx, ctx->Stencil.FailFunc, + ctx->Stencil.ZFailFunc, ctx->Stencil.ZPassFunc); + if (ctx->Driver.ClearStencil) + (*ctx->Driver.ClearStencil)( ctx, ctx->Stencil.Clear ); + if (ctx->Driver.Enable) + (*ctx->Driver.Enable)( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled ); + break; + case GL_TRANSFORM_BIT: + MEMCPY( &ctx->Transform, attr->data, + sizeof(struct gl_transform_attrib) ); + if (ctx->Driver.Enable) { + (*ctx->Driver.Enable)( ctx, GL_NORMALIZE, ctx->Transform.Normalize ); + (*ctx->Driver.Enable)( ctx, GL_RESCALE_NORMAL_EXT, ctx->Transform.RescaleNormals ); + } + ctx->Enabled &= ~(ENABLE_NORMALIZE|ENABLE_RESCALE); + if (ctx->Transform.Normalize) ctx->Enabled |= ENABLE_NORMALIZE; + if (ctx->Transform.RescaleNormals) ctx->Enabled |= ENABLE_RESCALE; + break; + case GL_TEXTURE_BIT: + /* Take care of texture object reference counters */ + { + GLuint u; + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + ctx->Texture.Unit[u].CurrentD[1]->RefCount--; + ctx->Texture.Unit[u].CurrentD[2]->RefCount--; + ctx->Texture.Unit[u].CurrentD[3]->RefCount--; + } + MEMCPY( &ctx->Texture, attr->data, + sizeof(struct gl_texture_attrib) ); + /* restore state of the currently bound texture objects */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + copy_texobj_state( ctx->Texture.Unit[u].CurrentD[1], + &(ctx->Texture.Unit[u].Saved1D) ); + copy_texobj_state( ctx->Texture.Unit[u].CurrentD[2], + &(ctx->Texture.Unit[u].Saved2D) ); + copy_texobj_state( ctx->Texture.Unit[u].CurrentD[3], + &(ctx->Texture.Unit[u].Saved3D) ); + gl_put_texobj_on_dirty_list( ctx, ctx->Texture.Unit[u].CurrentD[1] ); + gl_put_texobj_on_dirty_list( ctx, ctx->Texture.Unit[u].CurrentD[2] ); + gl_put_texobj_on_dirty_list( ctx, ctx->Texture.Unit[u].CurrentD[3] ); + + } + } + break; + case GL_VIEWPORT_BIT: + MEMCPY( &ctx->Viewport, attr->data, + sizeof(struct gl_viewport_attrib) ); + if (ctx->Driver.Viewport) { + (*ctx->Driver.Viewport)( ctx, ctx->Viewport.X, ctx->Viewport.Y, + ctx->Viewport.Width, ctx->Viewport.Height ); + } + if (ctx->Driver.DepthRange) { + (*ctx->Driver.DepthRange)( ctx, ctx->Viewport.Near, + ctx->Viewport.Far ); + } + break; + default: + gl_problem( ctx, "Bad attrib flag in PopAttrib"); + break; + } + + next = attr->next; + free( (void *) attr->data ); + free( (void *) attr ); + attr = next; + } + + ctx->NewState = NEW_ALL; +} + + +#define GL_CLIENT_PACK_BIT (1<<20) +#define GL_CLIENT_UNPACK_BIT (1<<21) + + +void gl_PushClientAttrib( GLcontext *ctx, GLbitfield mask ) +{ + struct gl_attrib_node *newnode; + struct gl_attrib_node *head; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushClientAttrib"); + + if (ctx->ClientAttribStackDepth>=MAX_CLIENT_ATTRIB_STACK_DEPTH) { + gl_error( ctx, GL_STACK_OVERFLOW, "glPushClientAttrib" ); + return; + } + + /* Build linked list of attribute nodes which save all attribute */ + /* groups specified by the mask. */ + head = NULL; + + if (mask & GL_CLIENT_PIXEL_STORE_BIT) { + struct gl_pixelstore_attrib *attr; + /* packing attribs */ + attr = MALLOC_STRUCT( gl_pixelstore_attrib ); + MEMCPY( attr, &ctx->Pack, sizeof(struct gl_pixelstore_attrib) ); + newnode = new_attrib_node( GL_CLIENT_PACK_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + /* unpacking attribs */ + attr = MALLOC_STRUCT( gl_pixelstore_attrib ); + MEMCPY( attr, &ctx->Unpack, sizeof(struct gl_pixelstore_attrib) ); + newnode = new_attrib_node( GL_CLIENT_UNPACK_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { + struct gl_array_attrib *attr; + attr = MALLOC_STRUCT( gl_array_attrib ); + MEMCPY( attr, &ctx->Array, sizeof(struct gl_array_attrib) ); + newnode = new_attrib_node( GL_CLIENT_VERTEX_ARRAY_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head; + ctx->ClientAttribStackDepth++; +} + + + + +void gl_PopClientAttrib( GLcontext *ctx ) +{ + struct gl_attrib_node *attr, *next; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopClientAttrib"); + + if (ctx->ClientAttribStackDepth==0) { + gl_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" ); + return; + } + + ctx->ClientAttribStackDepth--; + attr = ctx->ClientAttribStack[ctx->ClientAttribStackDepth]; + + while (attr) { + switch (attr->kind) { + case GL_CLIENT_PACK_BIT: + MEMCPY( &ctx->Pack, attr->data, + sizeof(struct gl_pixelstore_attrib) ); + break; + case GL_CLIENT_UNPACK_BIT: + MEMCPY( &ctx->Unpack, attr->data, + sizeof(struct gl_pixelstore_attrib) ); + break; + case GL_CLIENT_VERTEX_ARRAY_BIT: + MEMCPY( &ctx->Array, attr->data, + sizeof(struct gl_array_attrib) ); + break; + default: + gl_problem( ctx, "Bad attrib flag in PopClientAttrib"); + break; + } + + next = attr->next; + free( (void *) attr->data ); + free( (void *) attr ); + attr = next; + } + + ctx->NewState = NEW_ALL; +} + diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h new file mode 100644 index 00000000000..0661c261230 --- /dev/null +++ b/src/mesa/main/attrib.h @@ -0,0 +1,47 @@ +/* $Id: attrib.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 ATTRIB_H +#define ATTRIB_h + + +#include "types.h" + + +extern void gl_PushAttrib( GLcontext* ctx, GLbitfield mask ); + +extern void gl_PopAttrib( GLcontext* ctx ); + +extern void gl_PushClientAttrib( GLcontext *ctx, GLbitfield mask ); + +extern void gl_PopClientAttrib( GLcontext *ctx ); + + +#endif diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c new file mode 100644 index 00000000000..10119ac3b3f --- /dev/null +++ b/src/mesa/main/blend.c @@ -0,0 +1,812 @@ +/* $Id: blend.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include "alphabuf.h" +#include "blend.h" +#include "context.h" +#include "enums.h" +#include "macros.h" +#include "pb.h" +#include "span.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +void gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFunc"); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glBlendFunc %s %s\n", + gl_lookup_enum_by_nr(sfactor), + gl_lookup_enum_by_nr(dfactor)); + + switch (sfactor) { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" ); + return; + } + + switch (dfactor) { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" ); + return; + } + + if (ctx->Driver.BlendFunc) { + (*ctx->Driver.BlendFunc)( ctx, sfactor, dfactor ); + } + + ctx->Color.BlendFunc = NULL; + ctx->NewState |= NEW_RASTER_OPS; +} + + +/* GL_INGR_blend_func_separate */ +void +gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFuncSeparate"); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n", + gl_lookup_enum_by_nr(sfactorRGB), + gl_lookup_enum_by_nr(dfactorRGB), + gl_lookup_enum_by_nr(sfactorA), + gl_lookup_enum_by_nr(dfactorA)); + + switch (sfactorRGB) { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + ctx->Color.BlendSrcRGB = sfactorRGB; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)" ); + return; + } + + switch (dfactorRGB) { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + ctx->Color.BlendDstRGB = dfactorRGB; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)" ); + return; + } + + switch (sfactorA) { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + ctx->Color.BlendSrcA = sfactorA; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)" ); + return; + } + + switch (dfactorA) { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + ctx->Color.BlendDstA = dfactorA; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" ); + return; + } + + ctx->Color.BlendFunc = NULL; + ctx->NewState |= NEW_RASTER_OPS; +} + + + +/* This is really an extension function! */ +void gl_BlendEquation( GLcontext *ctx, GLenum mode ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendEquation"); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glBlendEquation %s\n", + gl_lookup_enum_by_nr(mode)); + + + switch (mode) { + case GL_MIN_EXT: + case GL_MAX_EXT: + case GL_LOGIC_OP: + case GL_FUNC_ADD_EXT: + case GL_FUNC_SUBTRACT_EXT: + case GL_FUNC_REVERSE_SUBTRACT_EXT: + ctx->Color.BlendEquation = mode; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" ); + return; + } + + /* This is needed to support 1.1's RGB logic ops AND + * 1.0's blending logicops. + */ + if (mode==GL_LOGIC_OP && ctx->Color.BlendEnabled) { + ctx->Color.ColorLogicOpEnabled = GL_TRUE; + } + else { + ctx->Color.ColorLogicOpEnabled = GL_FALSE; + } + + ctx->Color.BlendFunc = NULL; + ctx->NewState |= NEW_RASTER_OPS; +} + + + +void gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha ) +{ + ctx->Color.BlendColor[0] = CLAMP( red, 0.0, 1.0 ); + ctx->Color.BlendColor[1] = CLAMP( green, 0.0, 1.0 ); + ctx->Color.BlendColor[2] = CLAMP( blue, 0.0, 1.0 ); + ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0, 1.0 ); +} + + + +/* + * Common transparency blending mode. + */ +static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLubyte rgba[][4], CONST GLubyte 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]) { + GLint t = rgba[i][ACOMP]; /* t in [0,255] */ + if (t == 0) { + 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 == 255) { + /* no-op */ + } + else { + GLint s = 255 - t; + GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8; + GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8; + GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8; + GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8; + ASSERT(r <= 255); + ASSERT(g <= 255); + ASSERT(b <= 255); + ASSERT(a <= 255); + rgba[i][RCOMP] = r; + rgba[i][GCOMP] = g; + rgba[i][BCOMP] = b; + rgba[i][ACOMP] = a; + } + } + } +} + + + +/* + * Add src and dest. + */ +static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLubyte rgba[][4], CONST GLubyte 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]) { + 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] = MIN2( r, 255 ); + rgba[i][GCOMP] = MIN2( g, 255 ); + rgba[i][BCOMP] = MIN2( b, 255 ); + rgba[i][ACOMP] = MIN2( a, 255 ); + } + } +} + + + +/* + * Blend min function (for GL_EXT_blend_minmax) + */ +static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLubyte rgba[][4], CONST GLubyte 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] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } +} + + + +/* + * Blend max function (for GL_EXT_blend_minmax) + */ +static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLubyte rgba[][4], CONST GLubyte 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] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); + rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); + rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); + rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); + } + } +} + + + +/* + * Modulate: result = src * dest + */ +static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLubyte rgba[][4], CONST GLubyte dest[][4] ) +{ + GLuint i; + (void) ctx; + + for (i=0;i<n;i++) { + if (mask[i]) { + GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8; + GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8; + GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8; + GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8; + rgba[i][RCOMP] = r; + rgba[i][GCOMP] = g; + rgba[i][BCOMP] = b; + rgba[i][ACOMP] = a; + } + } +} + + + +/* + * 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 blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], + GLubyte rgba[][4], CONST GLubyte dest[][4] ) +{ + GLfloat rscale = 1.0F / 255.0F; + GLfloat gscale = 1.0F / 255.0F; + GLfloat bscale = 1.0F / 255.0F; + GLfloat ascale = 1.0F / 255.0F; + GLuint i; + + for (i=0;i<n;i++) { + if (mask[i]) { + GLint Rs, Gs, Bs, As; /* Source colors */ + GLint Rd, Gd, Bd, Ad; /* Dest colors */ + GLfloat sR, sG, sB, sA; /* Source scaling */ + GLfloat dR, dG, dB, dA; /* Dest scaling */ + GLfloat r, g, b, a; + + /* Source Color */ + Rs = rgba[i][RCOMP]; + Gs = rgba[i][GCOMP]; + Bs = rgba[i][BCOMP]; + As = rgba[i][ACOMP]; + + /* Frame buffer color */ + Rd = dest[i][RCOMP]; + Gd = dest[i][GCOMP]; + Bd = dest[i][BCOMP]; + Ad = dest[i][ACOMP]; + + /* 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 = (GLfloat) 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 < 1.0F - (GLfloat) Ad * ascale) { + 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; + default: + /* this should never happen */ + gl_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 = (GLfloat) 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; + default: + /* this should never happen */ + gl_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 = (GLfloat) 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] * ascale; + break; + default: + /* this should never happen */ + gl_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 = (GLfloat) 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] * ascale; + break; + default: + /* this should never happen */ + gl_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 (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; + } + + /* final clamping */ + rgba[i][RCOMP] = (GLint) CLAMP( r, 0.0F, 255.0F ); + rgba[i][GCOMP] = (GLint) CLAMP( g, 0.0F, 255.0F ); + rgba[i][BCOMP] = (GLint) CLAMP( b, 0.0F, 255.0F ); + rgba[i][ACOMP] = (GLint) CLAMP( a, 0.0F, 255.0F ); + } + } +} + + + +#if defined(USE_MMX_ASM) +#include "X86/mmx.h" +#include "X86/common_x86asm.h" +#endif + + +/* + * Analyze current blending parameters to pick fastest blending function. + * Result: the ctx->Color.BlendFunc pointer is updated. + */ +static void set_blend_function( 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 defined(USE_MMX_ASM) + /* Hmm. A table here would have 12^4 == way too many entries. + * Provide a hook for MMX instead. + */ + if (gl_x86_cpu_features & GL_CPU_MMX) { + gl_mmx_set_blend_function (ctx); + } else +#endif + if (srcRGB != srcA || dstRGB != dstA) { + ctx->Color.BlendFunc = blend_general; + } + else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA + && dstRGB==GL_ONE_MINUS_SRC_ALPHA) { + ctx->Color.BlendFunc = blend_transparency; + } + else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) { + ctx->Color.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))) { + ctx->Color.BlendFunc = blend_modulate; + } + else if (eq==GL_MIN_EXT) { + ctx->Color.BlendFunc = blend_min; + } + else if (eq==GL_MAX_EXT) { + ctx->Color.BlendFunc = blend_max; + } + else { + ctx->Color.BlendFunc = blend_general; + } +} + + + +/* + * Apply the blending operator to a span of pixels. + * Input: n - number of pixels in span + * x, y - location of leftmost pixel in span in window coords. + * mask - boolean mask indicating which pixels to blend. + * In/Out: rgba - pixel values + */ +void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y, + GLubyte rgba[][4], const GLubyte mask[] ) +{ + GLubyte dest[MAX_WIDTH][4]; + + /* Check if device driver can do the work */ + if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) { + return; + } + + /* Read span of current frame buffer pixels */ + gl_read_rgba_span( ctx, n, x, y, dest ); + + if (!ctx->Color.BlendFunc) + set_blend_function(ctx); + + (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest ); +} + + + + + +/* + * Apply the blending operator to an array of pixels. + * Input: n - number of pixels in span + * x, y - array of pixel locations + * mask - boolean mask indicating which pixels to blend. + * In/Out: rgba - pixel values + */ +void gl_blend_pixels( GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLubyte rgba[][4], const GLubyte mask[] ) +{ + GLubyte dest[PB_SIZE][4]; + + /* Check if device driver can do the work */ + if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) { + return; + } + + /* Read pixels from current color buffer */ + (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask ); + + if (ctx->RasterMask & ALPHABUF_BIT) { + gl_read_alpha_pixels( ctx, n, x, y, dest, mask ); + } + else { + GLuint i; + for (i=0; i<n; i++) { + dest[i][ACOMP] = 255; + } + } + + if (!ctx->Color.BlendFunc) + set_blend_function(ctx); + + (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest ); +} diff --git a/src/mesa/main/blend.h b/src/mesa/main/blend.h new file mode 100644 index 00000000000..837ea9d6bf2 --- /dev/null +++ b/src/mesa/main/blend.h @@ -0,0 +1,68 @@ +/* $Id: blend.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 BLEND_H +#define BLEND_H + + +#include "types.h" + + + +extern void +gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y, + GLubyte rgba[][4], const GLubyte mask[] ); + + +extern void +gl_blend_pixels( GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLubyte rgba[][4], const GLubyte mask[] ); + + +extern void +gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ); + + +extern void +gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ); + + +extern void +gl_BlendEquation( GLcontext *ctx, GLenum mode ); + + +extern void +gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha ); + + +#endif diff --git a/src/mesa/main/clip.c b/src/mesa/main/clip.c new file mode 100644 index 00000000000..9feaf2472ea --- /dev/null +++ b/src/mesa/main/clip.c @@ -0,0 +1,460 @@ +/* $Id: clip.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <string.h> +#include <stdlib.h> +#include "clip.h" +#include "context.h" +#include "macros.h" +#include "matrix.h" +#include "mmath.h" +#include "types.h" +#include "vb.h" +#include "xform.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + + +/* Linear interpolation between A and B: */ +#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) ) + + + +#define INTERP_SZ( t, vec, to, a, b, sz ) \ +do { \ + switch (sz) { \ + case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \ + case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \ + case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \ + case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \ + } \ +} while(0) + + + + +#define CLIP_RGBA0 0x1 +#define CLIP_RGBA1 0x2 +#define CLIP_TEX0 0x4 +#define CLIP_TEX1 0x8 +#define CLIP_INDEX0 0x10 +#define CLIP_INDEX1 0x20 +#define CLIP_EDGE 0x40 + +/* This is sparsely populated: */ +static clip_interp_func clip_interp_tab[0x80]; + +#define IND 0 +#define NAME clip_nil +#include "interp_tmp.h" + +#define IND (CLIP_RGBA0) +#define NAME clipRGBA0 +#include "interp_tmp.h" + +#define IND (CLIP_RGBA0|CLIP_RGBA1) +#define NAME clipRGBA0_RGBA1 +#include "interp_tmp.h" + +#define IND (CLIP_TEX0|CLIP_RGBA0) +#define NAME clipTEX0_RGBA0 +#include "interp_tmp.h" + +#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1) +#define NAME clipTEX0_RGBA0_RGBA1 +#include "interp_tmp.h" + +#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0) +#define NAME clipTEX1_TEX0_RGBA0 +#include "interp_tmp.h" + +#define IND (CLIP_TEX0) +#define NAME clipTEX0 +#include "interp_tmp.h" + +#define IND (CLIP_TEX1|CLIP_TEX0) +#define NAME clipTEX1_TEX0 +#include "interp_tmp.h" + +#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1) +#define NAME clipTEX1_TEX0_RGBA0_RGBA1 +#include "interp_tmp.h" + +#define IND (CLIP_INDEX0) +#define NAME clipINDEX0 +#include "interp_tmp.h" + +#define IND (CLIP_INDEX0|CLIP_INDEX1) +#define NAME clipINDEX0_INDEX1 +#include "interp_tmp.h" + +#define IND (CLIP_RGBA0|CLIP_EDGE) +#define NAME clipRGBA0_EDGE +#include "interp_tmp.h" + +#define IND (CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE) +#define NAME clipRGBA0_RGBA1_EDGE +#include "interp_tmp.h" + +#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE) +#define NAME clipTEX0_RGBA0_EDGE +#include "interp_tmp.h" + +#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE) +#define NAME clipTEX0_RGBA0_RGBA1_EDGE +#include "interp_tmp.h" + +#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE) +#define NAME clipTEX1_TEX0_RGBA0_EDGE +#include "interp_tmp.h" + +#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE) +#define NAME clipTEX1_TEX0_RGBA0_RGBA1_EDGE +#include "interp_tmp.h" + +#define IND (CLIP_INDEX0|CLIP_EDGE) +#define NAME clipINDEX0_EDGE +#include "interp_tmp.h" + +#define IND (CLIP_INDEX0|CLIP_INDEX1|CLIP_EDGE) +#define NAME clipINDEX0_INDEX1_EDGE +#include "interp_tmp.h" + + + + +/**********************************************************************/ +/* Get/Set User clip-planes. */ +/**********************************************************************/ + + + +void gl_ClipPlane( GLcontext* ctx, GLenum plane, const GLfloat *equation ) +{ + GLint p; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClipPlane"); + + p = (GLint) plane - (GLint) GL_CLIP_PLANE0; + if (p<0 || p>=MAX_CLIP_PLANES) { + gl_error( ctx, GL_INVALID_ENUM, "glClipPlane" ); + return; + } + + /* + * The equation is transformed by the transpose of the inverse of the + * current modelview matrix and stored in the resulting eye coordinates. + * + * KW: Eqn is then transformed to the current clip space, where user + * clipping now takes place. The clip-space equations are recalculated + * whenever the projection matrix changes. + */ + if (ctx->ModelView.flags & MAT_DIRTY_ALL_OVER) { + gl_matrix_analyze( &ctx->ModelView ); + } + gl_transform_vector( ctx->Transform.EyeUserPlane[p], equation, + ctx->ModelView.inv ); + + + if (ctx->Transform.ClipEnabled[p]) { + ctx->NewState |= NEW_USER_CLIP; + + if (ctx->ProjectionMatrix.flags & MAT_DIRTY_ALL_OVER) { + gl_matrix_analyze( &ctx->ProjectionMatrix ); + } + gl_transform_vector( ctx->Transform.ClipUserPlane[p], + ctx->Transform.EyeUserPlane[p], + ctx->ProjectionMatrix.inv ); + } +} + + +void gl_update_userclip( GLcontext *ctx ) +{ + GLuint p; + + for (p = 0 ; p < MAX_CLIP_PLANES ; p++) { + if (ctx->Transform.ClipEnabled[p]) { + gl_transform_vector( ctx->Transform.ClipUserPlane[p], + ctx->Transform.EyeUserPlane[p], + ctx->ProjectionMatrix.inv ); + } + } +} + +void gl_GetClipPlane( GLcontext* ctx, GLenum plane, GLdouble *equation ) +{ + GLint p; + + ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetClipPlane"); + + + p = (GLint) (plane - GL_CLIP_PLANE0); + if (p<0 || p>=MAX_CLIP_PLANES) { + gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" ); + return; + } + + equation[0] = (GLdouble) ctx->Transform.EyeUserPlane[p][0]; + equation[1] = (GLdouble) ctx->Transform.EyeUserPlane[p][1]; + equation[2] = (GLdouble) ctx->Transform.EyeUserPlane[p][2]; + equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3]; +} + + + + +/**********************************************************************/ +/* View volume clipping. */ +/**********************************************************************/ + + +/* + * Clip a point against the view volume. + * Input: v - vertex-vector describing the point to clip + * Return: 0 = outside view volume + * 1 = inside view volume + */ +GLuint gl_viewclip_point( const GLfloat v[] ) +{ + if ( v[0] > v[3] || v[0] < -v[3] + || v[1] > v[3] || v[1] < -v[3] + || v[2] > v[3] || v[2] < -v[3] ) { + return 0; + } + else { + return 1; + } +} + +/* + * Clip a point against the user clipping planes. + * Input: v - vertex-vector describing the point to clip. + * Return: 0 = point was clipped + * 1 = point not clipped + */ +GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] ) +{ + GLuint p; + + for (p=0;p<MAX_CLIP_PLANES;p++) { + if (ctx->Transform.ClipEnabled[p]) { + GLfloat dot = v[0] * ctx->Transform.ClipUserPlane[p][0] + + v[1] * ctx->Transform.ClipUserPlane[p][1] + + v[2] * ctx->Transform.ClipUserPlane[p][2] + + v[3] * ctx->Transform.ClipUserPlane[p][3]; + if (dot < 0.0F) { + return 0; + } + } + } + + return 1; +} + + + + +clip_poly_func gl_poly_clip_tab[5]; +clip_line_func gl_line_clip_tab[5]; + + +#if defined(__i386__) +#define NEGATIVE(x) ((*(int *)&x)<0) +#else +#define NEGATIVE(x) (x < 0) +#endif + +#define W(i) coord[i][3] +#define Z(i) coord[i][2] +#define Y(i) coord[i][1] +#define X(i) coord[i][0] +#define SIZE 4 +#define TAG(x) x##_4 +#include "clip_funcs.h" + + +#define W(i) 1.0 +#define Z(i) coord[i][2] +#define Y(i) coord[i][1] +#define X(i) coord[i][0] +#define SIZE 3 +#define TAG(x) x##_3 +#include "clip_funcs.h" + +#define W(i) 1.0 +#define Z(i) 0.0 +#define Y(i) coord[i][1] +#define X(i) coord[i][0] +#define SIZE 2 +#define TAG(x) x##_2 +#include "clip_funcs.h" + +#define USER_CLIPTEST(NAME, SZ) \ +static void NAME( struct vertex_buffer *VB ) \ +{ \ + GLcontext *ctx = VB->ctx; \ + GLubyte *clipMask = VB->ClipMask; \ + GLubyte *userClipMask = VB->UserClipMask; \ + GLuint start = VB->Start; \ + GLuint count = VB->Count; \ + GLuint p, i; \ + GLubyte bit; \ + \ + \ + for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \ + if (ctx->Transform.ClipEnabled[p]) { \ + GLuint nr = 0; \ + const GLfloat a = ctx->Transform.ClipUserPlane[p][0]; \ + const GLfloat b = ctx->Transform.ClipUserPlane[p][1]; \ + const GLfloat c = ctx->Transform.ClipUserPlane[p][2]; \ + const GLfloat d = ctx->Transform.ClipUserPlane[p][3]; \ + GLfloat *coord = VB->ClipPtr->start; \ + GLuint stride = VB->ClipPtr->stride; \ + \ + for (i = start ; i < count ; i++, STRIDE_F(coord, stride)) { \ + GLfloat dp = coord[0] * a + coord[1] * b; \ + if (SZ > 2) dp += coord[2] * c; \ + if (SZ > 3) dp += coord[3] * d; else dp += d; \ + \ + if (dp < 0) { \ + clipMask[i] |= CLIP_USER_BIT; \ + userClipMask[i] |= bit; \ + nr++; \ + } \ + } \ + \ + if (nr > 0) { \ + VB->ClipOrMask |= CLIP_USER_BIT; \ + VB->CullMode |= CLIP_MASK_ACTIVE; \ + if (nr == count - start) { \ + VB->ClipAndMask |= CLIP_USER_BIT; \ + VB->Culled = 1; \ + return; \ + } \ + } \ + } \ +} + + +USER_CLIPTEST(userclip2, 2) +USER_CLIPTEST(userclip3, 3) +USER_CLIPTEST(userclip4, 4) + +static void (*(usercliptab[5]))( struct vertex_buffer * ) = { + 0, + 0, + userclip2, + userclip3, + userclip4 +}; + +void gl_user_cliptest( struct vertex_buffer *VB ) +{ + usercliptab[VB->ClipPtr->size]( VB ); +} + + + +static clip_interp_func get_interp_func( GLcontext *ctx ) +{ + GLuint mask = 0; + + if (ctx->Visual->RGBAflag) + { + if (ctx->Light.ShadeModel==GL_SMOOTH) + { + mask |= CLIP_RGBA0; + + if (ctx->TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_SEPERATE_SPECULAR)) + mask |= CLIP_RGBA1; + } + + if (ctx->Texture.ReallyEnabled & 0xf0) + mask |= CLIP_TEX1|CLIP_TEX0; + + if (ctx->Texture.ReallyEnabled & 0xf) + mask |= CLIP_TEX0; + } + else if (ctx->Light.ShadeModel==GL_SMOOTH) + { + mask |= CLIP_INDEX0; + + if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) + mask |= CLIP_INDEX1; + } + + + return clip_interp_tab[mask]; +} + + +void gl_update_clipmask( GLcontext *ctx ) +{ + ctx->ClipInterpFunc = get_interp_func( ctx ); +} + +void gl_init_clip(void) +{ + init_clip_funcs_4(); + init_clip_funcs_3(); + init_clip_funcs_2(); + + clip_interp_tab[0] = clip_nil; + clip_interp_tab[CLIP_RGBA0] = clipRGBA0; + clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1] = clipRGBA0_RGBA1; + clip_interp_tab[CLIP_TEX0|CLIP_RGBA0] = clipTEX0_RGBA0; + clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = clipTEX0_RGBA0_RGBA1; + clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0] = clipTEX1_TEX0_RGBA0; + clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = clipTEX1_TEX0_RGBA0_RGBA1; + + clip_interp_tab[CLIP_TEX0] = clipTEX0; + clip_interp_tab[CLIP_TEX1|CLIP_TEX0] = clipTEX1_TEX0; + + clip_interp_tab[CLIP_INDEX0] = clipINDEX0; + clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1] = clipINDEX0_INDEX1; + + clip_interp_tab[CLIP_RGBA0|CLIP_EDGE] = clipRGBA0_EDGE; + clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE] = clipRGBA0_RGBA1_EDGE; + clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE] = clipTEX0_RGBA0_EDGE; + clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE] = clipTEX0_RGBA0_RGBA1_EDGE; + clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE] = clipTEX1_TEX0_RGBA0_EDGE; + clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE] = clipTEX1_TEX0_RGBA0_RGBA1_EDGE; + clip_interp_tab[CLIP_INDEX0|CLIP_EDGE] = clipINDEX0_EDGE; + clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1|CLIP_EDGE] = clipINDEX0_INDEX1_EDGE; +} + diff --git a/src/mesa/main/clip.h b/src/mesa/main/clip.h new file mode 100644 index 00000000000..03e09ca7e55 --- /dev/null +++ b/src/mesa/main/clip.h @@ -0,0 +1,105 @@ +/* $Id: clip.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 CLIP_H +#define CLIP_H + + +#include "types.h" + + + +#ifdef DEBUG +# define GL_VIEWCLIP_POINT( V ) gl_viewclip_point( V ) +#else +# define GL_VIEWCLIP_POINT( V ) \ + ( (V)[0] <= (V)[3] && (V)[0] >= -(V)[3] \ + && (V)[1] <= (V)[3] && (V)[1] >= -(V)[3] \ + && (V)[2] <= (V)[3] && (V)[2] >= -(V)[3] ) +#endif + + + +typedef GLuint (*clip_line_func)( struct vertex_buffer *VB, + GLuint *i, GLuint *j, + GLubyte mask); +typedef GLuint (*clip_poly_func)( struct vertex_buffer *VB, + GLuint n, GLuint vlist[], + GLubyte mask ); + + +extern clip_poly_func gl_poly_clip_tab[5]; +extern clip_line_func gl_line_clip_tab[5]; + +extern void gl_init_clip(void); + + +extern GLuint gl_viewclip_point( const GLfloat v[] ); + + + +extern GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] ); + + +extern void gl_user_cliptest( struct vertex_buffer *VB ); + + +extern void gl_ClipPlane( GLcontext* ctx, + GLenum plane, const GLfloat *equation ); + +extern void gl_GetClipPlane( GLcontext* ctx, + GLenum plane, GLdouble *equation ); + + +/* + * Clipping interpolation functions + */ + +extern void gl_clip_interp_all( struct vertex_buffer *VB, + GLuint dst, GLfloat t, GLuint in, GLuint out ); + +extern void gl_clip_interp_color_tex( struct vertex_buffer *VB, + GLuint dst, GLfloat t, GLuint in, GLuint out ); + +extern void gl_clip_interp_tex( struct vertex_buffer *VB, + GLuint dst, GLfloat t, GLuint in, GLuint out ); + +extern void gl_clip_interp_color( struct vertex_buffer *VB, + GLuint dst, GLfloat t, GLuint in, GLuint out ); + +extern void gl_clip_interp_none( struct vertex_buffer *VB, + GLuint dst, GLfloat t, GLuint in, GLuint out ); + + +extern void gl_update_userclip( GLcontext *ctx ); + +extern void gl_update_clipmask( GLcontext *ctx ); + +#endif diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c new file mode 100644 index 00000000000..22d785ba515 --- /dev/null +++ b/src/mesa/main/colortab.c @@ -0,0 +1,312 @@ +/* $Id: colortab.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include "colortab.h" +#include "context.h" +#include "macros.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/* + * Return GL_TRUE if k is a power of two, else return GL_FALSE. + */ +static GLboolean power_of_two( GLint k ) +{ + GLint i, m = 1; + for (i=0; i<32; i++) { + if (k == m) + return GL_TRUE; + m = m << 1; + } + return GL_FALSE; +} + + +static GLint decode_internal_format( GLint format ) +{ + switch (format) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return GL_ALPHA; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return GL_LUMINANCE; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return GL_LUMINANCE_ALPHA; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return GL_INTENSITY; + case 3: + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return GL_RGB; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_RGBA; + default: + return -1; /* error */ + } +} + + +void gl_ColorTable( GLcontext *ctx, GLenum target, + GLenum internalFormat, struct gl_image *table ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj; + GLboolean proxy = GL_FALSE; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorTable"); + + if (decode_internal_format(internalFormat) < 0) { + gl_error( ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)" ); + return; + } + + switch (target) { + case GL_TEXTURE_1D: + texObj = texUnit->CurrentD[1]; + break; + case GL_TEXTURE_2D: + texObj = texUnit->CurrentD[2]; + break; + case GL_TEXTURE_3D_EXT: + texObj = texUnit->CurrentD[3]; + break; + case GL_PROXY_TEXTURE_1D: + texObj = ctx->Texture.Proxy1D; + proxy = GL_TRUE; + break; + case GL_PROXY_TEXTURE_2D: + texObj = ctx->Texture.Proxy2D; + proxy = GL_TRUE; + break; + case GL_PROXY_TEXTURE_3D_EXT: + texObj = ctx->Texture.Proxy3D; + proxy = GL_TRUE; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + texObj = NULL; + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glColorTableEXT(target)"); + return; + } + + /* internalformat = just like glTexImage */ + + if (table->Width < 1 || table->Width > MAX_TEXTURE_PALETTE_SIZE + || !power_of_two(table->Width)) { + gl_error(ctx, GL_INVALID_VALUE, "glColorTableEXT(width)"); + if (proxy) { + texObj->PaletteSize = 0; + texObj->PaletteIntFormat = (GLenum) 0; + texObj->PaletteFormat = (GLenum) 0; + } + return; + } + + if (texObj) { + /* per-texture object palette */ + texObj->PaletteSize = table->Width; + texObj->PaletteIntFormat = internalFormat; + texObj->PaletteFormat = (GLenum) decode_internal_format(internalFormat); + if (!proxy) { + MEMCPY(texObj->Palette, table->Data, table->Width*table->Components); + if (ctx->Driver.UpdateTexturePalette) { + (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); + } + } + } + else { + /* shared texture palette */ + ctx->Texture.PaletteSize = table->Width; + ctx->Texture.PaletteIntFormat = internalFormat; + ctx->Texture.PaletteFormat = (GLenum) decode_internal_format(internalFormat); + MEMCPY(ctx->Texture.Palette, table->Data, table->Width*table->Components); + if (ctx->Driver.UpdateTexturePalette) { + (*ctx->Driver.UpdateTexturePalette)( ctx, NULL ); + } + } +} + + + +void gl_ColorSubTable( GLcontext *ctx, GLenum target, + GLsizei start, struct gl_image *data ) +{ + /* XXX TODO */ + gl_problem(ctx, "glColorSubTableEXT not implemented"); + (void) target; + (void) start; + (void) data; +} + + + +void gl_GetColorTable( GLcontext *ctx, GLenum target, GLenum format, + GLenum type, GLvoid *table ) +{ + ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetBooleanv"); + + switch (target) { + case GL_TEXTURE_1D: + break; + case GL_TEXTURE_2D: + break; + case GL_TEXTURE_3D_EXT: + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableEXT(target)"); + return; + } + + gl_problem(ctx, "glGetColorTableEXT not implemented!"); + (void) format; + (void) type; + (void) table; +} + + + +void gl_GetColorTableParameterfv( GLcontext *ctx, GLenum target, + GLenum pname, GLfloat *params ) +{ + GLint iparams[10]; + + gl_GetColorTableParameteriv( ctx, target, pname, iparams ); + *params = (GLfloat) iparams[0]; +} + + + +void gl_GetColorTableParameteriv( GLcontext *ctx, GLenum target, + GLenum pname, GLint *params ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj; + + ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetColorTableParameter"); + + switch (target) { + case GL_TEXTURE_1D: + texObj = texUnit->CurrentD[1]; + break; + case GL_TEXTURE_2D: + texObj = texUnit->CurrentD[2]; + break; + case GL_TEXTURE_3D_EXT: + texObj = texUnit->CurrentD[3]; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + texObj = NULL; + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)"); + return; + } + + switch (pname) { + case GL_COLOR_TABLE_FORMAT_EXT: + if (texObj) + *params = texObj->PaletteIntFormat; + else + *params = ctx->Texture.PaletteIntFormat; + break; + case GL_COLOR_TABLE_WIDTH_EXT: + if (texObj) + *params = texObj->PaletteSize; + else + *params = ctx->Texture.PaletteSize; + break; + case GL_COLOR_TABLE_RED_SIZE_EXT: + *params = 8; + break; + case GL_COLOR_TABLE_GREEN_SIZE_EXT: + *params = 8; + break; + case GL_COLOR_TABLE_BLUE_SIZE_EXT: + *params = 8; + break; + case GL_COLOR_TABLE_ALPHA_SIZE_EXT: + *params = 8; + break; + case GL_COLOR_TABLE_LUMINANCE_SIZE_EXT: + *params = 8; + break; + case GL_COLOR_TABLE_INTENSITY_SIZE_EXT: + *params = 8; + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter" ); + return; + } +} + + diff --git a/src/mesa/main/colortab.h b/src/mesa/main/colortab.h new file mode 100644 index 00000000000..8e75f13dac7 --- /dev/null +++ b/src/mesa/main/colortab.h @@ -0,0 +1,55 @@ +/* $Id: colortab.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 COLORTAB_H +#define COLORTAB_H + + +#include "types.h" + + +extern void gl_ColorTable( GLcontext *ctx, GLenum target, + GLenum internalformat, + struct gl_image *table ); + +extern void gl_ColorSubTable( GLcontext *ctx, GLenum target, + GLsizei start, struct gl_image *data ); + +extern void gl_GetColorTable( GLcontext *ctx, GLenum target, GLenum format, + GLenum type, GLvoid *table ); + +extern void gl_GetColorTableParameterfv( GLcontext *ctx, GLenum target, + GLenum pname, GLfloat *params ); + +extern void gl_GetColorTableParameteriv( GLcontext *ctx, GLenum target, + GLenum pname, GLint *params ); + + +#endif diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h new file mode 100644 index 00000000000..0b35aba7dc6 --- /dev/null +++ b/src/mesa/main/config.h @@ -0,0 +1,222 @@ +/* $Id: config.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + + +/* + * Tunable configuration parameters. + */ + + + +#ifndef CONFIG_H +#define CONFIG_H + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +/* + * + * OpenGL implementation limits + * + */ + + +/* Maximum modelview matrix stack depth: */ +#define MAX_MODELVIEW_STACK_DEPTH 32 + +/* Maximum projection matrix stack depth: */ +#define MAX_PROJECTION_STACK_DEPTH 32 + +/* Maximum texture matrix stack depth: */ +#define MAX_TEXTURE_STACK_DEPTH 10 + +/* Maximum attribute stack depth: */ +#define MAX_ATTRIB_STACK_DEPTH 16 + +/* Maximum client attribute stack depth: */ +#define MAX_CLIENT_ATTRIB_STACK_DEPTH 16 + +/* Maximum recursion depth of display list calls: */ +#define MAX_LIST_NESTING 64 + +/* Maximum number of lights: */ +#define MAX_LIGHTS 8 + +/* Maximum user-defined clipping planes: */ +#define MAX_CLIP_PLANES 6 + +/* Maximum pixel map lookup table size: */ +#define MAX_PIXEL_MAP_TABLE 256 + +/* Number of auxillary color buffers: */ +#define NUM_AUX_BUFFERS 0 + +/* Maximum order (degree) of curves: */ +#ifdef AMIGA +# define MAX_EVAL_ORDER 12 +#else +# define MAX_EVAL_ORDER 30 +#endif + +/* Maximum Name stack depth */ +#define MAX_NAME_STACK_DEPTH 64 + +/* Min and Max point sizes and granularity */ +#define MIN_POINT_SIZE 1.0 +#define MAX_POINT_SIZE 10.0 +#define POINT_SIZE_GRANULARITY 0.1 + +/* Min and Max line widths and granularity */ +#define MIN_LINE_WIDTH 1.0 +#define MAX_LINE_WIDTH 10.0 +#define LINE_WIDTH_GRANULARITY 1.0 + +/* Max texture palette size */ +#define MAX_TEXTURE_PALETTE_SIZE 256 + +/* Number of texture levels */ +#define MAX_TEXTURE_LEVELS 12 + +/* Number of texture units - GL_ARB_multitexture */ +#define MAX_TEXTURE_UNITS 2 + +/* Maximum viewport size: */ +#define MAX_WIDTH 1600 +#define MAX_HEIGHT 1200 + +/* Maxmimum size for CVA. May be overridden by the drivers. */ +#define MAX_ARRAY_LOCK_SIZE 3000 + + +/* + * + * Mesa-specific parameters + * + */ + + +/* + * Bits per accumulation buffer color component: 8 or 16 + */ +#define ACCUM_BITS 16 + + +#ifdef MESAD3D + /* Mesa / Direct3D driver only */ + extern float g_DepthScale, g_MaxDepth; +# define DEPTH_BITS 32 +# define DEPTH_SCALE g_DepthScale +# define MAX_DEPTH g_MaxDepth +#else + /* + * Bits per depth buffer value: 16 or 32 + */ +# define DEPTH_BITS 16 +# if DEPTH_BITS==16 +# define MAX_DEPTH 0xffff +# define DEPTH_SCALE 65535.0F +# elif DEPTH_BITS==32 +# define MAX_DEPTH 0x3fffffff +# define DEPTH_SCALE ((GLfloat) MAX_DEPTH) +# else +# error "illegal number of depth bits" +# endif +#endif + + +/* + * Bits per stencil value: 8 + */ +#define STENCIL_BITS 8 + + +/* + * Bits per color channel (must be 8 at this time!) + */ +#define CHAN_BITS 8 + + + +/* + * Color channel component order + * (changes will almost certainly cause problems at this time) + */ +#define RCOMP 0 +#define GCOMP 1 +#define BCOMP 2 +#define ACOMP 3 + + + +/* Vertex buffer size. KW: no restrictions on the divisibility of + * this number, though things may go better for you if you choose a + * value of 12n + 3. + */ + +#define VB_START 3 + +#if defined(FX) && !defined(MITS) +# define VB_MAX 72 + VB_START /* better performance */ +#else +# define VB_MAX 480 + VB_START +#endif + +/* + * Actual vertex buffer size. + * + * Arrays must also accomodate new vertices from clipping, and + * potential overflow from primitives which don't fit into neatly into + * VB_MAX vertices. (This only happens when mixed primitives are + * sharing the vb). + */ +#define VB_MAX_CLIPPED_VERTS (2 * (6 + MAX_CLIP_PLANES)) +#define VB_SIZE (VB_MAX + VB_MAX_CLIPPED_VERTS) + + +/* + * + * For X11 driver only: + * + */ + +/* + * When defined, use 6x6x6 dithering instead of 5x9x5. + * 5x9x5 better for general colors, 6x6x6 better for grayscale. + */ +/*#define DITHER666*/ + + + +typedef struct gl_context GLcontext; + +extern void gl_read_config_file( struct gl_context *ctx ); + +#endif diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c new file mode 100644 index 00000000000..55c74678213 --- /dev/null +++ b/src/mesa/main/context.c @@ -0,0 +1,2388 @@ +/* $Id: context.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +/* + * If multi-threading is enabled (-DTHREADS) then each thread has it's + * own rendering context. A thread obtains the pointer to its GLcontext + * with the gl_get_thread_context() function. Otherwise, the global + * pointer, CC, points to the current context used by all threads in + * the address space. + */ + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "accum.h" +#include "alphabuf.h" +#include "api.h" +#include "clip.h" +#include "context.h" +#include "cva.h" +#include "depth.h" +#include "dlist.h" +#include "eval.h" +#include "enums.h" +#include "fog.h" +#include "hash.h" +#include "light.h" +#include "lines.h" +#include "dlist.h" +#include "macros.h" +#include "matrix.h" +#include "mmath.h" +#include "pb.h" +#include "pipeline.h" +#include "points.h" +#include "pointers.h" +#include "quads.h" +#include "shade.h" +#include "simple_list.h" +#include "stencil.h" +#include "stages.h" +#include "triangle.h" +#include "translate.h" +#include "teximage.h" +#include "texobj.h" +#include "texstate.h" +#include "texture.h" +#include "types.h" +#include "varray.h" +#include "vb.h" +#include "vbcull.h" +#include "vbfill.h" +#include "vbrender.h" +#include "vbxform.h" +#include "xform.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/**********************************************************************/ +/***** Context and Thread management *****/ +/**********************************************************************/ + + +#ifdef THREADS + +#include "mthreads.h" /* Mesa platform independent threads interface */ + +static MesaTSD mesa_ctx_tsd; + +static void mesa_ctx_thread_init() { + MesaInitTSD(&mesa_ctx_tsd); +} + +GLcontext *gl_get_thread_context( void ) { + return (GLcontext *) MesaGetTSD(&mesa_ctx_tsd); +} + +static void set_thread_context( GLcontext *ctx ) { + MesaSetTSD(&mesa_ctx_tsd, ctx, mesa_ctx_thread_init); +} + + +#else + +/* One Current Context pointer for all threads in the address space */ +GLcontext *CC = NULL; +struct immediate *CURRENT_INPUT = NULL; + +#endif /*THREADS*/ + + + + +/**********************************************************************/ +/***** Profiling functions *****/ +/**********************************************************************/ + +#ifdef PROFILE + +#include <sys/times.h> +#include <sys/param.h> + + +/* + * Return system time in seconds. + * NOTE: this implementation may not be very portable! + */ +GLdouble gl_time( void ) +{ + static GLdouble prev_time = 0.0; + static GLdouble time; + struct tms tm; + clock_t clk; + + clk = times(&tm); + +#ifdef CLK_TCK + time = (double)clk / (double)CLK_TCK; +#else + time = (double)clk / (double)HZ; +#endif + + if (time>prev_time) { + prev_time = time; + return time; + } + else { + return prev_time; + } +} + +/* + * Reset the timing/profiling counters + */ +static void init_timings( GLcontext *ctx ) +{ + ctx->BeginEndCount = 0; + ctx->BeginEndTime = 0.0; + ctx->VertexCount = 0; + ctx->VertexTime = 0.0; + ctx->PointCount = 0; + ctx->PointTime = 0.0; + ctx->LineCount = 0; + ctx->LineTime = 0.0; + ctx->PolygonCount = 0; + ctx->PolygonTime = 0.0; + ctx->ClearCount = 0; + ctx->ClearTime = 0.0; + ctx->SwapCount = 0; + ctx->SwapTime = 0.0; +} + + +/* + * Print the accumulated timing/profiling data. + */ +static void print_timings( GLcontext *ctx ) +{ + GLdouble beginendrate; + GLdouble vertexrate; + GLdouble pointrate; + GLdouble linerate; + GLdouble polygonrate; + GLdouble overhead; + GLdouble clearrate; + GLdouble swaprate; + GLdouble avgvertices; + + if (ctx->BeginEndTime>0.0) { + beginendrate = ctx->BeginEndCount / ctx->BeginEndTime; + } + else { + beginendrate = 0.0; + } + if (ctx->VertexTime>0.0) { + vertexrate = ctx->VertexCount / ctx->VertexTime; + } + else { + vertexrate = 0.0; + } + if (ctx->PointTime>0.0) { + pointrate = ctx->PointCount / ctx->PointTime; + } + else { + pointrate = 0.0; + } + if (ctx->LineTime>0.0) { + linerate = ctx->LineCount / ctx->LineTime; + } + else { + linerate = 0.0; + } + if (ctx->PolygonTime>0.0) { + polygonrate = ctx->PolygonCount / ctx->PolygonTime; + } + else { + polygonrate = 0.0; + } + if (ctx->ClearTime>0.0) { + clearrate = ctx->ClearCount / ctx->ClearTime; + } + else { + clearrate = 0.0; + } + if (ctx->SwapTime>0.0) { + swaprate = ctx->SwapCount / ctx->SwapTime; + } + else { + swaprate = 0.0; + } + + if (ctx->BeginEndCount>0) { + avgvertices = (GLdouble) ctx->VertexCount / (GLdouble) ctx->BeginEndCount; + } + else { + avgvertices = 0.0; + } + + overhead = ctx->BeginEndTime - ctx->VertexTime - ctx->PointTime + - ctx->LineTime - ctx->PolygonTime; + + + printf(" Count Time (s) Rate (/s) \n"); + printf("--------------------------------------------------------\n"); + printf("glBegin/glEnd %7d %8.3f %10.3f\n", + ctx->BeginEndCount, ctx->BeginEndTime, beginendrate); + printf(" vertexes transformed %7d %8.3f %10.3f\n", + ctx->VertexCount, ctx->VertexTime, vertexrate ); + printf(" points rasterized %7d %8.3f %10.3f\n", + ctx->PointCount, ctx->PointTime, pointrate ); + printf(" lines rasterized %7d %8.3f %10.3f\n", + ctx->LineCount, ctx->LineTime, linerate ); + printf(" polygons rasterized %7d %8.3f %10.3f\n", + ctx->PolygonCount, ctx->PolygonTime, polygonrate ); + printf(" overhead %8.3f\n", overhead ); + printf("glClear %7d %8.3f %10.3f\n", + ctx->ClearCount, ctx->ClearTime, clearrate ); + printf("SwapBuffers %7d %8.3f %10.3f\n", + ctx->SwapCount, ctx->SwapTime, swaprate ); + printf("\n"); + + printf("Average number of vertices per begin/end: %8.3f\n", avgvertices ); +} +#endif + + + + + +/**********************************************************************/ +/***** Context allocation, initialization, destroying *****/ +/**********************************************************************/ + + +/* + * This function just calls all the various one-time-init functions in Mesa. + */ +static void one_time_init( void ) +{ + static GLboolean alreadyCalled = GL_FALSE; + if (!alreadyCalled) { + gl_init_clip(); + gl_init_eval(); + gl_init_fog(); + gl_init_math(); + gl_init_lists(); + gl_init_shade(); + gl_init_texture(); + gl_init_transformation(); + gl_init_translate(); + gl_init_vbrender(); + gl_init_vbxform(); + alreadyCalled = GL_TRUE; + } +#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__) + fprintf(stderr, "Mesa DEBUG build %s %s\n", __DATE__, __TIME__); +#endif +} + + +/* + * Allocate and initialize a shared context state structure. + */ +static struct gl_shared_state *alloc_shared_state( void ) +{ + GLuint i; + struct gl_shared_state *ss; + GLboolean outOfMemory; + + ss = (struct gl_shared_state*) calloc( 1, sizeof(struct gl_shared_state) ); + if (!ss) + return NULL; + + ss->DisplayList = NewHashTable(); + + ss->TexObjects = NewHashTable(); + + /* Default Texture objects */ + outOfMemory = GL_FALSE; + for (i=0;i<MAX_TEXTURE_UNITS;i++) { + GLuint d; + for (d = 1 ; d <= 3 ; d++) { + ss->DefaultD[d][i] = gl_alloc_texture_object(ss, 0, d); + if (!ss->DefaultD[d][i]) { + outOfMemory = GL_TRUE; + break; + } + ss->DefaultD[d][i]->RefCount++; /* don't free if not in use */ + } + } + + if (!ss->DisplayList || !ss->TexObjects || outOfMemory) { + /* Ran out of memory at some point. Free everything and return NULL */ + if (ss->DisplayList) + DeleteHashTable(ss->DisplayList); + if (ss->TexObjects) + DeleteHashTable(ss->TexObjects); + for (i=0;i<MAX_TEXTURE_UNITS;i++) { + if (ss->DefaultD[1][i]) + gl_free_texture_object(ss, ss->DefaultD[1][i]); + if (ss->DefaultD[2][i]) + gl_free_texture_object(ss, ss->DefaultD[2][i]); + if (ss->DefaultD[3][i]) + gl_free_texture_object(ss, ss->DefaultD[3][i]); + } + free(ss); + return NULL; + } + else { + return ss; + } +} + + +/* + * Deallocate a shared state context and all children structures. + */ +static void free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) +{ + /* Free display lists */ + while (1) { + GLuint list = HashFirstEntry(ss->DisplayList); + if (list) { + gl_destroy_list(ctx, list); + } + else { + break; + } + } + DeleteHashTable(ss->DisplayList); + + /* Free texture objects */ + while (ss->TexObjectList) + { + if (ctx->Driver.DeleteTexture) + (*ctx->Driver.DeleteTexture)( ctx, ss->TexObjectList ); + /* this function removes from linked list too! */ + gl_free_texture_object(ss, ss->TexObjectList); + } + DeleteHashTable(ss->TexObjects); + + free(ss); +} + + + + + + +/* + * Initialize the nth light. Note that the defaults for light 0 are + * different than the other lights. + */ +static void init_light( struct gl_light *l, GLuint n ) +{ + make_empty_list( l ); + + ASSIGN_4V( l->Ambient, 0.0, 0.0, 0.0, 1.0 ); + if (n==0) { + ASSIGN_4V( l->Diffuse, 1.0, 1.0, 1.0, 1.0 ); + ASSIGN_4V( l->Specular, 1.0, 1.0, 1.0, 1.0 ); + } + else { + ASSIGN_4V( l->Diffuse, 0.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 ); + } + ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 ); + ASSIGN_3V( l->EyeDirection, 0.0, 0.0, -1.0 ); + l->SpotExponent = 0.0; + gl_compute_spot_exp_table( l ); + l->SpotCutoff = 180.0; + l->CosCutoff = 0.0; /* KW: -ve values not admitted */ + l->ConstantAttenuation = 1.0; + l->LinearAttenuation = 0.0; + l->QuadraticAttenuation = 0.0; + l->Enabled = GL_FALSE; +} + + + +static void init_lightmodel( struct gl_lightmodel *lm ) +{ + ASSIGN_4V( lm->Ambient, 0.2, 0.2, 0.2, 1.0 ); + lm->LocalViewer = GL_FALSE; + lm->TwoSide = GL_FALSE; + lm->ColorControl = GL_SINGLE_COLOR; +} + + +static void init_material( struct gl_material *m ) +{ + ASSIGN_4V( m->Ambient, 0.2, 0.2, 0.2, 1.0 ); + ASSIGN_4V( m->Diffuse, 0.8, 0.8, 0.8, 1.0 ); + ASSIGN_4V( m->Specular, 0.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( m->Emission, 0.0, 0.0, 0.0, 1.0 ); + m->Shininess = 0.0; + m->AmbientIndex = 0; + m->DiffuseIndex = 1; + m->SpecularIndex = 1; +} + + + +static void init_texture_unit( GLcontext *ctx, GLuint unit ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + + texUnit->EnvMode = GL_MODULATE; + ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 ); + texUnit->TexGenEnabled = 0; + texUnit->GenModeS = GL_EYE_LINEAR; + texUnit->GenModeT = GL_EYE_LINEAR; + texUnit->GenModeR = GL_EYE_LINEAR; + texUnit->GenModeQ = GL_EYE_LINEAR; + /* Yes, these plane coefficients are correct! */ + ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 ); + + texUnit->CurrentD[1] = ctx->Shared->DefaultD[1][unit]; + texUnit->CurrentD[2] = ctx->Shared->DefaultD[2][unit]; + texUnit->CurrentD[3] = ctx->Shared->DefaultD[3][unit]; +} + + +static void init_fallback_arrays( GLcontext *ctx ) +{ + struct gl_client_array *cl; + GLuint i; + + cl = &ctx->Fallback.Normal; + cl->Size = 3; + cl->Type = GL_FLOAT; + cl->Stride = 0; + cl->StrideB = 0; + cl->Ptr = (void *) ctx->Current.Normal; + cl->Enabled = 1; + + cl = &ctx->Fallback.Color; + cl->Size = 4; + cl->Type = GL_UNSIGNED_BYTE; + cl->Stride = 0; + cl->StrideB = 0; + cl->Ptr = (void *) ctx->Current.ByteColor; + cl->Enabled = 1; + + cl = &ctx->Fallback.Index; + cl->Size = 1; + cl->Type = GL_UNSIGNED_INT; + cl->Stride = 0; + cl->StrideB = 0; + cl->Ptr = (void *) &ctx->Current.Index; + cl->Enabled = 1; + + for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) { + cl = &ctx->Fallback.TexCoord[i]; + cl->Size = 4; + cl->Type = GL_FLOAT; + cl->Stride = 0; + cl->StrideB = 0; + cl->Ptr = (void *) ctx->Current.Texcoord[i]; + cl->Enabled = 1; + } + + cl = &ctx->Fallback.EdgeFlag; + cl->Size = 1; + cl->Type = GL_UNSIGNED_BYTE; + cl->Stride = 0; + cl->StrideB = 0; + cl->Ptr = (void *) &ctx->Current.EdgeFlag; + cl->Enabled = 1; +} + +/* Initialize a 1-D evaluator map */ +static void init_1d_map( struct gl_1d_map *map, int n, const float *initial ) +{ + map->Order = 1; + map->u1 = 0.0; + map->u2 = 1.0; + map->Points = (GLfloat *) malloc(n * sizeof(GLfloat)); + if (map->Points) { + GLint i; + for (i=0;i<n;i++) + map->Points[i] = initial[i]; + } + map->Retain = GL_FALSE; +} + + +/* Initialize a 2-D evaluator map */ +static void init_2d_map( struct gl_2d_map *map, int n, const float *initial ) +{ + map->Uorder = 1; + map->Vorder = 1; + map->u1 = 0.0; + map->u2 = 1.0; + map->v1 = 0.0; + map->v2 = 1.0; + map->Points = (GLfloat *) malloc(n * sizeof(GLfloat)); + if (map->Points) { + GLint i; + for (i=0;i<n;i++) + map->Points[i] = initial[i]; + } + map->Retain = GL_FALSE; +} + + + +/* + * Initialize a gl_context structure to default values. + */ +static void initialize_context( GLcontext *ctx ) +{ + GLuint i, j; + + if (ctx) { + /* Constants, may be overriden by device driver */ + ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS; + ctx->Const.MaxTextureSize = 1 << (MAX_TEXTURE_LEVELS - 1); + ctx->Const.MaxTextureUnits = MAX_TEXTURE_UNITS; + ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE; + + + /* Modelview matrix */ + gl_matrix_ctr( &ctx->ModelView ); + gl_matrix_alloc_inv( &ctx->ModelView ); + + ctx->ModelViewStackDepth = 0; + for (i = 0 ; i < MAX_MODELVIEW_STACK_DEPTH ; i++) { + gl_matrix_ctr( &ctx->ModelViewStack[i] ); + gl_matrix_alloc_inv( &ctx->ModelViewStack[i] ); + } + + /* Projection matrix - need inv for user clipping in clip space*/ + gl_matrix_ctr( &ctx->ProjectionMatrix ); + gl_matrix_alloc_inv( &ctx->ProjectionMatrix ); + + gl_matrix_ctr( &ctx->ModelProjectMatrix ); + gl_matrix_ctr( &ctx->ModelProjectWinMatrix ); + ctx->ModelProjectWinMatrixUptodate = GL_FALSE; + + ctx->ProjectionStackDepth = 0; + ctx->NearFarStack[0][0] = 1.0; /* These values seem weird by make */ + ctx->NearFarStack[0][1] = 0.0; /* sense mathematically. */ + + for (i = 0 ; i < MAX_PROJECTION_STACK_DEPTH ; i++) { + gl_matrix_ctr( &ctx->ProjectionStack[i] ); + gl_matrix_alloc_inv( &ctx->ProjectionStack[i] ); + } + + /* Texture matrix */ + for (i=0; i<MAX_TEXTURE_UNITS; i++) { + gl_matrix_ctr( &ctx->TextureMatrix[i] ); + ctx->TextureStackDepth[i] = 0; + for (j = 0 ; j < MAX_TEXTURE_STACK_DEPTH ; j++) { + ctx->TextureStack[i][j].inv = 0; + } + } + + /* Accumulate buffer group */ + ASSIGN_4V( ctx->Accum.ClearColor, 0.0, 0.0, 0.0, 0.0 ); + + /* Color buffer group */ + ctx->Color.IndexMask = 0xffffffff; + ctx->Color.ColorMask[0] = 0xff; + ctx->Color.ColorMask[1] = 0xff; + ctx->Color.ColorMask[2] = 0xff; + ctx->Color.ColorMask[3] = 0xff; + ctx->Color.SWmasking = GL_FALSE; + ctx->Color.ClearIndex = 0; + ASSIGN_4V( ctx->Color.ClearColor, 0.0, 0.0, 0.0, 0.0 ); + ctx->Color.DrawBuffer = GL_FRONT; + ctx->Color.AlphaEnabled = GL_FALSE; + ctx->Color.AlphaFunc = GL_ALWAYS; + ctx->Color.AlphaRef = 0; + ctx->Color.BlendEnabled = GL_FALSE; + ctx->Color.BlendSrcRGB = GL_ONE; + ctx->Color.BlendDstRGB = GL_ZERO; + ctx->Color.BlendSrcA = GL_ONE; + ctx->Color.BlendDstA = GL_ZERO; + ctx->Color.BlendEquation = GL_FUNC_ADD_EXT; + ctx->Color.BlendFunc = NULL; /* this pointer set only when needed */ + ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 ); + ctx->Color.IndexLogicOpEnabled = GL_FALSE; + ctx->Color.ColorLogicOpEnabled = GL_FALSE; + ctx->Color.SWLogicOpEnabled = GL_FALSE; + ctx->Color.LogicOp = GL_COPY; + ctx->Color.DitherFlag = GL_TRUE; + ctx->Color.MultiDrawBuffer = GL_FALSE; + + /* Current group */ + ASSIGN_4V( ctx->Current.ByteColor, 255, 255, 255, 255); + ctx->Current.Index = 1; + for (i=0; i<MAX_TEXTURE_UNITS; i++) + ASSIGN_4V( ctx->Current.Texcoord[i], 0.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( ctx->Current.RasterPos, 0.0, 0.0, 0.0, 1.0 ); + ctx->Current.RasterDistance = 0.0; + ASSIGN_4V( ctx->Current.RasterColor, 1.0, 1.0, 1.0, 1.0 ); + ctx->Current.RasterIndex = 1; + for (i=0; i<MAX_TEXTURE_UNITS; i++) + ASSIGN_4V( ctx->Current.RasterMultiTexCoord[i], 0.0, 0.0, 0.0, 1.0 ); + ctx->Current.RasterTexCoord = ctx->Current.RasterMultiTexCoord[0]; + ctx->Current.RasterPosValid = GL_TRUE; + ctx->Current.EdgeFlag = GL_TRUE; + ASSIGN_3V( ctx->Current.Normal, 0.0, 0.0, 1.0 ); + ctx->Current.Primitive = (GLenum) (GL_POLYGON + 1); + + ctx->Current.Flag = (VERT_NORM|VERT_INDEX|VERT_RGBA|VERT_EDGE| + VERT_TEX0_1|VERT_TEX1_1|VERT_MATERIAL); + + init_fallback_arrays( ctx ); + + /* Depth buffer group */ + ctx->Depth.Test = GL_FALSE; + ctx->Depth.Clear = 1.0; + ctx->Depth.Func = GL_LESS; + ctx->Depth.Mask = GL_TRUE; + + /* Evaluators group */ + ctx->Eval.Map1Color4 = GL_FALSE; + ctx->Eval.Map1Index = GL_FALSE; + ctx->Eval.Map1Normal = GL_FALSE; + ctx->Eval.Map1TextureCoord1 = GL_FALSE; + ctx->Eval.Map1TextureCoord2 = GL_FALSE; + ctx->Eval.Map1TextureCoord3 = GL_FALSE; + ctx->Eval.Map1TextureCoord4 = GL_FALSE; + ctx->Eval.Map1Vertex3 = GL_FALSE; + ctx->Eval.Map1Vertex4 = GL_FALSE; + ctx->Eval.Map2Color4 = GL_FALSE; + ctx->Eval.Map2Index = GL_FALSE; + ctx->Eval.Map2Normal = GL_FALSE; + ctx->Eval.Map2TextureCoord1 = GL_FALSE; + ctx->Eval.Map2TextureCoord2 = GL_FALSE; + ctx->Eval.Map2TextureCoord3 = GL_FALSE; + ctx->Eval.Map2TextureCoord4 = GL_FALSE; + ctx->Eval.Map2Vertex3 = GL_FALSE; + ctx->Eval.Map2Vertex4 = GL_FALSE; + ctx->Eval.AutoNormal = GL_FALSE; + ctx->Eval.MapGrid1un = 1; + ctx->Eval.MapGrid1u1 = 0.0; + ctx->Eval.MapGrid1u2 = 1.0; + ctx->Eval.MapGrid2un = 1; + ctx->Eval.MapGrid2vn = 1; + ctx->Eval.MapGrid2u1 = 0.0; + ctx->Eval.MapGrid2u2 = 1.0; + ctx->Eval.MapGrid2v1 = 0.0; + ctx->Eval.MapGrid2v2 = 1.0; + + /* Evaluator data */ + { + static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 }; + static GLfloat normal[3] = { 0.0, 0.0, 1.0 }; + static GLfloat index[1] = { 1.0 }; + static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 }; + static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 }; + + init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex ); + init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex ); + init_1d_map( &ctx->EvalMap.Map1Index, 1, index ); + init_1d_map( &ctx->EvalMap.Map1Color4, 4, color ); + init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal ); + init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord ); + init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord ); + init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord ); + init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord ); + + init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex ); + init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex ); + init_2d_map( &ctx->EvalMap.Map2Index, 1, index ); + init_2d_map( &ctx->EvalMap.Map2Color4, 4, color ); + init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal ); + init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord ); + init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord ); + init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord ); + init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord ); + } + + /* Fog group */ + ctx->Fog.Enabled = GL_FALSE; + ctx->Fog.Mode = GL_EXP; + ASSIGN_4V( ctx->Fog.Color, 0.0, 0.0, 0.0, 0.0 ); + ctx->Fog.Index = 0.0; + ctx->Fog.Density = 1.0; + ctx->Fog.Start = 0.0; + ctx->Fog.End = 1.0; + + /* Hint group */ + ctx->Hint.PerspectiveCorrection = GL_DONT_CARE; + ctx->Hint.PointSmooth = GL_DONT_CARE; + ctx->Hint.LineSmooth = GL_DONT_CARE; + ctx->Hint.PolygonSmooth = GL_DONT_CARE; + ctx->Hint.Fog = GL_DONT_CARE; + + ctx->Hint.AllowDrawWin = GL_TRUE; + ctx->Hint.AllowDrawSpn = GL_TRUE; + ctx->Hint.AllowDrawMem = GL_TRUE; + ctx->Hint.StrictLighting = GL_TRUE; + + /* Pipeline */ + gl_pipeline_init( ctx ); + gl_cva_init( ctx ); + + /* Extensions */ + gl_extensions_ctr( ctx ); + + ctx->AllowVertexCull = 0; + + /* Lighting group */ + for (i=0;i<MAX_LIGHTS;i++) { + init_light( &ctx->Light.Light[i], i ); + } + make_empty_list( &ctx->Light.EnabledList ); + + init_lightmodel( &ctx->Light.Model ); + init_material( &ctx->Light.Material[0] ); + init_material( &ctx->Light.Material[1] ); + ctx->Light.ShadeModel = GL_SMOOTH; + ctx->Light.Enabled = GL_FALSE; + ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK; + ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE; + ctx->Light.ColorMaterialBitmask + = gl_material_bitmask( ctx, + GL_FRONT_AND_BACK, + GL_AMBIENT_AND_DIFFUSE, ~0, 0 ); + + ctx->Light.ColorMaterialEnabled = GL_FALSE; + + /* Line group */ + ctx->Line.SmoothFlag = GL_FALSE; + ctx->Line.StippleFlag = GL_FALSE; + ctx->Line.Width = 1.0; + ctx->Line.StipplePattern = 0xffff; + ctx->Line.StippleFactor = 1; + + /* Display List group */ + ctx->List.ListBase = 0; + + /* Pixel group */ + ctx->Pixel.RedBias = 0.0; + ctx->Pixel.RedScale = 1.0; + ctx->Pixel.GreenBias = 0.0; + ctx->Pixel.GreenScale = 1.0; + ctx->Pixel.BlueBias = 0.0; + ctx->Pixel.BlueScale = 1.0; + ctx->Pixel.AlphaBias = 0.0; + ctx->Pixel.AlphaScale = 1.0; + ctx->Pixel.ScaleOrBiasRGBA = GL_FALSE; + ctx->Pixel.DepthBias = 0.0; + ctx->Pixel.DepthScale = 1.0; + ctx->Pixel.IndexOffset = 0; + ctx->Pixel.IndexShift = 0; + ctx->Pixel.ZoomX = 1.0; + ctx->Pixel.ZoomY = 1.0; + ctx->Pixel.MapColorFlag = GL_FALSE; + ctx->Pixel.MapStencilFlag = GL_FALSE; + ctx->Pixel.MapStoSsize = 1; + ctx->Pixel.MapItoIsize = 1; + ctx->Pixel.MapItoRsize = 1; + ctx->Pixel.MapItoGsize = 1; + ctx->Pixel.MapItoBsize = 1; + ctx->Pixel.MapItoAsize = 1; + ctx->Pixel.MapRtoRsize = 1; + ctx->Pixel.MapGtoGsize = 1; + ctx->Pixel.MapBtoBsize = 1; + ctx->Pixel.MapAtoAsize = 1; + ctx->Pixel.MapStoS[0] = 0; + ctx->Pixel.MapItoI[0] = 0; + ctx->Pixel.MapItoR[0] = 0.0; + ctx->Pixel.MapItoG[0] = 0.0; + ctx->Pixel.MapItoB[0] = 0.0; + ctx->Pixel.MapItoA[0] = 0.0; + ctx->Pixel.MapItoR8[0] = 0; + ctx->Pixel.MapItoG8[0] = 0; + ctx->Pixel.MapItoB8[0] = 0; + ctx->Pixel.MapItoA8[0] = 0; + ctx->Pixel.MapRtoR[0] = 0.0; + ctx->Pixel.MapGtoG[0] = 0.0; + ctx->Pixel.MapBtoB[0] = 0.0; + ctx->Pixel.MapAtoA[0] = 0.0; + + /* Point group */ + ctx->Point.SmoothFlag = GL_FALSE; + ctx->Point.Size = 1.0; + ctx->Point.Params[0] = 1.0; + ctx->Point.Params[1] = 0.0; + ctx->Point.Params[2] = 0.0; + ctx->Point.Attenuated = GL_FALSE; + ctx->Point.MinSize = 0.0; + ctx->Point.MaxSize = (GLfloat) MAX_POINT_SIZE; + ctx->Point.Threshold = 1.0; + + /* Polygon group */ + ctx->Polygon.CullFlag = GL_FALSE; + ctx->Polygon.CullFaceMode = GL_BACK; + ctx->Polygon.FrontFace = GL_CCW; + ctx->Polygon.FrontBit = 0; + ctx->Polygon.FrontMode = GL_FILL; + ctx->Polygon.BackMode = GL_FILL; + ctx->Polygon.Unfilled = GL_FALSE; + ctx->Polygon.SmoothFlag = GL_FALSE; + ctx->Polygon.StippleFlag = GL_FALSE; + ctx->Polygon.OffsetFactor = 0.0F; + ctx->Polygon.OffsetUnits = 0.0F; + ctx->Polygon.OffsetPoint = GL_FALSE; + ctx->Polygon.OffsetLine = GL_FALSE; + ctx->Polygon.OffsetFill = GL_FALSE; + + /* Polygon Stipple group */ + MEMSET( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) ); + + /* Scissor group */ + ctx->Scissor.Enabled = GL_FALSE; + ctx->Scissor.X = 0; + ctx->Scissor.Y = 0; + ctx->Scissor.Width = 0; + ctx->Scissor.Height = 0; + + /* Stencil group */ + ctx->Stencil.Enabled = GL_FALSE; + ctx->Stencil.Function = GL_ALWAYS; + ctx->Stencil.FailFunc = GL_KEEP; + ctx->Stencil.ZPassFunc = GL_KEEP; + ctx->Stencil.ZFailFunc = GL_KEEP; + ctx->Stencil.Ref = 0; + ctx->Stencil.ValueMask = 0xff; + ctx->Stencil.Clear = 0; + ctx->Stencil.WriteMask = 0xff; + + /* Texture group */ + ctx->Texture.CurrentUnit = 0; /* multitexture */ + ctx->Texture.CurrentTransformUnit = 0; /* multitexture */ + ctx->Texture.Enabled = 0; + + for (i=0; i<MAX_TEXTURE_UNITS; i++) + init_texture_unit( ctx, i ); + + ctx->Texture.SharedPalette = GL_FALSE; + ctx->Texture.Palette[0] = 255; + ctx->Texture.Palette[1] = 255; + ctx->Texture.Palette[2] = 255; + ctx->Texture.Palette[3] = 255; + ctx->Texture.PaletteSize = 1; + ctx->Texture.PaletteIntFormat = GL_RGBA; + ctx->Texture.PaletteFormat = GL_RGBA; + + /* Transformation group */ + ctx->Transform.MatrixMode = GL_MODELVIEW; + ctx->Transform.Normalize = GL_FALSE; + ctx->Transform.RescaleNormals = GL_FALSE; + for (i=0;i<MAX_CLIP_PLANES;i++) { + ctx->Transform.ClipEnabled[i] = GL_FALSE; + ASSIGN_4V( ctx->Transform.EyeUserPlane[i], 0.0, 0.0, 0.0, 0.0 ); + } + ctx->Transform.AnyClip = GL_FALSE; + + /* Viewport group */ + ctx->Viewport.X = 0; + ctx->Viewport.Y = 0; + ctx->Viewport.Width = 0; + ctx->Viewport.Height = 0; + ctx->Viewport.Near = 0.0; + ctx->Viewport.Far = 1.0; + gl_matrix_ctr(&ctx->Viewport.WindowMap); + +#define Sz 10 +#define Tz 14 + ctx->Viewport.WindowMap.m[Sz] = 0.5 * DEPTH_SCALE; + ctx->Viewport.WindowMap.m[Tz] = 0.5 * DEPTH_SCALE; +#undef Sz +#undef Tz + + ctx->Viewport.WindowMap.flags = MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION; + ctx->Viewport.WindowMap.type = MATRIX_3D_NO_ROT; + + /* Vertex arrays */ + ctx->Array.Vertex.Size = 4; + ctx->Array.Vertex.Type = GL_FLOAT; + ctx->Array.Vertex.Stride = 0; + ctx->Array.Vertex.StrideB = 0; + ctx->Array.Vertex.Ptr = NULL; + ctx->Array.Vertex.Enabled = GL_FALSE; + ctx->Array.Normal.Type = GL_FLOAT; + ctx->Array.Normal.Stride = 0; + ctx->Array.Normal.StrideB = 0; + ctx->Array.Normal.Ptr = NULL; + ctx->Array.Normal.Enabled = GL_FALSE; + ctx->Array.Color.Size = 4; + ctx->Array.Color.Type = GL_FLOAT; + ctx->Array.Color.Stride = 0; + ctx->Array.Color.StrideB = 0; + ctx->Array.Color.Ptr = NULL; + ctx->Array.Color.Enabled = GL_FALSE; + ctx->Array.Index.Type = GL_FLOAT; + ctx->Array.Index.Stride = 0; + ctx->Array.Index.StrideB = 0; + ctx->Array.Index.Ptr = NULL; + ctx->Array.Index.Enabled = GL_FALSE; + for (i = 0; i < MAX_TEXTURE_UNITS; i++) { + ctx->Array.TexCoord[i].Size = 4; + ctx->Array.TexCoord[i].Type = GL_FLOAT; + ctx->Array.TexCoord[i].Stride = 0; + ctx->Array.TexCoord[i].StrideB = 0; + ctx->Array.TexCoord[i].Ptr = NULL; + ctx->Array.TexCoord[i].Enabled = GL_FALSE; + } + ctx->Array.TexCoordInterleaveFactor = 1; + ctx->Array.EdgeFlag.Stride = 0; + ctx->Array.EdgeFlag.StrideB = 0; + ctx->Array.EdgeFlag.Ptr = NULL; + ctx->Array.EdgeFlag.Enabled = GL_FALSE; + ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */ + + /* Pixel transfer */ + ctx->Pack.Alignment = 4; + ctx->Pack.RowLength = 0; + ctx->Pack.SkipPixels = 0; + ctx->Pack.SkipRows = 0; + ctx->Pack.SwapBytes = GL_FALSE; + ctx->Pack.LsbFirst = GL_FALSE; + ctx->Unpack.Alignment = 4; + ctx->Unpack.RowLength = 0; + ctx->Unpack.SkipPixels = 0; + ctx->Unpack.SkipRows = 0; + ctx->Unpack.SwapBytes = GL_FALSE; + ctx->Unpack.LsbFirst = GL_FALSE; + + /* Feedback */ + ctx->Feedback.Type = GL_2D; /* TODO: verify */ + ctx->Feedback.Buffer = NULL; + ctx->Feedback.BufferSize = 0; + ctx->Feedback.Count = 0; + + /* Selection/picking */ + ctx->Select.Buffer = NULL; + ctx->Select.BufferSize = 0; + ctx->Select.BufferCount = 0; + ctx->Select.Hits = 0; + ctx->Select.NameStackDepth = 0; + + /* Optimized Accum buffer */ + ctx->IntegerAccumMode = GL_TRUE; + ctx->IntegerAccumScaler = 0.0; + + /* multitexture */ + ctx->TexCoordUnit = 0; + + /* Renderer and client attribute stacks */ + ctx->AttribStackDepth = 0; + ctx->ClientAttribStackDepth = 0; + + /*** Miscellaneous ***/ + ctx->NewState = NEW_ALL; + ctx->RenderMode = GL_RENDER; + ctx->StippleCounter = 0; + ctx->NeedNormals = GL_FALSE; + ctx->DoViewportMapping = GL_TRUE; + + ctx->NeedEyeCoords = GL_FALSE; + ctx->NeedEyeNormals = GL_FALSE; + ctx->vb_proj_matrix = &ctx->ModelProjectMatrix; + + /* Display list */ + ctx->CallDepth = 0; + ctx->ExecuteFlag = GL_TRUE; + ctx->CompileFlag = GL_FALSE; + ctx->CurrentListPtr = NULL; + ctx->CurrentBlock = NULL; + ctx->CurrentListNum = 0; + ctx->CurrentPos = 0; + + ctx->ErrorValue = (GLenum) GL_NO_ERROR; + + ctx->CatchSignals = GL_TRUE; + + /* For debug/development only */ + ctx->NoRaster = getenv("MESA_NO_RASTER") ? GL_TRUE : GL_FALSE; + + /* Dither disable */ + ctx->NoDither = getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE; + if (ctx->NoDither) { + if (getenv("MESA_DEBUG")) { + fprintf(stderr, "MESA_NO_DITHER set - dithering disabled\n"); + } + ctx->Color.DitherFlag = GL_FALSE; + } + } +} + + + +/* + * Allocate a new GLvisual object. + * Input: rgbFlag - GL_TRUE=RGB(A) mode, GL_FALSE=Color Index mode + * alphaFlag - alloc software alpha buffers? + * dbFlag - double buffering? + * stereoFlag - stereo buffer? + * depthFits - requested minimum bits per depth buffer value + * stencilFits - requested minimum bits per stencil buffer value + * accumFits - requested minimum bits per accum buffer component + * indexFits - number of bits per pixel if rgbFlag==GL_FALSE + * red/green/blue/alphaFits - number of bits per color component + * in frame buffer for RGB(A) mode. + * Return: pointer to new GLvisual or NULL if requested parameters can't + * be met. + */ +GLvisual *gl_create_visual( GLboolean rgbFlag, + GLboolean alphaFlag, + GLboolean dbFlag, + GLboolean stereoFlag, + GLint depthBits, + GLint stencilBits, + GLint accumBits, + GLint indexBits, + GLint redBits, + GLint greenBits, + GLint blueBits, + GLint alphaBits ) +{ + GLvisual *vis; + + if (depthBits > (GLint) (8*sizeof(GLdepth))) { + /* can't meet depth buffer requirements */ + return NULL; + } + if (stencilBits > (GLint) (8*sizeof(GLstencil))) { + /* can't meet stencil buffer requirements */ + return NULL; + } + if (accumBits > (GLint) (8*sizeof(GLaccum))) { + /* can't meet accum buffer requirements */ + return NULL; + } + + vis = (GLvisual *) calloc( 1, sizeof(GLvisual) ); + if (!vis) { + return NULL; + } + + vis->RGBAflag = rgbFlag; + vis->DBflag = dbFlag; + vis->StereoFlag = stereoFlag; + vis->RedBits = redBits; + vis->GreenBits = greenBits; + vis->BlueBits = blueBits; + vis->AlphaBits = alphaFlag ? 8*sizeof(GLubyte) : alphaBits; + + vis->IndexBits = indexBits; + vis->DepthBits = (depthBits>0) ? 8*sizeof(GLdepth) : 0; + vis->AccumBits = (accumBits>0) ? 8*sizeof(GLaccum) : 0; + vis->StencilBits = (stencilBits>0) ? 8*sizeof(GLstencil) : 0; + + vis->SoftwareAlpha = alphaFlag; + + return vis; +} + + + +void gl_destroy_visual( GLvisual *vis ) +{ + free( vis ); +} + + + +/* + * Allocate the proxy textures. If we run out of memory part way through + * the allocations clean up and return GL_FALSE. + * Return: GL_TRUE=success, GL_FALSE=failure + */ +static GLboolean alloc_proxy_textures( GLcontext *ctx ) +{ + GLboolean out_of_memory; + GLint i; + + ctx->Texture.Proxy1D = gl_alloc_texture_object(NULL, 0, 1); + if (!ctx->Texture.Proxy1D) { + return GL_FALSE; + } + + ctx->Texture.Proxy2D = gl_alloc_texture_object(NULL, 0, 2); + if (!ctx->Texture.Proxy2D) { + gl_free_texture_object(NULL, ctx->Texture.Proxy1D); + return GL_FALSE; + } + + ctx->Texture.Proxy3D = gl_alloc_texture_object(NULL, 0, 3); + if (!ctx->Texture.Proxy3D) { + gl_free_texture_object(NULL, ctx->Texture.Proxy1D); + gl_free_texture_object(NULL, ctx->Texture.Proxy2D); + return GL_FALSE; + } + + out_of_memory = GL_FALSE; + for (i=0;i<MAX_TEXTURE_LEVELS;i++) { + ctx->Texture.Proxy1D->Image[i] = gl_alloc_texture_image(); + ctx->Texture.Proxy2D->Image[i] = gl_alloc_texture_image(); + ctx->Texture.Proxy3D->Image[i] = gl_alloc_texture_image(); + if (!ctx->Texture.Proxy1D->Image[i] + || !ctx->Texture.Proxy2D->Image[i] + || !ctx->Texture.Proxy3D->Image[i]) { + out_of_memory = GL_TRUE; + } + } + if (out_of_memory) { + for (i=0;i<MAX_TEXTURE_LEVELS;i++) { + if (ctx->Texture.Proxy1D->Image[i]) { + gl_free_texture_image(ctx->Texture.Proxy1D->Image[i]); + } + if (ctx->Texture.Proxy2D->Image[i]) { + gl_free_texture_image(ctx->Texture.Proxy2D->Image[i]); + } + if (ctx->Texture.Proxy3D->Image[i]) { + gl_free_texture_image(ctx->Texture.Proxy3D->Image[i]); + } + } + gl_free_texture_object(NULL, ctx->Texture.Proxy1D); + gl_free_texture_object(NULL, ctx->Texture.Proxy2D); + gl_free_texture_object(NULL, ctx->Texture.Proxy3D); + return GL_FALSE; + } + else { + return GL_TRUE; + } +} + + + +#define MALLOC_STRUCT(T) (struct T *) malloc( sizeof(struct T) ) + +/* + * Allocate and initialize a GLcontext structure. + * Input: visual - a GLvisual pointer + * sharelist - another context to share display lists with or NULL + * driver_ctx - pointer to device driver's context state struct + * Return: pointer to a new gl_context struct or NULL if error. + */ +GLcontext *gl_create_context( GLvisual *visual, + GLcontext *share_list, + void *driver_ctx, + GLboolean direct ) +{ + GLcontext *ctx; + GLuint i; + + (void) direct; /* not used */ + + /* do some implementation tests */ + assert( sizeof(GLbyte) == 1 ); + assert( sizeof(GLshort) >= 2 ); + assert( sizeof(GLint) >= 4 ); + assert( sizeof(GLubyte) == 1 ); + assert( sizeof(GLushort) >= 2 ); + assert( sizeof(GLuint) >= 4 ); + + /* misc one-time initializations */ + one_time_init(); + + ctx = (GLcontext *) calloc( 1, sizeof(GLcontext) ); + if (!ctx) { + return NULL; + } + + ctx->DriverCtx = driver_ctx; + ctx->Visual = visual; + ctx->Buffer = NULL; + + ctx->VB = gl_vb_create_for_immediate( ctx ); + if (!ctx->VB) { + free( ctx ); + return NULL; + } + ctx->input = ctx->VB->IM; + + ctx->PB = gl_alloc_pb(); + if (!ctx->PB) { + free( ctx->VB ); + free( ctx ); + return NULL; + } + + if (share_list) { + /* share the group of display lists of another context */ + ctx->Shared = share_list->Shared; + } + else { + /* allocate new group of display lists */ + ctx->Shared = alloc_shared_state(); + if (!ctx->Shared) { + free(ctx->VB); + free(ctx->PB); + free(ctx); + return NULL; + } + } + ctx->Shared->RefCount++; + + initialize_context( ctx ); + gl_reset_vb( ctx->VB ); + gl_reset_input( ctx ); + + + ctx->ShineTabList = MALLOC_STRUCT( gl_shine_tab ); + make_empty_list( ctx->ShineTabList ); + + for (i = 0 ; i < 10 ; i++) { + struct gl_shine_tab *s = MALLOC_STRUCT( gl_shine_tab ); + s->shininess = -1; + s->refcount = 0; + insert_at_tail( ctx->ShineTabList, s ); + } + + for (i = 0 ; i < 4 ; i++) { + ctx->ShineTable[i] = ctx->ShineTabList->prev; + ctx->ShineTable[i]->refcount++; + } + + if (visual->DBflag) { + ctx->Color.DrawBuffer = GL_BACK; + ctx->Color.DriverDrawBuffer = GL_BACK_LEFT; + ctx->Color.DrawDestMask = BACK_LEFT_BIT; + ctx->Pixel.ReadBuffer = GL_BACK; + ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT; + } + else { + ctx->Color.DrawBuffer = GL_FRONT; + ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT; + ctx->Color.DrawDestMask = FRONT_LEFT_BIT; + ctx->Pixel.ReadBuffer = GL_FRONT; + ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT; + } + +#ifdef PROFILE + init_timings( ctx ); +#endif + +#ifdef GL_VERSION_1_1 + if (!alloc_proxy_textures(ctx)) { + free_shared_state(ctx, ctx->Shared); + free(ctx->VB); + free(ctx->PB); + free(ctx); + return NULL; + } +#endif + + gl_init_api_function_pointers( ctx ); + ctx->API = ctx->Exec; /* GL_EXECUTE is default */ + + return ctx; +} + +/* Just reads the config files... + */ +void gl_context_initialize( GLcontext *ctx ) +{ + gl_read_config_file( ctx ); +} + + + + +/* + * Destroy a gl_context structure. + */ +void gl_destroy_context( GLcontext *ctx ) +{ + if (ctx) { + + GLuint i; + struct gl_shine_tab *s, *tmps; + +#ifdef PROFILE + if (getenv("MESA_PROFILE")) { + print_timings( ctx ); + } +#endif + + gl_matrix_dtr( &ctx->ModelView ); + for (i = 0 ; i < MAX_MODELVIEW_STACK_DEPTH ; i++) { + gl_matrix_dtr( &ctx->ModelViewStack[i] ); + } + + + free( ctx->PB ); + free( ctx->VB ); + + ctx->Shared->RefCount--; + assert(ctx->Shared->RefCount>=0); + if (ctx->Shared->RefCount==0) { + /* free shared state */ + free_shared_state( ctx, ctx->Shared ); + } + + foreach_s( s, tmps, ctx->ShineTabList ) { + free( s ); + } + free( ctx->ShineTabList ); + + /* Free proxy texture objects */ + gl_free_texture_object( NULL, ctx->Texture.Proxy1D ); + gl_free_texture_object( NULL, ctx->Texture.Proxy2D ); + gl_free_texture_object( NULL, ctx->Texture.Proxy3D ); + + /* Free evaluator data */ + if (ctx->EvalMap.Map1Vertex3.Points) + free( ctx->EvalMap.Map1Vertex3.Points ); + if (ctx->EvalMap.Map1Vertex4.Points) + free( ctx->EvalMap.Map1Vertex4.Points ); + if (ctx->EvalMap.Map1Index.Points) + free( ctx->EvalMap.Map1Index.Points ); + if (ctx->EvalMap.Map1Color4.Points) + free( ctx->EvalMap.Map1Color4.Points ); + if (ctx->EvalMap.Map1Normal.Points) + free( ctx->EvalMap.Map1Normal.Points ); + if (ctx->EvalMap.Map1Texture1.Points) + free( ctx->EvalMap.Map1Texture1.Points ); + if (ctx->EvalMap.Map1Texture2.Points) + free( ctx->EvalMap.Map1Texture2.Points ); + if (ctx->EvalMap.Map1Texture3.Points) + free( ctx->EvalMap.Map1Texture3.Points ); + if (ctx->EvalMap.Map1Texture4.Points) + free( ctx->EvalMap.Map1Texture4.Points ); + + if (ctx->EvalMap.Map2Vertex3.Points) + free( ctx->EvalMap.Map2Vertex3.Points ); + if (ctx->EvalMap.Map2Vertex4.Points) + free( ctx->EvalMap.Map2Vertex4.Points ); + if (ctx->EvalMap.Map2Index.Points) + free( ctx->EvalMap.Map2Index.Points ); + if (ctx->EvalMap.Map2Color4.Points) + free( ctx->EvalMap.Map2Color4.Points ); + if (ctx->EvalMap.Map2Normal.Points) + free( ctx->EvalMap.Map2Normal.Points ); + if (ctx->EvalMap.Map2Texture1.Points) + free( ctx->EvalMap.Map2Texture1.Points ); + if (ctx->EvalMap.Map2Texture2.Points) + free( ctx->EvalMap.Map2Texture2.Points ); + if (ctx->EvalMap.Map2Texture3.Points) + free( ctx->EvalMap.Map2Texture3.Points ); + if (ctx->EvalMap.Map2Texture4.Points) + free( ctx->EvalMap.Map2Texture4.Points ); + + free( (void *) ctx ); + +#ifndef THREADS + if (ctx==CC) { + CC = NULL; + CURRENT_INPUT = NULL; + } +#endif + + } +} + + + +/* + * Create a new framebuffer. A GLframebuffer is a struct which + * encapsulates the depth, stencil and accum buffers and related + * parameters. + * Input: visual - a GLvisual pointer + * Return: pointer to new GLframebuffer struct or NULL if error. + */ +GLframebuffer *gl_create_framebuffer( GLvisual *visual ) +{ + GLframebuffer *buffer; + + buffer = (GLframebuffer *) calloc( 1, sizeof(GLframebuffer) ); + if (!buffer) { + return NULL; + } + + buffer->Visual = visual; + + return buffer; +} + + + +/* + * Free a framebuffer struct and its buffers. + */ +void gl_destroy_framebuffer( GLframebuffer *buffer ) +{ + if (buffer) { + if (buffer->Depth) { + free( buffer->Depth ); + } + if (buffer->Accum) { + free( buffer->Accum ); + } + if (buffer->Stencil) { + free( buffer->Stencil ); + } + if (buffer->FrontLeftAlpha) { + free( buffer->FrontLeftAlpha ); + } + if (buffer->BackLeftAlpha) { + free( buffer->BackLeftAlpha ); + } + if (buffer->FrontRightAlpha) { + free( buffer->FrontRightAlpha ); + } + if (buffer->BackRightAlpha) { + free( buffer->BackRightAlpha ); + } + free(buffer); + } +} + + + +/* + * Set the current context, binding the given frame buffer to the context. + */ +void gl_make_current( GLcontext *ctx, GLframebuffer *buffer ) +{ + GET_CONTEXT; + + /* Flush the old context + */ + if (CC) { + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(CC, "gl_make_current"); + } + +#ifdef THREADS + /* TODO: unbind old buffer from context? */ + set_thread_context( ctx ); +#else + if (CC && CC->Buffer) { + /* unbind frame buffer from context */ + CC->Buffer = NULL; + } + CC = ctx; + if (ctx) { + SET_IMMEDIATE(ctx, ctx->input); + } +#endif + + if (MESA_VERBOSE) fprintf(stderr, "gl_make_current()\n"); + + if (ctx && buffer) { + /* TODO: check if ctx and buffer's visual match??? */ + ctx->Buffer = buffer; /* Bind the frame buffer to the context */ + ctx->NewState = NEW_ALL; /* just to be safe */ + gl_update_state( ctx ); + } +} + + +/* + * Return current context handle. + */ +GLcontext *gl_get_current_context( void ) +{ +#ifdef THREADS + return gl_get_thread_context(); +#else + return CC; +#endif +} + + + +/* + * Copy attribute groups from one context to another. + * Input: src - source context + * dst - destination context + * mask - bitwise OR of GL_*_BIT flags + */ +void gl_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask ) +{ + if (mask & GL_ACCUM_BUFFER_BIT) { + MEMCPY( &dst->Accum, &src->Accum, sizeof(struct gl_accum_attrib) ); + } + if (mask & GL_COLOR_BUFFER_BIT) { + MEMCPY( &dst->Color, &src->Color, sizeof(struct gl_colorbuffer_attrib) ); + } + if (mask & GL_CURRENT_BIT) { + MEMCPY( &dst->Current, &src->Current, sizeof(struct gl_current_attrib) ); + } + if (mask & GL_DEPTH_BUFFER_BIT) { + MEMCPY( &dst->Depth, &src->Depth, sizeof(struct gl_depthbuffer_attrib) ); + } + if (mask & GL_ENABLE_BIT) { + /* no op */ + } + if (mask & GL_EVAL_BIT) { + MEMCPY( &dst->Eval, &src->Eval, sizeof(struct gl_eval_attrib) ); + } + if (mask & GL_FOG_BIT) { + MEMCPY( &dst->Fog, &src->Fog, sizeof(struct gl_fog_attrib) ); + } + if (mask & GL_HINT_BIT) { + MEMCPY( &dst->Hint, &src->Hint, sizeof(struct gl_hint_attrib) ); + } + if (mask & GL_LIGHTING_BIT) { + MEMCPY( &dst->Light, &src->Light, sizeof(struct gl_light_attrib) ); +/* gl_reinit_light_attrib( &dst->Light ); */ + } + if (mask & GL_LINE_BIT) { + MEMCPY( &dst->Line, &src->Line, sizeof(struct gl_line_attrib) ); + } + if (mask & GL_LIST_BIT) { + MEMCPY( &dst->List, &src->List, sizeof(struct gl_list_attrib) ); + } + if (mask & GL_PIXEL_MODE_BIT) { + MEMCPY( &dst->Pixel, &src->Pixel, sizeof(struct gl_pixel_attrib) ); + } + if (mask & GL_POINT_BIT) { + MEMCPY( &dst->Point, &src->Point, sizeof(struct gl_point_attrib) ); + } + if (mask & GL_POLYGON_BIT) { + MEMCPY( &dst->Polygon, &src->Polygon, sizeof(struct gl_polygon_attrib) ); + } + if (mask & GL_POLYGON_STIPPLE_BIT) { + /* Use loop instead of MEMCPY due to problem with Portland Group's + * C compiler. Reported by John Stone. + */ + int i; + for (i=0;i<32;i++) { + dst->PolygonStipple[i] = src->PolygonStipple[i]; + } + } + if (mask & GL_SCISSOR_BIT) { + MEMCPY( &dst->Scissor, &src->Scissor, sizeof(struct gl_scissor_attrib) ); + } + if (mask & GL_STENCIL_BUFFER_BIT) { + MEMCPY( &dst->Stencil, &src->Stencil, sizeof(struct gl_stencil_attrib) ); + } + if (mask & GL_TEXTURE_BIT) { + MEMCPY( &dst->Texture, &src->Texture, sizeof(struct gl_texture_attrib) ); + } + if (mask & GL_TRANSFORM_BIT) { + MEMCPY( &dst->Transform, &src->Transform, sizeof(struct gl_transform_attrib) ); + } + if (mask & GL_VIEWPORT_BIT) { + MEMCPY( &dst->Viewport, &src->Viewport, sizeof(struct gl_viewport_attrib) ); + } +} + + + +/* + * Someday a GLS library or OpenGL-like debugger may call this function + * to register it's own set of API entry points. + * Input: ctx - the context to set API pointers for + * api - if NULL, restore original API pointers + * else, set API function table to this table. + */ +void gl_set_api_table( GLcontext *ctx, const struct gl_api_table *api ) +{ + if (api) { + MEMCPY( &ctx->API, api, sizeof(struct gl_api_table) ); + } + else { + MEMCPY( &ctx->API, &ctx->Exec, sizeof(struct gl_api_table) ); + } +} + + + + +/**********************************************************************/ +/***** Miscellaneous functions *****/ +/**********************************************************************/ + + +/* + * This function is called when the Mesa user has stumbled into a code + * path which may not be implemented fully or correctly. + */ +void gl_problem( const GLcontext *ctx, const char *s ) +{ + fprintf( stderr, "Mesa implementation error: %s\n", s ); + fprintf( stderr, "Report to [email protected]\n" ); + (void) ctx; +} + + + +/* + * This is called to inform the user that he or she has tried to do + * something illogical or if there's likely a bug in their program + * (like enabled depth testing without a depth buffer). + */ +void gl_warning( const GLcontext *ctx, const char *s ) +{ + GLboolean debug; +#ifdef DEBUG + debug = GL_TRUE; +#else + if (getenv("MESA_DEBUG")) { + debug = GL_TRUE; + } + else { + debug = GL_FALSE; + } +#endif + if (debug) { + fprintf( stderr, "Mesa warning: %s\n", s ); + } + (void) ctx; +} + + + +void gl_compile_error( GLcontext *ctx, GLenum error, const char *s ) +{ + if (ctx->CompileFlag) + gl_save_error( ctx, error, s ); + + if (ctx->ExecuteFlag) + gl_error( ctx, error, s ); +} + + +/* + * This is Mesa's error handler. Normally, all that's done is the updating + * of the current error value. If Mesa is compiled with -DDEBUG or if the + * environment variable "MESA_DEBUG" is defined then a real error message + * is printed to stderr. + * Input: error - the error value + * s - a diagnostic string + */ +void gl_error( GLcontext *ctx, GLenum error, const char *s ) +{ + GLboolean debug; + +#ifdef DEBUG + debug = GL_TRUE; +#else + if (getenv("MESA_DEBUG")) { + debug = GL_TRUE; + } + else { + debug = GL_FALSE; + } +#endif + + if (debug) { + char errstr[1000]; + + switch (error) { + case GL_NO_ERROR: + strcpy( errstr, "GL_NO_ERROR" ); + break; + case GL_INVALID_VALUE: + strcpy( errstr, "GL_INVALID_VALUE" ); + break; + case GL_INVALID_ENUM: + strcpy( errstr, "GL_INVALID_ENUM" ); + break; + case GL_INVALID_OPERATION: + strcpy( errstr, "GL_INVALID_OPERATION" ); + break; + case GL_STACK_OVERFLOW: + strcpy( errstr, "GL_STACK_OVERFLOW" ); + break; + case GL_STACK_UNDERFLOW: + strcpy( errstr, "GL_STACK_UNDERFLOW" ); + break; + case GL_OUT_OF_MEMORY: + strcpy( errstr, "GL_OUT_OF_MEMORY" ); + break; + default: + strcpy( errstr, "unknown" ); + break; + } + fprintf( stderr, "Mesa user error: %s in %s\n", errstr, s ); + } + + if (ctx->ErrorValue==GL_NO_ERROR) { + ctx->ErrorValue = error; + } + + /* Call device driver's error handler, if any. This is used on the Mac. */ + if (ctx->Driver.Error) { + (*ctx->Driver.Error)( ctx ); + } +} + + + +/* + * Execute a glGetError command + */ +GLenum gl_GetError( GLcontext *ctx ) +{ + GLenum e = ctx->ErrorValue; + + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL( ctx, "glGetError", 0); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glGetError <-- %s\n", gl_lookup_enum_by_nr(e)); + + ctx->ErrorValue = (GLenum) GL_NO_ERROR; + return e; +} + + + +void gl_ResizeBuffersMESA( GLcontext *ctx ) +{ + GLuint buf_width, buf_height; + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glResizeBuffersMESA\n"); + + /* ask device driver for size of output buffer */ + (*ctx->Driver.GetBufferSize)( ctx, &buf_width, &buf_height ); + + /* see if size of device driver's color buffer (window) has changed */ + if (ctx->Buffer->Width == (GLint) buf_width && + ctx->Buffer->Height == (GLint) buf_height) + return; + + ctx->NewState |= NEW_RASTER_OPS; /* to update scissor / window bounds */ + + /* save buffer size */ + ctx->Buffer->Width = buf_width; + ctx->Buffer->Height = buf_height; + + /* Reallocate other buffers if needed. */ + if (ctx->Visual->DepthBits>0) { + /* reallocate depth buffer */ + (*ctx->Driver.AllocDepthBuffer)( ctx ); + } + if (ctx->Visual->StencilBits>0) { + /* reallocate stencil buffer */ + gl_alloc_stencil_buffer( ctx ); + } + if (ctx->Visual->AccumBits>0) { + /* reallocate accum buffer */ + gl_alloc_accum_buffer( ctx ); + } + if (ctx->Visual->SoftwareAlpha) { + gl_alloc_alpha_buffers( ctx ); + } +} + + + + +/**********************************************************************/ +/***** State update logic *****/ +/**********************************************************************/ + + +/* + * Since the device driver may or may not support pixel logic ops we + * have to make some extensive tests to determine whether or not + * software-implemented logic operations have to be used. + */ +static void update_pixel_logic( GLcontext *ctx ) +{ + if (ctx->Visual->RGBAflag) { + /* RGBA mode blending w/ Logic Op */ + if (ctx->Color.ColorLogicOpEnabled) { + if (ctx->Driver.LogicOp + && (*ctx->Driver.LogicOp)( ctx, ctx->Color.LogicOp )) { + /* Device driver can do logic, don't have to do it in software */ + ctx->Color.SWLogicOpEnabled = GL_FALSE; + } + else { + /* Device driver can't do logic op so we do it in software */ + ctx->Color.SWLogicOpEnabled = GL_TRUE; + } + } + else { + /* no logic op */ + if (ctx->Driver.LogicOp) { + (void) (*ctx->Driver.LogicOp)( ctx, GL_COPY ); + } + ctx->Color.SWLogicOpEnabled = GL_FALSE; + } + } + else { + /* CI mode Logic Op */ + if (ctx->Color.IndexLogicOpEnabled) { + if (ctx->Driver.LogicOp + && (*ctx->Driver.LogicOp)( ctx, ctx->Color.LogicOp )) { + /* Device driver can do logic, don't have to do it in software */ + ctx->Color.SWLogicOpEnabled = GL_FALSE; + } + else { + /* Device driver can't do logic op so we do it in software */ + ctx->Color.SWLogicOpEnabled = GL_TRUE; + } + } + else { + /* no logic op */ + if (ctx->Driver.LogicOp) { + (void) (*ctx->Driver.LogicOp)( ctx, GL_COPY ); + } + ctx->Color.SWLogicOpEnabled = GL_FALSE; + } + } +} + + + +/* + * Check if software implemented RGBA or Color Index masking is needed. + */ +static void update_pixel_masking( GLcontext *ctx ) +{ + if (ctx->Visual->RGBAflag) { + GLuint *colorMask = (GLuint *) ctx->Color.ColorMask; + if (*colorMask == 0xffffffff) { + /* disable masking */ + if (ctx->Driver.ColorMask) { + (void) (*ctx->Driver.ColorMask)( ctx, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); + } + ctx->Color.SWmasking = GL_FALSE; + } + else { + /* Ask driver to do color masking, if it can't then + * do it in software + */ + GLboolean red = ctx->Color.ColorMask[RCOMP] ? GL_TRUE : GL_FALSE; + GLboolean green = ctx->Color.ColorMask[GCOMP] ? GL_TRUE : GL_FALSE; + GLboolean blue = ctx->Color.ColorMask[BCOMP] ? GL_TRUE : GL_FALSE; + GLboolean alpha = ctx->Color.ColorMask[ACOMP] ? GL_TRUE : GL_FALSE; + if (ctx->Driver.ColorMask + && (*ctx->Driver.ColorMask)( ctx, red, green, blue, alpha )) { + ctx->Color.SWmasking = GL_FALSE; + } + else { + ctx->Color.SWmasking = GL_TRUE; + } + } + } + else { + if (ctx->Color.IndexMask==0xffffffff) { + /* disable masking */ + if (ctx->Driver.IndexMask) { + (void) (*ctx->Driver.IndexMask)( ctx, 0xffffffff ); + } + ctx->Color.SWmasking = GL_FALSE; + } + else { + /* Ask driver to do index masking, if it can't then + * do it in software + */ + if (ctx->Driver.IndexMask + && (*ctx->Driver.IndexMask)( ctx, ctx->Color.IndexMask )) { + ctx->Color.SWmasking = GL_FALSE; + } + else { + ctx->Color.SWmasking = GL_TRUE; + } + } + } +} + + +static void update_fog_mode( GLcontext *ctx ) +{ + if (ctx->Fog.Enabled) { + if (ctx->Texture.Enabled) + ctx->FogMode = FOG_FRAGMENT; + else if (ctx->Hint.Fog == GL_NICEST) + ctx->FogMode = FOG_FRAGMENT; + else + ctx->FogMode = FOG_VERTEX; + + if (ctx->Driver.GetParameteri) + if ((ctx->Driver.GetParameteri)( ctx, DD_HAVE_HARDWARE_FOG )) + ctx->FogMode = FOG_FRAGMENT; + } + else { + ctx->FogMode = FOG_NONE; + } +} + + +/* + * Recompute the value of ctx->RasterMask, etc. according to + * the current context. + */ +static void update_rasterflags( GLcontext *ctx ) +{ + ctx->RasterMask = 0; + + if (ctx->Color.AlphaEnabled) ctx->RasterMask |= ALPHATEST_BIT; + if (ctx->Color.BlendEnabled) ctx->RasterMask |= BLEND_BIT; + if (ctx->Depth.Test) ctx->RasterMask |= DEPTH_BIT; + if (ctx->FogMode==FOG_FRAGMENT) ctx->RasterMask |= FOG_BIT; + if (ctx->Color.SWLogicOpEnabled) ctx->RasterMask |= LOGIC_OP_BIT; + if (ctx->Scissor.Enabled) ctx->RasterMask |= SCISSOR_BIT; + if (ctx->Stencil.Enabled) ctx->RasterMask |= STENCIL_BIT; + if (ctx->Color.SWmasking) ctx->RasterMask |= MASKING_BIT; + + if (ctx->Visual->SoftwareAlpha && ctx->Color.ColorMask[ACOMP] + && ctx->Color.DrawBuffer != GL_NONE) + ctx->RasterMask |= ALPHABUF_BIT; + + if ( ctx->Viewport.X<0 + || ctx->Viewport.X + ctx->Viewport.Width > ctx->Buffer->Width + || ctx->Viewport.Y<0 + || ctx->Viewport.Y + ctx->Viewport.Height > ctx->Buffer->Height) { + ctx->RasterMask |= WINCLIP_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. + */ + + ctx->TriangleCaps &= ~DD_MULTIDRAW; + + if (ctx->Color.MultiDrawBuffer) { + ctx->RasterMask |= MULTI_DRAW_BIT; + ctx->TriangleCaps |= DD_MULTIDRAW; + } + else if (ctx->Color.DrawBuffer==GL_NONE) { + ctx->RasterMask |= MULTI_DRAW_BIT; + ctx->TriangleCaps |= DD_MULTIDRAW; + } + else if (ctx->Visual->RGBAflag && ctx->Color.ColorMask==0) { + /* all RGBA channels disabled */ + ctx->RasterMask |= MULTI_DRAW_BIT; + ctx->TriangleCaps |= DD_MULTIDRAW; + ctx->Color.DrawDestMask = 0; + } + else if (!ctx->Visual->RGBAflag && ctx->Color.IndexMask==0) { + /* all color index bits disabled */ + ctx->RasterMask |= MULTI_DRAW_BIT; + ctx->TriangleCaps |= DD_MULTIDRAW; + ctx->Color.DrawDestMask = 0; + } +} + + +void gl_print_state( const char *msg, GLuint state ) +{ + fprintf(stderr, + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + msg, + state, + (state & NEW_LIGHTING) ? "lighting, " : "", + (state & NEW_RASTER_OPS) ? "raster-ops, " : "", + (state & NEW_TEXTURING) ? "texturing, " : "", + (state & NEW_POLYGON) ? "polygon, " : "", + (state & NEW_DRVSTATE0) ? "driver-0, " : "", + (state & NEW_DRVSTATE1) ? "driver-1, " : "", + (state & NEW_DRVSTATE2) ? "driver-2, " : "", + (state & NEW_DRVSTATE3) ? "driver-3, " : "", + (state & NEW_MODELVIEW) ? "modelview, " : "", + (state & NEW_PROJECTION) ? "projection, " : "", + (state & NEW_TEXTURE_MATRIX) ? "texture-matrix, " : "", + (state & NEW_USER_CLIP) ? "user-clip, " : "", + (state & NEW_TEXTURE_ENV) ? "texture-env, " : "", + (state & NEW_CLIENT_STATE) ? "client-state, " : "", + (state & NEW_FOG) ? "fog, " : "", + (state & NEW_NORMAL_TRANSFORM) ? "normal-transform, " : "", + (state & NEW_VIEWPORT) ? "viewport, " : "", + (state & NEW_TEXTURE_ENABLE) ? "texture-enable, " : ""); +} + +void gl_print_enable_flags( const char *msg, GLuint flags ) +{ + fprintf(stderr, + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s\n", + msg, + flags, + (flags & ENABLE_TEX0) ? "tex-0, " : "", + (flags & ENABLE_TEX1) ? "tex-1, " : "", + (flags & ENABLE_LIGHT) ? "light, " : "", + (flags & ENABLE_FOG) ? "fog, " : "", + (flags & ENABLE_USERCLIP) ? "userclip, " : "", + (flags & ENABLE_TEXGEN0) ? "tex-gen-0, " : "", + (flags & ENABLE_TEXGEN1) ? "tex-gen-1, " : "", + (flags & ENABLE_TEXMAT0) ? "tex-mat-0, " : "", + (flags & ENABLE_TEXMAT1) ? "tex-mat-1, " : "", + (flags & ENABLE_NORMALIZE) ? "normalize, " : "", + (flags & ENABLE_RESCALE) ? "rescale, " : ""); +} + + +/* + * If ctx->NewState is non-zero then this function MUST be called before + * rendering any primitive. Basically, function pointers and miscellaneous + * flags are updated to reflect the current state of the state machine. + */ +void gl_update_state( GLcontext *ctx ) +{ + GLuint i; + + if (MESA_VERBOSE & VERBOSE_STATE) + gl_print_state("", ctx->NewState); + + if (ctx->NewState & NEW_CLIENT_STATE) + gl_update_client_state( ctx ); + + if ((ctx->NewState & NEW_TEXTURE_ENABLE) && + (ctx->Enabled & ENABLE_TEX_ANY) != ctx->Texture.Enabled) + ctx->NewState |= NEW_TEXTURING | NEW_RASTER_OPS; + + if (ctx->NewState & NEW_TEXTURE_ENV) { + if (ctx->Texture.Unit[0].EnvMode == ctx->Texture.Unit[0].LastEnvMode && + ctx->Texture.Unit[1].EnvMode == ctx->Texture.Unit[1].LastEnvMode) + ctx->NewState &= ~NEW_TEXTURE_ENV; + ctx->Texture.Unit[0].LastEnvMode = ctx->Texture.Unit[0].EnvMode; + ctx->Texture.Unit[1].LastEnvMode = ctx->Texture.Unit[1].EnvMode; + } + + if ((ctx->NewState & ~(NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE)) == 0) + goto finished; + + if (ctx->NewState & NEW_TEXTURE_MATRIX) { + ctx->Enabled &= ~(ENABLE_TEXMAT0|ENABLE_TEXMAT1); + + for (i=0; i < MAX_TEXTURE_UNITS; i++) { + if (ctx->TextureMatrix[i].flags & MAT_DIRTY_ALL_OVER) + { + gl_matrix_analyze( &ctx->TextureMatrix[i] ); + ctx->TextureMatrix[i].flags &= ~MAT_DIRTY_DEPENDENTS; + + if (ctx->Texture.Unit[i].Enabled && + ctx->TextureMatrix[i].type != MATRIX_IDENTITY) + ctx->Enabled |= ENABLE_TEXMAT0 << i; + } + } + } + + if (ctx->NewState & NEW_TEXTURING) { + ctx->Texture.NeedNormals = GL_FALSE; + gl_update_dirty_texobjs(ctx); + ctx->Enabled &= ~(ENABLE_TEXGEN0|ENABLE_TEXGEN1); + ctx->Texture.ReallyEnabled = 0; + + for (i=0; i < MAX_TEXTURE_UNITS; i++) { + if (ctx->Texture.Unit[i].Enabled) { + gl_update_texture_unit( ctx, &ctx->Texture.Unit[i] ); + + ctx->Texture.ReallyEnabled |= + ctx->Texture.Unit[i].ReallyEnabled<<(i*4); + + if (ctx->Texture.Unit[i].GenFlags != 0) { + ctx->Enabled |= ENABLE_TEXGEN0 << i; + + if (ctx->Texture.Unit[i].GenFlags & TEXGEN_NEED_NORMALS) + { + ctx->Texture.NeedNormals = GL_TRUE; + ctx->Texture.NeedEyeCoords = GL_TRUE; + } + + if (ctx->Texture.Unit[i].GenFlags & TEXGEN_NEED_EYE_COORD) + { + ctx->Texture.NeedEyeCoords = GL_TRUE; + } + } + } + } + + ctx->Texture.Enabled = ctx->Enabled & ENABLE_TEX_ANY; + ctx->NeedNormals = (ctx->Light.Enabled || ctx->Texture.NeedNormals); + } + + if (ctx->NewState & (NEW_RASTER_OPS | NEW_LIGHTING)) { + if (ctx->NewState & NEW_RASTER_OPS) { + update_pixel_logic(ctx); + update_pixel_masking(ctx); + update_fog_mode(ctx); + update_rasterflags(ctx); + if (ctx->Driver.Dither) { + (*ctx->Driver.Dither)( ctx, ctx->Color.DitherFlag ); + } + + /* Check if incoming colors can be modified during rasterization */ + if (ctx->Fog.Enabled || + ctx->Texture.Enabled || + ctx->Color.BlendEnabled || + ctx->Color.SWmasking || + ctx->Color.SWLogicOpEnabled) { + ctx->MutablePixels = GL_TRUE; + } + else { + ctx->MutablePixels = GL_FALSE; + } + + /* update scissor region */ + + ctx->Buffer->Xmin = 0; + ctx->Buffer->Ymin = 0; + ctx->Buffer->Xmax = ctx->Buffer->Width-1; + ctx->Buffer->Ymax = ctx->Buffer->Height-1; + if (ctx->Scissor.Enabled) { + if (ctx->Scissor.X > ctx->Buffer->Xmin) { + ctx->Buffer->Xmin = ctx->Scissor.X; + } + if (ctx->Scissor.Y > ctx->Buffer->Ymin) { + ctx->Buffer->Ymin = ctx->Scissor.Y; + } + if (ctx->Scissor.X + ctx->Scissor.Width - 1 < ctx->Buffer->Xmax) { + ctx->Buffer->Xmax = ctx->Scissor.X + ctx->Scissor.Width - 1; + } + if (ctx->Scissor.Y + ctx->Scissor.Height - 1 < ctx->Buffer->Ymax) { + ctx->Buffer->Ymax = ctx->Scissor.Y + ctx->Scissor.Height - 1; + } + } + + /* + * Update Device Driver interface + */ + ctx->Driver.AllocDepthBuffer = gl_alloc_depth_buffer; + if (ctx->Depth.Mask) { + switch (ctx->Depth.Func) { + case GL_LESS: + ctx->Driver.DepthTestSpan = gl_depth_test_span_less; + ctx->Driver.DepthTestPixels = gl_depth_test_pixels_less; + break; + case GL_GREATER: + ctx->Driver.DepthTestSpan = gl_depth_test_span_greater; + ctx->Driver.DepthTestPixels = gl_depth_test_pixels_greater; + break; + default: + ctx->Driver.DepthTestSpan = gl_depth_test_span_generic; + ctx->Driver.DepthTestPixels = gl_depth_test_pixels_generic; + } + } + else { + ctx->Driver.DepthTestSpan = gl_depth_test_span_generic; + ctx->Driver.DepthTestPixels = gl_depth_test_pixels_generic; + } + ctx->Driver.ReadDepthSpanFloat = gl_read_depth_span_float; + ctx->Driver.ReadDepthSpanInt = gl_read_depth_span_int; + } + + if (ctx->NewState & NEW_LIGHTING) { + ctx->TriangleCaps &= ~(DD_TRI_LIGHT_TWOSIDE|DD_EARLY_CULL); + if (ctx->Light.Enabled) { + if (ctx->Light.Model.TwoSide) + ctx->TriangleCaps |= (DD_TRI_LIGHT_TWOSIDE|DD_EARLY_CULL); + gl_update_lighting(ctx); + } + } + } + + if (ctx->NewState & (NEW_POLYGON | NEW_LIGHTING)) { + + + if (ctx->NewState & NEW_POLYGON) { + /* Setup CullBits bitmask */ + if (ctx->Polygon.CullFlag) { + switch(ctx->Polygon.CullFaceMode) { + case GL_FRONT: + ctx->Polygon.CullBits = 2; + break; + case GL_BACK: + ctx->Polygon.CullBits = 1; + break; + default: + case GL_FRONT_AND_BACK: + ctx->Polygon.CullBits = 3; + break; + } + } + else + ctx->Polygon.CullBits = 3; + + /* Any Polygon offsets enabled? */ + ctx->TriangleCaps &= ~DD_TRI_OFFSET; + + if (ctx->Polygon.OffsetPoint || + ctx->Polygon.OffsetLine || + ctx->Polygon.OffsetFill) + ctx->TriangleCaps |= DD_TRI_OFFSET; + + /* reset Z offsets now */ + ctx->PointZoffset = 0.0; + ctx->LineZoffset = 0.0; + ctx->PolygonZoffset = 0.0; + } + } + + if (ctx->NewState & ~(NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE| + NEW_DRIVER_STATE|NEW_USER_CLIP| + NEW_POLYGON)) + gl_update_clipmask(ctx); + + if (ctx->NewState & (NEW_LIGHTING| + NEW_RASTER_OPS| + NEW_TEXTURING| + NEW_TEXTURE_ENV| + NEW_POLYGON| + NEW_DRVSTATE0| + NEW_DRVSTATE1| + NEW_DRVSTATE2| + NEW_DRVSTATE3| + NEW_USER_CLIP)) + { + ctx->IndirectTriangles = ctx->TriangleCaps & ~ctx->Driver.TriangleCaps; + ctx->IndirectTriangles |= DD_SW_RASTERIZE; + + ctx->Driver.PointsFunc = NULL; + ctx->Driver.LineFunc = NULL; + ctx->Driver.TriangleFunc = NULL; + ctx->Driver.QuadFunc = NULL; + ctx->Driver.RectFunc = NULL; + ctx->Driver.RenderVBClippedTab = NULL; + ctx->Driver.RenderVBCulledTab = NULL; + ctx->Driver.RenderVBRawTab = NULL; + + /* + * Here the driver sets up all the ctx->Driver function pointers to + * it's specific, private functions. + */ + ctx->Driver.UpdateState(ctx); + + /* + * In case the driver didn't hook in an optimized point, line or + * triangle function we'll now select "core/fallback" point, line + * and triangle functions. + */ + if (ctx->IndirectTriangles & DD_SW_RASTERIZE) { + gl_set_point_function(ctx); + gl_set_line_function(ctx); + gl_set_triangle_function(ctx); + gl_set_quad_function(ctx); + } + + gl_set_render_vb_function(ctx); + } + + /* Should only be calc'd when !need_eye_coords and not culling. + */ + if (ctx->NewState & (NEW_MODELVIEW|NEW_PROJECTION)) { + if (ctx->NewState & NEW_MODELVIEW) { + gl_matrix_analyze( &ctx->ModelView ); + ctx->ProjectionMatrix.flags &= ~MAT_DIRTY_DEPENDENTS; + } + + if (ctx->NewState & NEW_PROJECTION) { + gl_matrix_analyze( &ctx->ProjectionMatrix ); + ctx->ProjectionMatrix.flags &= ~MAT_DIRTY_DEPENDENTS; + + if (ctx->Transform.AnyClip) { + gl_update_userclip( ctx ); + } + } + + gl_calculate_model_project_matrix( ctx ); + ctx->ModelProjectWinMatrixUptodate = 0; + } + + /* Figure out whether we can light in object space or not. If we + * can, find the current positions of the lights in object space + */ + if ((ctx->Enabled & (ENABLE_POINT_ATTEN | ENABLE_LIGHT | + ENABLE_TEXGEN0 | ENABLE_TEXGEN1)) && + (ctx->NewState & (NEW_LIGHTING | + NEW_MODELVIEW | + NEW_PROJECTION | + NEW_TEXTURING | + NEW_RASTER_OPS | + NEW_USER_CLIP))) + { + GLboolean oldcoord, oldnorm; + + oldcoord = ctx->NeedEyeCoords; + oldnorm = ctx->NeedEyeNormals; + + ctx->NeedNormals = (ctx->Light.Enabled || ctx->Texture.NeedNormals); + ctx->NeedEyeCoords = ((ctx->Fog.Enabled && ctx->Hint.Fog != GL_NICEST) || + ctx->Point.Attenuated); + ctx->NeedEyeNormals = GL_FALSE; + + if (ctx->Light.Enabled) { + if (ctx->Light.Flags & LIGHT_POSITIONAL) { + /* Need length for attenuation */ + if (!TEST_MAT_FLAGS( &ctx->ModelView, MAT_FLAGS_LENGTH_PRESERVING)) + ctx->NeedEyeCoords = GL_TRUE; + } else if (ctx->Light.NeedVertices) { + /* Need angle for spot calculations */ + if (!TEST_MAT_FLAGS( &ctx->ModelView, MAT_FLAGS_ANGLE_PRESERVING)) + ctx->NeedEyeCoords = GL_TRUE; + } + ctx->NeedEyeNormals = ctx->NeedEyeCoords; + } + if (ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) { + if (ctx->Texture.NeedEyeCoords) ctx->NeedEyeCoords = GL_TRUE; + if (ctx->Texture.NeedNormals) + ctx->NeedNormals = ctx->NeedEyeNormals = GL_TRUE; + } + + ctx->vb_proj_matrix = &ctx->ModelProjectMatrix; + + if (ctx->NeedEyeCoords) + ctx->vb_proj_matrix = &ctx->ProjectionMatrix; + + if (ctx->Light.Enabled) { + gl_update_lighting_function(ctx); + + if ( (ctx->NewState & NEW_LIGHTING) || + ((ctx->NewState & (NEW_MODELVIEW| NEW_PROJECTION)) && + !ctx->NeedEyeCoords) || + oldcoord != ctx->NeedEyeCoords || + oldnorm != ctx->NeedEyeNormals) { + gl_compute_light_positions(ctx); + } + + ctx->rescale_factor = 1.0F; + + if (ctx->ModelView.flags & (MAT_FLAG_UNIFORM_SCALE | + MAT_FLAG_GENERAL_SCALE | + MAT_FLAG_GENERAL_3D | + MAT_FLAG_GENERAL) ) + + { + GLfloat *m = ctx->ModelView.inv; + GLfloat f = m[2]*m[2] + m[6]*m[6] + m[10]*m[10]; + if (f > 1e-12 && (f-1)*(f-1) > 1e-12) + ctx->rescale_factor = 1.0/GL_SQRT(f); + } + } + + gl_update_normal_transform( ctx ); + } + + finished: + gl_update_pipelines(ctx); + ctx->NewState = 0; +} diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h new file mode 100644 index 00000000000..f136da42b2d --- /dev/null +++ b/src/mesa/main/context.h @@ -0,0 +1,167 @@ +/* $Id: context.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 CONTEXT_H +#define CONTEXT_H + + +#include "types.h" + + + +#ifdef THREADS + /* + * A seperate GLcontext for each thread + */ + extern GLcontext *gl_get_thread_context( void ); +#else + /* + * All threads use same pointer to current context. + */ + extern GLcontext *CC; + extern struct immediate *CURRENT_INPUT; +#endif + + + +/* + * There are three Mesa datatypes which are meant to be used by device + * drivers: + * GLcontext: this contains the Mesa rendering state + * GLvisual: this describes the color buffer (rgb vs. ci), whether + * or not there's a depth buffer, stencil buffer, etc. + * GLframebuffer: contains pointers to the depth buffer, stencil + * buffer, accum buffer and alpha buffers. + * + * These types should be encapsulated by corresponding device driver + * datatypes. See xmesa.h and xmesaP.h for an example. + * + * In OOP terms, GLcontext, GLvisual, and GLframebuffer are base classes + * which the device driver must derive from. + * + * The following functions create and destroy these datatypes. + */ + + +/* + * Create/destroy a GLvisual. A GLvisual is like a GLX visual. It describes + * the colorbuffer, depth buffer, stencil buffer and accum buffer which will + * be used by the GL context and framebuffer. + */ +extern GLvisual *gl_create_visual( GLboolean rgbFlag, + GLboolean alphaFlag, + GLboolean dbFlag, + GLboolean stereoFlag, + GLint depthBits, + GLint stencilBits, + GLint accumBits, + GLint indexBits, + GLint redBits, + GLint greenBits, + GLint blueBits, + GLint alphaBits ); + +extern void gl_destroy_visual( GLvisual *vis ); + + +/* + * Create/destroy a GLcontext. A GLcontext is like a GLX context. It + * contains the rendering state. + */ +extern GLcontext *gl_create_context( GLvisual *visual, + GLcontext *share_list, + void *driver_ctx, + GLboolean direct); + +extern void gl_destroy_context( GLcontext *ctx ); + +/* Called by the driver after both the context and driver are fully + * initialized. Currently just reads the config file. + */ +extern void gl_context_initialize( GLcontext *ctx ); + +/* + * Create/destroy a GLframebuffer. A GLframebuffer is like a GLX drawable. + * It bundles up the depth buffer, stencil buffer and accum buffers into a + * single entity. + */ +extern GLframebuffer *gl_create_framebuffer( GLvisual *visual ); + +extern void gl_destroy_framebuffer( GLframebuffer *buffer ); + + + +extern void gl_make_current( GLcontext *ctx, GLframebuffer *buffer ); + +extern GLcontext *gl_get_current_context(void); + +extern void gl_copy_context(const GLcontext *src, GLcontext *dst, GLuint mask); + +extern void gl_set_api_table( GLcontext *ctx, const struct gl_api_table *api ); + + + +/* + * GL_MESA_resize_buffers extension + */ +extern void gl_ResizeBuffersMESA( GLcontext *ctx ); + + + +/* + * Miscellaneous + */ + +extern void gl_problem( const GLcontext *ctx, const char *s ); + +extern void gl_warning( const GLcontext *ctx, const char *s ); + +extern void gl_error( GLcontext *ctx, GLenum error, const char *s ); +extern void gl_compile_error( GLcontext *ctx, GLenum error, const char *s ); + +extern GLenum gl_GetError( GLcontext *ctx ); + + +extern void gl_update_state( GLcontext *ctx ); + + +/* for debugging */ +extern void gl_print_state( const char *msg, GLuint state ); + +/* for debugging */ +extern void gl_print_enable_flags( const char *msg, GLuint flags ); + + +#ifdef PROFILE +extern GLdouble gl_time( void ); +#endif + + +#endif diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h new file mode 100644 index 00000000000..479d73edd12 --- /dev/null +++ b/src/mesa/main/dd.h @@ -0,0 +1,635 @@ +/* $Id: dd.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 DD_INCLUDED +#define DD_INCLUDED + + +#include "macros.h" + + +struct gl_pixelstore_attrib; + + +struct vertex_buffer; +struct immediate; +struct gl_pipeline_stage; + + +/* THIS FILE ONLY INCLUDED BY types.h !!!!! */ + + +/* + * Device Driver (DD) interface + * + * + * All device driver functions are accessed through pointers in the + * dd_function_table struct (defined below) which is stored in the GLcontext + * struct. Since the device driver is strictly accessed trough a table of + * function pointers we can: + * 1. switch between a number of different device drivers at runtime. + * 2. use optimized functions dependant on current rendering state or + * frame buffer configuration. + * + * The function pointers in the dd_function_table struct are divided into + * two groups: mandatory and optional. + * Mandatory functions have to be implemented by every device driver. + * Optional functions may or may not be implemented by the device driver. + * The optional functions provide ways to take advantage of special hardware + * or optimized algorithms. + * + * The function pointers in the dd_function_table struct are first + * initialized in the "MakeCurrent" function. The "MakeCurrent" function + * is a little different in each device driver. See the X/Mesa, GLX, or + * OS/Mesa drivers for examples. + * + * Later, Mesa may call the dd_function_table's UpdateState() function. + * This function should initialize the dd_function_table's pointers again. + * The UpdateState() function is called whenever the core (GL) rendering + * state is changed in a way which may effect rasterization. For example, + * the TriangleFunc() pointer may have to point to different functions + * depending on whether smooth or flat shading is enabled. + * + * Note that the first argument to every device driver function is a + * GLcontext *. In turn, the GLcontext->DriverCtx pointer points to + * the driver-specific context struct. See the X/Mesa or OS/Mesa interface + * for an example. + * + * For more information about writing a device driver see the ddsample.c + * file and other device drivers (xmesa[123].c, osmesa.c, etc) for examples. + * + * + * Look below in the dd_function_table struct definition for descriptions + * of each device driver function. + * + * + * In the future more function pointers may be added for glReadPixels + * glCopyPixels, etc. + * + * + * Notes: + * ------ + * RGBA = red/green/blue/alpha + * CI = color index (color mapped mode) + * mono = all pixels have the same color or index + * + * The write_ functions all take an array of mask flags which indicate + * whether or not the pixel should be written. One special case exists + * in the write_color_span function: if the mask array is NULL, then + * draw all pixels. This is an optimization used for glDrawPixels(). + * + * IN ALL CASES: + * X coordinates start at 0 at the left and increase to the right + * Y coordinates start at 0 at the bottom and increase upward + * + */ + + + + +/* Used by the GetParameteri device driver function */ +#define DD_HAVE_HARDWARE_FOG 3 + + + + + +/* + * Device Driver function table. + */ +struct dd_function_table { + + /********************************************************************** + *** Mandatory functions: these functions must be implemented by *** + *** every device driver. *** + **********************************************************************/ + + const char * (*RendererString)(void); + /* + * Return a string which uniquely identifies this device driver. + * The string should contain no whitespace. Examples: "X11" "OffScreen" + * "MSWindows" "SVGA". + * NOTE: This function will be obsolete in favor of GetString in the future! + */ + + void (*UpdateState)( GLcontext *ctx ); + /* + * UpdateState() is called whenver Mesa thinks the device driver should + * update its state and/or the other pointers (such as PointsFunc, + * LineFunc, or TriangleFunc). + */ + + void (*ClearIndex)( GLcontext *ctx, GLuint index ); + /* + * Called whenever glClearIndex() is called. Set the index for clearing + * the color buffer. + */ + + void (*ClearColor)( GLcontext *ctx, GLubyte red, GLubyte green, + GLubyte blue, GLubyte alpha ); + /* + * Called whenever glClearColor() is called. Set the color for clearing + * the color buffer. + */ + + GLbitfield (*Clear)( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint x, GLint y, GLint width, GLint height ); + /* Clear the color/depth/stencil/accum buffer(s). + * 'mask' indicates which buffers need to be cleared. Return a bitmask + * indicating which buffers weren't cleared by the driver function. + * If 'all' is true then the clear the whole buffer, else clear the + * region defined by (x,y,width,height). + */ + + void (*Index)( GLcontext *ctx, GLuint index ); + /* + * Sets current color index for drawing flat-shaded primitives. + */ + + void (*Color)( GLcontext *ctx, + GLubyte red, GLubyte green, GLubyte glue, GLubyte alpha ); + /* + * Sets current color for drawing flat-shaded primitives. + */ + + GLboolean (*SetBuffer)( GLcontext *ctx, GLenum buffer ); + /* + * Selects the color buffer(s) for reading and writing. + * The following values must be accepted when applicable: + * GL_FRONT_LEFT - this buffer always exists + * GL_BACK_LEFT - when double buffering + * GL_FRONT_RIGHT - when using stereo + * GL_BACK_RIGHT - when using stereo and double buffering + * The folowing values may optionally be accepted. Return GL_TRUE + * if accepted, GL_FALSE if not accepted. In practice, only drivers + * which can write to multiple color buffers at once should accept + * these values. + * GL_FRONT - write to front left and front right if it exists + * GL_BACK - write to back left and back right if it exists + * GL_LEFT - write to front left and back left if it exists + * GL_RIGHT - write to right left and back right if they exist + * GL_FRONT_AND_BACK - write to all four buffers if they exist + * GL_NONE - disable buffer write in device driver. + */ + + void (*GetBufferSize)( GLcontext *ctx, + GLuint *width, GLuint *height ); + /* + * Returns the width and height of the current color buffer. + */ + + + /*** + *** Functions for writing pixels to the frame buffer: + ***/ + + void (*WriteRGBASpan)( const GLcontext *ctx, + GLuint n, GLint x, GLint y, + CONST GLubyte rgba[][4], const GLubyte mask[] ); + void (*WriteRGBSpan)( const GLcontext *ctx, + GLuint n, GLint x, GLint y, + CONST GLubyte rgb[][3], const GLubyte mask[] ); + /* Write a horizontal run of RGB[A] pixels. The later version is only + * used to accelerate GL_RGB, GL_UNSIGNED_BYTE glDrawPixels() calls. + */ + + void (*WriteMonoRGBASpan)( const GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLubyte mask[] ); + /* Write a horizontal run of mono-RGBA pixels. + */ + + void (*WriteRGBAPixels)( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + CONST GLubyte rgba[][4], const GLubyte mask[] ); + /* Write array of RGBA pixels at random locations. + */ + + void (*WriteMonoRGBAPixels)( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLubyte mask[] ); + /* Write an array of mono-RGBA pixels at random locations. + */ + + void (*WriteCI32Span)( const GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLuint index[], const GLubyte mask[] ); + void (*WriteCI8Span)( const GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLubyte index[], const GLubyte mask[] ); + /* Write a horizontal run of CI pixels. 32 or 8bpp. + */ + + void (*WriteMonoCISpan)( const GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLubyte mask[] ); + /* Write a horizontal run of mono-CI pixels. + */ + + void (*WriteCI32Pixels)( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLuint index[], const GLubyte mask[] ); + /* + * Write a random array of CI pixels. + */ + + void (*WriteMonoCIPixels)( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLubyte mask[] ); + /* + * Write a random array of mono-CI pixels. + */ + + + /*** + *** Functions to read pixels from frame buffer: + ***/ + + void (*ReadCI32Span)( const GLcontext *ctx, + GLuint n, GLint x, GLint y, GLuint index[] ); + /* Read a horizontal run of color index pixels. + */ + + void (*ReadRGBASpan)( const GLcontext *ctx, GLuint n, GLint x, GLint y, + GLubyte rgba[][4] ); + /* Read a horizontal run of RGBA pixels. + */ + + void (*ReadCI32Pixels)( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLuint indx[], const GLubyte mask[] ); + /* Read a random array of CI pixels. + */ + + void (*ReadRGBAPixels)( const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLubyte rgba[][4], const GLubyte mask[] ); + /* Read a random array of RGBA pixels. + */ + + + /********************************************************************** + *** Optional functions: these functions may or may not be *** + *** implemented by the device driver. If the device driver *** + *** doesn't implement them it should never touch these pointers *** + *** since Mesa will either set them to NULL or point them at a *** + *** fall-back function. *** + **********************************************************************/ + + const char * (*ExtensionString)( GLcontext *ctx ); + /* Return a space-separated list of extensions for this driver. + * NOTE: This function will be obsolete in favor of GetString in the future! + */ + + const GLubyte * (*GetString)( GLcontext *ctx, GLenum name ); + /* Return a string as needed by glGetString(). + * NOTE: This will replace the ExtensionString and RendererString + * functions in the future! + */ + + void (*Finish)( GLcontext *ctx ); + /* + * Called whenever glFinish() is called. + */ + + void (*Flush)( GLcontext *ctx ); + /* + * Called whenever glFlush() is called. + */ + + GLboolean (*IndexMask)( GLcontext *ctx, GLuint mask ); + /* + * Implements glIndexMask() if possible, else return GL_FALSE. + */ + + GLboolean (*ColorMask)( GLcontext *ctx, + GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ); + /* + * Implements glColorMask() if possible, else return GL_FALSE. + */ + + GLboolean (*LogicOp)( GLcontext *ctx, GLenum op ); + /* + * Implements glLogicOp() if possible, else return GL_FALSE. + */ + + void (*Dither)( GLcontext *ctx, GLboolean enable ); + /* + * Enable/disable dithering. + * NOTE: This function will be removed in the future in favor + * of the "Enable" driver function. + */ + + void (*Error)( GLcontext *ctx ); + /* + * Called whenever an error is generated. ctx->ErrorValue contains + * the error value. + */ + + void (*NearFar)( GLcontext *ctx, GLfloat nearVal, GLfloat farVal ); + /* + * Called from glFrustum and glOrtho to tell device driver the + * near and far clipping plane Z values. The 3Dfx driver, for example, + * uses this. + */ + + GLint (*GetParameteri)( const GLcontext *ctx, GLint param ); + /* Query the device driver to get an integer parameter. + * Current parameters: + * DD_MAX_TEXTURE_SIZE return maximum texture size + * + * DD_MAX_TEXTURES number of texture sets/stages, usually 1 + * + * DD_HAVE_HARDWARE_FOG the driver should return 1 (0 otherwise) + * when the hardware support per fragment + * fog for free (like the Voodoo Graphics) + * so the Mesa core will start to ever use + * per fragment fog + */ + + + /*** + *** For supporting hardware Z buffers: + ***/ + + void (*AllocDepthBuffer)( GLcontext *ctx ); + /* + * Called when the depth buffer must be allocated or possibly resized. + */ + + GLuint (*DepthTestSpan)( GLcontext *ctx, + GLuint n, GLint x, GLint y, const GLdepth z[], + GLubyte mask[] ); + void (*DepthTestPixels)( GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ); + /* + * Apply the depth buffer test to an span/array of pixels and return + * an updated pixel mask. This function is not used when accelerated + * point, line, polygon functions are used. + */ + + void (*ReadDepthSpanFloat)( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLfloat depth[]); + void (*ReadDepthSpanInt)( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLdepth depth[] ); + /* + * Return depth values as integers for glReadPixels. + * Floats should be returned in the range [0,1]. + * Ints (GLdepth) values should be in the range [0,MAXDEPTH]. + */ + + + /*** + *** Accelerated point, line, polygon, glDrawPixels and glBitmap functions: + ***/ + + points_func PointsFunc; + line_func LineFunc; + triangle_func TriangleFunc; + quad_func QuadFunc; + rect_func RectFunc; + + + GLboolean (*DrawPixels)( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ); + /* Device driver hook for optimized glDrawPixels. 'unpack' describes how + * to unpack the source image data. + */ + + GLboolean (*Bitmap)( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap ); + /* Device driver hook for optimized glBitmap. 'unpack' describes how + * to unpack the source image data. + */ + + void (*RenderStart)( GLcontext *ctx ); + void (*RenderFinish)( GLcontext *ctx ); + /* KW: These replace Begin and End, and have more relaxed semantics. + * They are called prior-to and after one or more vb flush, and are + * thus decoupled from the gl_begin/gl_end pairs, which are possibly + * more frequent. If a begin/end pair covers >1 vertex buffer, these + * are called at most once for the pair. (a bit broken at present) + */ + + void (*RasterSetup)( struct vertex_buffer *VB, GLuint start, GLuint end ); + /* This function, if not NULL, is called whenever new window coordinates + * are put in the vertex buffer. The vertices in question are those n + * such that start <= n < end. + * The device driver can convert the window coords to its own specialized + * format. The 3Dfx driver uses this. + * + * Note: Deprecated in favour of RegisterPipelineStages, below. + */ + + + render_func *RenderVBClippedTab; + render_func *RenderVBCulledTab; + render_func *RenderVBRawTab; + /* These function tables allow the device driver to rasterize an + * entire begin/end group of primitives at once. See the + * gl_render_vb() function in vbrender.c for more details. + */ + + + GLuint TriangleCaps; + /* Holds a list of the reasons why we might normally want to call + * render_triangle, but which are in fact implemented by the + * driver. The FX driver sets this to DD_TRI_CULL, and will soon + * implement DD_TRI_OFFSET. + */ + + + GLboolean (*MultipassFunc)( struct vertex_buffer *VB, GLuint passno ); + /* Driver may request additional render passes by returning GL_TRUE + * when this function is called. This function will be called + * after the first pass, and passes will be made until the function + * returns GL_FALSE. If no function is registered, only one pass + * is made. + * + * This function will be first invoked with passno == 1. + */ + + /*** + *** Texture mapping functions: + ***/ + + void (*TexEnv)( GLcontext *ctx, GLenum pname, const GLfloat *param ); + /* + * Called whenever glTexEnv*() is called. + * Pname will be one of GL_TEXTURE_ENV_MODE or GL_TEXTURE_ENV_COLOR. + * If pname is GL_TEXTURE_ENV_MODE then param will be one + * of GL_MODULATE, GL_BLEND, GL_DECAL, or GL_REPLACE. + */ + + void (*TexImage)( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, GLint level, + GLint internalFormat, + const struct gl_texture_image *image ); + /* + * Called whenever a texture object's image is changed. + * texObject is the number of the texture object being changed. + * level indicates the mipmap level. + * internalFormat is the format in which the texture is to be stored. + * image is a pointer to a gl_texture_image struct which contains + * the actual image data. + */ + + void (*TexSubImage)( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLint internalFormat, + const struct gl_texture_image *image ); + /* + * Called from glTexSubImage() to define a sub-region of a texture. + */ + + void (*TexParameter)( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, + GLenum pname, const GLfloat *params ); + /* + * Called whenever glTexParameter*() is called. + * target is GL_TEXTURE_1D or GL_TEXTURE_2D + * texObject is the texture object to modify + * pname is one of GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, + * GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, or GL_TEXTURE_BORDER_COLOR. + * params is dependant on pname. See man glTexParameter. + */ + + void (*BindTexture)( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj ); + /* + * Called whenever glBindTexture() is called. This specifies which + * texture is to be the current one. No dirty flags will be set. + */ + + void (*DeleteTexture)( GLcontext *ctx, struct gl_texture_object *tObj ); + /* + * Called when a texture object is about to be deallocated. Driver + * should free anything attached to the DriverData pointers. + */ + + void (*UpdateTexturePalette)( GLcontext *ctx, + struct gl_texture_object *tObj ); + /* + * Called when the texture's color lookup table is changed. + * If tObj is NULL then the shared texture palette ctx->Texture.Palette + * was changed. + */ + + void (*UseGlobalTexturePalette)( GLcontext *ctx, GLboolean state ); + /* + * Called via glEnable/Disable(GL_SHARED_TEXTURE_PALETTE_EXT) + */ + + void (*ActiveTexture)( GLcontext *ctx, GLuint texUnitNumber ); + /* + * Called by glActiveTextureARB to set current texture unit. + */ + + + /*** + *** NEW in Mesa 3.x + ***/ + + void (*RegisterVB)( struct vertex_buffer *VB ); + void (*UnregisterVB)( struct vertex_buffer *VB ); + /* Do any processing (eg allocate memory) required to set up a new + * vertex_buffer. + */ + + + void (*ResetVB)( struct vertex_buffer *VB ); + void (*ResetCvaVB)( struct vertex_buffer *VB, GLuint stages ); + /* Do any reset operations necessary to the driver data associated + * with these vertex buffers. + */ + + GLuint RenderVectorFlags; + /* What do the render tables require of the vectors they deal + * with? + */ + + GLuint (*RegisterPipelineStages)( struct gl_pipeline_stage *out, + const struct gl_pipeline_stage *in, + GLuint nr ); + /* Register new pipeline stages, or modify existing ones. See also + * the OptimizePipeline() functions. + */ + + + GLboolean (*BuildPrecalcPipeline)( GLcontext *ctx ); + GLboolean (*BuildEltPipeline)( GLcontext *ctx ); + /* Perform the full pipeline build, or return false. + */ + + + void (*OptimizePrecalcPipeline)( GLcontext *ctx, struct gl_pipeline *pipe ); + void (*OptimizeImmediatePipeline)( GLcontext *ctx, struct gl_pipeline *pipe); + /* Check to see if a fast path exists for this combination of stages + * in the precalc and immediate (elt) pipelines. + */ + + + /* + * State-changing functions (drawing functions are above) + * + * These functions are called by their corresponding OpenGL API functions. + * They're ALSO called by the gl_PopAttrib() function!!! + * May add more functions like these to the device driver in the future. + * This should reduce the amount of state checking that + * the driver's UpdateState() function must do. + */ + void (*AlphaFunc)(GLcontext *ctx, GLenum func, GLclampf ref); + void (*BlendFunc)(GLcontext *ctx, GLenum sfactor, GLenum dfactor); + void (*ClearDepth)(GLcontext *ctx, GLclampd d); + void (*CullFace)(GLcontext *ctx, GLenum mode); + void (*FrontFace)(GLcontext *ctx, GLenum mode); + void (*DepthFunc)(GLcontext *ctx, GLenum func); + void (*DepthMask)(GLcontext *ctx, GLboolean flag); + void (*DepthRange)(GLcontext *ctx, GLclampd nearval, GLclampd farval); + void (*Enable)(GLcontext* ctx, GLenum cap, GLboolean state); + void (*Fogfv)(GLcontext *ctx, GLenum pname, const GLfloat *params); + void (*Hint)(GLcontext *ctx, GLenum target, GLenum mode); + void (*PolygonMode)(GLcontext *ctx, GLenum face, GLenum mode); + void (*Scissor)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h); + void (*ShadeModel)(GLcontext *ctx, GLenum mode); + void (*ClearStencil)(GLcontext *ctx, GLint s); + void (*StencilFunc)(GLcontext *ctx, GLenum func, GLint ref, GLuint mask); + void (*StencilMask)(GLcontext *ctx, GLuint mask); + void (*StencilOp)(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass); + void (*Viewport)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h); +}; + + + +#endif + diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c new file mode 100644 index 00000000000..6d5a2be237e --- /dev/null +++ b/src/mesa/main/depth.c @@ -0,0 +1,879 @@ +/* $Id: depth.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +/* + * Depth buffer functions + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "context.h" +#include "enums.h" +#include "depth.h" +#include "macros.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/**********************************************************************/ +/***** API Functions *****/ +/**********************************************************************/ + + + +void gl_ClearDepth( GLcontext* ctx, GLclampd depth ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearDepth"); + ctx->Depth.Clear = (GLfloat) CLAMP( depth, 0.0, 1.0 ); + if (ctx->Driver.ClearDepth) + (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear ); +} + + + +void gl_DepthFunc( GLcontext* ctx, GLenum func ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthFunc"); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glDepthFunc %s\n", gl_lookup_enum_by_nr(func)); + + + switch (func) { + case GL_NEVER: + case GL_LESS: /* (default) pass if incoming z < stored z */ + case GL_GEQUAL: + case GL_LEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + case GL_EQUAL: + case GL_ALWAYS: + if (ctx->Depth.Func != func) { + ctx->Depth.Func = func; + ctx->NewState |= NEW_RASTER_OPS; + if (ctx->Driver.DepthFunc) { + (*ctx->Driver.DepthFunc)( ctx, func ); + } + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glDepth.Func" ); + } +} + + + +void gl_DepthMask( GLcontext* ctx, GLboolean flag ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthMask"); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glDepthMask %d\n", flag); + + /* + * GL_TRUE indicates depth buffer writing is enabled (default) + * GL_FALSE indicates depth buffer writing is disabled + */ + if (ctx->Depth.Mask != flag) { + ctx->Depth.Mask = flag; + ctx->NewState |= NEW_RASTER_OPS; + if (ctx->Driver.DepthMask) { + (*ctx->Driver.DepthMask)( ctx, flag ); + } + } +} + + + +/**********************************************************************/ +/***** Depth Testing Functions *****/ +/**********************************************************************/ + + +/* + * Depth test horizontal spans of fragments. These functions are called + * via ctx->Driver.depth_test_span only. + * + * Input: n - number of pixels in the span + * x, y - location of leftmost pixel in span in window coords + * z - array [n] of integer depth values + * In/Out: mask - array [n] of flags (1=draw pixel, 0=don't draw) + * Return: number of pixels which passed depth test + */ + + +/* + * glDepthFunc( any ) and glDepthMask( GL_TRUE or GL_FALSE ). + */ +GLuint gl_depth_test_span_generic( GLcontext* ctx, + GLuint n, GLint x, GLint y, + const GLdepth z[], + GLubyte mask[] ) +{ + GLdepth *zptr = Z_ADDRESS( ctx, x, y ); + GLubyte *m = mask; + GLuint i; + GLuint passed = 0; + + /* switch cases ordered from most frequent to less frequent */ + switch (ctx->Depth.Func) { + case GL_LESS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++,zptr++,m++) { + if (*m) { + if (z[i] < *zptr) { + /* pass */ + *zptr = z[i]; + passed++; + } + else { + /* fail */ + *m = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0; i<n; i++,zptr++,m++) { + if (*m) { + if (z[i] < *zptr) { + /* pass */ + passed++; + } + else { + *m = 0; + } + } + } + } + break; + case GL_LEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] <= *zptr) { + *zptr = z[i]; + passed++; + } + else { + *m = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] <= *zptr) { + /* pass */ + passed++; + } + else { + *m = 0; + } + } + } + } + break; + case GL_GEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] >= *zptr) { + *zptr = z[i]; + passed++; + } + else { + *m = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] >= *zptr) { + /* pass */ + passed++; + } + else { + *m = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] > *zptr) { + *zptr = z[i]; + passed++; + } + else { + *m = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] > *zptr) { + /* pass */ + passed++; + } + else { + *m = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] != *zptr) { + *zptr = z[i]; + passed++; + } + else { + *m = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] != *zptr) { + /* pass */ + passed++; + } + else { + *m = 0; + } + } + } + } + break; + case GL_EQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] == *zptr) { + *zptr = z[i]; + passed++; + } + else { + *m =0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + if (z[i] == *zptr) { + /* pass */ + passed++; + } + else { + *m =0; + } + } + } + } + break; + case GL_ALWAYS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;i<n;i++,zptr++,m++) { + if (*m) { + *zptr = z[i]; + passed++; + } + } + } + else { + /* Don't update Z buffer or mask */ + passed = n; + } + break; + case GL_NEVER: + for (i=0;i<n;i++) { + mask[i] = 0; + } + break; + default: + gl_problem(ctx, "Bad depth func in gl_depth_test_span_generic"); + } /*switch*/ + + return passed; +} + + + +/* + * glDepthFunc(GL_LESS) and glDepthMask(GL_TRUE). + */ +GLuint gl_depth_test_span_less( GLcontext* ctx, + GLuint n, GLint x, GLint y, const GLdepth z[], + GLubyte mask[] ) +{ + GLdepth *zptr = Z_ADDRESS( ctx, x, y ); + GLuint i; + GLuint passed = 0; + + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] < zptr[i]) { + /* pass */ + zptr[i] = z[i]; + passed++; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + return passed; +} + + +/* + * glDepthFunc(GL_GREATER) and glDepthMask(GL_TRUE). + */ +GLuint gl_depth_test_span_greater( GLcontext* ctx, + GLuint n, GLint x, GLint y, + const GLdepth z[], + GLubyte mask[] ) +{ + GLdepth *zptr = Z_ADDRESS( ctx, x, y ); + GLuint i; + GLuint passed = 0; + + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] > zptr[i]) { + /* pass */ + zptr[i] = z[i]; + passed++; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + return passed; +} + + + +/* + * Depth test an array of randomly positioned fragments. + */ + + +#define ZADDR_SETUP GLdepth *depthbuffer = ctx->Buffer->Depth; \ + GLint width = ctx->Buffer->Width; + +#define ZADDR( X, Y ) (depthbuffer + (Y) * width + (X) ) + + + +/* + * glDepthFunc( any ) and glDepthMask( GL_TRUE or GL_FALSE ). + */ +void gl_depth_test_pixels_generic( GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ) +{ + register GLdepth *zptr; + register GLuint i; + + /* switch cases ordered from most frequent to less frequent */ + switch (ctx->Depth.Func) { + case GL_LESS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] < *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] < *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_LEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] <= *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] <= *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] >= *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] >= *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] > *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] > *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] != *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] != *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_EQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] == *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] == *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_ALWAYS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + *zptr = z[i]; + } + } + } + else { + /* Don't update Z buffer or mask */ + } + break; + case GL_NEVER: + /* depth test never passes */ + for (i=0;i<n;i++) { + mask[i] = 0; + } + break; + default: + gl_problem(ctx, "Bad depth func in gl_depth_test_pixels_generic"); + } /*switch*/ +} + + + +/* + * glDepthFunc( GL_LESS ) and glDepthMask( GL_TRUE ). + */ +void gl_depth_test_pixels_less( GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ) +{ + GLdepth *zptr; + GLuint i; + + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] < *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } +} + + +/* + * glDepthFunc( GL_GREATER ) and glDepthMask( GL_TRUE ). + */ +void gl_depth_test_pixels_greater( GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ) +{ + GLdepth *zptr; + GLuint i; + + for (i=0; i<n; i++) { + if (mask[i]) { + zptr = Z_ADDRESS(ctx,x[i],y[i]); + if (z[i] > *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } +} + + + + +/**********************************************************************/ +/***** Read Depth Buffer *****/ +/**********************************************************************/ + + +/* + * Return a span of depth values from the depth buffer as floats in [0,1]. + * This function is only called through Driver.read_depth_span_float() + * Input: n - how many pixels + * x,y - location of first pixel + * Output: depth - the array of depth values + */ +void gl_read_depth_span_float( GLcontext* ctx, + GLuint n, GLint x, GLint y, GLfloat depth[] ) +{ + GLdepth *zptr; + GLfloat scale; + GLuint i; + + scale = 1.0F / DEPTH_SCALE; + + if (ctx->Buffer->Depth) { + zptr = Z_ADDRESS( ctx, x, y ); + for (i=0;i<n;i++) { + depth[i] = (GLfloat) zptr[i] * scale; + } + } + else { + for (i=0;i<n;i++) { + depth[i] = 0.0F; + } + } +} + + +/* + * Return a span of depth values from the depth buffer as integers in + * [0,MAX_DEPTH]. + * This function is only called through Driver.read_depth_span_int() + * Input: n - how many pixels + * x,y - location of first pixel + * Output: depth - the array of depth values + */ +void gl_read_depth_span_int( GLcontext* ctx, + GLuint n, GLint x, GLint y, GLdepth depth[] ) +{ + if (ctx->Buffer->Depth) { + GLdepth *zptr = Z_ADDRESS( ctx, x, y ); + MEMCPY( depth, zptr, n * sizeof(GLdepth) ); + } + else { + GLuint i; + for (i=0;i<n;i++) { + depth[i] = 0; + } + } +} + + + +/**********************************************************************/ +/***** Allocate and Clear Depth Buffer *****/ +/**********************************************************************/ + + + +/* + * Allocate a new depth buffer. If there's already a depth buffer allocated + * it will be free()'d. The new depth buffer will be uniniitalized. + * This function is only called through Driver.alloc_depth_buffer. + */ +void gl_alloc_depth_buffer( GLcontext* ctx ) +{ + /* deallocate current depth buffer if present */ + if (ctx->Buffer->Depth) { + free(ctx->Buffer->Depth); + ctx->Buffer->Depth = NULL; + } + + /* allocate new depth buffer, but don't initialize it */ + ctx->Buffer->Depth = (GLdepth *) malloc( ctx->Buffer->Width + * ctx->Buffer->Height + * sizeof(GLdepth) ); + if (!ctx->Buffer->Depth) { + /* out of memory */ + ctx->Depth.Test = GL_FALSE; + gl_error( ctx, GL_OUT_OF_MEMORY, "Couldn't allocate depth buffer" ); + } +} + + + + +/* + * Clear the depth buffer. If the depth buffer doesn't exist yet we'll + * allocate it now. + * This function is only called through Driver.clear_depth_buffer. + */ +void gl_clear_depth_buffer( GLcontext* ctx ) +{ + GLdepth clear_value = (GLdepth) (ctx->Depth.Clear * DEPTH_SCALE); + + if (ctx->Visual->DepthBits==0 || !ctx->Buffer->Depth || !ctx->Depth.Mask) { + /* no depth buffer, or writing to it is disabled */ + return; + } + + /* The loops in this function have been written so the IRIX 5.3 + * C compiler can unroll them. Hopefully other compilers can too! + */ + + if (ctx->Scissor.Enabled) { + /* only clear scissor region */ + GLint y; + for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) { + GLdepth *d = Z_ADDRESS( ctx, ctx->Buffer->Xmin, y ); + GLint n = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1; + do { + *d++ = clear_value; + n--; + } while (n); + } + } + else { + /* clear whole buffer */ + if (sizeof(GLdepth)==2 && (clear_value&0xff)==(clear_value>>8)) { + /* lower and upper bytes of clear_value are same, use MEMSET */ + MEMSET( ctx->Buffer->Depth, clear_value&0xff, + 2*ctx->Buffer->Width*ctx->Buffer->Height); + } + else { + GLdepth *d = ctx->Buffer->Depth; + GLint n = ctx->Buffer->Width * ctx->Buffer->Height; + while (n>=16) { + d[0] = clear_value; d[1] = clear_value; + d[2] = clear_value; d[3] = clear_value; + d[4] = clear_value; d[5] = clear_value; + d[6] = clear_value; d[7] = clear_value; + d[8] = clear_value; d[9] = clear_value; + d[10] = clear_value; d[11] = clear_value; + d[12] = clear_value; d[13] = clear_value; + d[14] = clear_value; d[15] = clear_value; + d += 16; + n -= 16; + } + while (n>0) { + *d++ = clear_value; + n--; + } + } + } +} + + + diff --git a/src/mesa/main/depth.h b/src/mesa/main/depth.h new file mode 100644 index 00000000000..559afc64fb3 --- /dev/null +++ b/src/mesa/main/depth.h @@ -0,0 +1,98 @@ +/* $Id: depth.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 DEPTH_H +#define DEPTH_H + + +#include "types.h" + + +/* + * Return the address of the Z-buffer value for window coordinate (x,y): + */ +#define Z_ADDRESS( CTX, X, Y ) \ + ((CTX)->Buffer->Depth + (CTX)->Buffer->Width * (Y) + (X)) + + + + +extern GLuint +gl_depth_test_span_generic( GLcontext* ctx, GLuint n, GLint x, GLint y, + const GLdepth z[], GLubyte mask[] ); + +extern GLuint +gl_depth_test_span_less( GLcontext* ctx, GLuint n, GLint x, GLint y, + const GLdepth z[], GLubyte mask[] ); + +extern GLuint +gl_depth_test_span_greater( GLcontext* ctx, GLuint n, GLint x, GLint y, + const GLdepth z[], GLubyte mask[] ); + + + +extern void +gl_depth_test_pixels_generic( GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ); + +extern void +gl_depth_test_pixels_less( GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ); + +extern void +gl_depth_test_pixels_greater( GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ); + + +extern void gl_read_depth_span_float( GLcontext* ctx, + GLuint n, GLint x, GLint y, + GLfloat depth[] ); + + +extern void gl_read_depth_span_int( GLcontext* ctx, GLuint n, GLint x, GLint y, + GLdepth depth[] ); + + +extern void gl_alloc_depth_buffer( GLcontext* ctx ); + + +extern void gl_clear_depth_buffer( GLcontext* ctx ); + + +extern void gl_ClearDepth( GLcontext* ctx, GLclampd depth ); + +extern void gl_DepthFunc( GLcontext* ctx, GLenum func ); + +extern void gl_DepthMask( GLcontext* ctx, GLboolean flag ); + +#endif diff --git a/src/mesa/main/descrip.mms b/src/mesa/main/descrip.mms new file mode 100644 index 00000000000..d6ab05799d5 --- /dev/null +++ b/src/mesa/main/descrip.mms @@ -0,0 +1,156 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen [email protected] +# Last revision : 3 May 1999 + +.first + define gl [-.include.gl] + +.include [-]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [-.include] +LIBDIR = [-.lib] +CFLAGS = /include=($(INCDIR),[])/define=(FBIND=1) + +CORE_SOURCES = accum.c alpha.c alphabuf.c api1.c api2.c apiext.c attrib.c \ +bitmap.c blend.c clip.c colortab.c context.c copypix.c depth.c \ +dlist.c drawpix.c enable.c eval.c feedback.c fog.c \ +get.c hash.c image.c light.c lines.c logic.c masking.c matrix.c \ +misc.c mmath.c mthreads.c pb.c pixel.c points.c pointers.c polygon.c \ +quads.c rastpos.c readpix.c rect.c scissor.c shade.c span.c \ +stencil.c teximage.c texobj.c texstate.c texture.c translate.c triangle.c \ +varray.c winpos.c vb.c vbcull.c vbfill.c vbrender.c vbxform.c xform.c \ +zoom.c bbox.c cva.c vector.c vbindirect.c config.c enums.c extensions.c \ +pipeline.c [.x86]x86.c + +DRIVER_SOURCES = [.x]glxapi.c [.x]fakeglx.c [.x]realglx.c [.x]xfonts.c \ +[.x]xmesa1.c [.x]xmesa2.c [.x]xmesa3.c [.x]xmesa4.c \ +[.osmesa]osmesa.c \ +[.svga]svgamesa.c \ +[.fx]fxapi.c [.fx]fxdd.c [.fx]fxddtex.c [.fx]fxvsetup.c [.fx]fxsetup.c \ +[.fx]fxtrifuncs.c \ +[.fx]fxrender.c [.fx]fxtexman.c [.fx]fxddspan.c [.fx]fxcva.c + +ASM_SOURCES = + +OBJECTS =\ +accum.obj,alpha.obj,alphabuf.obj,api1.obj,api2.obj,apiext.obj,attrib.obj,\ +bitmap.obj,blend.obj,clip.obj,colortab.obj,context.obj,copypix.obj,depth.obj,\ +dlist.obj,drawpix.obj,enable.obj,eval.obj,feedback.obj,fog.obj + + +OBJECTS3=get.obj,hash.obj,image.obj,light.obj,lines.obj,logic.obj,masking.obj,matrix.obj,\ +misc.obj,mmath.obj,mthreads.obj,pb.obj,pixel.obj,points.obj,pointers.obj,polygon.obj,\ +quads.obj,rastpos.obj,readpix.obj,rect.obj,scissor.obj,shade.obj,span.obj + + +OBJECTS4=stencil.obj,teximage.obj,texobj.obj,texstate.obj,texture.obj,translate.obj,\ +triangle.obj,varray.obj,winpos.obj,vb.obj,vbcull.obj,vbfill.obj,vbrender.obj + +OBJECTS6=vbxform.obj,xform.obj,zoom.obj,bbox.obj,cva.obj,vector.obj,vbindirect.obj,\ + config.obj,enums.obj,extensions.obj,pipeline.obj,[.x86]x86.obj + +OBJECTS2=[.x]glxapi.obj,[.x]fakeglx.obj,[.x]realglx.obj,[.x]xfonts.obj,\ +[.x]xmesa1.obj,[.x]xmesa2.obj,[.x]xmesa3.obj,[.x]xmesa4.obj,\ +[.osmesa]osmesa.obj,\ +[.svga]svgamesa.obj + +OBJECTS5=[.fx]fxapi.obj,[.fx]fxdd.obj,[.fx]fxddtex.obj,[.fx]fxvsetup.obj,\ +[.fx]fxsetup.obj,\ +[.fx]fxtrifuncs.obj,\ +[.fx]fxrender.obj,[.fx]fxtexman.obj,[.fx]fxddspan.obj,[.fx]fxcva.obj + +##### RULES ##### + +VERSION=Mesa V3.1 + +##### TARGETS ##### +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS),$(OBJECTS2) $(OBJECTS3) $(OBJECTS4)\ + $(OBJECTS5) $(OBJECTS6) +.ifdef SHARE + @ WRITE_ SYS$OUTPUT " generating mesagl1.opt" + @ OPEN_/WRITE FILE mesagl1.opt + @ WRITE_ FILE "!" + @ WRITE_ FILE "! mesagl1.opt generated by DESCRIP.$(MMS_EXT)" + @ WRITE_ FILE "!" + @ WRITE_ FILE "IDENTIFICATION=""$(VERSION)""" + @ WRITE_ FILE "GSMATCH=LEQUAL,3,1 + @ WRITE_ FILE "$(OBJECTS)" + @ WRITE_ FILE "$(OBJECTS3)" + @ WRITE_ FILE "$(OBJECTS4)" + @ WRITE_ FILE "$(OBJECTS6)" + @ WRITE_ FILE "$(OBJECTS2)" + @ WRITE_ FILE "$(OBJECTS5)" + @ WRITE_ FILE "SYS$SHARE:DECW$XEXTLIBSHR/SHARE" + @ WRITE_ FILE "SYS$SHARE:DECW$XLIBSHR/SHARE" + @ CLOSE_ FILE + @ WRITE_ SYS$OUTPUT " generating mesagl.map ..." + @ LINK_/NODEB/NOSHARE/NOEXE/MAP=mesagl.map/FULL mesagl1.opt/OPT + @ WRITE_ SYS$OUTPUT " analyzing mesagl.map ..." + @ @[-.vms]ANALYZE_MAP.COM mesagl.map mesagl.opt + @ WRITE_ SYS$OUTPUT " linking $(GL_LIB) ..." + @ LINK_/NODEB/SHARE=$(GL_LIB)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesagl.opt/opt +.else + @ $(MAKELIB) $(GL_LIB) $(OBJECTS) + @ library $(GL_LIB) $(OBJECTS2) + @ library $(GL_LIB) $(OBJECTS3) + @ library $(GL_LIB) $(OBJECTS4) + @ library $(GL_LIB) $(OBJECTS5) + @ library $(GL_LIB) $(OBJECTS6) +.endif + @ rename $(GL_LIB)* $(LIBDIR) + +clean : + purge + delete *.obj;* + +triangle.obj : triangle.c + +[.x86]x86.obj : [.x86]x86.c + $(CC) $(CFLAGS) /obj=[.x86]x86.obj [.x86]x86.c +[.x]glxapi.obj : [.x]glxapi.c + $(CC) $(CFLAGS) /obj=[.x]glxapi.obj [.x]glxapi.c +[.x]fakeglx.obj : [.x]fakeglx.c + $(CC) $(CFLAGS) /obj=[.x]fakeglx.obj [.x]fakeglx.c +[.x]realglx.obj : [.x]realglx.c + $(CC) $(CFLAGS) /obj=[.x]realglx.obj [.x]realglx.c +[.x]xfonts.obj : [.x]xfonts.c + $(CC) $(CFLAGS) /obj=[.x]xfonts.obj [.x]xfonts.c +[.x]xmesa1.obj : [.x]xmesa1.c + $(CC) $(CFLAGS) /obj=[.x]xmesa1.obj [.x]xmesa1.c +[.x]xmesa2.obj : [.x]xmesa2.c + $(CC) $(CFLAGS) /obj=[.x]xmesa2.obj [.x]xmesa2.c +[.x]xmesa3.obj : [.x]xmesa3.c + $(CC) $(CFLAGS) /obj=[.x]xmesa3.obj [.x]xmesa3.c +[.x]xmesa4.obj : [.x]xmesa4.c + $(CC) $(CFLAGS) /obj=[.x]xmesa4.obj [.x]xmesa4.c +[.osmesa]osmesa.obj : [.osmesa]osmesa.c + $(CC) $(CFLAGS) /obj=[.osmesa]osmesa.obj [.osmesa]osmesa.c +[.svga]svgamesa.obj : [.svga]svgamesa.c + $(CC) $(CFLAGS) /obj=[.svga]svgamesa.obj [.svga]svgamesa.c +[.fx]fxapi.obj : [.fx]fxapi.c + $(CC) $(CFLAGS) /obj=[.fx]fxapi.obj [.fx]fxapi.c +[.fx]fxcva.obj : [.fx]fxcva.c + $(CC) $(CFLAGS) /obj=[.fx]fxcva.obj [.fx]fxcva.c +[.fx]fxdd.obj : [.fx]fxdd.c + $(CC) $(CFLAGS) /obj=[.fx]fxdd.obj [.fx]fxdd.c +[.fx]fxddtex.obj : [.fx]fxddtex.c + $(CC) $(CFLAGS) /obj=[.fx]fxddtex.obj [.fx]fxddtex.c +[.fx]fxvsetup.obj : [.fx]fxvsetup.c + $(CC) $(CFLAGS) /obj=[.fx]fxvsetup.obj [.fx]fxvsetup.c +[.fx]fxsetup.obj : [.fx]fxsetup.c + $(CC) $(CFLAGS) /obj=[.fx]fxsetup.obj [.fx]fxsetup.c +[.fx]fxtrifuncs.obj : [.fx]fxtrifuncs.c + $(CC) $(CFLAGS) /obj=[.fx]fxtrifuncs.obj [.fx]fxtrifuncs.c +[.fx]fxrender.obj : [.fx]fxrender.c + $(CC) $(CFLAGS) /obj=[.fx]fxrender.obj [.fx]fxrender.c +[.fx]fxtexman.obj : [.fx]fxtexman.c + $(CC) $(CFLAGS) /obj=[.fx]fxtexman.obj [.fx]fxtexman.c +[.fx]fxddspan.obj : [.fx]fxddspan.c + $(CC) $(CFLAGS) /obj=[.fx]fxddspan.obj [.fx]fxddspan.c + +.include mms_depend. diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c new file mode 100644 index 00000000000..001de0367b2 --- /dev/null +++ b/src/mesa/main/dlist.c @@ -0,0 +1,3501 @@ +/* $Id: dlist.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "accum.h" +#include "api.h" +#include "alpha.h" +#include "attrib.h" +#include "bitmap.h" +#include "bbox.h" +#include "blend.h" +#include "clip.h" +#include "colortab.h" +#include "context.h" +#include "copypix.h" +#include "depth.h" +#include "drawpix.h" +#include "enable.h" +#include "enums.h" +#include "eval.h" +#include "feedback.h" +#include "fog.h" +#include "get.h" +#include "hash.h" +#include "image.h" +#include "light.h" +#include "lines.h" +#include "dlist.h" +#include "logic.h" +#include "macros.h" +#include "masking.h" +#include "matrix.h" +#include "misc.h" +#include "pipeline.h" +#include "pixel.h" +#include "points.h" +#include "polygon.h" +#include "rastpos.h" +#include "readpix.h" +#include "rect.h" +#include "scissor.h" +#include "stencil.h" +#include "texobj.h" +#include "teximage.h" +#include "texstate.h" +#include "types.h" +#include "varray.h" +#include "vb.h" +#include "vbfill.h" +#include "vbxform.h" +#include "winpos.h" +#include "xform.h" +#ifdef XFree86Server +#undef MISC_H +#include "GL/xf86glx.h" +#endif +#endif + + + +/* +Functions which aren't compiled but executed immediately: + glIsList + glGenLists + glDeleteLists + glEndList + glFeedbackBuffer + glSelectBuffer + glRenderMode + glReadPixels + glPixelStore + glFlush + glFinish + glIsEnabled + glGet* + +Functions which cause errors if called while compiling a display list: + glNewList +*/ + + + +/* + * Display list instructions are stored as sequences of "nodes". Nodes + * are allocated in blocks. Each block has BLOCK_SIZE nodes. Blocks + * are linked together with a pointer. + */ + + +/* How many nodes to allocate at a time: + * - reduced now that we hold vertices etc. elsewhere. + */ +#define BLOCK_SIZE 64 + + +/* + * Display list opcodes. + * + * The fact that these identifiers are assigned consecutive + * integer values starting at 0 is very important, see InstSize array usage) + * + * KW: Commented out opcodes now handled by vertex-cassettes. + */ +typedef enum { + OPCODE_ACCUM, + OPCODE_ALPHA_FUNC, + OPCODE_BIND_TEXTURE, + OPCODE_BITMAP, + OPCODE_BLEND_COLOR, + OPCODE_BLEND_EQUATION, + OPCODE_BLEND_FUNC, + OPCODE_BLEND_FUNC_SEPARATE, + OPCODE_CALL_LIST, + OPCODE_CALL_LIST_OFFSET, + OPCODE_CLEAR, + OPCODE_CLEAR_ACCUM, + OPCODE_CLEAR_COLOR, + OPCODE_CLEAR_DEPTH, + OPCODE_CLEAR_INDEX, + OPCODE_CLEAR_STENCIL, + OPCODE_CLIP_PLANE, + OPCODE_COLOR_MASK, + OPCODE_COLOR_MATERIAL, + OPCODE_COLOR_TABLE, + OPCODE_COLOR_SUB_TABLE, + OPCODE_COPY_PIXELS, + OPCODE_COPY_TEX_IMAGE1D, + OPCODE_COPY_TEX_IMAGE2D, + OPCODE_COPY_TEX_IMAGE3D, + OPCODE_COPY_TEX_SUB_IMAGE1D, + OPCODE_COPY_TEX_SUB_IMAGE2D, + OPCODE_COPY_TEX_SUB_IMAGE3D, + OPCODE_CULL_FACE, + OPCODE_DEPTH_FUNC, + OPCODE_DEPTH_MASK, + OPCODE_DEPTH_RANGE, + OPCODE_DISABLE, + OPCODE_DRAW_BUFFER, + OPCODE_DRAW_PIXELS, + OPCODE_ENABLE, + OPCODE_EVALCOORD1, + OPCODE_EVALCOORD2, + OPCODE_EVALMESH1, + OPCODE_EVALMESH2, + OPCODE_EVALPOINT1, + OPCODE_EVALPOINT2, + OPCODE_FOG, + OPCODE_FRONT_FACE, + OPCODE_FRUSTUM, + OPCODE_HINT, + OPCODE_INDEX_MASK, + OPCODE_INIT_NAMES, + OPCODE_LIGHT, + OPCODE_LIGHT_MODEL, + OPCODE_LINE_STIPPLE, + OPCODE_LINE_WIDTH, + OPCODE_LIST_BASE, + OPCODE_LOAD_IDENTITY, + OPCODE_LOAD_MATRIX, + OPCODE_LOAD_NAME, + OPCODE_LOGIC_OP, + OPCODE_MAP1, + OPCODE_MAP2, + OPCODE_MAPGRID1, + OPCODE_MAPGRID2, + OPCODE_MATRIX_MODE, + OPCODE_MULT_MATRIX, + OPCODE_ORTHO, + OPCODE_PASSTHROUGH, + OPCODE_PIXEL_MAP, + OPCODE_PIXEL_TRANSFER, + OPCODE_PIXEL_ZOOM, + OPCODE_POINT_SIZE, + OPCODE_POINT_PARAMETERS, + OPCODE_POLYGON_MODE, + OPCODE_POLYGON_STIPPLE, + OPCODE_POLYGON_OFFSET, + OPCODE_POP_ATTRIB, + OPCODE_POP_MATRIX, + OPCODE_POP_NAME, + OPCODE_PRIORITIZE_TEXTURE, + OPCODE_PUSH_ATTRIB, + OPCODE_PUSH_MATRIX, + OPCODE_PUSH_NAME, + OPCODE_RASTER_POS, + OPCODE_RECTF, + OPCODE_READ_BUFFER, + OPCODE_SCALE, + OPCODE_SCISSOR, + OPCODE_SELECT_TEXTURE_SGIS, + OPCODE_SELECT_TEXTURE_COORD_SET, + OPCODE_SHADE_MODEL, + OPCODE_STENCIL_FUNC, + OPCODE_STENCIL_MASK, + OPCODE_STENCIL_OP, + OPCODE_TEXENV, + OPCODE_TEXGEN, + OPCODE_TEXPARAMETER, + OPCODE_TEX_IMAGE1D, + OPCODE_TEX_IMAGE2D, + OPCODE_TEX_IMAGE3D, + OPCODE_TEX_SUB_IMAGE1D, + OPCODE_TEX_SUB_IMAGE2D, + OPCODE_TEX_SUB_IMAGE3D, + OPCODE_TRANSLATE, + OPCODE_VIEWPORT, + OPCODE_WINDOW_POS, + /* GL_ARB_multitexture */ + OPCODE_ACTIVE_TEXTURE, + OPCODE_CLIENT_ACTIVE_TEXTURE, + /* The following three are meta instructions */ + OPCODE_ERROR, /* raise compiled-in error */ + OPCODE_VERTEX_CASSETTE, /* render prebuilt vertex buffer */ + OPCODE_CONTINUE, + OPCODE_END_OF_LIST +} OpCode; + + +/* + * Each instruction in the display list is stored as a sequence of + * contiguous nodes in memory. + * Each node is the union of a variety of datatypes. + */ +union node { + OpCode opcode; + GLboolean b; + GLbitfield bf; + GLubyte ub; + GLshort s; + GLushort us; + GLint i; + GLuint ui; + GLenum e; + GLfloat f; + GLvoid *data; + void *next; /* If prev node's opcode==OPCODE_CONTINUE */ +}; + + + +/* Number of nodes of storage needed for each instruction: */ +static GLuint InstSize[ OPCODE_END_OF_LIST+1 ]; + + + +/**********************************************************************/ +/***** Private *****/ +/**********************************************************************/ + + +/* + * Allocate space for a display list instruction. + * Input: opcode - type of instruction + * argcount - number of arguments following the instruction + * Return: pointer to first node in the instruction + */ +static Node *alloc_instruction( GLcontext *ctx, OpCode opcode, GLint argcount ) +{ + Node *n, *newblock; + GLuint count = InstSize[opcode]; + + assert( (GLint) count == argcount+1 ); + + if (ctx->CurrentPos + count + 2 > BLOCK_SIZE) { + /* This block is full. Allocate a new block and chain to it */ + n = ctx->CurrentBlock + ctx->CurrentPos; + n[0].opcode = OPCODE_CONTINUE; + newblock = (Node *) malloc( sizeof(Node) * BLOCK_SIZE ); + if (!newblock) { + gl_error( ctx, GL_OUT_OF_MEMORY, "Building display list" ); + return NULL; + } + n[1].next = (Node *) newblock; + ctx->CurrentBlock = newblock; + ctx->CurrentPos = 0; + } + + n = ctx->CurrentBlock + ctx->CurrentPos; + ctx->CurrentPos += count; + + n[0].opcode = opcode; + + return n; +} + + + +/* + * Make an empty display list. This is used by glGenLists() to + * reserver display list IDs. + */ +static Node *make_empty_list( void ) +{ + Node *n = (Node *) malloc( sizeof(Node) ); + n[0].opcode = OPCODE_END_OF_LIST; + return n; +} + + + +/* + * Destroy all nodes in a display list. + * Input: list - display list number + */ +void gl_destroy_list( GLcontext *ctx, GLuint list ) +{ + Node *n, *block; + GLboolean done; + + if (list==0) + return; + + block = (Node *) HashLookup(ctx->Shared->DisplayList, list); + n = block; + + done = block ? GL_FALSE : GL_TRUE; + while (!done) { + switch (n[0].opcode) { + /* special cases first */ + case OPCODE_VERTEX_CASSETTE: + if ( ! -- ((struct immediate *) n[1].data)->ref_count ) + gl_immediate_free( (struct immediate *) n[1].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_MAP1: + gl_free_control_points( ctx, n[1].e, (GLfloat *) n[6].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_MAP2: + gl_free_control_points( ctx, n[1].e, (GLfloat *) n[10].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_DRAW_PIXELS: + gl_free_image( (struct gl_image *) n[1].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_BITMAP: + gl_free_image( (struct gl_image *) n[7].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COLOR_TABLE: + gl_free_image( (struct gl_image *) n[3].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COLOR_SUB_TABLE: + gl_free_image( (struct gl_image *) n[3].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_POLYGON_STIPPLE: + free( n[1].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_IMAGE1D: + gl_free_image( (struct gl_image *) n[8].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_IMAGE2D: + gl_free_image( (struct gl_image *) n[9].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_SUB_IMAGE1D: + { + struct gl_image *image; + image = (struct gl_image *) n[7].data; + gl_free_image( image ); + } + break; + case OPCODE_TEX_SUB_IMAGE2D: + { + struct gl_image *image; + image = (struct gl_image *) n[9].data; + gl_free_image( image ); + } + break; + case OPCODE_CONTINUE: + n = (Node *) n[1].next; + free( block ); + block = n; + break; + case OPCODE_END_OF_LIST: + free( block ); + done = GL_TRUE; + break; + default: + /* Most frequent case */ + n += InstSize[n[0].opcode]; + break; + } + } + + HashRemove(ctx->Shared->DisplayList, list); +} + + + +/* + * Translate the nth element of list from type to GLuint. + */ +static GLuint translate_id( GLsizei n, GLenum type, const GLvoid *list ) +{ + GLbyte *bptr; + GLubyte *ubptr; + GLshort *sptr; + GLushort *usptr; + GLint *iptr; + GLuint *uiptr; + GLfloat *fptr; + + switch (type) { + case GL_BYTE: + bptr = (GLbyte *) list; + return (GLuint) *(bptr+n); + case GL_UNSIGNED_BYTE: + ubptr = (GLubyte *) list; + return (GLuint) *(ubptr+n); + case GL_SHORT: + sptr = (GLshort *) list; + return (GLuint) *(sptr+n); + case GL_UNSIGNED_SHORT: + usptr = (GLushort *) list; + return (GLuint) *(usptr+n); + case GL_INT: + iptr = (GLint *) list; + return (GLuint) *(iptr+n); + case GL_UNSIGNED_INT: + uiptr = (GLuint *) list; + return (GLuint) *(uiptr+n); + case GL_FLOAT: + fptr = (GLfloat *) list; + return (GLuint) *(fptr+n); + case GL_2_BYTES: + ubptr = ((GLubyte *) list) + 2*n; + return (GLuint) *ubptr * 256 + (GLuint) *(ubptr+1); + case GL_3_BYTES: + ubptr = ((GLubyte *) list) + 3*n; + return (GLuint) *ubptr * 65536 + + (GLuint) *(ubptr+1) * 256 + + (GLuint) *(ubptr+2); + case GL_4_BYTES: + ubptr = ((GLubyte *) list) + 4*n; + return (GLuint) *ubptr * 16777216 + + (GLuint) *(ubptr+1) * 65536 + + (GLuint) *(ubptr+2) * 256 + + (GLuint) *(ubptr+3); + default: + return 0; + } +} + + + + +/**********************************************************************/ +/***** Public *****/ +/**********************************************************************/ + +void gl_init_lists( void ) +{ + static int init_flag = 0; + + if (init_flag==0) { + InstSize[OPCODE_ACCUM] = 3; + InstSize[OPCODE_ALPHA_FUNC] = 3; + InstSize[OPCODE_BIND_TEXTURE] = 3; + InstSize[OPCODE_BITMAP] = 8; + InstSize[OPCODE_BLEND_COLOR] = 5; + InstSize[OPCODE_BLEND_EQUATION] = 2; + InstSize[OPCODE_BLEND_FUNC] = 3; + InstSize[OPCODE_BLEND_FUNC_SEPARATE] = 5; + InstSize[OPCODE_CALL_LIST] = 2; + InstSize[OPCODE_CALL_LIST_OFFSET] = 2; + InstSize[OPCODE_CLEAR] = 2; + InstSize[OPCODE_CLEAR_ACCUM] = 5; + InstSize[OPCODE_CLEAR_COLOR] = 5; + InstSize[OPCODE_CLEAR_DEPTH] = 2; + InstSize[OPCODE_CLEAR_INDEX] = 2; + InstSize[OPCODE_CLEAR_STENCIL] = 2; + InstSize[OPCODE_CLIP_PLANE] = 6; + InstSize[OPCODE_COLOR_MASK] = 5; + InstSize[OPCODE_COLOR_MATERIAL] = 3; + InstSize[OPCODE_COLOR_TABLE] = 4; + InstSize[OPCODE_COLOR_SUB_TABLE] = 4; + InstSize[OPCODE_COPY_PIXELS] = 6; + InstSize[OPCODE_COPY_TEX_IMAGE1D] = 8; + InstSize[OPCODE_COPY_TEX_IMAGE2D] = 9; + InstSize[OPCODE_COPY_TEX_SUB_IMAGE1D] = 7; + InstSize[OPCODE_COPY_TEX_SUB_IMAGE2D] = 9; + InstSize[OPCODE_COPY_TEX_SUB_IMAGE3D] = 10; + InstSize[OPCODE_CULL_FACE] = 2; + InstSize[OPCODE_DEPTH_FUNC] = 2; + InstSize[OPCODE_DEPTH_MASK] = 2; + InstSize[OPCODE_DEPTH_RANGE] = 3; + InstSize[OPCODE_DISABLE] = 2; + InstSize[OPCODE_DRAW_BUFFER] = 2; + InstSize[OPCODE_DRAW_PIXELS] = 2; + InstSize[OPCODE_ENABLE] = 2; + InstSize[OPCODE_EVALCOORD1] = 2; + InstSize[OPCODE_EVALCOORD2] = 3; + InstSize[OPCODE_EVALMESH1] = 4; + InstSize[OPCODE_EVALMESH2] = 6; + InstSize[OPCODE_EVALPOINT1] = 2; + InstSize[OPCODE_EVALPOINT2] = 3; + InstSize[OPCODE_FOG] = 6; + InstSize[OPCODE_FRONT_FACE] = 2; + InstSize[OPCODE_FRUSTUM] = 7; + InstSize[OPCODE_HINT] = 3; + InstSize[OPCODE_INDEX_MASK] = 2; + InstSize[OPCODE_INIT_NAMES] = 1; + InstSize[OPCODE_LIGHT] = 7; + InstSize[OPCODE_LIGHT_MODEL] = 6; + InstSize[OPCODE_LINE_STIPPLE] = 3; + InstSize[OPCODE_LINE_WIDTH] = 2; + InstSize[OPCODE_LIST_BASE] = 2; + InstSize[OPCODE_LOAD_IDENTITY] = 1; + InstSize[OPCODE_LOAD_MATRIX] = 17; + InstSize[OPCODE_LOAD_NAME] = 2; + InstSize[OPCODE_LOGIC_OP] = 2; + InstSize[OPCODE_MAP1] = 7; + InstSize[OPCODE_MAP2] = 11; + InstSize[OPCODE_MAPGRID1] = 4; + InstSize[OPCODE_MAPGRID2] = 7; + InstSize[OPCODE_MATRIX_MODE] = 2; + InstSize[OPCODE_MULT_MATRIX] = 17; + InstSize[OPCODE_ORTHO] = 7; + InstSize[OPCODE_PASSTHROUGH] = 2; + InstSize[OPCODE_PIXEL_MAP] = 4; + InstSize[OPCODE_PIXEL_TRANSFER] = 3; + InstSize[OPCODE_PIXEL_ZOOM] = 3; + InstSize[OPCODE_POINT_SIZE] = 2; + InstSize[OPCODE_POINT_PARAMETERS] = 5; + InstSize[OPCODE_POLYGON_MODE] = 3; + InstSize[OPCODE_POLYGON_STIPPLE] = 2; + InstSize[OPCODE_POLYGON_OFFSET] = 3; + InstSize[OPCODE_POP_ATTRIB] = 1; + InstSize[OPCODE_POP_MATRIX] = 1; + InstSize[OPCODE_POP_NAME] = 1; + InstSize[OPCODE_PRIORITIZE_TEXTURE] = 3; + InstSize[OPCODE_PUSH_ATTRIB] = 2; + InstSize[OPCODE_PUSH_MATRIX] = 1; + InstSize[OPCODE_PUSH_NAME] = 2; + InstSize[OPCODE_RASTER_POS] = 5; + InstSize[OPCODE_RECTF] = 5; + InstSize[OPCODE_READ_BUFFER] = 2; + InstSize[OPCODE_SCALE] = 4; + InstSize[OPCODE_SCISSOR] = 5; + InstSize[OPCODE_STENCIL_FUNC] = 4; + InstSize[OPCODE_STENCIL_MASK] = 2; + InstSize[OPCODE_STENCIL_OP] = 4; + InstSize[OPCODE_SHADE_MODEL] = 2; + InstSize[OPCODE_TEXENV] = 7; + InstSize[OPCODE_TEXGEN] = 7; + InstSize[OPCODE_TEXPARAMETER] = 7; + InstSize[OPCODE_TEX_IMAGE1D] = 9; + InstSize[OPCODE_TEX_IMAGE2D] = 10; + InstSize[OPCODE_TEX_IMAGE3D] = 11; + InstSize[OPCODE_TEX_SUB_IMAGE1D] = 8; + InstSize[OPCODE_TEX_SUB_IMAGE2D] = 10; + InstSize[OPCODE_TEX_SUB_IMAGE3D] = 12; + InstSize[OPCODE_TRANSLATE] = 4; + InstSize[OPCODE_VIEWPORT] = 5; + InstSize[OPCODE_WINDOW_POS] = 5; + InstSize[OPCODE_CONTINUE] = 2; + InstSize[OPCODE_ERROR] = 3; + InstSize[OPCODE_VERTEX_CASSETTE] = 2; + InstSize[OPCODE_END_OF_LIST] = 1; + /* GL_ARB_multitexture */ + InstSize[OPCODE_ACTIVE_TEXTURE] = 2; + InstSize[OPCODE_CLIENT_ACTIVE_TEXTURE] = 2; + } + init_flag = 1; +} + + +/* + * Display List compilation functions + */ + + + +static void save_Accum( GLcontext *ctx, GLenum op, GLfloat value ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_ACCUM, 2 ); + if (n) { + n[1].e = op; + n[2].f = value; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Accum)( ctx, op, value ); + } +} + + +static void save_AlphaFunc( GLcontext *ctx, GLenum func, GLclampf ref ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_ALPHA_FUNC, 2 ); + if (n) { + n[1].e = func; + n[2].f = (GLfloat) ref; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.AlphaFunc)( ctx, func, ref ); + } +} + +static void save_BindTexture( GLcontext *ctx, GLenum target, GLuint texture ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_BIND_TEXTURE, 2 ); + if (n) { + n[1].e = target; + n[2].ui = texture; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.BindTexture)( ctx, target, texture ); + } +} + + +static void save_Bitmap( GLcontext *ctx, + GLsizei width, GLsizei height, + GLfloat xorig, GLfloat yorig, + GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap, + const struct gl_pixelstore_attrib *packing ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_BITMAP, 7 ); + if (n) { + struct gl_image *image = gl_unpack_bitmap( ctx, width, height, + bitmap, packing ); + if (image) { + image->RefCount = 1; + } + n[1].i = (GLint) width; + n[2].i = (GLint) height; + n[3].f = xorig; + n[4].f = yorig; + n[5].f = xmove; + n[6].f = ymove; + n[7].data = (void *) image; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Bitmap)( ctx, width, height, + xorig, yorig, xmove, ymove, bitmap, packing ); + } +} + + +static void save_BlendEquation( GLcontext *ctx, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_BLEND_EQUATION, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.BlendEquation)( ctx, mode ); + } +} + + +static void save_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_BLEND_FUNC, 2 ); + if (n) { + n[1].e = sfactor; + n[2].e = dfactor; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.BlendFunc)( ctx, sfactor, dfactor ); + } +} + + +static void save_BlendFuncSeparate( GLcontext *ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_BLEND_FUNC_SEPARATE, 4 ); + if (n) { + n[1].e = sfactorRGB; + n[2].e = dfactorRGB; + n[3].e = sfactorA; + n[4].e = dfactorA; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB, + sfactorA, dfactorA); + } +} + + +static void save_BlendColor( GLcontext *ctx, GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_BLEND_COLOR, 4 ); + if (n) { + n[1].f = red; + n[2].f = green; + n[3].f = blue; + n[4].f = alpha; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.BlendColor)( ctx, red, green, blue, alpha ); + } +} + + +static void save_CallList( GLcontext *ctx, GLuint list ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CALL_LIST, 1 ); + if (n) { + n[1].ui = list; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CallList)( ctx, list ); + } +} + + +static void save_CallLists( GLcontext *ctx, + GLsizei n, GLenum type, const GLvoid *lists ) +{ + GLint i; + FLUSH_VB(ctx, "dlist"); + + for (i=0;i<n;i++) { + GLuint list = translate_id( i, type, lists ); + Node *n = alloc_instruction( ctx, OPCODE_CALL_LIST_OFFSET, 1 ); + if (n) { + n[1].ui = list; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CallLists)( ctx, n, type, lists ); + } +} + + +static void save_Clear( GLcontext *ctx, GLbitfield mask ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLEAR, 1 ); + if (n) { + n[1].bf = mask; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Clear)( ctx, mask ); + } +} + + +static void save_ClearAccum( GLcontext *ctx, GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLEAR_ACCUM, 4 ); + if (n) { + n[1].f = red; + n[2].f = green; + n[3].f = blue; + n[4].f = alpha; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ClearAccum)( ctx, red, green, blue, alpha ); + } +} + + +static void save_ClearColor( GLcontext *ctx, GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLEAR_COLOR, 4 ); + if (n) { + n[1].f = red; + n[2].f = green; + n[3].f = blue; + n[4].f = alpha; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ClearColor)( ctx, red, green, blue, alpha ); + } +} + + +static void save_ClearDepth( GLcontext *ctx, GLclampd depth ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLEAR_DEPTH, 1 ); + if (n) { + n[1].f = (GLfloat) depth; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ClearDepth)( ctx, depth ); + } +} + + +static void save_ClearIndex( GLcontext *ctx, GLfloat c ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLEAR_INDEX, 1 ); + if (n) { + n[1].f = c; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ClearIndex)( ctx, c ); + } +} + + +static void save_ClearStencil( GLcontext *ctx, GLint s ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLEAR_STENCIL, 1 ); + if (n) { + n[1].i = s; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ClearStencil)( ctx, s ); + } +} + + +static void save_ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *equ ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLIP_PLANE, 5 ); + if (n) { + n[1].e = plane; + n[2].f = equ[0]; + n[3].f = equ[1]; + n[4].f = equ[2]; + n[5].f = equ[3]; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ClipPlane)( ctx, plane, equ ); + } +} + + + +static void save_ColorMask( GLcontext *ctx, GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COLOR_MASK, 4 ); + if (n) { + n[1].b = red; + n[2].b = green; + n[3].b = blue; + n[4].b = alpha; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ColorMask)( ctx, red, green, blue, alpha ); + } +} + + +static void save_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COLOR_MATERIAL, 2 ); + if (n) { + n[1].e = face; + n[2].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ColorMaterial)( ctx, face, mode ); + } +} + + +static void save_ColorTable( GLcontext *ctx, GLenum target, GLenum internalFormat, + struct gl_image *table ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COLOR_TABLE, 3 ); + if (n) { + n[1].e = target; + n[2].e = internalFormat; + n[3].data = (GLvoid *) table; + if (table) { + /* must retain this image */ + table->RefCount = 1; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ColorTable)( ctx, target, internalFormat, table ); + } +} + + +static void save_ColorSubTable( GLcontext *ctx, GLenum target, + GLsizei start, struct gl_image *data ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COLOR_SUB_TABLE, 3 ); + if (n) { + n[1].e = target; + n[2].i = start; + n[3].data = (GLvoid *) data; + if (data) { + /* must retain this image */ + data->RefCount = 1; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ColorSubTable)( ctx, target, start, data ); + } +} + + + +static void save_CopyPixels( GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, GLenum type ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COPY_PIXELS, 5 ); + if (n) { + n[1].i = x; + n[2].i = y; + n[3].i = (GLint) width; + n[4].i = (GLint) height; + n[5].e = type; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CopyPixels)( ctx, x, y, width, height, type ); + } +} + + + +static void save_CopyTexImage1D( GLcontext *ctx, + GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, GLsizei width, + GLint border ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COPY_TEX_IMAGE1D, 7 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalformat; + n[4].i = x; + n[5].i = y; + n[6].i = width; + n[7].i = border; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CopyTexImage1D)( ctx, target, level, internalformat, + x, y, width, border ); + } +} + + +static void save_CopyTexImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, GLsizei width, + GLsizei height, GLint border ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COPY_TEX_IMAGE2D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalformat; + n[4].i = x; + n[5].i = y; + n[6].i = width; + n[7].i = height; + n[8].i = border; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CopyTexImage2D)( ctx, target, level, internalformat, + x, y, width, height, border ); + } +} + + + +static void save_CopyTexSubImage1D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, + GLsizei width ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COPY_TEX_SUB_IMAGE1D, 6 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = x; + n[5].i = y; + n[6].i = width; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CopyTexSubImage1D)( ctx, target, level, xoffset, x, y, width ); + } +} + + +static void save_CopyTexSubImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLint height ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COPY_TEX_SUB_IMAGE2D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = x; + n[6].i = y; + n[7].i = width; + n[8].i = height; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CopyTexSubImage2D)( ctx, target, level, xoffset, yoffset, + x, y, width, height ); + } +} + + +static void save_CopyTexSubImage3DEXT( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, + GLsizei width, GLint height ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_COPY_TEX_SUB_IMAGE3D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = zoffset; + n[6].i = x; + n[7].i = y; + n[8].i = width; + n[9].i = height; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CopyTexSubImage3DEXT)( ctx, target, level, xoffset, yoffset, zoffset, + x, y, width, height ); + } +} + + +static void save_CullFace( GLcontext *ctx, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CULL_FACE, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.CullFace)( ctx, mode ); + } +} + + +static void save_DepthFunc( GLcontext *ctx, GLenum func ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_DEPTH_FUNC, 1 ); + if (n) { + n[1].e = func; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.DepthFunc)( ctx, func ); + } +} + + +static void save_DepthMask( GLcontext *ctx, GLboolean mask ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_DEPTH_MASK, 1 ); + if (n) { + n[1].b = mask; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.DepthMask)( ctx, mask ); + } +} + + +static void save_DepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_DEPTH_RANGE, 2 ); + if (n) { + n[1].f = (GLfloat) nearval; + n[2].f = (GLfloat) farval; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.DepthRange)( ctx, nearval, farval ); + } +} + + +static void save_Disable( GLcontext *ctx, GLenum cap ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_DISABLE, 1 ); + if (n) { + n[1].e = cap; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Disable)( ctx, cap ); + } +} + + +static void save_DrawBuffer( GLcontext *ctx, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_DRAW_BUFFER, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.DrawBuffer)( ctx, mode ); + } +} + + +static void save_DrawPixels( GLcontext *ctx, struct gl_image *image ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_DRAW_PIXELS, 1 ); + if (n) { + n[1].data = (GLvoid *) image; + } + if (image) { + image->RefCount = 1; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.DrawPixels)( ctx, image ); + } +} + + + +static void save_Enable( GLcontext *ctx, GLenum cap ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_ENABLE, 1 ); + if (n) { + n[1].e = cap; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Enable)( ctx, cap ); + } +} + + + +static void save_EvalMesh1( GLcontext *ctx, + GLenum mode, GLint i1, GLint i2 ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_EVALMESH1, 3 ); + if (n) { + n[1].e = mode; + n[2].i = i1; + n[3].i = i2; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.EvalMesh1)( ctx, mode, i1, i2 ); + } +} + + +static void save_EvalMesh2( GLcontext *ctx, + GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_EVALMESH2, 5 ); + if (n) { + n[1].e = mode; + n[2].i = i1; + n[3].i = i2; + n[4].i = j1; + n[5].i = j2; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.EvalMesh2)( ctx, mode, i1, i2, j1, j2 ); + } +} + + + + +static void save_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_FOG, 5 ); + if (n) { + n[1].e = pname; + n[2].f = params[0]; + n[3].f = params[1]; + n[4].f = params[2]; + n[5].f = params[3]; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Fogfv)( ctx, pname, params ); + } +} + + +static void save_FrontFace( GLcontext *ctx, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_FRONT_FACE, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.FrontFace)( ctx, mode ); + } +} + + +static void save_Frustum( GLcontext *ctx, GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_FRUSTUM, 6 ); + if (n) { + n[1].f = left; + n[2].f = right; + n[3].f = bottom; + n[4].f = top; + n[5].f = nearval; + n[6].f = farval; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Frustum)( ctx, left, right, bottom, top, nearval, farval ); + } +} + + +static GLboolean save_Hint( GLcontext *ctx, GLenum target, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_HINT, 2 ); + if (n) { + n[1].e = target; + n[2].e = mode; + } + if (ctx->ExecuteFlag) { + return (*ctx->Exec.Hint)( ctx, target, mode ); + } + return GL_TRUE; /* not queried */ +} + + + +static void save_IndexMask( GLcontext *ctx, GLuint mask ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_INDEX_MASK, 1 ); + if (n) { + n[1].ui = mask; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.IndexMask)( ctx, mask ); + } +} + + +static void save_InitNames( GLcontext *ctx ) +{ + FLUSH_VB(ctx, "dlist"); + (void) alloc_instruction( ctx, OPCODE_INIT_NAMES, 0 ); + if (ctx->ExecuteFlag) { + (*ctx->Exec.InitNames)( ctx ); + } +} + + +static void save_Lightfv( GLcontext *ctx, GLenum light, GLenum pname, + const GLfloat *params, GLint numparams ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LIGHT, 6 ); + if (OPCODE_LIGHT) { + GLint i; + n[1].e = light; + n[2].e = pname; + for (i=0;i<numparams;i++) { + n[3+i].f = params[i]; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Lightfv)( ctx, light, pname, params, numparams ); + } +} + + +static void save_LightModelfv( GLcontext *ctx, + GLenum pname, const GLfloat *params ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LIGHT_MODEL, 5 ); + if (n) { + n[1].e = pname; + n[2].f = params[0]; + n[3].f = params[1]; + n[4].f = params[2]; + n[5].f = params[3]; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.LightModelfv)( ctx, pname, params ); + } +} + + +static void save_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LINE_STIPPLE, 2 ); + if (n) { + n[1].i = factor; + n[2].us = pattern; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.LineStipple)( ctx, factor, pattern ); + } +} + + +static void save_LineWidth( GLcontext *ctx, GLfloat width ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LINE_WIDTH, 1 ); + if (n) { + n[1].f = width; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.LineWidth)( ctx, width ); + } +} + + +static void save_ListBase( GLcontext *ctx, GLuint base ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LIST_BASE, 1 ); + if (n) { + n[1].ui = base; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ListBase)( ctx, base ); + } +} + + +static void save_LoadIdentity( GLcontext *ctx ) +{ + FLUSH_VB(ctx, "dlist"); + (void) alloc_instruction( ctx, OPCODE_LOAD_IDENTITY, 0 ); + if (ctx->ExecuteFlag) { + (*ctx->Exec.LoadIdentity)( ctx ); + } +} + + +static void save_LoadMatrixf( GLcontext *ctx, const GLfloat *m ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LOAD_MATRIX, 16 ); + if (n) { + GLuint i; + for (i=0;i<16;i++) { + n[1+i].f = m[i]; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.LoadMatrixf)( ctx, m ); + } +} + + +static void save_LoadName( GLcontext *ctx, GLuint name ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LOAD_NAME, 1 ); + if (n) { + n[1].ui = name; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.LoadName)( ctx, name ); + } +} + + +static void save_LogicOp( GLcontext *ctx, GLenum opcode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_LOGIC_OP, 1 ); + if (n) { + n[1].e = opcode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.LogicOp)( ctx, opcode ); + } +} + + +static void save_Map1f( GLcontext *ctx, + GLenum target, GLfloat u1, GLfloat u2, GLint stride, + GLint order, const GLfloat *points, GLboolean retain ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_MAP1, 6 ); + if (n) { + n[1].e = target; + n[2].f = u1; + n[3].f = u2; + n[4].i = stride; + n[5].i = order; + n[6].data = (void *) points; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Map1f)( ctx, target, u1, u2, stride, order, points, GL_TRUE ); + } + (void) retain; +} + + +static void save_Map2f( GLcontext *ctx, GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points, GLboolean retain ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_MAP2, 10 ); + if (n) { + n[1].e = target; + n[2].f = u1; + n[3].f = u2; + n[4].f = v1; + n[5].f = v2; + n[6].i = ustride; + n[7].i = vstride; + n[8].i = uorder; + n[9].i = vorder; + n[10].data = (void *) points; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Map2f)( ctx, target, + u1, u2, ustride, uorder, + v1, v2, vstride, vorder, points, GL_TRUE ); + } + (void) retain; +} + + +static void save_MapGrid1f( GLcontext *ctx, GLint un, GLfloat u1, GLfloat u2 ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_MAPGRID1, 3 ); + if (n) { + n[1].i = un; + n[2].f = u1; + n[3].f = u2; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.MapGrid1f)( ctx, un, u1, u2 ); + } +} + + +static void save_MapGrid2f( GLcontext *ctx, + GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_MAPGRID2, 6 ); + if (n) { + n[1].i = un; + n[2].f = u1; + n[3].f = u2; + n[4].i = vn; + n[5].f = v1; + n[6].f = v2; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.MapGrid2f)( ctx, un, u1, u2, vn, v1, v2 ); + } +} + + +static void save_MatrixMode( GLcontext *ctx, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_MATRIX_MODE, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.MatrixMode)( ctx, mode ); + } +} + + +static void save_MultMatrixf( GLcontext *ctx, const GLfloat *m ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_MULT_MATRIX, 16 ); + if (n) { + GLuint i; + for (i=0;i<16;i++) { + n[1+i].f = m[i]; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.MultMatrixf)( ctx, m ); + } +} + + +static void save_NewList( GLcontext *ctx, GLuint list, GLenum mode ) +{ + /* It's an error to call this function while building a display list */ + gl_error( ctx, GL_INVALID_OPERATION, "glNewList" ); + (void) list; + (void) mode; +} + + + +static void save_Ortho( GLcontext *ctx, GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_ORTHO, 6 ); + if (n) { + n[1].f = left; + n[2].f = right; + n[3].f = bottom; + n[4].f = top; + n[5].f = nearval; + n[6].f = farval; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Ortho)( ctx, left, right, bottom, top, nearval, farval ); + } +} + + +static void save_PixelMapfv( GLcontext *ctx, + GLenum map, GLint mapsize, const GLfloat *values ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_PIXEL_MAP, 3 ); + if (n) { + n[1].e = map; + n[2].i = mapsize; + n[3].data = (void *) malloc( mapsize * sizeof(GLfloat) ); + MEMCPY( n[3].data, (void *) values, mapsize * sizeof(GLfloat) ); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PixelMapfv)( ctx, map, mapsize, values ); + } +} + + +static void save_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_PIXEL_TRANSFER, 2 ); + if (n) { + n[1].e = pname; + n[2].f = param; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PixelTransferf)( ctx, pname, param ); + } +} + + +static void save_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_PIXEL_ZOOM, 2 ); + if (n) { + n[1].f = xfactor; + n[2].f = yfactor; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PixelZoom)( ctx, xfactor, yfactor ); + } +} + + +static void save_PointParameterfvEXT( GLcontext *ctx, GLenum pname, + const GLfloat *params) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_POINT_PARAMETERS, 4 ); + if (n) { + n[1].e = pname; + n[2].f = params[0]; + n[3].f = params[1]; + n[4].f = params[2]; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PointParameterfvEXT)( ctx, pname, params ); + } +} + + +static void save_PointSize( GLcontext *ctx, GLfloat size ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_POINT_SIZE, 1 ); + if (n) { + n[1].f = size; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PointSize)( ctx, size ); + } +} + + +static void save_PolygonMode( GLcontext *ctx, GLenum face, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_POLYGON_MODE, 2 ); + if (n) { + n[1].e = face; + n[2].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PolygonMode)( ctx, face, mode ); + } +} + + +/* + * Polygon stipple must have been upacked already! + */ +static void save_PolygonStipple( GLcontext *ctx, const GLuint *pattern ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_POLYGON_STIPPLE, 1 ); + if (n) { + void *data; + n[1].data = malloc( 32 * 4 ); + data = n[1].data; /* This needed for Acorn compiler */ + MEMCPY( data, pattern, 32 * 4 ); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PolygonStipple)( ctx, pattern ); + } +} + + +static void save_PolygonOffset( GLcontext *ctx, GLfloat factor, GLfloat units ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_POLYGON_OFFSET, 2 ); + if (n) { + n[1].f = factor; + n[2].f = units; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PolygonOffset)( ctx, factor, units ); + } +} + + +static void save_PopAttrib( GLcontext *ctx ) +{ + FLUSH_VB(ctx, "dlist"); + (void) alloc_instruction( ctx, OPCODE_POP_ATTRIB, 0 ); + if (ctx->ExecuteFlag) { + (*ctx->Exec.PopAttrib)( ctx ); + } +} + + +static void save_PopMatrix( GLcontext *ctx ) +{ + FLUSH_VB(ctx, "dlist"); + (void) alloc_instruction( ctx, OPCODE_POP_MATRIX, 0 ); + if (ctx->ExecuteFlag) { + (*ctx->Exec.PopMatrix)( ctx ); + } +} + + +static void save_PopName( GLcontext *ctx ) +{ + FLUSH_VB(ctx, "dlist"); + (void) alloc_instruction( ctx, OPCODE_POP_NAME, 0 ); + if (ctx->ExecuteFlag) { + (*ctx->Exec.PopName)( ctx ); + } +} + + +static void save_PrioritizeTextures( GLcontext *ctx, + GLsizei num, const GLuint *textures, + const GLclampf *priorities ) +{ + GLint i; + FLUSH_VB(ctx, "dlist"); + + for (i=0;i<num;i++) { + Node *n; + n = alloc_instruction( ctx, OPCODE_PRIORITIZE_TEXTURE, 2 ); + if (n) { + n[1].ui = textures[i]; + n[2].f = priorities[i]; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PrioritizeTextures)( ctx, num, textures, priorities ); + } +} + + +static void save_PushAttrib( GLcontext *ctx, GLbitfield mask ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_PUSH_ATTRIB, 1 ); + if (n) { + n[1].bf = mask; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PushAttrib)( ctx, mask ); + } +} + + +static void save_PushMatrix( GLcontext *ctx ) +{ + FLUSH_VB(ctx, "dlist"); + (void) alloc_instruction( ctx, OPCODE_PUSH_MATRIX, 0 ); + if (ctx->ExecuteFlag) { + (*ctx->Exec.PushMatrix)( ctx ); + } +} + + +static void save_PushName( GLcontext *ctx, GLuint name ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_PUSH_NAME, 1 ); + if (n) { + n[1].ui = name; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PushName)( ctx, name ); + } +} + + +static void save_RasterPos4f( GLcontext *ctx, + GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_RASTER_POS, 4 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + n[4].f = w; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.RasterPos4f)( ctx, x, y, z, w ); + } +} + + +static void save_PassThrough( GLcontext *ctx, GLfloat token ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_PASSTHROUGH, 1 ); + if (n) { + n[1].f = token; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.PassThrough)( ctx, token ); + } +} + + +static void save_ReadBuffer( GLcontext *ctx, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_READ_BUFFER, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ReadBuffer)( ctx, mode ); + } +} + + +static void save_Rectf( GLcontext *ctx, + GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_RECTF, 4 ); + if (n) { + n[1].f = x1; + n[2].f = y1; + n[3].f = x2; + n[4].f = y2; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Rectf)( ctx, x1, y1, x2, y2 ); + } +} + + +static void save_Rotatef( GLcontext *ctx, GLfloat angle, + GLfloat x, GLfloat y, GLfloat z ) +{ + GLfloat m[16]; + gl_rotation_matrix( angle, x, y, z, m ); + save_MultMatrixf( ctx, m ); /* save and maybe execute */ +} + + +static void save_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_SCALE, 3 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Scalef)( ctx, x, y, z ); + } +} + + +static void save_Scissor( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_SCISSOR, 4 ); + if (n) { + n[1].i = x; + n[2].i = y; + n[3].i = width; + n[4].i = height; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Scissor)( ctx, x, y, width, height ); + } +} + + +static void save_ShadeModel( GLcontext *ctx, GLenum mode ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_SHADE_MODEL, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ShadeModel)( ctx, mode ); + } +} + + +static void save_StencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_STENCIL_FUNC, 3 ); + if (n) { + n[1].e = func; + n[2].i = ref; + n[3].ui = mask; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.StencilFunc)( ctx, func, ref, mask ); + } +} + + +static void save_StencilMask( GLcontext *ctx, GLuint mask ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_STENCIL_MASK, 1 ); + if (n) { + n[1].ui = mask; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.StencilMask)( ctx, mask ); + } +} + + +static void save_StencilOp( GLcontext *ctx, + GLenum fail, GLenum zfail, GLenum zpass ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_STENCIL_OP, 3 ); + if (n) { + n[1].e = fail; + n[2].e = zfail; + n[3].e = zpass; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.StencilOp)( ctx, fail, zfail, zpass ); + } +} + + + + +static void save_TexEnvfv( GLcontext *ctx, + GLenum target, GLenum pname, const GLfloat *params ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEXENV, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexEnvfv)( ctx, target, pname, params ); + } +} + + +static void save_TexGenfv( GLcontext *ctx, + GLenum coord, GLenum pname, const GLfloat *params ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEXGEN, 6 ); + if (n) { + n[1].e = coord; + n[2].e = pname; + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexGenfv)( ctx, coord, pname, params ); + } +} + + +static void save_TexParameterfv( GLcontext *ctx, GLenum target, + GLenum pname, const GLfloat *params ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEXPARAMETER, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexParameterfv)( ctx, target, pname, params ); + } +} + + +static void save_TexImage1D( GLcontext *ctx, GLenum target, + GLint level, GLint components, + GLsizei width, GLint border, + GLenum format, GLenum type, + struct gl_image *teximage ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEX_IMAGE1D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = border; + n[6].e = format; + n[7].e = type; + n[8].data = teximage; + if (teximage) { + /* this prevents gl_TexImage2D() from freeing the image */ + teximage->RefCount = 1; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexImage1D)( ctx, target, level, components, width, + border, format, type, teximage ); + } +} + + +static void save_TexImage2D( GLcontext *ctx, GLenum target, + GLint level, GLint components, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + struct gl_image *teximage ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEX_IMAGE2D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = border; + n[7].e = format; + n[8].e = type; + n[9].data = teximage; + if (teximage) { + /* this prevents gl_TexImage2D() from freeing the image */ + teximage->RefCount = 1; + } + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexImage2D)( ctx, target, level, components, width, + height, border, format, type, teximage ); + } +} + + +static void save_TexImage3DEXT( GLcontext *ctx, GLenum target, + GLint level, GLint components, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, + GLenum format, GLenum type, + struct gl_image *teximage ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEX_IMAGE3D, 10 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = (GLint) depth; + n[7].i = border; + n[8].e = format; + n[9].e = type; + n[10].data = teximage; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexImage3DEXT)( ctx, target, level, components, width, + height, depth, border, format, type, teximage ); + } +} + + +static void save_TexSubImage1D( GLcontext *ctx, + GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, GLenum type, + struct gl_image *image ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE1D, 7 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = (GLint) width; + n[5].e = format; + n[6].e = type; + n[7].data = image; + if (image) + image->RefCount = 1; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexSubImage1D)( ctx, target, level, xoffset, width, + format, type, image ); + } +} + + +static void save_TexSubImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + struct gl_image *image ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE2D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = (GLint) width; + n[6].i = (GLint) height; + n[7].e = format; + n[8].e = type; + n[9].data = image; + if (image) + image->RefCount = 1; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexSubImage2D)( ctx, target, level, xoffset, yoffset, + width, height, format, type, image ); + } +} + + +static void save_TexSubImage3DEXT( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset,GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + struct gl_image *image ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE3D, 11 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = zoffset; + n[6].i = (GLint) width; + n[7].i = (GLint) height; + n[8].i = (GLint) depth; + n[9].e = format; + n[10].e = type; + n[11].data = image; + if (image) + image->RefCount = 1; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexSubImage3DEXT)( ctx, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, type, image ); + } +} + + +static void save_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_TRANSLATE, 3 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Translatef)( ctx, x, y, z ); + } +} + + + +static void save_Viewport( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_VIEWPORT, 4 ); + if (n) { + n[1].i = x; + n[2].i = y; + n[3].i = (GLint) width; + n[4].i = (GLint) height; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.Viewport)( ctx, x, y, width, height ); + } +} + + +static void save_WindowPos4fMESA( GLcontext *ctx, + GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_WINDOW_POS, 4 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + n[4].f = w; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.WindowPos4fMESA)( ctx, x, y, z, w ); + } +} + + + + + + +/* GL_ARB_multitexture */ +static void save_ActiveTexture( GLcontext *ctx, GLenum target ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_ACTIVE_TEXTURE, 1 ); + if (n) { + n[1].e = target; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ActiveTexture)( ctx, target ); + } +} + + +/* GL_ARB_multitexture */ +static void save_ClientActiveTexture( GLcontext *ctx, GLenum target ) +{ + Node *n; + FLUSH_VB(ctx, "dlist"); + n = alloc_instruction( ctx, OPCODE_CLIENT_ACTIVE_TEXTURE, 1 ); + if (n) { + n[1].e = target; + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.ClientActiveTexture)( ctx, target ); + } +} + + + + + +void gl_compile_cassette( GLcontext *ctx ) +{ + Node *n = alloc_instruction( ctx, OPCODE_VERTEX_CASSETTE, 1 ); + struct immediate *new_im = gl_immediate_alloc(ctx); + struct immediate *im = ctx->input; + + if (!n || !new_im) { + if (n) free(n); + if (new_im) gl_immediate_free(new_im); + return; + } + + /* Do some easy optimizations of the cassette. If current value of + * clip volume hint is GL_FASTEST, we are not clipping anyway, so + * don't calculate the bounds. But - they will not be calculated + * later even if the hint is changed, so this is a slightly odd + * behaviour. + */ + if (ctx->Hint.ClipVolumeClipping != GL_FASTEST && + im->v.Obj.size < 4 && + im->Count > 15) + { + im->Bounds = (GLfloat (*)[3]) malloc(6 * sizeof(GLfloat)); + (gl_calc_bound_tab[im->v.Obj.size])( im->Bounds, &im->v.Obj ); + } + + + n[1].data = (void *)im; + SET_IMMEDIATE( ctx, new_im ); +} + +/* KW: Compile commands + * + * Will appear in the list before the vertex buffer containing the + * command that provoked the error. I don't see this as a problem. + */ +void gl_save_error( GLcontext *ctx, GLenum error, const char *s ) +{ + Node *n; + n = alloc_instruction( ctx, OPCODE_ERROR, 2 ); + if (n) { + n[1].e = error; + n[2].data = (void *) s; + } + /* execute already done */ +} + +/**********************************************************************/ +/* Display list execution */ +/**********************************************************************/ + + +/* + * Execute a display list. Note that the ListBase offset must have already + * been added before calling this function. I.e. the list argument is + * the absolute list number, not relative to ListBase. + * Input: list - display list number + */ +static void execute_list( GLcontext *ctx, GLuint list ) +{ + Node *n; + GLboolean done; + OpCode opcode; + + if (!gl_IsList(ctx,list)) + return; + +/* mesa_print_display_list( list ); */ + + ctx->CallDepth++; + + n = (Node *) HashLookup(ctx->Shared->DisplayList, list); + + done = GL_FALSE; + while (!done) { + opcode = n[0].opcode; + + switch (opcode) { + case OPCODE_ERROR: + gl_error( ctx, n[1].e, (const char *) n[2].data ); + break; + case OPCODE_VERTEX_CASSETTE: + if (ctx->NewState) + gl_update_state(ctx); + if (!ctx->CVA.elt.pipeline_valid) + gl_build_immediate_pipeline( ctx ); + gl_fixup_cassette( ctx, (struct immediate *) n[1].data ); + gl_execute_cassette( ctx, (struct immediate *) n[1].data ); + break; + case OPCODE_ACCUM: + gl_Accum( ctx, n[1].e, n[2].f ); + break; + case OPCODE_ALPHA_FUNC: + gl_AlphaFunc( ctx, n[1].e, n[2].f ); + break; + case OPCODE_BIND_TEXTURE: + gl_BindTexture( ctx, n[1].e, n[2].ui ); + break; + case OPCODE_BITMAP: + { + static struct gl_pixelstore_attrib defaultPacking = { + 1, /* Alignment */ + 0, /* RowLength */ + 0, /* SkipPixels */ + 0, /* SkipRows */ + 0, /* ImageHeight */ + 0, /* SkipImages */ + GL_FALSE, /* SwapBytes */ + GL_FALSE /* LsbFirst */ + }; + const struct gl_image *image = (struct gl_image *) n[7].data; + const GLubyte *bitmap = image ? image->Data : NULL; + gl_Bitmap( ctx, (GLsizei) n[1].i, (GLsizei) n[2].i, + n[3].f, n[4].f, n[5].f, n[6].f, + bitmap, &defaultPacking ); + } + break; + case OPCODE_BLEND_COLOR: + gl_BlendColor( ctx, n[1].f, n[2].f, n[3].f, n[4].f ); + break; + case OPCODE_BLEND_EQUATION: + gl_BlendEquation( ctx, n[1].e ); + break; + case OPCODE_BLEND_FUNC: + gl_BlendFunc( ctx, n[1].e, n[2].e ); + break; + case OPCODE_BLEND_FUNC_SEPARATE: + gl_BlendFuncSeparate( ctx, n[1].e, n[2].e, n[3].e, n[4].e ); + break; + case OPCODE_CALL_LIST: + /* Generated by glCallList(), don't add ListBase */ + if (ctx->CallDepth<MAX_LIST_NESTING) { + execute_list( ctx, n[1].ui ); + } + break; + case OPCODE_CALL_LIST_OFFSET: + /* Generated by glCallLists() so we must add ListBase */ + if (ctx->CallDepth<MAX_LIST_NESTING) { + execute_list( ctx, ctx->List.ListBase + n[1].ui ); + } + break; + case OPCODE_CLEAR: + gl_Clear( ctx, n[1].bf ); + break; + case OPCODE_CLEAR_COLOR: + gl_ClearColor( ctx, n[1].f, n[2].f, n[3].f, n[4].f ); + break; + case OPCODE_CLEAR_ACCUM: + gl_ClearAccum( ctx, n[1].f, n[2].f, n[3].f, n[4].f ); + break; + case OPCODE_CLEAR_DEPTH: + gl_ClearDepth( ctx, (GLclampd) n[1].f ); + break; + case OPCODE_CLEAR_INDEX: + gl_ClearIndex( ctx, n[1].ui ); + break; + case OPCODE_CLEAR_STENCIL: + gl_ClearStencil( ctx, n[1].i ); + break; + case OPCODE_CLIP_PLANE: + { + GLfloat equ[4]; + equ[0] = n[2].f; + equ[1] = n[3].f; + equ[2] = n[4].f; + equ[3] = n[5].f; + gl_ClipPlane( ctx, n[1].e, equ ); + } + break; + case OPCODE_COLOR_MASK: + gl_ColorMask( ctx, n[1].b, n[2].b, n[3].b, n[4].b ); + break; + case OPCODE_COLOR_MATERIAL: + gl_ColorMaterial( ctx, n[1].e, n[2].e ); + break; + case OPCODE_COLOR_TABLE: + gl_ColorTable( ctx, n[1].e, n[2].e, (struct gl_image *) n[3].data); + break; + case OPCODE_COLOR_SUB_TABLE: + gl_ColorSubTable( ctx, n[1].e, n[2].i, + (struct gl_image *) n[3].data); + break; + case OPCODE_COPY_PIXELS: + gl_CopyPixels( ctx, n[1].i, n[2].i, + (GLsizei) n[3].i, (GLsizei) n[4].i, n[5].e ); + break; + case OPCODE_COPY_TEX_IMAGE1D: + gl_CopyTexImage1D( ctx, n[1].e, n[2].i, n[3].e, n[4].i, + n[5].i, n[6].i, n[7].i ); + break; + case OPCODE_COPY_TEX_IMAGE2D: + gl_CopyTexImage2D( ctx, n[1].e, n[2].i, n[3].e, n[4].i, + n[5].i, n[6].i, n[7].i, n[8].i ); + break; + case OPCODE_COPY_TEX_SUB_IMAGE1D: + gl_CopyTexSubImage1D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, + n[5].i, n[6].i ); + break; + case OPCODE_COPY_TEX_SUB_IMAGE2D: + gl_CopyTexSubImage2D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, + n[5].i, n[6].i, n[7].i, n[8].i ); + break; + case OPCODE_COPY_TEX_SUB_IMAGE3D: + gl_CopyTexSubImage3DEXT( ctx, n[1].e, n[2].i, n[3].i, n[4].i, + n[5].i, n[6].i, n[7].i, n[8].i , n[9].i); + break; + case OPCODE_CULL_FACE: + gl_CullFace( ctx, n[1].e ); + break; + case OPCODE_DEPTH_FUNC: + gl_DepthFunc( ctx, n[1].e ); + break; + case OPCODE_DEPTH_MASK: + gl_DepthMask( ctx, n[1].b ); + break; + case OPCODE_DEPTH_RANGE: + gl_DepthRange( ctx, (GLclampd) n[1].f, (GLclampd) n[2].f ); + break; + case OPCODE_DISABLE: + gl_Disable( ctx, n[1].e ); + break; + case OPCODE_DRAW_BUFFER: + gl_DrawBuffer( ctx, n[1].e ); + break; + case OPCODE_DRAW_PIXELS: + gl_DrawPixels( ctx, (struct gl_image *) n[1].data ); + break; + case OPCODE_ENABLE: + gl_Enable( ctx, n[1].e ); + break; + case OPCODE_EVALMESH1: + gl_EvalMesh1( ctx, n[1].e, n[2].i, n[3].i ); + break; + case OPCODE_EVALMESH2: + gl_EvalMesh2( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].i ); + break; + case OPCODE_FOG: + { + GLfloat p[4]; + p[0] = n[2].f; + p[1] = n[3].f; + p[2] = n[4].f; + p[3] = n[5].f; + gl_Fogfv( ctx, n[1].e, p ); + } + break; + case OPCODE_FRONT_FACE: + gl_FrontFace( ctx, n[1].e ); + break; + case OPCODE_FRUSTUM: + gl_Frustum( ctx, n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f ); + break; + case OPCODE_HINT: + gl_Hint( ctx, n[1].e, n[2].e ); + break; + case OPCODE_INDEX_MASK: + gl_IndexMask( ctx, n[1].ui ); + break; + case OPCODE_INIT_NAMES: + gl_InitNames( ctx ); + break; + case OPCODE_LIGHT: + { + GLfloat p[4]; + p[0] = n[3].f; + p[1] = n[4].f; + p[2] = n[5].f; + p[3] = n[6].f; + gl_Lightfv( ctx, n[1].e, n[2].e, p, 4 ); + } + break; + case OPCODE_LIGHT_MODEL: + { + GLfloat p[4]; + p[0] = n[2].f; + p[1] = n[3].f; + p[2] = n[4].f; + p[3] = n[5].f; + gl_LightModelfv( ctx, n[1].e, p ); + } + break; + case OPCODE_LINE_STIPPLE: + gl_LineStipple( ctx, n[1].i, n[2].us ); + break; + case OPCODE_LINE_WIDTH: + gl_LineWidth( ctx, n[1].f ); + break; + case OPCODE_LIST_BASE: + gl_ListBase( ctx, n[1].ui ); + break; + case OPCODE_LOAD_IDENTITY: + gl_LoadIdentity( ctx ); + break; + case OPCODE_LOAD_MATRIX: + if (sizeof(Node)==sizeof(GLfloat)) { + gl_LoadMatrixf( ctx, &n[1].f ); + } + else { + GLfloat m[16]; + GLuint i; + for (i=0;i<16;i++) { + m[i] = n[1+i].f; + } + gl_LoadMatrixf( ctx, m ); + } + break; + case OPCODE_LOAD_NAME: + gl_LoadName( ctx, n[1].ui ); + break; + case OPCODE_LOGIC_OP: + gl_LogicOp( ctx, n[1].e ); + break; + case OPCODE_MAP1: + gl_Map1f( ctx, n[1].e, n[2].f, n[3].f, + n[4].i, n[5].i, (GLfloat *) n[6].data, GL_TRUE ); + break; + case OPCODE_MAP2: + gl_Map2f( ctx, n[1].e, + n[2].f, n[3].f, /* u1, u2 */ + n[6].i, n[8].i, /* ustride, uorder */ + n[4].f, n[5].f, /* v1, v2 */ + n[7].i, n[9].i, /* vstride, vorder */ + (GLfloat *) n[10].data, + GL_TRUE); + break; + case OPCODE_MAPGRID1: + gl_MapGrid1f( ctx, n[1].i, n[2].f, n[3].f ); + break; + case OPCODE_MAPGRID2: + gl_MapGrid2f( ctx, n[1].i, n[2].f, n[3].f, n[4].i, n[5].f, n[6].f); + break; + case OPCODE_MATRIX_MODE: + gl_MatrixMode( ctx, n[1].e ); + break; + case OPCODE_MULT_MATRIX: + if (sizeof(Node)==sizeof(GLfloat)) { + gl_MultMatrixf( ctx, &n[1].f ); + } + else { + GLfloat m[16]; + GLuint i; + for (i=0;i<16;i++) { + m[i] = n[1+i].f; + } + gl_MultMatrixf( ctx, m ); + } + break; + case OPCODE_ORTHO: + gl_Ortho( ctx, n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f ); + break; + case OPCODE_PASSTHROUGH: + gl_PassThrough( ctx, n[1].f ); + break; + case OPCODE_PIXEL_MAP: + gl_PixelMapfv( ctx, n[1].e, n[2].i, (GLfloat *) n[3].data ); + break; + case OPCODE_PIXEL_TRANSFER: + gl_PixelTransferf( ctx, n[1].e, n[2].f ); + break; + case OPCODE_PIXEL_ZOOM: + gl_PixelZoom( ctx, n[1].f, n[2].f ); + break; + case OPCODE_POINT_SIZE: + gl_PointSize( ctx, n[1].f ); + break; + case OPCODE_POINT_PARAMETERS: + { + GLfloat params[3]; + params[0] = n[2].f; + params[1] = n[3].f; + params[2] = n[4].f; + gl_PointParameterfvEXT( ctx, n[1].e, params ); + } + break; + case OPCODE_POLYGON_MODE: + gl_PolygonMode( ctx, n[1].e, n[2].e ); + break; + case OPCODE_POLYGON_STIPPLE: + gl_PolygonStipple( ctx, (GLuint *) n[1].data ); + break; + case OPCODE_POLYGON_OFFSET: + gl_PolygonOffset( ctx, n[1].f, n[2].f ); + break; + case OPCODE_POP_ATTRIB: + gl_PopAttrib( ctx ); + break; + case OPCODE_POP_MATRIX: + gl_PopMatrix( ctx ); + break; + case OPCODE_POP_NAME: + gl_PopName( ctx ); + break; + case OPCODE_PRIORITIZE_TEXTURE: + gl_PrioritizeTextures( ctx, 1, &n[1].ui, &n[2].f ); + break; + case OPCODE_PUSH_ATTRIB: + gl_PushAttrib( ctx, n[1].bf ); + break; + case OPCODE_PUSH_MATRIX: + gl_PushMatrix( ctx ); + break; + case OPCODE_PUSH_NAME: + gl_PushName( ctx, n[1].ui ); + break; + case OPCODE_RASTER_POS: + gl_RasterPos4f( ctx, n[1].f, n[2].f, n[3].f, n[4].f ); + break; + case OPCODE_READ_BUFFER: + gl_ReadBuffer( ctx, n[1].e ); + break; + case OPCODE_RECTF: + gl_Rectf( ctx, n[1].f, n[2].f, n[3].f, n[4].f ); + break; + case OPCODE_SCALE: + gl_Scalef( ctx, n[1].f, n[2].f, n[3].f ); + break; + case OPCODE_SCISSOR: + gl_Scissor( ctx, n[1].i, n[2].i, n[3].i, n[4].i ); + break; + case OPCODE_SHADE_MODEL: + gl_ShadeModel( ctx, n[1].e ); + break; + case OPCODE_STENCIL_FUNC: + gl_StencilFunc( ctx, n[1].e, n[2].i, n[3].ui ); + break; + case OPCODE_STENCIL_MASK: + gl_StencilMask( ctx, n[1].ui ); + break; + case OPCODE_STENCIL_OP: + gl_StencilOp( ctx, n[1].e, n[2].e, n[3].e ); + break; + case OPCODE_TEXENV: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + gl_TexEnvfv( ctx, n[1].e, n[2].e, params ); + } + break; + case OPCODE_TEXGEN: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + gl_TexGenfv( ctx, n[1].e, n[2].e, params ); + } + break; + case OPCODE_TEXPARAMETER: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + gl_TexParameterfv( ctx, n[1].e, n[2].e, params ); + } + break; + case OPCODE_TEX_IMAGE1D: + gl_TexImage1D( ctx, + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].e, /* border */ + n[6].e, /* format */ + n[7].e, /* type */ + (struct gl_image *) n[8].data ); + break; + case OPCODE_TEX_IMAGE2D: + gl_TexImage2D( ctx, + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].i, /* height */ + n[6].e, /* border */ + n[7].e, /* format */ + n[8].e, /* type */ + (struct gl_image *) n[9].data ); + break; + case OPCODE_TEX_IMAGE3D: + gl_TexImage3DEXT( ctx, + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].i, /* height */ + n[6].i, /* depth */ + n[7].e, /* border */ + n[8].e, /* format */ + n[9].e, /* type */ + (struct gl_image *) n[10].data ); + break; + case OPCODE_TEX_SUB_IMAGE1D: + gl_TexSubImage1D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, + n[6].e, (struct gl_image *) n[7].data ); + break; + case OPCODE_TEX_SUB_IMAGE2D: + gl_TexSubImage2D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, + n[6].i, n[7].e, n[8].e, + (struct gl_image *) n[9].data ); + break; + case OPCODE_TEX_SUB_IMAGE3D: + gl_TexSubImage3DEXT( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].i, + n[6].i, n[7].i, n[8].i, n[9].e, n[10].e, + (struct gl_image *) n[11].data ); + break; + case OPCODE_TRANSLATE: + gl_Translatef( ctx, n[1].f, n[2].f, n[3].f ); + break; + case OPCODE_VIEWPORT: + gl_Viewport( ctx, + n[1].i, n[2].i, (GLsizei) n[3].i, (GLsizei) n[4].i ); + break; + case OPCODE_WINDOW_POS: + gl_WindowPos4fMESA( ctx, n[1].f, n[2].f, n[3].f, n[4].f ); + break; + case OPCODE_ACTIVE_TEXTURE: /* GL_ARB_multitexture */ + gl_ActiveTexture( ctx, n[1].e ); + break; + case OPCODE_CLIENT_ACTIVE_TEXTURE: /* GL_ARB_multitexture */ + gl_ClientActiveTexture( ctx, n[1].e ); + break; + case OPCODE_CONTINUE: + n = (Node *) n[1].next; + break; + case OPCODE_END_OF_LIST: + done = GL_TRUE; + break; + default: + { + char msg[1000]; + sprintf(msg, "Error in execute_list: opcode=%d", (int) opcode); + gl_problem( ctx, msg ); + } + done = GL_TRUE; + } + + /* increment n to point to next compiled command */ + if (opcode!=OPCODE_CONTINUE) { + n += InstSize[opcode]; + } + + } + ctx->CallDepth--; +} + + + + + +/**********************************************************************/ +/* GL functions */ +/**********************************************************************/ + + + + +/* + * Test if a display list number is valid. + */ +GLboolean gl_IsList( GLcontext *ctx, GLuint list ) +{ + if (list > 0 && HashLookup(ctx->Shared->DisplayList, list)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + + +/* + * Delete a sequence of consecutive display lists. + */ +void gl_DeleteLists( GLcontext *ctx, GLuint list, GLsizei range ) +{ + GLuint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDeleteLists"); + if (range<0) { + gl_error( ctx, GL_INVALID_VALUE, "glDeleteLists" ); + return; + } + for (i=list;i<list+range;i++) { + gl_destroy_list( ctx, i ); + } +} + + + +/* + * Return a display list number, n, such that lists n through n+range-1 + * are free. + */ +GLuint gl_GenLists( GLcontext *ctx, GLsizei range ) +{ + GLuint base; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glGenLists", 0); + if (range<0) { + gl_error( ctx, GL_INVALID_VALUE, "glGenLists" ); + return 0; + } + if (range==0) { + return 0; + } + + base = HashFindFreeKeyBlock(ctx->Shared->DisplayList, range); + if (base) { + /* reserve the list IDs by with empty/dummy lists */ + GLint i; + for (i=0; i<range; i++) { + HashInsert(ctx->Shared->DisplayList, base+i, make_empty_list()); + } + } + return base; +} + + + +/* + * Begin a new display list. + */ +void gl_NewList( GLcontext *ctx, GLuint list, GLenum mode ) +{ + struct immediate *IM; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glNewList"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glNewList %u %s\n", list, gl_lookup_enum_by_nr(mode)); + + if (list==0) { + gl_error( ctx, GL_INVALID_VALUE, "glNewList" ); + return; + } + + if (mode!=GL_COMPILE && mode!=GL_COMPILE_AND_EXECUTE) { + gl_error( ctx, GL_INVALID_ENUM, "glNewList" ); + return; + } + + if (ctx->CurrentListPtr) { + /* already compiling a display list */ + gl_error( ctx, GL_INVALID_OPERATION, "glNewList" ); + return; + } + + /* Allocate new display list */ + ctx->CurrentListNum = list; + ctx->CurrentBlock = (Node *) malloc( sizeof(Node) * BLOCK_SIZE ); + ctx->CurrentListPtr = ctx->CurrentBlock; + ctx->CurrentPos = 0; + + IM = gl_immediate_alloc( ctx ); + SET_IMMEDIATE( ctx, IM ); + gl_reset_input( ctx ); + + ctx->CompileFlag = GL_TRUE; + ctx->CompileCVAFlag = GL_FALSE; + ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE); + ctx->API = ctx->Save; /* Switch the API function pointers */ +} + + + +/* + * End definition of current display list. + */ +void gl_EndList( GLcontext *ctx ) +{ + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glEndList\n"); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glEndList" ); + + /* Check that a list is under construction */ + if (!ctx->CurrentListPtr) { + gl_error( ctx, GL_INVALID_OPERATION, "glEndList" ); + return; + } + + (void) alloc_instruction( ctx, OPCODE_END_OF_LIST, 0 ); + + + + /* Destroy old list, if any */ + gl_destroy_list(ctx, ctx->CurrentListNum); + /* Install the list */ + HashInsert(ctx->Shared->DisplayList, ctx->CurrentListNum, ctx->CurrentListPtr); + + ctx->CurrentListNum = 0; + ctx->CurrentListPtr = NULL; + ctx->ExecuteFlag = GL_TRUE; + ctx->CompileFlag = GL_FALSE; + /* ctx->CompileCVAFlag = ...; */ + + /* KW: Put back the old input pointer. + */ + free( ctx->input ); + SET_IMMEDIATE( ctx, ctx->VB->IM ); + + ctx->API = ctx->Exec; /* Switch the API function pointers */ +} + + + +void gl_CallList( GLcontext *ctx, GLuint list ) +{ + /* VERY IMPORTANT: Save the CompileFlag status, turn it off, */ + /* execute the display list, and restore the CompileFlag. */ + GLboolean save_compile_flag; + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glCallList %u\n", list); + + + save_compile_flag = ctx->CompileFlag; + ctx->CompileFlag = GL_FALSE; + + FLUSH_VB( ctx, "call list" ); + +/* mesa_print_display_list( list ); */ + + execute_list( ctx, list ); + ctx->CompileFlag = save_compile_flag; + + /* also restore API function pointers to point to "save" versions */ + if (save_compile_flag) + ctx->API = ctx->Save; + + +/* RESET_IMMEDIATE( ctx ); */ +} + + + +/* + * Execute glCallLists: call multiple display lists. + */ +void gl_CallLists( GLcontext *ctx, + GLsizei n, GLenum type, const GLvoid *lists ) +{ + GLuint list; + GLint i; + GLboolean save_compile_flag; + + /* Save the CompileFlag status, turn it off, execute display list, + * and restore the CompileFlag. + */ + save_compile_flag = ctx->CompileFlag; + ctx->CompileFlag = GL_FALSE; + + FLUSH_VB( ctx, "call lists" ); + + for (i=0;i<n;i++) { + list = translate_id( i, type, lists ); + execute_list( ctx, ctx->List.ListBase + list ); + } + + ctx->CompileFlag = save_compile_flag; + + /* also restore API function pointers to point to "save" versions */ + if (save_compile_flag) + ctx->API = ctx->Save; + + +/* RESET_IMMEDIATE( ctx ); */ +} + + + +/* + * Set the offset added to list numbers in glCallLists. + */ +void gl_ListBase( GLcontext *ctx, GLuint base ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glListBase"); + ctx->List.ListBase = base; +} + + + + + + +/* + * Assign all the pointers in 'table' to point to Mesa's display list + * building functions. + */ +void gl_init_dlist_pointers( struct gl_api_table *table ) +{ + table->Accum = save_Accum; + table->AlphaFunc = save_AlphaFunc; + table->AreTexturesResident = gl_AreTexturesResident; + table->BindTexture = save_BindTexture; + table->Bitmap = save_Bitmap; + table->BlendColor = save_BlendColor; + table->BlendEquation = save_BlendEquation; + table->BlendFunc = save_BlendFunc; + table->BlendFuncSeparate = save_BlendFuncSeparate; + table->CallList = save_CallList; + table->CallLists = save_CallLists; + table->Clear = save_Clear; + table->ClearAccum = save_ClearAccum; + table->ClearColor = save_ClearColor; + table->ClearDepth = save_ClearDepth; + table->ClearIndex = save_ClearIndex; + table->ClearStencil = save_ClearStencil; + table->ClipPlane = save_ClipPlane; + table->ColorMask = save_ColorMask; + table->ColorMaterial = save_ColorMaterial; + table->ColorTable = save_ColorTable; + table->ColorSubTable = save_ColorSubTable; + table->CopyPixels = save_CopyPixels; + table->CopyTexImage1D = save_CopyTexImage1D; + table->CopyTexImage2D = save_CopyTexImage2D; + table->CopyTexSubImage1D = save_CopyTexSubImage1D; + table->CopyTexSubImage2D = save_CopyTexSubImage2D; + table->CopyTexSubImage3DEXT = save_CopyTexSubImage3DEXT; + table->CullFace = save_CullFace; + table->DeleteLists = gl_DeleteLists; /* NOT SAVED */ + table->DeleteTextures = gl_DeleteTextures; /* NOT SAVED */ + table->DepthFunc = save_DepthFunc; + table->DepthMask = save_DepthMask; + table->DepthRange = save_DepthRange; + table->Disable = save_Disable; + table->DisableClientState = gl_DisableClientState; /* NOT SAVED */ + table->DrawBuffer = save_DrawBuffer; + table->DrawPixels = save_DrawPixels; + table->Enable = save_Enable; + table->Error = gl_save_error; + table->EnableClientState = gl_EnableClientState; /* NOT SAVED */ + table->EndList = gl_EndList; /* NOT SAVED */ + table->EvalMesh1 = save_EvalMesh1; + table->EvalMesh2 = save_EvalMesh2; + table->FeedbackBuffer = gl_FeedbackBuffer; /* NOT SAVED */ + table->Finish = gl_Finish; /* NOT SAVED */ + table->Flush = gl_Flush; /* NOT SAVED */ + table->Fogfv = save_Fogfv; + table->FrontFace = save_FrontFace; + table->Frustum = save_Frustum; + table->GenLists = gl_GenLists; /* NOT SAVED */ + table->GenTextures = gl_GenTextures; /* NOT SAVED */ + + /* NONE OF THESE COMMANDS ARE COMPILED INTO DISPLAY LISTS */ + table->GetBooleanv = gl_GetBooleanv; + table->GetClipPlane = gl_GetClipPlane; + table->GetColorTable = gl_GetColorTable; + table->GetColorTableParameteriv = gl_GetColorTableParameteriv; + table->GetDoublev = gl_GetDoublev; + table->GetError = gl_GetError; + table->GetFloatv = gl_GetFloatv; + table->GetIntegerv = gl_GetIntegerv; + table->GetString = gl_GetString; + table->GetLightfv = gl_GetLightfv; + table->GetLightiv = gl_GetLightiv; + table->GetMapdv = gl_GetMapdv; + table->GetMapfv = gl_GetMapfv; + table->GetMapiv = gl_GetMapiv; + table->GetMaterialfv = gl_GetMaterialfv; + table->GetMaterialiv = gl_GetMaterialiv; + table->GetPixelMapfv = gl_GetPixelMapfv; + table->GetPixelMapuiv = gl_GetPixelMapuiv; + table->GetPixelMapusv = gl_GetPixelMapusv; + table->GetPointerv = gl_GetPointerv; + table->GetPolygonStipple = gl_GetPolygonStipple; + table->GetTexEnvfv = gl_GetTexEnvfv; + table->GetTexEnviv = gl_GetTexEnviv; + table->GetTexGendv = gl_GetTexGendv; + table->GetTexGenfv = gl_GetTexGenfv; + table->GetTexGeniv = gl_GetTexGeniv; + table->GetTexImage = gl_GetTexImage; + table->GetTexLevelParameterfv = gl_GetTexLevelParameterfv; + table->GetTexLevelParameteriv = gl_GetTexLevelParameteriv; + table->GetTexParameterfv = gl_GetTexParameterfv; + table->GetTexParameteriv = gl_GetTexParameteriv; + + table->Hint = save_Hint; + table->IndexMask = save_IndexMask; + table->InitNames = save_InitNames; + table->IsEnabled = gl_IsEnabled; /* NOT SAVED */ + table->IsTexture = gl_IsTexture; /* NOT SAVED */ + table->IsList = gl_IsList; /* NOT SAVED */ + table->LightModelfv = save_LightModelfv; + table->Lightfv = save_Lightfv; + table->LineStipple = save_LineStipple; + table->LineWidth = save_LineWidth; + table->ListBase = save_ListBase; + table->LoadIdentity = save_LoadIdentity; + table->LoadMatrixf = save_LoadMatrixf; + table->LoadName = save_LoadName; + table->LogicOp = save_LogicOp; + table->Map1f = save_Map1f; + table->Map2f = save_Map2f; + table->MapGrid1f = save_MapGrid1f; + table->MapGrid2f = save_MapGrid2f; + table->MatrixMode = save_MatrixMode; + table->MultMatrixf = save_MultMatrixf; + table->NewList = save_NewList; + table->Ortho = save_Ortho; + table->PointParameterfvEXT = save_PointParameterfvEXT; + table->PassThrough = save_PassThrough; + table->PixelMapfv = save_PixelMapfv; + table->PixelStorei = gl_PixelStorei; /* NOT SAVED */ + table->PixelTransferf = save_PixelTransferf; + table->PixelZoom = save_PixelZoom; + table->PointSize = save_PointSize; + table->PolygonMode = save_PolygonMode; + table->PolygonOffset = save_PolygonOffset; + table->PolygonStipple = save_PolygonStipple; + table->PopAttrib = save_PopAttrib; + table->PopClientAttrib = gl_PopClientAttrib; /* NOT SAVED */ + table->PopMatrix = save_PopMatrix; + table->PopName = save_PopName; + table->PrioritizeTextures = save_PrioritizeTextures; + table->PushAttrib = save_PushAttrib; + table->PushClientAttrib = gl_PushClientAttrib; /* NOT SAVED */ + table->PushMatrix = save_PushMatrix; + table->PushName = save_PushName; + table->RasterPos4f = save_RasterPos4f; + table->ReadBuffer = save_ReadBuffer; + table->ReadPixels = gl_ReadPixels; /* NOT SAVED */ + table->Rectf = save_Rectf; + table->RenderMode = gl_RenderMode; /* NOT SAVED */ + table->Rotatef = save_Rotatef; + table->Scalef = save_Scalef; + table->Scissor = save_Scissor; + table->SelectBuffer = gl_SelectBuffer; /* NOT SAVED */ + table->ShadeModel = save_ShadeModel; + table->StencilFunc = save_StencilFunc; + table->StencilMask = save_StencilMask; + table->StencilOp = save_StencilOp; + table->TexEnvfv = save_TexEnvfv; + table->TexGenfv = save_TexGenfv; + table->TexImage1D = save_TexImage1D; + table->TexImage2D = save_TexImage2D; + table->TexImage3DEXT = save_TexImage3DEXT; + table->TexSubImage1D = save_TexSubImage1D; + table->TexSubImage2D = save_TexSubImage2D; + table->TexSubImage3DEXT = save_TexSubImage3DEXT; + table->TexParameterfv = save_TexParameterfv; + table->Translatef = save_Translatef; + table->Viewport = save_Viewport; + + /* GL_MESA_window_pos extension */ + table->WindowPos4fMESA = save_WindowPos4fMESA; + + /* GL_MESA_resize_buffers extension */ + table->ResizeBuffersMESA = gl_ResizeBuffersMESA; + + /* GL_ARB_multitexture */ + table->ActiveTexture = save_ActiveTexture; + table->ClientActiveTexture = save_ClientActiveTexture; +} + + + +/*** + *** Debugging code + ***/ +static const char *enum_string( GLenum k ) +{ + return gl_lookup_enum_by_nr( k ); +} + + +/* + * Print the commands in a display list. For debugging only. + * TODO: many commands aren't handled yet. + */ +static void print_list( GLcontext *ctx, FILE *f, GLuint list ) +{ + Node *n; + GLboolean done; + OpCode opcode; + + if (!glIsList(list)) { + fprintf(f,"%u is not a display list ID\n",list); + return; + } + + n = (Node *) HashLookup(ctx->Shared->DisplayList, list); + + fprintf( f, "START-LIST %u, address %p\n", list, (void*)n ); + + done = n ? GL_FALSE : GL_TRUE; + while (!done) { + opcode = n[0].opcode; + + switch (opcode) { + case OPCODE_ACCUM: + fprintf(f,"accum %s %g\n", enum_string(n[1].e), n[2].f ); + break; + case OPCODE_BITMAP: + fprintf(f,"Bitmap %d %d %g %g %g %g %p\n", n[1].i, n[2].i, + n[3].f, n[4].f, n[5].f, n[6].f, (void *) n[7].data ); + break; + case OPCODE_CALL_LIST: + fprintf(f,"CallList %d\n", (int) n[1].ui ); + break; + case OPCODE_CALL_LIST_OFFSET: + fprintf(f,"CallList %d + offset %u = %u\n", (int) n[1].ui, + ctx->List.ListBase, ctx->List.ListBase + n[1].ui ); + break; + case OPCODE_DISABLE: + fprintf(f,"Disable %s\n", enum_string(n[1].e)); + break; + case OPCODE_ENABLE: + fprintf(f,"Enable %s\n", enum_string(n[1].e)); + break; + case OPCODE_FRUSTUM: + fprintf(f,"Frustum %g %g %g %g %g %g\n", + n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f ); + break; + case OPCODE_LINE_STIPPLE: + fprintf(f,"LineStipple %d %x\n", n[1].i, (int) n[2].us ); + break; + case OPCODE_LOAD_IDENTITY: + fprintf(f,"LoadIdentity\n"); + break; + case OPCODE_LOAD_MATRIX: + fprintf(f,"LoadMatrix\n"); + fprintf(f," %8f %8f %8f %8f\n", n[1].f, n[5].f, n[9].f, n[13].f); + fprintf(f," %8f %8f %8f %8f\n", n[2].f, n[6].f, n[10].f, n[14].f); + fprintf(f," %8f %8f %8f %8f\n", n[3].f, n[7].f, n[11].f, n[15].f); + fprintf(f," %8f %8f %8f %8f\n", n[4].f, n[8].f, n[12].f, n[16].f); + break; + case OPCODE_MULT_MATRIX: + fprintf(f,"MultMatrix (or Rotate)\n"); + fprintf(f," %8f %8f %8f %8f\n", n[1].f, n[5].f, n[9].f, n[13].f); + fprintf(f," %8f %8f %8f %8f\n", n[2].f, n[6].f, n[10].f, n[14].f); + fprintf(f," %8f %8f %8f %8f\n", n[3].f, n[7].f, n[11].f, n[15].f); + fprintf(f," %8f %8f %8f %8f\n", n[4].f, n[8].f, n[12].f, n[16].f); + break; + case OPCODE_ORTHO: + fprintf(f,"Ortho %g %g %g %g %g %g\n", + n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f ); + break; + case OPCODE_POP_ATTRIB: + fprintf(f,"PopAttrib\n"); + break; + case OPCODE_POP_MATRIX: + fprintf(f,"PopMatrix\n"); + break; + case OPCODE_POP_NAME: + fprintf(f,"PopName\n"); + break; + case OPCODE_PUSH_ATTRIB: + fprintf(f,"PushAttrib %x\n", n[1].bf ); + break; + case OPCODE_PUSH_MATRIX: + fprintf(f,"PushMatrix\n"); + break; + case OPCODE_PUSH_NAME: + fprintf(f,"PushName %d\n", (int) n[1].ui ); + break; + case OPCODE_RASTER_POS: + fprintf(f,"RasterPos %g %g %g %g\n", n[1].f, n[2].f,n[3].f,n[4].f); + break; + case OPCODE_RECTF: + fprintf( f, "Rectf %g %g %g %g\n", n[1].f, n[2].f, n[3].f, n[4].f); + break; + case OPCODE_SCALE: + fprintf(f,"Scale %g %g %g\n", n[1].f, n[2].f, n[3].f ); + break; + case OPCODE_TRANSLATE: + fprintf(f,"Translate %g %g %g\n", n[1].f, n[2].f, n[3].f ); + break; + + /* + * meta opcodes/commands + */ + case OPCODE_ERROR: + fprintf(f,"Error: %s %s\n", enum_string(n[1].e), (const char *)n[2].data ); + break; + case OPCODE_VERTEX_CASSETTE: + fprintf(f,"VERTEX-CASSETTE, id %u, %u elements\n", + ((struct immediate *) n[1].data)->id, + ((struct immediate *) n[1].data)->Count - VB_START ); + break; + case OPCODE_CONTINUE: + fprintf(f,"DISPLAY-LIST-CONTINUE\n"); + n = (Node *) n[1].next; + break; + case OPCODE_END_OF_LIST: + fprintf(f,"END-LIST %u\n", list); + done = GL_TRUE; + break; + default: + if (opcode < 0 || opcode > OPCODE_END_OF_LIST) { + fprintf(f,"ERROR IN DISPLAY LIST: opcode = %d, address = %p\n", + opcode, (void*) n); + return; + } + else { + fprintf(f,"command %d, %u operands\n",opcode,InstSize[opcode]); + } + } + + /* increment n to point to next compiled command */ + if (opcode!=OPCODE_CONTINUE) { + n += InstSize[opcode]; + } + } +} + + + + + + + + +/* + * Clients may call this function to help debug display list problems. + * This function is _ONLY_FOR_DEBUGGING_PURPOSES_. It may be removed, + * changed, or break in the future without notice. + */ +void mesa_print_display_list( GLuint list ) +{ + GET_CONTEXT; + print_list( CC, stdout, list ); +} diff --git a/src/mesa/main/dlist.h b/src/mesa/main/dlist.h new file mode 100644 index 00000000000..c5a59181904 --- /dev/null +++ b/src/mesa/main/dlist.h @@ -0,0 +1,79 @@ +/* $Id: dlist.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 DLIST_H +#define DLIST_H + + +#include "types.h" + +struct display_list { + union node *nodes; + GLuint OrFlag; + struct gl_current_attrib outputs; +}; + +struct display_list_compilation { + struct display_list *list; + union node *current_block; + GLuint current_pos; +}; + + +extern void gl_init_lists( void ); + +extern void gl_destroy_list( GLcontext *ctx, GLuint list ); + +extern void gl_CallList( GLcontext *ctx, GLuint list ); + +extern void gl_CallLists( GLcontext *ctx, + GLsizei n, GLenum type, const GLvoid *lists ); + +extern void gl_DeleteLists( GLcontext *ctx, GLuint list, GLsizei range ); + +extern void gl_EndList( GLcontext *ctx ); + +extern GLuint gl_GenLists( GLcontext *ctx, GLsizei range ); + +extern GLboolean gl_IsList( GLcontext *ctx, GLuint list ); + +extern void gl_ListBase( GLcontext *ctx, GLuint base ); + +extern void gl_NewList( GLcontext *ctx, GLuint list, GLenum mode ); + +extern void gl_init_dlist_pointers( struct gl_api_table *table ); + + +extern void gl_compile_cassette( GLcontext *ctx ); + +extern void gl_save_error( GLcontext *ctx, GLenum error, const char *s ); + + +#endif diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c new file mode 100644 index 00000000000..a78f345a814 --- /dev/null +++ b/src/mesa/main/drawpix.c @@ -0,0 +1,946 @@ +/* $Id: drawpix.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include "context.h" +#include "drawpix.h" +#include "feedback.h" +#include "image.h" +#include "macros.h" +#include "mmath.h" +#include "pixel.h" +#include "span.h" +#include "stencil.h" +#include "types.h" +#include "zoom.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/* TODO: apply texture mapping to fragments */ + + +/* + * Try to do a fast glDrawPixels. Conditions include: + * not using a display list + * simple pixel unpacking + * no raster ops + * etc.... + * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead + */ +GLboolean gl_direct_DrawPixels( GLcontext *ctx, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GLubyte rgb[MAX_WIDTH][3]; + GLubyte rgba[MAX_WIDTH][4]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels", + GL_FALSE); + + + if (!ctx->Current.RasterPosValid) { + /* no-op */ + return GL_TRUE; + } + + if (ctx->NewState) { + gl_update_state(ctx); + } + + /* see if device driver can do the drawpix */ + if (ctx->Driver.DrawPixels) { + GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); + GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); + if ((*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type, + unpack, pixels)) + return GL_TRUE; + } + + if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0 + && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0 + && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0 + && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0 + && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0 + && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0 + && ctx->Pixel.MapColorFlag==0 + && unpack->Alignment==1 + && !unpack->SwapBytes + && !unpack->LsbFirst) { + + GLint destX = (GLint) (ctx->Current.RasterPos[0] + 0.5F); + GLint destY = (GLint) (ctx->Current.RasterPos[1] + 0.5F); + 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; + + 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 gl_write_zoomed_*_span() functions + * handle the clipping. + */ + if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { + /* horizontal clipping */ + if (destX < ctx->Buffer->Xmin) { + skipPixels += (ctx->Buffer->Xmin - destX); + drawWidth -= (ctx->Buffer->Xmin - destX); + destX = ctx->Buffer->Xmin; + } + if (destX + drawWidth > ctx->Buffer->Xmax) + drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1); + if (drawWidth <= 0) + return GL_TRUE; + + /* vertical clipping */ + if (destY < ctx->Buffer->Ymin) { + skipRows += (ctx->Buffer->Ymin - destY); + drawHeight -= (ctx->Buffer->Ymin - destY); + destY = ctx->Buffer->Ymin; + } + if (destY + drawHeight > ctx->Buffer->Ymax) + drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1); + 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] * DEPTH_SCALE); + GLint i; + assert(drawWidth < MAX_WIDTH); + for (i=0; i<drawWidth; i++) + zSpan[i] = z; + + /* save Y value of first row */ + zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F); + } + + + /* + * 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==GL_UNSIGNED_BYTE) { + if (ctx->Visual->RGBAflag) { + GLubyte *src = (GLubyte *) 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++) { + (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, + (void *) src, NULL); + src += rowLength * 4; + destY++; + } + } + else { + /* with zooming */ + GLint row; + for (row=0; row<drawHeight; row++) { + gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, + zSpan, (void *) src, zoomY0); + src += rowLength * 4; + destY++; + } + } + } + return GL_TRUE; + } + else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) { + if (ctx->Visual->RGBAflag) { + GLubyte *src = (GLubyte *) pixels + + (skipRows * rowLength + skipPixels) * 3; + if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { + GLint row; + for (row=0; row<drawHeight; row++) { + (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, + (void *) src, NULL); + src += rowLength * 3; + destY++; + } + } + else { + /* with zooming */ + GLint row; + for (row=0; row<drawHeight; row++) { + gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, + zSpan, (void *) src, zoomY0); + src += rowLength * 3; + destY++; + } + } + } + return GL_TRUE; + } + else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) { + if (ctx->Visual->RGBAflag) { + GLubyte *src = (GLubyte *) 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++) { + rgb[i][0] = src[i]; + rgb[i][1] = src[i]; + rgb[i][2] = src[i]; + } + (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, + (void *) rgb, NULL); + src += rowLength; + destY++; + } + } + else { + /* with zooming */ + GLint row; + assert(drawWidth < MAX_WIDTH); + for (row=0; row<drawHeight; row++) { + GLint i; + for (i=0;i<drawWidth;i++) { + rgb[i][0] = src[i]; + rgb[i][1] = src[i]; + rgb[i][2] = src[i]; + } + gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, + zSpan, (void *) rgb, zoomY0); + src += rowLength; + destY++; + } + } + } + return GL_TRUE; + } + else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) { + if (ctx->Visual->RGBAflag) { + GLubyte *src = (GLubyte *) 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; + GLubyte *ptr = src; + for (i=0;i<drawWidth;i++) { + rgba[i][0] = *ptr; + rgba[i][1] = *ptr; + rgba[i][2] = *ptr++; + rgba[i][3] = *ptr++; + } + (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, + (void *) rgba, NULL); + src += rowLength*2; + destY++; + } + } + else { + /* with zooming */ + GLint row; + assert(drawWidth < MAX_WIDTH); + for (row=0; row<drawHeight; row++) { + GLubyte *ptr = src; + GLint i; + for (i=0;i<drawWidth;i++) { + rgba[i][0] = *ptr; + rgba[i][1] = *ptr; + rgba[i][2] = *ptr++; + rgba[i][3] = *ptr++; + } + gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, + zSpan, (void *) 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->RGBAflag) { + /* 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); + gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba); + (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, + (const GLubyte (*)[4])rgba, + NULL); + src += rowLength; + destY++; + } + return GL_TRUE; + } + else { + /* with zooming */ + GLint row; + for (row=0; row<drawHeight; row++) { + assert(drawWidth < MAX_WIDTH); + gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba); + gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, + zSpan, (void *) rgba, zoomY0); + src += rowLength; + destY++; + } + return GL_TRUE; + } + } + else { + /* 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++) { + (*ctx->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; + } + } + else { + /* can't do direct render, have to use slow path */ + return GL_FALSE; + } +} + + + +/* + * Do glDrawPixels of index pixels. + */ +static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y, + const struct gl_image *image ) +{ + GLint width, height, widthInBytes; + const GLint desty = y; + GLint i, j; + GLdepth zspan[MAX_WIDTH]; + const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; + + assert(image); + assert(image->Format == GL_COLOR_INDEX); + + width = image->Width; + height = image->Height; + if (image->Type == GL_BITMAP) + widthInBytes = (width + 7) / 8; + else + widthInBytes = width; + + /* Fragment depth values */ + if (ctx->Depth.Test) { + GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); + for (i=0;i<width;i++) { + zspan[i] = zval; + } + } + + /* process the image row by row */ + for (i=0;i<height;i++,y++) { + GLuint ispan[MAX_WIDTH]; + + /* convert to uints */ + switch (image->Type) { + case GL_UNSIGNED_BYTE: + { + GLubyte *src = (GLubyte *) image->Data + i * width; + for (j=0;j<width;j++) { + ispan[j] = (GLuint) *src++; + } + } + break; + case GL_FLOAT: + { + GLfloat *src = (GLfloat *) image->Data + i * width; + for (j=0;j<width;j++) { + ispan[j] = (GLuint) (GLint) *src++; + } + } + break; + case GL_BITMAP: + { + GLubyte *src = (GLubyte *) image->Data + i * widthInBytes; + for (j=0;j<width;j++) { + ispan[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1; + } + } + break; + default: + gl_problem( ctx, "draw_index_pixels type" ); + return; + } + + /* apply shift and offset */ + if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) { + gl_shift_and_offset_ci( ctx, width, ispan ); + } + + if (ctx->Visual->RGBAflag) { + /* Convert index to RGBA and write to frame buffer */ + GLubyte rgba[MAX_WIDTH][4]; + gl_map_ci_to_rgba( ctx, width, ispan, rgba ); + if (zoom) { + gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, + (const GLubyte (*)[4])rgba, desty ); + } + else { + gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); + } + } + else { + /* optionally apply index map then write to frame buffer */ + if (ctx->Pixel.MapColorFlag) { + gl_map_ci(ctx, width, ispan); + } + if (zoom) { + gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty ); + } + else { + gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP ); + } + } + } + +} + + + +/* + * 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, + const struct gl_image *image ) +{ + GLint widthInBytes, width, height; + const GLint desty = y; + GLint i; + const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; + + assert(image); + assert(image->Format == GL_STENCIL_INDEX); + assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP); + + if (image->Type == GL_UNSIGNED_BYTE) + widthInBytes = image->Width; + else + widthInBytes = (image->Width + 7) / 8; + width = image->Width; + height = image->Height; + + /* process the image row by row */ + for (i=0;i<height;i++,y++) { + GLstencil *src = (GLstencil*)image->Data + i * widthInBytes; + GLstencil *stencilValues; + GLstencil stencilCopy[MAX_WIDTH]; + + if (image->Type == GL_BITMAP) { + /* convert bitmap data to GLubyte (0 or 1) data */ + GLint j; + for (j = 0; j < width; j++) { + stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1; + } + src = stencilCopy; + } + + if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift + || ctx->Pixel.MapStencilFlag) { + + /* make copy of stencil values */ + if (src != stencilCopy) + MEMCPY( stencilCopy, src, width * sizeof(GLstencil)); + + /* apply shift and offset */ + if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) { + gl_shift_and_offset_stencil( ctx, width, stencilCopy ); + } + + /* mapping */ + if (ctx->Pixel.MapStencilFlag) { + gl_map_stencil( ctx, width, stencilCopy ); + } + + stencilValues = stencilCopy; + } + else { + /* use stencil values in-place */ + stencilValues = src; + } + + /* write stencil values to stencil buffer */ + if (zoom) { + gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y, + stencilValues, desty ); + } + else { + gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues ); + } + } +} + + + +/* + * Do a glDrawPixels of depth values. + */ +static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, + const struct gl_image *image ) +{ + GLint width, height; + const GLint desty = y; + GLubyte rgba[MAX_WIDTH][4]; + GLuint ispan[MAX_WIDTH]; + 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; + + assert(image); + assert(image->Format == GL_DEPTH_COMPONENT); + + width = image->Width; + height = image->Height; + + /* Color or index */ + if (ctx->Visual->RGBAflag) { + GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F); + GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F); + GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F); + GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F); + GLint i; + for (i=0; i<width; i++) { + rgba[i][RCOMP] = r; + rgba[i][GCOMP] = g; + rgba[i][BCOMP] = b; + rgba[i][ACOMP] = a; + } + } + else { + GLint i; + for (i=0;i<width;i++) { + ispan[i] = ctx->Current.RasterIndex; + } + } + + if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort) + && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { + /* Special case: directly write 16-bit depth values */ + GLint j; + for (j=0;j<height;j++,y++) { + GLdepth *zptr = (GLdepth *) image->Data + j * width; + gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP ); + } + } + else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint) + && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) { + /* Special case: directly write 32-bit depth values */ + GLint i, j; + /* Compute shift value to scale 32-bit uints down to depth values. */ + GLuint shift = 0; + GLuint max = MAX_DEPTH; + while ((max&0x80000000)==0) { + max = max << 1; + shift++; + } + for (j=0;j<height;j++,y++) { + GLdepth zspan[MAX_WIDTH]; + GLuint *zptr = (GLuint *) image->Data + j * width; + for (i=0;i<width;i++) { + zspan[i] = zptr[i] >> shift; + } + gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); + } + } + else { + /* General case (slower) */ + GLint i, j; + + /* process image row by row */ + for (i=0;i<height;i++,y++) { + GLfloat depth[MAX_WIDTH]; + GLdepth zspan[MAX_WIDTH]; + + switch (image->Type) { + case GL_UNSIGNED_SHORT: + { + GLushort *src = (GLushort *) image->Data + i * width; + for (j=0;j<width;j++) { + depth[j] = USHORT_TO_FLOAT( *src++ ); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *src = (GLuint *) image->Data + i * width; + for (j=0;j<width;j++) { + depth[j] = UINT_TO_FLOAT( *src++ ); + } + } + break; + case GL_FLOAT: + { + GLfloat *src = (GLfloat *) image->Data + i * width; + for (j=0;j<width;j++) { + depth[j] = *src++; + } + } + break; + default: + gl_problem(ctx, "Bad type in draw_depth_pixels"); + return; + } + + /* apply depth scale and bias */ + if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) { + for (j=0;j<width;j++) { + depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; + } + } + + /* clamp depth values to [0,1] and convert from floats to integers */ + for (j=0;j<width;j++) { + zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE); + } + + if (ctx->Visual->RGBAflag) { + if (zoom) { + gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, + (const GLubyte (*)[4])rgba, desty ); + } + else { + gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP ); + } + } + else { + if (zoom) { + gl_write_zoomed_index_span( ctx, width, x, y, zspan, + ispan, GL_BITMAP ); + } + else { + gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP ); + } + } + + } + } +} + + + +/* Simple unpacking parameters: */ +static struct gl_pixelstore_attrib NoUnpack = { + 1, /* Alignment */ + 0, /* RowLength */ + 0, /* SkipPixels */ + 0, /* SkipRows */ + 0, /* ImageHeight */ + 0, /* SkipImages */ + GL_FALSE, /* SwapBytes */ + GL_FALSE /* LsbFirst */ +}; + + +/* + * Do glDrawPixels of RGBA pixels. + */ +static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, + const struct gl_image *image ) +{ + GLint width, height; + GLint i, j; + const GLint desty = y; + GLdepth zspan[MAX_WIDTH]; + GLboolean quickDraw; + const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; + + assert(image); + + /* Try an optimized glDrawPixels first */ + if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height, + image->Format, image->Type, image->Data )) + return; + + width = image->Width; + height = image->Height; + + /* Fragment depth values */ + if (ctx->Depth.Test) { + /* fill in array of z values */ + GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE); + for (i=0;i<width;i++) { + zspan[i] = z; + } + } + + if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0 + && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) { + quickDraw = GL_TRUE; + } + else { + quickDraw = GL_FALSE; + } + + { + /* General solution */ + GLboolean r_flag, g_flag, b_flag, a_flag, l_flag; + GLuint components; + GLubyte rgba[MAX_WIDTH][4]; + GLfloat rf[MAX_WIDTH]; + GLfloat gf[MAX_WIDTH]; + GLfloat bf[MAX_WIDTH]; + DEFARRAY(GLfloat,af,MAX_WIDTH); + CHECKARRAY(af,return); + + r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE; + switch (image->Format) { + case GL_RED: + r_flag = GL_TRUE; + components = 1; + break; + case GL_GREEN: + g_flag = GL_TRUE; + components = 1; + break; + case GL_BLUE: + b_flag = GL_TRUE; + components = 1; + break; + case GL_ALPHA: + a_flag = GL_TRUE; + components = 1; + break; + case GL_RGB: + r_flag = g_flag = b_flag = GL_TRUE; + components = 3; + break; + case GL_LUMINANCE: + l_flag = GL_TRUE; + components = 1; + break; + case GL_LUMINANCE_ALPHA: + l_flag = a_flag = GL_TRUE; + components = 2; + break; + case GL_RGBA: + r_flag = g_flag = b_flag = a_flag = GL_TRUE; + components = 4; + break; + default: + gl_problem(ctx, "Bad type in draw_rgba_pixels"); + goto cleanup; + } + + /* process the image row by row */ + for (i=0;i<height;i++,y++) { + /* convert to floats */ + switch (image->Type) { + case GL_UNSIGNED_BYTE: + { + GLubyte *src = (GLubyte *) image->Data + i * width * components; + for (j=0;j<width;j++) { + if (l_flag) { + rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++); + } + else { + rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; + gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; + bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0; + } + af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0; + } + } + break; + case GL_FLOAT: + { + GLfloat *src = (GLfloat *) image->Data + i * width * components; + for (j=0;j<width;j++) { + if (l_flag) { + rf[j] = gf[j] = bf[j] = *src++; + } + else { + rf[j] = r_flag ? *src++ : 0.0; + gf[j] = g_flag ? *src++ : 0.0; + bf[j] = b_flag ? *src++ : 0.0; + } + af[j] = a_flag ? *src++ : 1.0; + } + } + break; + default: + gl_problem( ctx, "draw_rgba_pixels type" ); + goto cleanup; + } + + /* apply scale and bias */ + if (ctx->Pixel.ScaleOrBiasRGBA) { + gl_scale_and_bias_color(ctx, width, rf, gf, bf, af); + } + + /* apply pixel mappings */ + if (ctx->Pixel.MapColorFlag) { + gl_map_color(ctx, width, rf, gf, bf, af); + } + + /* convert to integers */ + for (j=0;j<width;j++) { + rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F); + rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F); + rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F); + rgba[j][ACOMP] = (GLint) (af[j] * 255.0F); + } + + /* write to frame buffer */ + if (quickDraw) { + (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, + (const GLubyte (*)[4])rgba, NULL); + } + else if (zoom) { + gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, + (const GLubyte (*)[4])rgba, desty ); + } + else { + gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP); + } + } +cleanup: + UNDEFARRAY(af); + } +} + + + +/* + * Execute glDrawPixels + */ +void gl_DrawPixels( GLcontext* ctx, struct gl_image *image ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels"); + + + if (gl_image_error_test( ctx, image, "glDrawPixels" )) + return; + + if (ctx->RenderMode==GL_RENDER) { + GLint x, y; + if (!ctx->Current.RasterPosValid) { + return; + } + + x = (GLint) (ctx->Current.RasterPos[0] + 0.5F); + y = (GLint) (ctx->Current.RasterPos[1] + 0.5F); + + switch (image->Format) { + case GL_COLOR_INDEX: + draw_index_pixels( ctx, x, y, image ); + break; + case GL_STENCIL_INDEX: + draw_stencil_pixels( ctx, x, y, image ); + break; + case GL_DEPTH_COMPONENT: + draw_depth_pixels( ctx, x, y, image ); + break; + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_RGB: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + draw_rgba_pixels( ctx, x, y, image ); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" ); + return; + } + } + else if (ctx->RenderMode==GL_FEEDBACK) { + if (ctx->Current.RasterPosValid) { + GLfloat color[4]; + GLfloat texcoord[4], invq; + UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor); + invq = 1.0F / ctx->Current.Texcoord[0][3]; + texcoord[0] = ctx->Current.Texcoord[0][0] * invq; + texcoord[1] = ctx->Current.Texcoord[0][1] * invq; + texcoord[2] = ctx->Current.Texcoord[0][2] * invq; + texcoord[3] = ctx->Current.Texcoord[0][3]; + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); + gl_feedback_vertex( ctx, + ctx->Current.RasterPos[0], + ctx->Current.RasterPos[1], + ctx->Current.RasterPos[2], + ctx->Current.RasterPos[3], + color, ctx->Current.Index, texcoord ); + } + } + else if (ctx->RenderMode==GL_SELECT) { + if (ctx->Current.RasterPosValid) { + gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); + } + } +} + diff --git a/src/mesa/main/drawpix.h b/src/mesa/main/drawpix.h new file mode 100644 index 00000000000..cb517ced03b --- /dev/null +++ b/src/mesa/main/drawpix.h @@ -0,0 +1,54 @@ +/* $Id: drawpix.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 DRAWPIXELS_H +#define DRAWPIXELS_H + + +#include "types.h" + + +extern GLboolean +gl_direct_DrawPixels( GLcontext *ctx, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels ); + + +#if 000 +extern void gl_DrawPixels( GLcontext *ctx, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels ); +#endif + + +extern void gl_DrawPixels( GLcontext *ctx, struct gl_image *image ); + + +#endif diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c new file mode 100644 index 00000000000..7f661fb75f0 --- /dev/null +++ b/src/mesa/main/enable.c @@ -0,0 +1,699 @@ +/* $Id: enable.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <string.h> +#include <stdio.h> +#include "context.h" +#include "enable.h" +#include "light.h" +#include "macros.h" +#include "matrix.h" +#include "mmath.h" +#include "simple_list.h" +#include "types.h" +#include "vbfill.h" +#include "xform.h" +#include "enums.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/* + * Perform glEnable and glDisable calls. + */ +void gl_set_enable( GLcontext *ctx, GLenum cap, GLboolean state ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "gl_enable/disable" ); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "%s %s (%x)\n", + state ? "glEnable" : "glDisable", + gl_lookup_enum_by_nr(cap), + ctx->NewState); + + switch (cap) { + case GL_ALPHA_TEST: + if (ctx->Color.AlphaEnabled!=state) { + ctx->Color.AlphaEnabled = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_AUTO_NORMAL: + ctx->Eval.AutoNormal = state; + break; + case GL_BLEND: + if (ctx->Color.BlendEnabled!=state) { + ctx->Color.BlendEnabled = state; + /* The following needed to accomodate 1.0 RGB logic op blending */ + if (ctx->Color.BlendEquation==GL_LOGIC_OP && state) { + ctx->Color.ColorLogicOpEnabled = GL_TRUE; + } + else { + ctx->Color.ColorLogicOpEnabled = GL_FALSE; + } + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + if (cap >= GL_CLIP_PLANE0 && + cap <= GL_CLIP_PLANE5 && + ctx->Transform.ClipEnabled[cap-GL_CLIP_PLANE0] != state) + { + GLuint p = cap-GL_CLIP_PLANE0; + + ctx->Transform.ClipEnabled[p] = state; + ctx->NewState |= NEW_USER_CLIP; + + if (state) { + ctx->Enabled |= ENABLE_USERCLIP; + ctx->Transform.AnyClip++; + + if (ctx->ProjectionMatrix.flags & MAT_DIRTY_ALL_OVER) { + gl_matrix_analyze( &ctx->ProjectionMatrix ); + } + + gl_transform_vector( ctx->Transform.ClipUserPlane[p], + ctx->Transform.EyeUserPlane[p], + ctx->ProjectionMatrix.inv ); + } else { + if (--ctx->Transform.AnyClip == 0) + ctx->Enabled &= ~ENABLE_USERCLIP; + } + } + break; + case GL_COLOR_MATERIAL: + if (ctx->Light.ColorMaterialEnabled!=state) { + ctx->Light.ColorMaterialEnabled = state; + ctx->NewState |= NEW_LIGHTING; + } + break; + case GL_CULL_FACE: + if (ctx->Polygon.CullFlag!=state) { + ctx->Polygon.CullFlag = state; + ctx->TriangleCaps ^= DD_TRI_CULL; + ctx->NewState |= NEW_POLYGON; + } + break; + case GL_DEPTH_TEST: + if (state && ctx->Visual->DepthBits==0) { + gl_warning(ctx,"glEnable(GL_DEPTH_TEST) but no depth buffer"); + return; + } + if (ctx->Depth.Test!=state) { + ctx->Depth.Test = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_DITHER: + if (ctx->NoDither) { + /* MESA_NO_DITHER env var */ + state = GL_FALSE; + } + if (ctx->Color.DitherFlag!=state) { + ctx->Color.DitherFlag = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_FOG: + if (ctx->Fog.Enabled!=state) { + ctx->Fog.Enabled = state; + ctx->Enabled ^= ENABLE_FOG; + ctx->NewState |= NEW_FOG; + } + break; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + if (ctx->Light.Light[cap-GL_LIGHT0].Enabled != state) + { + ctx->Light.Light[cap-GL_LIGHT0].Enabled = state; + + if (state) { + insert_at_tail(&ctx->Light.EnabledList, + &ctx->Light.Light[cap-GL_LIGHT0]); + if (ctx->Light.Enabled) + ctx->Enabled |= ENABLE_LIGHT; + } else { + remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]); + if (is_empty_list(&ctx->Light.EnabledList)) + ctx->Enabled &= ~ENABLE_LIGHT; + } + + ctx->NewState |= NEW_LIGHTING; + } + break; + case GL_LIGHTING: + if (ctx->Light.Enabled!=state) { + ctx->Light.Enabled = state; + ctx->Enabled &= ~ENABLE_LIGHT; + if (state && !is_empty_list(&ctx->Light.EnabledList)) + ctx->Enabled |= ENABLE_LIGHT; + ctx->NewState |= NEW_LIGHTING; + } + break; + case GL_LINE_SMOOTH: + if (ctx->Line.SmoothFlag!=state) { + ctx->Line.SmoothFlag = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_LINE_STIPPLE: + if (ctx->Line.StippleFlag!=state) { + ctx->Line.StippleFlag = state; + ctx->TriangleCaps ^= DD_LINE_STIPPLE; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_INDEX_LOGIC_OP: + if (ctx->Color.IndexLogicOpEnabled!=state) { + ctx->Color.IndexLogicOpEnabled = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_COLOR_LOGIC_OP: + if (ctx->Color.ColorLogicOpEnabled!=state) { + ctx->Color.ColorLogicOpEnabled = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_MAP1_COLOR_4: + ctx->Eval.Map1Color4 = state; + break; + case GL_MAP1_INDEX: + ctx->Eval.Map1Index = state; + break; + case GL_MAP1_NORMAL: + ctx->Eval.Map1Normal = state; + break; + case GL_MAP1_TEXTURE_COORD_1: + ctx->Eval.Map1TextureCoord1 = state; + break; + case GL_MAP1_TEXTURE_COORD_2: + ctx->Eval.Map1TextureCoord2 = state; + break; + case GL_MAP1_TEXTURE_COORD_3: + ctx->Eval.Map1TextureCoord3 = state; + break; + case GL_MAP1_TEXTURE_COORD_4: + ctx->Eval.Map1TextureCoord4 = state; + break; + case GL_MAP1_VERTEX_3: + ctx->Eval.Map1Vertex3 = state; + break; + case GL_MAP1_VERTEX_4: + ctx->Eval.Map1Vertex4 = state; + break; + case GL_MAP2_COLOR_4: + ctx->Eval.Map2Color4 = state; + break; + case GL_MAP2_INDEX: + ctx->Eval.Map2Index = state; + break; + case GL_MAP2_NORMAL: + ctx->Eval.Map2Normal = state; + break; + case GL_MAP2_TEXTURE_COORD_1: + ctx->Eval.Map2TextureCoord1 = state; + break; + case GL_MAP2_TEXTURE_COORD_2: + ctx->Eval.Map2TextureCoord2 = state; + break; + case GL_MAP2_TEXTURE_COORD_3: + ctx->Eval.Map2TextureCoord3 = state; + break; + case GL_MAP2_TEXTURE_COORD_4: + ctx->Eval.Map2TextureCoord4 = state; + break; + case GL_MAP2_VERTEX_3: + ctx->Eval.Map2Vertex3 = state; + break; + case GL_MAP2_VERTEX_4: + ctx->Eval.Map2Vertex4 = state; + break; + case GL_NORMALIZE: + if (ctx->Transform.Normalize != state) { + ctx->Transform.Normalize = state; + ctx->NewState |= NEW_NORMAL_TRANSFORM|NEW_LIGHTING; + ctx->Enabled ^= ENABLE_NORMALIZE; + } + break; + case GL_POINT_SMOOTH: + if (ctx->Point.SmoothFlag!=state) { + ctx->Point.SmoothFlag = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_POLYGON_SMOOTH: + if (ctx->Polygon.SmoothFlag!=state) { + ctx->Polygon.SmoothFlag = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_POLYGON_STIPPLE: + if (ctx->Polygon.StippleFlag!=state) { + ctx->Polygon.StippleFlag = state; + ctx->TriangleCaps ^= DD_TRI_STIPPLE; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_POLYGON_OFFSET_POINT: + if (ctx->Polygon.OffsetPoint!=state) { + ctx->Polygon.OffsetPoint = state; + ctx->NewState |= NEW_POLYGON; + } + break; + case GL_POLYGON_OFFSET_LINE: + if (ctx->Polygon.OffsetLine!=state) { + ctx->Polygon.OffsetLine = state; + ctx->NewState |= NEW_POLYGON; + } + break; + case GL_POLYGON_OFFSET_FILL: + /*case GL_POLYGON_OFFSET_EXT:*/ + if (ctx->Polygon.OffsetFill!=state) { + ctx->Polygon.OffsetFill = state; + ctx->NewState |= NEW_POLYGON; + } + break; + case GL_RESCALE_NORMAL_EXT: + if (ctx->Transform.RescaleNormals != state) { + ctx->Transform.RescaleNormals = state; + ctx->NewState |= NEW_NORMAL_TRANSFORM|NEW_LIGHTING; + ctx->Enabled ^= ENABLE_RESCALE; + } + break; + case GL_SCISSOR_TEST: + if (ctx->Scissor.Enabled!=state) { + ctx->Scissor.Enabled = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + ctx->Texture.SharedPalette = state; + if (ctx->Driver.UseGlobalTexturePalette) + (*ctx->Driver.UseGlobalTexturePalette)( ctx, state ); + break; + case GL_STENCIL_TEST: + if (state && ctx->Visual->StencilBits==0) { + gl_warning(ctx, "glEnable(GL_STENCIL_TEST) but no stencil buffer"); + return; + } + if (ctx->Stencil.Enabled!=state) { + ctx->Stencil.Enabled = state; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + case GL_TEXTURE_1D: + if (ctx->Visual->RGBAflag) { + const GLuint curr = ctx->Texture.CurrentUnit; + const GLuint flag = TEXTURE0_1D << (curr * 4); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + ctx->NewState |= NEW_TEXTURE_ENABLE; + if (state) { + texUnit->Enabled |= TEXTURE0_1D; + ctx->Enabled |= flag; + } + else { + texUnit->Enabled &= ~TEXTURE0_1D; + ctx->Enabled &= ~flag; + } + } + break; + case GL_TEXTURE_2D: + if (ctx->Visual->RGBAflag) { + const GLuint curr = ctx->Texture.CurrentUnit; + const GLuint flag = TEXTURE0_2D << (curr * 4); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + ctx->NewState |= NEW_TEXTURE_ENABLE; + if (state) { + texUnit->Enabled |= TEXTURE0_2D; + ctx->Enabled |= flag; + } + else { + texUnit->Enabled &= ~TEXTURE0_2D; + ctx->Enabled &= ~flag; + } + } + break; + case GL_TEXTURE_3D: + if (ctx->Visual->RGBAflag) { + const GLuint curr = ctx->Texture.CurrentUnit; + const GLuint flag = TEXTURE0_3D << (curr * 4); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + ctx->NewState |= NEW_TEXTURE_ENABLE; + if (state) { + texUnit->Enabled |= TEXTURE0_3D; + ctx->Enabled |= flag; + } + else { + texUnit->Enabled &= ~TEXTURE0_3D; + ctx->Enabled &= ~flag; + } + } + break; + case GL_TEXTURE_GEN_Q: + { + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (state) + texUnit->TexGenEnabled |= Q_BIT; + else + texUnit->TexGenEnabled &= ~Q_BIT; + ctx->NewState |= NEW_TEXTURING; + } + break; + case GL_TEXTURE_GEN_R: + { + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (state) + texUnit->TexGenEnabled |= R_BIT; + else + texUnit->TexGenEnabled &= ~R_BIT; + ctx->NewState |= NEW_TEXTURING; + } + break; + case GL_TEXTURE_GEN_S: + { + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (state) + texUnit->TexGenEnabled |= S_BIT; + else + texUnit->TexGenEnabled &= ~S_BIT; + ctx->NewState |= NEW_TEXTURING; + } + break; + case GL_TEXTURE_GEN_T: + { + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (state) + texUnit->TexGenEnabled |= T_BIT; + else + texUnit->TexGenEnabled &= ~T_BIT; + ctx->NewState |= NEW_TEXTURING; + } + break; + + /* + * CLIENT STATE!!! + */ + case GL_VERTEX_ARRAY: + ctx->Array.Vertex.Enabled = state; + break; + case GL_NORMAL_ARRAY: + ctx->Array.Normal.Enabled = state; + break; + case GL_COLOR_ARRAY: + ctx->Array.Color.Enabled = state; + break; + case GL_INDEX_ARRAY: + ctx->Array.Index.Enabled = state; + break; + case GL_TEXTURE_COORD_ARRAY: + ctx->Array.TexCoord[ctx->TexCoordUnit].Enabled = state; + break; + case GL_EDGE_FLAG_ARRAY: + ctx->Array.EdgeFlag.Enabled = state; + break; + + default: + if (state) { + gl_error( ctx, GL_INVALID_ENUM, "glEnable" ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glDisable" ); + } + return; + } + + if (ctx->Driver.Enable) { + (*ctx->Driver.Enable)( ctx, cap, state ); + } +} + + + + +void gl_Enable( GLcontext* ctx, GLenum cap ) +{ + gl_set_enable( ctx, cap, GL_TRUE ); +} + + + +void gl_Disable( GLcontext* ctx, GLenum cap ) +{ + gl_set_enable( ctx, cap, GL_FALSE ); +} + + + +GLboolean gl_IsEnabled( GLcontext* ctx, GLenum cap ) +{ + switch (cap) { + case GL_ALPHA_TEST: + return ctx->Color.AlphaEnabled; + case GL_AUTO_NORMAL: + return ctx->Eval.AutoNormal; + case GL_BLEND: + return ctx->Color.BlendEnabled; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + return ctx->Transform.ClipEnabled[cap-GL_CLIP_PLANE0]; + case GL_COLOR_MATERIAL: + return ctx->Light.ColorMaterialEnabled; + case GL_CULL_FACE: + return ctx->Polygon.CullFlag; + case GL_DEPTH_TEST: + return ctx->Depth.Test; + case GL_DITHER: + return ctx->Color.DitherFlag; + case GL_FOG: + return ctx->Fog.Enabled; + case GL_LIGHTING: + return ctx->Light.Enabled; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + return ctx->Light.Light[cap-GL_LIGHT0].Enabled; + case GL_LINE_SMOOTH: + return ctx->Line.SmoothFlag; + case GL_LINE_STIPPLE: + return ctx->Line.StippleFlag; + case GL_INDEX_LOGIC_OP: + return ctx->Color.IndexLogicOpEnabled; + case GL_COLOR_LOGIC_OP: + return ctx->Color.ColorLogicOpEnabled; + case GL_MAP1_COLOR_4: + return ctx->Eval.Map1Color4; + case GL_MAP1_INDEX: + return ctx->Eval.Map1Index; + case GL_MAP1_NORMAL: + return ctx->Eval.Map1Normal; + case GL_MAP1_TEXTURE_COORD_1: + return ctx->Eval.Map1TextureCoord1; + case GL_MAP1_TEXTURE_COORD_2: + return ctx->Eval.Map1TextureCoord2; + case GL_MAP1_TEXTURE_COORD_3: + return ctx->Eval.Map1TextureCoord3; + case GL_MAP1_TEXTURE_COORD_4: + return ctx->Eval.Map1TextureCoord4; + case GL_MAP1_VERTEX_3: + return ctx->Eval.Map1Vertex3; + case GL_MAP1_VERTEX_4: + return ctx->Eval.Map1Vertex4; + case GL_MAP2_COLOR_4: + return ctx->Eval.Map2Color4; + case GL_MAP2_INDEX: + return ctx->Eval.Map2Index; + case GL_MAP2_NORMAL: + return ctx->Eval.Map2Normal; + case GL_MAP2_TEXTURE_COORD_1: + return ctx->Eval.Map2TextureCoord1; + case GL_MAP2_TEXTURE_COORD_2: + return ctx->Eval.Map2TextureCoord2; + case GL_MAP2_TEXTURE_COORD_3: + return ctx->Eval.Map2TextureCoord3; + case GL_MAP2_TEXTURE_COORD_4: + return ctx->Eval.Map2TextureCoord4; + case GL_MAP2_VERTEX_3: + return ctx->Eval.Map2Vertex3; + case GL_MAP2_VERTEX_4: + return ctx->Eval.Map2Vertex4; + case GL_NORMALIZE: + return ctx->Transform.Normalize; + case GL_POINT_SMOOTH: + return ctx->Point.SmoothFlag; + case GL_POLYGON_SMOOTH: + return ctx->Polygon.SmoothFlag; + case GL_POLYGON_STIPPLE: + return ctx->Polygon.StippleFlag; + case GL_POLYGON_OFFSET_POINT: + return ctx->Polygon.OffsetPoint; + case GL_POLYGON_OFFSET_LINE: + return ctx->Polygon.OffsetLine; + case GL_POLYGON_OFFSET_FILL: + /*case GL_POLYGON_OFFSET_EXT:*/ + return ctx->Polygon.OffsetFill; + case GL_RESCALE_NORMAL_EXT: + return ctx->Transform.RescaleNormals; + case GL_SCISSOR_TEST: + return ctx->Scissor.Enabled; + case GL_SHARED_TEXTURE_PALETTE_EXT: + return ctx->Texture.SharedPalette; + case GL_STENCIL_TEST: + return ctx->Stencil.Enabled; + case GL_TEXTURE_1D: + { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE0_1D) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_2D: + { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE0_2D) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_3D: + { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE0_2D) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_Q: + { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_R: + { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_S: + { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_T: + { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE; + } + + /* + * CLIENT STATE!!! + */ + case GL_VERTEX_ARRAY: + return ctx->Array.Vertex.Enabled; + case GL_NORMAL_ARRAY: + return ctx->Array.Normal.Enabled; + case GL_COLOR_ARRAY: + return ctx->Array.Color.Enabled; + case GL_INDEX_ARRAY: + return ctx->Array.Index.Enabled; + case GL_TEXTURE_COORD_ARRAY: + return ctx->Array.TexCoord[ctx->TexCoordUnit].Enabled; + case GL_EDGE_FLAG_ARRAY: + return ctx->Array.EdgeFlag.Enabled; + default: + gl_error( ctx, GL_INVALID_ENUM, "glIsEnabled" ); + return GL_FALSE; + } +} + + + + +static void gl_client_state( GLcontext *ctx, GLenum cap, GLboolean state ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, + (state + ? "glEnableClientState" + : "glDisableClientState") ); + + switch (cap) { + case GL_VERTEX_ARRAY: + ctx->Array.Vertex.Enabled = state; + break; + case GL_NORMAL_ARRAY: + ctx->Array.Normal.Enabled = state; + break; + case GL_COLOR_ARRAY: + ctx->Array.Color.Enabled = state; + break; + case GL_INDEX_ARRAY: + ctx->Array.Index.Enabled = state; + break; + case GL_TEXTURE_COORD_ARRAY: + ctx->Array.TexCoord[ctx->TexCoordUnit].Enabled = state; + break; + case GL_EDGE_FLAG_ARRAY: + ctx->Array.EdgeFlag.Enabled = state; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glEnable/DisableClientState" ); + } + + ctx->NewState |= NEW_CLIENT_STATE; +} + + + +void gl_EnableClientState( GLcontext *ctx, GLenum cap ) +{ + gl_client_state( ctx, cap, GL_TRUE ); +} + + + +void gl_DisableClientState( GLcontext *ctx, GLenum cap ) +{ + gl_client_state( ctx, cap, GL_FALSE ); +} + diff --git a/src/mesa/main/enable.h b/src/mesa/main/enable.h new file mode 100644 index 00000000000..92a916a9849 --- /dev/null +++ b/src/mesa/main/enable.h @@ -0,0 +1,51 @@ +/* $Id: enable.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 ENABLE_H +#define ENABLE_H + + +#include "types.h" + + +extern void gl_set_enable( GLcontext* ctx, GLenum cap, GLboolean state ); + +extern void gl_Disable( GLcontext* ctx, GLenum cap ); + +extern void gl_Enable( GLcontext* ctx, GLenum cap ); + +extern GLboolean gl_IsEnabled( GLcontext* ctx, GLenum cap ); + +extern void gl_EnableClientState( GLcontext *ctx, GLenum cap ); + +extern void gl_DisableClientState( GLcontext *ctx, GLenum cap ); + + +#endif diff --git a/src/mesa/main/enums.c b/src/mesa/main/enums.c new file mode 100644 index 00000000000..69b520ef403 --- /dev/null +++ b/src/mesa/main/enums.c @@ -0,0 +1,893 @@ +/* $Id: enums.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 "GL/gl.h" +#include "enums.h" +#include <stdlib.h> +#include <string.h> + + +typedef struct { + const char *c; + int n; +} enum_elt; + +enum_elt all_enums[] = +{ + /* Boolean values */ + { "GL_FALSE", 0 }, + { "GL_TRUE", 1 }, + + /* Data types */ + { "GL_BYTE", 0x1400 }, + { "GL_UNSIGNED_BYTE", 0x1401 }, + { "GL_SHORT", 0x1402 }, + { "GL_UNSIGNED_SHORT", 0x1403 }, + { "GL_INT", 0x1404 }, + { "GL_UNSIGNED_INT", 0x1405 }, + { "GL_FLOAT", 0x1406 }, + { "GL_DOUBLE", 0x140A }, + { "GL_2_BYTES", 0x1407 }, + { "GL_3_BYTES", 0x1408 }, + { "GL_4_BYTES", 0x1409 }, + + /* Primitives */ + { "GL_LINES", 0x0001 }, + { "GL_POINTS", 0x0000 }, + { "GL_LINE_STRIP", 0x0003 }, + { "GL_LINE_LOOP", 0x0002 }, + { "GL_TRIANGLES", 0x0004 }, + { "GL_TRIANGLE_STRIP", 0x0005 }, + { "GL_TRIANGLE_FAN", 0x0006 }, + { "GL_QUADS", 0x0007 }, + { "GL_QUAD_STRIP", 0x0008 }, + { "GL_POLYGON", 0x0009 }, + { "GL_EDGE_FLAG", 0x0B43 }, + + /* Vertex Arrays */ + { "GL_VERTEX_ARRAY", 0x8074 }, + { "GL_NORMAL_ARRAY", 0x8075 }, + { "GL_COLOR_ARRAY", 0x8076 }, + { "GL_INDEX_ARRAY", 0x8077 }, + { "GL_TEXTURE_COORD_ARRAY", 0x8078 }, + { "GL_EDGE_FLAG_ARRAY", 0x8079 }, + { "GL_VERTEX_ARRAY_SIZE", 0x807A }, + { "GL_VERTEX_ARRAY_TYPE", 0x807B }, + { "GL_VERTEX_ARRAY_STRIDE", 0x807C }, + { "GL_NORMAL_ARRAY_TYPE", 0x807E }, + { "GL_NORMAL_ARRAY_STRIDE", 0x807F }, + { "GL_COLOR_ARRAY_SIZE", 0x8081 }, + { "GL_COLOR_ARRAY_TYPE", 0x8082 }, + { "GL_COLOR_ARRAY_STRIDE", 0x8083 }, + { "GL_INDEX_ARRAY_TYPE", 0x8085 }, + { "GL_INDEX_ARRAY_STRIDE", 0x8086 }, + { "GL_TEXTURE_COORD_ARRAY_SIZE", 0x8088 }, + { "GL_TEXTURE_COORD_ARRAY_TYPE", 0x8089 }, + { "GL_TEXTURE_COORD_ARRAY_STRIDE", 0x808A }, + { "GL_EDGE_FLAG_ARRAY_STRIDE", 0x808C }, + { "GL_VERTEX_ARRAY_POINTER", 0x808E }, + { "GL_NORMAL_ARRAY_POINTER", 0x808F }, + { "GL_COLOR_ARRAY_POINTER", 0x8090 }, + { "GL_INDEX_ARRAY_POINTER", 0x8091 }, + { "GL_TEXTURE_COORD_ARRAY_POINTER", 0x8092 }, + { "GL_EDGE_FLAG_ARRAY_POINTER", 0x8093 }, + { "GL_V2F", 0x2A20 }, + { "GL_V3F", 0x2A21 }, + { "GL_C4UB_V2F", 0x2A22 }, + { "GL_C4UB_V3F", 0x2A23 }, + { "GL_C3F_V3F", 0x2A24 }, + { "GL_N3F_V3F", 0x2A25 }, + { "GL_C4F_N3F_V3F", 0x2A26 }, + { "GL_T2F_V3F", 0x2A27 }, + { "GL_T4F_V4F", 0x2A28 }, + { "GL_T2F_C4UB_V3F", 0x2A29 }, + { "GL_T2F_C3F_V3F", 0x2A2A }, + { "GL_T2F_N3F_V3F", 0x2A2B }, + { "GL_T2F_C4F_N3F_V3F", 0x2A2C }, + { "GL_T4F_C4F_N3F_V4F", 0x2A2D }, + + /* Matrix Mode */ + { "GL_MATRIX_MODE", 0x0BA0 }, + { "GL_MODELVIEW", 0x1700 }, + { "GL_PROJECTION", 0x1701 }, + { "GL_TEXTURE", 0x1702 }, + + /* Points */ + { "GL_POINT_SMOOTH", 0x0B10 }, + { "GL_POINT_SIZE", 0x0B11 }, + { "GL_POINT_SIZE_GRANULARITY ", 0x0B13 }, + { "GL_POINT_SIZE_RANGE", 0x0B12 }, + + /* Lines */ + { "GL_LINE_SMOOTH", 0x0B20 }, + { "GL_LINE_STIPPLE", 0x0B24 }, + { "GL_LINE_STIPPLE_PATTERN", 0x0B25 }, + { "GL_LINE_STIPPLE_REPEAT", 0x0B26 }, + { "GL_LINE_WIDTH", 0x0B21 }, + { "GL_LINE_WIDTH_GRANULARITY", 0x0B23 }, + { "GL_LINE_WIDTH_RANGE", 0x0B22 }, + + /* Polygons */ + { "GL_POINT", 0x1B00 }, + { "GL_LINE", 0x1B01 }, + { "GL_FILL", 0x1B02 }, + { "GL_CCW", 0x0901 }, + { "GL_CW", 0x0900 }, + { "GL_FRONT", 0x0404 }, + { "GL_BACK", 0x0405 }, + { "GL_CULL_FACE", 0x0B44 }, + { "GL_CULL_FACE_MODE", 0x0B45 }, + { "GL_POLYGON_SMOOTH", 0x0B41 }, + { "GL_POLYGON_STIPPLE", 0x0B42 }, + { "GL_FRONT_FACE", 0x0B46 }, + { "GL_POLYGON_MODE", 0x0B40 }, + { "GL_POLYGON_OFFSET_FACTOR", 0x8038 }, + { "GL_POLYGON_OFFSET_UNITS", 0x2A00 }, + { "GL_POLYGON_OFFSET_POINT", 0x2A01 }, + { "GL_POLYGON_OFFSET_LINE", 0x2A02 }, + { "GL_POLYGON_OFFSET_FILL", 0x8037 }, + + /* Display Lists */ + { "GL_COMPILE", 0x1300 }, + { "GL_COMPILE_AND_EXECUTE", 0x1301 }, + { "GL_LIST_BASE", 0x0B32 }, + { "GL_LIST_INDEX", 0x0B33 }, + { "GL_LIST_MODE", 0x0B30 }, + + /* Depth buffer */ + { "GL_NEVER", 0x0200 }, + { "GL_LESS", 0x0201 }, + { "GL_GEQUAL", 0x0206 }, + { "GL_LEQUAL", 0x0203 }, + { "GL_GREATER", 0x0204 }, + { "GL_NOTEQUAL", 0x0205 }, + { "GL_EQUAL", 0x0202 }, + { "GL_ALWAYS", 0x0207 }, + { "GL_DEPTH_TEST", 0x0B71 }, + { "GL_DEPTH_BITS", 0x0D56 }, + { "GL_DEPTH_CLEAR_VALUE", 0x0B73 }, + { "GL_DEPTH_FUNC", 0x0B74 }, + { "GL_DEPTH_RANGE", 0x0B70 }, + { "GL_DEPTH_WRITEMASK", 0x0B72 }, + { "GL_DEPTH_COMPONENT", 0x1902 }, + + /* Lighting */ + { "GL_LIGHTING", 0x0B50 }, + { "GL_LIGHT0", 0x4000 }, + { "GL_LIGHT1", 0x4001 }, + { "GL_LIGHT2", 0x4002 }, + { "GL_LIGHT3", 0x4003 }, + { "GL_LIGHT4", 0x4004 }, + { "GL_LIGHT5", 0x4005 }, + { "GL_LIGHT6", 0x4006 }, + { "GL_LIGHT7", 0x4007 }, + { "GL_SPOT_EXPONENT", 0x1205 }, + { "GL_SPOT_CUTOFF", 0x1206 }, + { "GL_CONSTANT_ATTENUATION", 0x1207 }, + { "GL_LINEAR_ATTENUATION", 0x1208 }, + { "GL_QUADRATIC_ATTENUATION", 0x1209 }, + { "GL_AMBIENT", 0x1200 }, + { "GL_DIFFUSE", 0x1201 }, + { "GL_SPECULAR", 0x1202 }, + { "GL_SHININESS", 0x1601 }, + { "GL_EMISSION", 0x1600 }, + { "GL_POSITION", 0x1203 }, + { "GL_SPOT_DIRECTION", 0x1204 }, + { "GL_AMBIENT_AND_DIFFUSE", 0x1602 }, + { "GL_COLOR_INDEXES", 0x1603 }, + { "GL_LIGHT_MODEL_TWO_SIDE", 0x0B52 }, + { "GL_LIGHT_MODEL_LOCAL_VIEWER", 0x0B51 }, + { "GL_LIGHT_MODEL_AMBIENT", 0x0B53 }, + { "GL_FRONT_AND_BACK", 0x0408 }, + { "GL_SHADE_MODEL", 0x0B54 }, + { "GL_FLAT", 0x1D00 }, + { "GL_SMOOTH", 0x1D01 }, + { "GL_COLOR_MATERIAL", 0x0B57 }, + { "GL_COLOR_MATERIAL_FACE", 0x0B55 }, + { "GL_COLOR_MATERIAL_PARAMETER", 0x0B56 }, + { "GL_NORMALIZE", 0x0BA1 }, + + /* User clipping planes */ + { "GL_CLIP_PLANE0", 0x3000 }, + { "GL_CLIP_PLANE1", 0x3001 }, + { "GL_CLIP_PLANE2", 0x3002 }, + { "GL_CLIP_PLANE3", 0x3003 }, + { "GL_CLIP_PLANE4", 0x3004 }, + { "GL_CLIP_PLANE5", 0x3005 }, + + /* Accumulation buffer */ + { "GL_ACCUM_RED_BITS", 0x0D58 }, + { "GL_ACCUM_GREEN_BITS", 0x0D59 }, + { "GL_ACCUM_BLUE_BITS", 0x0D5A }, + { "GL_ACCUM_ALPHA_BITS", 0x0D5B }, + { "GL_ACCUM_CLEAR_VALUE", 0x0B80 }, + { "GL_ACCUM", 0x0100 }, + { "GL_ADD", 0x0104 }, + { "GL_LOAD", 0x0101 }, + { "GL_MULT", 0x0103 }, + { "GL_RETURN", 0x0102 }, + + /* Alpha testing */ + { "GL_ALPHA_TEST", 0x0BC0 }, + { "GL_ALPHA_TEST_REF", 0x0BC2 }, + { "GL_ALPHA_TEST_FUNC", 0x0BC1 }, + + /* Blending */ + { "GL_BLEND", 0x0BE2 }, + { "GL_BLEND_SRC", 0x0BE1 }, + { "GL_BLEND_DST", 0x0BE0 }, + { "GL_ZERO", 0 }, + { "GL_ONE", 1 }, + { "GL_SRC_COLOR", 0x0300 }, + { "GL_ONE_MINUS_SRC_COLOR", 0x0301 }, + { "GL_DST_COLOR", 0x0306 }, + { "GL_ONE_MINUS_DST_COLOR", 0x0307 }, + { "GL_SRC_ALPHA", 0x0302 }, + { "GL_ONE_MINUS_SRC_ALPHA", 0x0303 }, + { "GL_DST_ALPHA", 0x0304 }, + { "GL_ONE_MINUS_DST_ALPHA", 0x0305 }, + { "GL_SRC_ALPHA_SATURATE", 0x0308 }, + { "GL_CONSTANT_COLOR", 0x8001 }, + { "GL_ONE_MINUS_CONSTANT_COLOR", 0x8002 }, + { "GL_CONSTANT_ALPHA", 0x8003 }, + { "GL_ONE_MINUS_CONSTANT_ALPHA", 0x8004 }, + + /* Render Mode */ + { "GL_FEEDBACK", 0x1C01 }, + { "GL_RENDER", 0x1C00 }, + { "GL_SELECT", 0x1C02 }, + + /* Feedback */ + { "GL_2D", 0x0600 }, + { "GL_3D", 0x0601 }, + { "GL_3D_COLOR", 0x0602 }, + { "GL_3D_COLOR_TEXTURE", 0x0603 }, + { "GL_4D_COLOR_TEXTURE", 0x0604 }, + { "GL_POINT_TOKEN", 0x0701 }, + { "GL_LINE_TOKEN", 0x0702 }, + { "GL_LINE_RESET_TOKEN", 0x0707 }, + { "GL_POLYGON_TOKEN", 0x0703 }, + { "GL_BITMAP_TOKEN", 0x0704 }, + { "GL_DRAW_PIXEL_TOKEN", 0x0705 }, + { "GL_COPY_PIXEL_TOKEN", 0x0706 }, + { "GL_PASS_THROUGH_TOKEN", 0x0700 }, + { "GL_FEEDBACK_BUFFER_POINTER", 0x0DF0 }, + { "GL_FEEDBACK_BUFFER_SIZE", 0x0DF1 }, + { "GL_FEEDBACK_BUFFER_TYPE", 0x0DF2 }, + + /* Selection */ + { "GL_SELECTION_BUFFER_POINTER", 0x0DF3 }, + { "GL_SELECTION_BUFFER_SIZE", 0x0DF4 }, + + /* Fog */ + { "GL_FOG", 0x0B60 }, + { "GL_FOG_MODE", 0x0B65 }, + { "GL_FOG_DENSITY", 0x0B62 }, + { "GL_FOG_COLOR", 0x0B66 }, + { "GL_FOG_INDEX", 0x0B61 }, + { "GL_FOG_START", 0x0B63 }, + { "GL_FOG_END", 0x0B64 }, + { "GL_LINEAR", 0x2601 }, + { "GL_EXP", 0x0800 }, + { "GL_EXP2", 0x0801 }, + + /* Logic Ops */ + { "GL_LOGIC_OP", 0x0BF1 }, + { "GL_INDEX_LOGIC_OP", 0x0BF1 }, + { "GL_COLOR_LOGIC_OP", 0x0BF2 }, + { "GL_LOGIC_OP_MODE", 0x0BF0 }, + { "GL_CLEAR", 0x1500 }, + { "GL_SET", 0x150F }, + { "GL_COPY", 0x1503 }, + { "GL_COPY_INVERTED", 0x150C }, + { "GL_NOOP", 0x1505 }, + { "GL_INVERT", 0x150A }, + { "GL_AND", 0x1501 }, + { "GL_NAND", 0x150E }, + { "GL_OR", 0x1507 }, + { "GL_NOR", 0x1508 }, + { "GL_XOR", 0x1506 }, + { "GL_EQUIV", 0x1509 }, + { "GL_AND_REVERSE", 0x1502 }, + { "GL_AND_INVERTED", 0x1504 }, + { "GL_OR_REVERSE", 0x150B }, + { "GL_OR_INVERTED", 0x150D }, + + /* Stencil */ + { "GL_STENCIL_TEST", 0x0B90 }, + { "GL_STENCIL_WRITEMASK", 0x0B98 }, + { "GL_STENCIL_BITS", 0x0D57 }, + { "GL_STENCIL_FUNC", 0x0B92 }, + { "GL_STENCIL_VALUE_MASK", 0x0B93 }, + { "GL_STENCIL_REF", 0x0B97 }, + { "GL_STENCIL_FAIL", 0x0B94 }, + { "GL_STENCIL_PASS_DEPTH_PASS", 0x0B96 }, + { "GL_STENCIL_PASS_DEPTH_FAIL", 0x0B95 }, + { "GL_STENCIL_CLEAR_VALUE", 0x0B91 }, + { "GL_STENCIL_INDEX", 0x1901 }, + { "GL_KEEP", 0x1E00 }, + { "GL_REPLACE", 0x1E01 }, + { "GL_INCR", 0x1E02 }, + { "GL_DECR", 0x1E03 }, + + /* Buffers, Pixel Drawing/Reading */ + { "GL_NONE", 0 }, + { "GL_LEFT", 0x0406 }, + { "GL_RIGHT", 0x0407 }, + { "GL_FRONT_LEFT", 0x0400 }, + { "GL_FRONT_RIGHT", 0x0401 }, + { "GL_BACK_LEFT", 0x0402 }, + { "GL_BACK_RIGHT", 0x0403 }, + { "GL_AUX0", 0x0409 }, + { "GL_AUX1", 0x040A }, + { "GL_AUX2", 0x040B }, + { "GL_AUX3", 0x040C }, + { "GL_COLOR_INDEX", 0x1900 }, + { "GL_RED", 0x1903 }, + { "GL_GREEN", 0x1904 }, + { "GL_BLUE", 0x1905 }, + { "GL_ALPHA", 0x1906 }, + { "GL_LUMINANCE", 0x1909 }, + { "GL_LUMINANCE_ALPHA", 0x190A }, + { "GL_ALPHA_BITS", 0x0D55 }, + { "GL_RED_BITS", 0x0D52 }, + { "GL_GREEN_BITS", 0x0D53 }, + { "GL_BLUE_BITS", 0x0D54 }, + { "GL_INDEX_BITS", 0x0D51 }, + { "GL_SUBPIXEL_BITS", 0x0D50 }, + { "GL_AUX_BUFFERS", 0x0C00 }, + { "GL_READ_BUFFER", 0x0C02 }, + { "GL_DRAW_BUFFER", 0x0C01 }, + { "GL_DOUBLEBUFFER", 0x0C32 }, + { "GL_STEREO", 0x0C33 }, + { "GL_BITMAP", 0x1A00 }, + { "GL_COLOR", 0x1800 }, + { "GL_DEPTH", 0x1801 }, + { "GL_STENCIL", 0x1802 }, + { "GL_DITHER", 0x0BD0 }, + { "GL_RGB", 0x1907 }, + { "GL_RGBA", 0x1908 }, + + /* Implementation limits */ + { "GL_MAX_LIST_NESTING", 0x0B31 }, + { "GL_MAX_ATTRIB_STACK_DEPTH", 0x0D35 }, + { "GL_MAX_MODELVIEW_STACK_DEPTH", 0x0D36 }, + { "GL_MAX_NAME_STACK_DEPTH", 0x0D37 }, + { "GL_MAX_PROJECTION_STACK_DEPTH", 0x0D38 }, + { "GL_MAX_TEXTURE_STACK_DEPTH", 0x0D39 }, + { "GL_MAX_EVAL_ORDER", 0x0D30 }, + { "GL_MAX_LIGHTS", 0x0D31 }, + { "GL_MAX_CLIP_PLANES", 0x0D32 }, + { "GL_MAX_TEXTURE_SIZE", 0x0D33 }, + { "GL_MAX_PIXEL_MAP_TABLE", 0x0D34 }, + { "GL_MAX_VIEWPORT_DIMS", 0x0D3A }, + { "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH", 0x0D3B }, + + + { "GL_ATTRIB_STACK_DEPTH", 0x0BB0 }, + { "GL_CLIENT_ATTRIB_STACK_DEPTH", 0x0BB1 }, + { "GL_COLOR_CLEAR_VALUE", 0x0C22 }, + { "GL_COLOR_WRITEMASK", 0x0C23 }, + { "GL_CURRENT_INDEX", 0x0B01 }, + { "GL_CURRENT_COLOR", 0x0B00 }, + { "GL_CURRENT_NORMAL", 0x0B02 }, + { "GL_CURRENT_RASTER_COLOR", 0x0B04 }, + { "GL_CURRENT_RASTER_DISTANCE", 0x0B09 }, + { "GL_CURRENT_RASTER_INDEX", 0x0B05 }, + { "GL_CURRENT_RASTER_POSITION", 0x0B07 }, + { "GL_CURRENT_RASTER_TEXTURE_COORDS", 0x0B06}, + { "GL_CURRENT_RASTER_POSITION_VALID", 0x0B08 }, + { "GL_CURRENT_TEXTURE_COORDS", 0x0B03 }, + { "GL_INDEX_CLEAR_VALUE", 0x0C20 }, + { "GL_INDEX_MODE", 0x0C30 }, + { "GL_INDEX_WRITEMASK", 0x0C21 }, + { "GL_MODELVIEW_MATRIX", 0x0BA6 }, + { "GL_MODELVIEW_STACK_DEPTH", 0x0BA3 }, + { "GL_NAME_STACK_DEPTH", 0x0D70 }, + { "GL_PROJECTION_MATRIX", 0x0BA7 }, + { "GL_PROJECTION_STACK_DEPTH", 0x0BA4 }, + { "GL_RENDER_MODE", 0x0C40 }, + { "GL_RGBA_MODE", 0x0C31 }, + { "GL_TEXTURE_MATRIX", 0x0BA8 }, + { "GL_TEXTURE_STACK_DEPTH", 0x0BA5 }, + { "GL_VIEWPORT", 0x0BA2 }, + + + /* Evaluators */ + { "GL_AUTO_NORMAL", 0x0D80 }, + { "GL_MAP1_COLOR_4", 0x0D90 }, + { "GL_MAP1_GRID_DOMAIN", 0x0DD0 }, + { "GL_MAP1_GRID_SEGMENTS", 0x0DD1 }, + { "GL_MAP1_INDEX", 0x0D91 }, + { "GL_MAP1_NORMAL", 0x0D92 }, + { "GL_MAP1_TEXTURE_COORD_1", 0x0D93 }, + { "GL_MAP1_TEXTURE_COORD_2", 0x0D94 }, + { "GL_MAP1_TEXTURE_COORD_3", 0x0D95 }, + { "GL_MAP1_TEXTURE_COORD_4", 0x0D96 }, + { "GL_MAP1_VERTEX_3", 0x0D97 }, + { "GL_MAP1_VERTEX_4", 0x0D98 }, + { "GL_MAP2_COLOR_4", 0x0DB0 }, + { "GL_MAP2_GRID_DOMAIN", 0x0DD2 }, + { "GL_MAP2_GRID_SEGMENTS", 0x0DD3 }, + { "GL_MAP2_INDEX", 0x0DB1 }, + { "GL_MAP2_NORMAL", 0x0DB2 }, + { "GL_MAP2_TEXTURE_COORD_1", 0x0DB3 }, + { "GL_MAP2_TEXTURE_COORD_2", 0x0DB4 }, + { "GL_MAP2_TEXTURE_COORD_3", 0x0DB5 }, + { "GL_MAP2_TEXTURE_COORD_4", 0x0DB6 }, + { "GL_MAP2_VERTEX_3", 0x0DB7 }, + { "GL_MAP2_VERTEX_4", 0x0DB8 }, + { "GL_COEFF", 0x0A00 }, + { "GL_DOMAIN", 0x0A02 }, + { "GL_ORDER", 0x0A01 }, + + /* Hints */ + { "GL_FOG_HINT", 0x0C54 }, + { "GL_LINE_SMOOTH_HINT", 0x0C52 }, + { "GL_PERSPECTIVE_CORRECTION_HINT", 0x0C50 }, + { "GL_POINT_SMOOTH_HINT", 0x0C51 }, + { "GL_POLYGON_SMOOTH_HINT", 0x0C53 }, + { "GL_DONT_CARE", 0x1100 }, + { "GL_FASTEST", 0x1101 }, + { "GL_NICEST", 0x1102 }, + + /* Scissor box */ + { "GL_SCISSOR_TEST", 0x0C11 }, + { "GL_SCISSOR_BOX", 0x0C10 }, + + /* Pixel Mode / Transfer */ + { "GL_MAP_COLOR", 0x0D10 }, + { "GL_MAP_STENCIL", 0x0D11 }, + { "GL_INDEX_SHIFT", 0x0D12 }, + { "GL_INDEX_OFFSET", 0x0D13 }, + { "GL_RED_SCALE", 0x0D14 }, + { "GL_RED_BIAS", 0x0D15 }, + { "GL_GREEN_SCALE", 0x0D18 }, + { "GL_GREEN_BIAS", 0x0D19 }, + { "GL_BLUE_SCALE", 0x0D1A }, + { "GL_BLUE_BIAS", 0x0D1B }, + { "GL_ALPHA_SCALE", 0x0D1C }, + { "GL_ALPHA_BIAS", 0x0D1D }, + { "GL_DEPTH_SCALE", 0x0D1E }, + { "GL_DEPTH_BIAS", 0x0D1F }, + { "GL_PIXEL_MAP_S_TO_S_SIZE", 0x0CB1 }, + { "GL_PIXEL_MAP_I_TO_I_SIZE", 0x0CB0 }, + { "GL_PIXEL_MAP_I_TO_R_SIZE", 0x0CB2 }, + { "GL_PIXEL_MAP_I_TO_G_SIZE", 0x0CB3 }, + { "GL_PIXEL_MAP_I_TO_B_SIZE", 0x0CB4 }, + { "GL_PIXEL_MAP_I_TO_A_SIZE", 0x0CB5 }, + { "GL_PIXEL_MAP_R_TO_R_SIZE", 0x0CB6 }, + { "GL_PIXEL_MAP_G_TO_G_SIZE", 0x0CB7 }, + { "GL_PIXEL_MAP_B_TO_B_SIZE", 0x0CB8 }, + { "GL_PIXEL_MAP_A_TO_A_SIZE", 0x0CB9 }, + { "GL_PIXEL_MAP_S_TO_S", 0x0C71 }, + { "GL_PIXEL_MAP_I_TO_I", 0x0C70 }, + { "GL_PIXEL_MAP_I_TO_R", 0x0C72 }, + { "GL_PIXEL_MAP_I_TO_G", 0x0C73 }, + { "GL_PIXEL_MAP_I_TO_B", 0x0C74 }, + { "GL_PIXEL_MAP_I_TO_A", 0x0C75 }, + { "GL_PIXEL_MAP_R_TO_R", 0x0C76 }, + { "GL_PIXEL_MAP_G_TO_G", 0x0C77 }, + { "GL_PIXEL_MAP_B_TO_B", 0x0C78 }, + { "GL_PIXEL_MAP_A_TO_A", 0x0C79 }, + { "GL_PACK_ALIGNMENT", 0x0D05 }, + { "GL_PACK_LSB_FIRST", 0x0D01 }, + { "GL_PACK_ROW_LENGTH", 0x0D02 }, + { "GL_PACK_SKIP_PIXELS", 0x0D04 }, + { "GL_PACK_SKIP_ROWS", 0x0D03 }, + { "GL_PACK_SWAP_BYTES", 0x0D00 }, + { "GL_UNPACK_ALIGNMENT", 0x0CF5 }, + { "GL_UNPACK_LSB_FIRST", 0x0CF1 }, + { "GL_UNPACK_ROW_LENGTH", 0x0CF2 }, + { "GL_UNPACK_SKIP_PIXELS", 0x0CF4 }, + { "GL_UNPACK_SKIP_ROWS", 0x0CF3 }, + { "GL_UNPACK_SWAP_BYTES", 0x0CF0 }, + { "GL_ZOOM_X", 0x0D16 }, + { "GL_ZOOM_Y", 0x0D17 }, + + /* Texture mapping */ + { "GL_TEXTURE_ENV", 0x2300 }, + { "GL_TEXTURE_ENV_MODE", 0x2200 }, + { "GL_TEXTURE_1D", 0x0DE0 }, + { "GL_TEXTURE_2D", 0x0DE1 }, + { "GL_TEXTURE_WRAP_S", 0x2802 }, + { "GL_TEXTURE_WRAP_T", 0x2803 }, + { "GL_TEXTURE_MAG_FILTER", 0x2800 }, + { "GL_TEXTURE_MIN_FILTER", 0x2801 }, + { "GL_TEXTURE_ENV_COLOR", 0x2201 }, + { "GL_TEXTURE_GEN_S", 0x0C60 }, + { "GL_TEXTURE_GEN_T", 0x0C61 }, + { "GL_TEXTURE_GEN_MODE", 0x2500 }, + { "GL_TEXTURE_BORDER_COLOR", 0x1004 }, + { "GL_TEXTURE_WIDTH", 0x1000 }, + { "GL_TEXTURE_HEIGHT", 0x1001 }, + { "GL_TEXTURE_BORDER", 0x1005 }, + { "GL_TEXTURE_COMPONENTS", 0x1003 }, + { "GL_TEXTURE_RED_SIZE", 0x805C }, + { "GL_TEXTURE_GREEN_SIZE", 0x805D }, + { "GL_TEXTURE_BLUE_SIZE", 0x805E }, + { "GL_TEXTURE_ALPHA_SIZE", 0x805F }, + { "GL_TEXTURE_LUMINANCE_SIZE", 0x8060 }, + { "GL_TEXTURE_INTENSITY_SIZE", 0x8061 }, + { "GL_NEAREST_MIPMAP_NEAREST", 0x2700 }, + { "GL_NEAREST_MIPMAP_LINEAR", 0x2702 }, + { "GL_LINEAR_MIPMAP_NEAREST", 0x2701 }, + { "GL_LINEAR_MIPMAP_LINEAR", 0x2703 }, + { "GL_OBJECT_LINEAR", 0x2401 }, + { "GL_OBJECT_PLANE", 0x2501 }, + { "GL_EYE_LINEAR", 0x2400 }, + { "GL_EYE_PLANE", 0x2502 }, + { "GL_SPHERE_MAP", 0x2402 }, + { "GL_DECAL", 0x2101 }, + { "GL_MODULATE", 0x2100 }, + { "GL_NEAREST", 0x2600 }, + { "GL_REPEAT", 0x2901 }, + { "GL_CLAMP", 0x2900 }, + { "GL_S", 0x2000 }, + { "GL_T", 0x2001 }, + { "GL_R", 0x2002 }, + { "GL_Q", 0x2003 }, + { "GL_TEXTURE_GEN_R", 0x0C62 }, + { "GL_TEXTURE_GEN_Q", 0x0C63 }, + + /* GL 1.1 texturing */ + { "GL_PROXY_TEXTURE_1D", 0x8063 }, + { "GL_PROXY_TEXTURE_2D", 0x8064 }, + { "GL_TEXTURE_PRIORITY", 0x8066 }, + { "GL_TEXTURE_RESIDENT", 0x8067 }, + { "GL_TEXTURE_BINDING_1D", 0x8068 }, + { "GL_TEXTURE_BINDING_2D", 0x8069 }, + { "GL_TEXTURE_INTERNAL_FORMAT", 0x1003 }, + + /* GL 1.2 texturing */ + { "GL_PACK_SKIP_IMAGES", 0x806B }, + { "GL_PACK_IMAGE_HEIGHT", 0x806C }, + { "GL_UNPACK_SKIP_IMAGES", 0x806D }, + { "GL_UNPACK_IMAGE_HEIGHT", 0x806E }, + { "GL_TEXTURE_3D", 0x806F }, + { "GL_PROXY_TEXTURE_3D", 0x8070 }, + { "GL_TEXTURE_DEPTH", 0x8071 }, + { "GL_TEXTURE_WRAP_R", 0x8072 }, + { "GL_MAX_3D_TEXTURE_SIZE", 0x8073 }, + { "GL_TEXTURE_BINDING_3D", 0x806A }, + + /* Internal texture formats (GL 1.1) */ + { "GL_ALPHA4", 0x803B }, + { "GL_ALPHA8", 0x803C }, + { "GL_ALPHA12", 0x803D }, + { "GL_ALPHA16", 0x803E }, + { "GL_LUMINANCE4", 0x803F }, + { "GL_LUMINANCE8", 0x8040 }, + { "GL_LUMINANCE12", 0x8041 }, + { "GL_LUMINANCE16", 0x8042 }, + { "GL_LUMINANCE4_ALPHA4", 0x8043 }, + { "GL_LUMINANCE6_ALPHA2", 0x8044 }, + { "GL_LUMINANCE8_ALPHA8", 0x8045 }, + { "GL_LUMINANCE12_ALPHA4", 0x8046 }, + { "GL_LUMINANCE12_ALPHA12", 0x8047 }, + { "GL_LUMINANCE16_ALPHA16", 0x8048 }, + { "GL_INTENSITY", 0x8049 }, + { "GL_INTENSITY4", 0x804A }, + { "GL_INTENSITY8", 0x804B }, + { "GL_INTENSITY12", 0x804C }, + { "GL_INTENSITY16", 0x804D }, + { "GL_R3_G3_B2", 0x2A10 }, + { "GL_RGB4", 0x804F }, + { "GL_RGB5", 0x8050 }, + { "GL_RGB8", 0x8051 }, + { "GL_RGB10", 0x8052 }, + { "GL_RGB12", 0x8053 }, + { "GL_RGB16", 0x8054 }, + { "GL_RGBA2", 0x8055 }, + { "GL_RGBA4", 0x8056 }, + { "GL_RGB5_A1", 0x8057 }, + { "GL_RGBA8", 0x8058 }, + { "GL_RGB10_A2", 0x8059 }, + { "GL_RGBA12", 0x805A }, + { "GL_RGBA16", 0x805B }, + + /* Utility */ + { "GL_VENDOR", 0x1F00 }, + { "GL_RENDERER", 0x1F01 }, + { "GL_VERSION", 0x1F02 }, + { "GL_EXTENSIONS", 0x1F03 }, + + /* Errors */ + { "GL_INVALID_VALUE", 0x0501 }, + { "GL_INVALID_ENUM", 0x0500 }, + { "GL_INVALID_OPERATION", 0x0502 }, + { "GL_STACK_OVERFLOW", 0x0503 }, + { "GL_STACK_UNDERFLOW", 0x0504 }, + { "GL_OUT_OF_MEMORY", 0x0505 }, + + /* + * Extensions + */ + + { "GL_CONSTANT_COLOR_EXT", 0x8001 }, + { "GL_ONE_MINUS_CONSTANT_COLOR_EXT", 0x8002 }, + { "GL_CONSTANT_ALPHA_EXT", 0x8003 }, + { "GL_ONE_MINUS_CONSTANT_ALPHA_EXT", 0x8004 }, + { "GL_BLEND_EQUATION_EXT", 0x8009 }, + { "GL_MIN_EXT", 0x8007 }, + { "GL_MAX_EXT", 0x8008 }, + { "GL_FUNC_ADD_EXT", 0x8006 }, + { "GL_FUNC_SUBTRACT_EXT", 0x800A }, + { "GL_FUNC_REVERSE_SUBTRACT_EXT", 0x800B }, + { "GL_BLEND_COLOR_EXT", 0x8005 }, + + { "GL_POLYGON_OFFSET_EXT", 0x8037 }, + { "GL_POLYGON_OFFSET_FACTOR_EXT", 0x8038 }, + { "GL_POLYGON_OFFSET_BIAS_EXT", 0x8039 }, + + + { "GL_VERTEX_ARRAY_EXT", 0x8074 }, + { "GL_NORMAL_ARRAY_EXT", 0x8075 }, + { "GL_COLOR_ARRAY_EXT", 0x8076 }, + { "GL_INDEX_ARRAY_EXT", 0x8077 }, + { "GL_TEXTURE_COORD_ARRAY_EXT", 0x8078 }, + { "GL_EDGE_FLAG_ARRAY_EXT", 0x8079 }, + { "GL_VERTEX_ARRAY_SIZE_EXT", 0x807A }, + { "GL_VERTEX_ARRAY_TYPE_EXT", 0x807B }, + { "GL_VERTEX_ARRAY_STRIDE_EXT", 0x807C }, + { "GL_VERTEX_ARRAY_COUNT_EXT", 0x807D }, + { "GL_NORMAL_ARRAY_TYPE_EXT", 0x807E }, + { "GL_NORMAL_ARRAY_STRIDE_EXT", 0x807F }, + { "GL_NORMAL_ARRAY_COUNT_EXT", 0x8080 }, + { "GL_COLOR_ARRAY_SIZE_EXT", 0x8081 }, + { "GL_COLOR_ARRAY_TYPE_EXT", 0x8082 }, + { "GL_COLOR_ARRAY_STRIDE_EXT", 0x8083 }, + { "GL_COLOR_ARRAY_COUNT_EXT", 0x8084 }, + { "GL_INDEX_ARRAY_TYPE_EXT", 0x8085 }, + { "GL_INDEX_ARRAY_STRIDE_EXT", 0x8086 }, + { "GL_INDEX_ARRAY_COUNT_EXT", 0x8087 }, + { "GL_TEXTURE_COORD_ARRAY_SIZE_EXT", 0x8088 }, + { "GL_TEXTURE_COORD_ARRAY_TYPE_EXT", 0x8089 }, + { "GL_TEXTURE_COORD_ARRAY_STRIDE_EXT", 0x808A }, + { "GL_TEXTURE_COORD_ARRAY_COUNT_EXT", 0x808B }, + { "GL_EDGE_FLAG_ARRAY_STRIDE_EXT", 0x808C }, + { "GL_EDGE_FLAG_ARRAY_COUNT_EXT", 0x808D }, + { "GL_VERTEX_ARRAY_POINTER_EXT", 0x808E }, + { "GL_NORMAL_ARRAY_POINTER_EXT", 0x808F }, + { "GL_COLOR_ARRAY_POINTER_EXT", 0x8090 }, + { "GL_INDEX_ARRAY_POINTER_EXT", 0x8091 }, + { "GL_TEXTURE_COORD_ARRAY_POINTER_EXT", 0x8092 }, + { "GL_EDGE_FLAG_ARRAY_POINTER_EXT", 0x8093 }, + + { "GL_TEXTURE_PRIORITY_EXT", 0x8066 }, + { "GL_TEXTURE_RESIDENT_EXT", 0x8067 }, + { "GL_TEXTURE_1D_BINDING_EXT", 0x8068 }, + { "GL_TEXTURE_2D_BINDING_EXT", 0x8069 }, + + { "GL_PACK_SKIP_IMAGES_EXT", 0x806B }, + { "GL_PACK_IMAGE_HEIGHT_EXT", 0x806C }, + { "GL_UNPACK_SKIP_IMAGES_EXT", 0x806D }, + { "GL_UNPACK_IMAGE_HEIGHT_EXT", 0x806E }, + { "GL_TEXTURE_3D_EXT", 0x806F }, + { "GL_PROXY_TEXTURE_3D_EXT", 0x8070 }, + { "GL_TEXTURE_DEPTH_EXT", 0x8071 }, + { "GL_TEXTURE_WRAP_R_EXT", 0x8072 }, + { "GL_MAX_3D_TEXTURE_SIZE_EXT", 0x8073 }, + { "GL_TEXTURE_3D_BINDING_EXT", 0x806A }, + + { "GL_TABLE_TOO_LARGE_EXT", 0x8031 }, + { "GL_COLOR_TABLE_FORMAT_EXT", 0x80D8 }, + { "GL_COLOR_TABLE_WIDTH_EXT", 0x80D9 }, + { "GL_COLOR_TABLE_RED_SIZE_EXT", 0x80DA }, + { "GL_COLOR_TABLE_GREEN_SIZE_EXT", 0x80DB }, + { "GL_COLOR_TABLE_BLUE_SIZE_EXT", 0x80DC }, + { "GL_COLOR_TABLE_ALPHA_SIZE_EXT", 0x80DD }, + { "GL_COLOR_TABLE_LUMINANCE_SIZE_EXT", 0x80DE }, + { "GL_COLOR_TABLE_INTENSITY_SIZE_EXT", 0x80DF }, + { "GL_TEXTURE_INDEX_SIZE_EXT", 0x80ED }, + { "GL_COLOR_INDEX1_EXT", 0x80E2 }, + { "GL_COLOR_INDEX2_EXT", 0x80E3 }, + { "GL_COLOR_INDEX4_EXT", 0x80E4 }, + { "GL_COLOR_INDEX8_EXT", 0x80E5 }, + { "GL_COLOR_INDEX12_EXT", 0x80E6 }, + { "GL_COLOR_INDEX16_EXT", 0x80E7 }, + + { "GL_SHARED_TEXTURE_PALETTE_EXT", 0x81FB }, + + { "GL_POINT_SIZE_MIN_EXT", 0x8126 }, + { "GL_POINT_SIZE_MAX_EXT", 0x8127 }, + { "GL_POINT_FADE_THRESHOLD_SIZE_EXT", 0x8128 }, + { "GL_DISTANCE_ATTENUATION_EXT", 0x8129 }, + + { "GL_RESCALE_NORMAL_EXT", 0x803A }, + + { "GL_ABGR_EXT", 0x8000 }, + + { "GL_INCR_WRAP_EXT", 0x8507 }, + { "GL_DECR_WRAP_EXT", 0x8508 }, + + { "GL_CLAMP_TO_EDGE_SGIS", 0x812F }, + + { "GL_BLEND_DST_RGB_INGR", 0x80C8 }, + { "GL_BLEND_SRC_RGB_INGR", 0x80C9 }, + { "GL_BLEND_DST_ALPHA_INGR", 0x80CA }, + { "GL_BLEND_SRC_ALPHA_INGR", 0x80CB }, + + { "GL_RESCALE_NORMAL", 0x803A }, + { "GL_CLAMP_TO_EDGE", 0x812F }, + { "GL_MAX_ELEMENTS_VERTICES", 0xF0E8 }, + { "GL_MAX_ELEMENTS_INDICES", 0xF0E9 }, + { "GL_BGR", 0x80E0 }, + { "GL_BGRA", 0x80E1 }, + { "GL_UNSIGNED_BYTE_3_3_2", 0x8032 }, + { "GL_UNSIGNED_BYTE_2_3_3_REV", 0x8362 }, + { "GL_UNSIGNED_SHORT_5_6_5", 0x8363 }, + { "GL_UNSIGNED_SHORT_5_6_5_REV", 0x8364 }, + { "GL_UNSIGNED_SHORT_4_4_4_4", 0x8033 }, + { "GL_UNSIGNED_SHORT_4_4_4_4_REV", 0x8365 }, + { "GL_UNSIGNED_SHORT_5_5_5_1", 0x8034 }, + { "GL_UNSIGNED_SHORT_1_5_5_5_REV", 0x8366 }, + { "GL_UNSIGNED_INT_8_8_8_8", 0x8035 }, + { "GL_UNSIGNED_INT_8_8_8_8_REV", 0x8367 }, + { "GL_UNSIGNED_INT_10_10_10_2", 0x8036 }, + { "GL_UNSIGNED_INT_2_10_10_10_REV", 0x8368 }, + { "GL_LIGHT_MODEL_COLOR_CONTROL", 0x81F8 }, + { "GL_SINGLE_COLOR", 0x81F9 }, + { "GL_SEPARATE_SPECULAR_COLOR", 0x81FA }, + { "GL_TEXTURE_MIN_LOD", 0x813A }, + { "GL_TEXTURE_MAX_LOD", 0x813B }, + { "GL_TEXTURE_BASE_LEVEL", 0x813C }, + { "GL_TEXTURE_MAX_LEVEL", 0x813D }, + + { "GL_TEXTURE0_ARB", 0x84C0 }, + { "GL_TEXTURE1_ARB", 0x84C1 }, + { "GL_TEXTURE2_ARB", 0x84C2 }, + { "GL_TEXTURE3_ARB", 0x84C3 }, + { "GL_ACTIVE_TEXTURE_ARB", 0x84E0 }, + { "GL_CLIENT_ACTIVE_TEXTURE_ARB", 0x84E1 }, + { "GL_MAX_TEXTURE_UNITS_ARB", 0x84E2 }, + + { "GL_NORMAL_MAP_NV", 0x8511 }, + { "GL_REFLECTION_MAP_NV", 0x8512 }, + + { "GL_PREFER_DOUBLEBUFFER_HINT_PGI", 107000 }, + { "GL_STRICT_DEPTHFUNC_HINT_PGI", 107030 }, + { "GL_STRICT_LIGHTING_HINT_PGI", 107031 }, + { "GL_STRICT_SCISSOR_HINT_PGI", 107032 }, + { "GL_FULL_STIPPLE_HINT_PGI", 107033 }, + { "GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI", 107011 }, + { "GL_NATIVE_GRAPHICS_END_HINT_PGI", 107012 }, + { "GL_CONSERVE_MEMORY_HINT_PGI", 107005 }, + { "GL_RECLAIM_MEMORY_HINT_PGI", 107006 }, + { "GL_ALWAYS_FAST_HINT_PGI", 107020 }, + { "GL_ALWAYS_SOFT_HINT_PGI", 107021 }, + { "GL_ALLOW_DRAW_OBJ_HINT_PGI", 107022 }, + { "GL_ALLOW_DRAW_WIN_HINT_PGI", 107023 }, + { "GL_ALLOW_DRAW_FRG_HINT_PGI", 107024 }, + { "GL_ALLOW_DRAW_SPN_HINT_PGI", 107024 }, + { "GL_ALLOW_DRAW_MEM_HINT_PGI", 107025 }, + { "GL_CLIP_NEAR_HINT_PGI", 107040 }, + { "GL_CLIP_FAR_HINT_PGI", 107041 }, + { "GL_WIDE_LINE_HINT_PGI", 107042 }, + { "GL_BACK_NORMALS_HINT_PGI", 107043 }, + { "GL_NATIVE_GRAPHICS_HANDLE_PGI", 107010 }, + + /* GL_EXT_compiled_vertex_array */ + { "GL_ARRAY_ELEMENT_LOCK_FIRST_SGI", 0x81A8}, + { "GL_ARRAY_ELEMENT_LOCK_COUNT_SGI", 0x81A9}, + + /* GL_EXT_clip_volume_hint */ + { "GL_CLIP_VOLUME_CLIPPING_HINT_EXT", 0x80F0} + +}; + +#define Elements(x) sizeof(x)/sizeof(*x) + +typedef int (GLWINAPIV *cfunc)(const void *, const void *); + +static enum_elt **index1 = 0; +static int sorted = 0; + +static int compar_name( const enum_elt *a, const enum_elt *b ) +{ + return strcmp(a->c, b->c); +} + + +/* note the extra level of indirection + */ +static int compar_nr( const enum_elt **a, const enum_elt **b ) +{ + return (*a)->n - (*b)->n; +} + + +static void sort_enums( void ) +{ + int i; + index1 = (enum_elt **)malloc( Elements(all_enums) * sizeof(enum_elt *) ); + sorted = 1; + + qsort( all_enums, Elements(all_enums), sizeof(*all_enums), + (cfunc) compar_name ); + + for (i = 0 ; i < Elements(all_enums) ; i++) + index1[i] = &all_enums[i]; + + qsort( index1, Elements(all_enums), sizeof(*index1), (cfunc) compar_nr ); +} + + + +int gl_lookup_enum_by_name( const char *symbol ) +{ + enum_elt tmp; + enum_elt *e; + + if (!sorted) + sort_enums(); + + if (!symbol) + return 0; + + tmp.c = symbol; + e = (enum_elt *)bsearch( &tmp, all_enums, Elements(all_enums), + sizeof(*all_enums), (cfunc) compar_name ); + + return e ? e->n : -1; +} + + +const char *gl_lookup_enum_by_nr( int nr ) +{ + enum_elt tmp, *e, **f; + + if (!sorted) + sort_enums(); + + tmp.n = nr; + e = &tmp; + + f = (enum_elt **)bsearch( &e, index1, Elements(all_enums), + sizeof(*index1), (cfunc) compar_nr ); + + return f ? (*f)->c : "(unknown)"; +} + + +#if 0 +int main() +{ + int i; + static const char *test[] = { + "GL_POLYGON", + "GL_TRUE", + "GL_BANANA", + "GL_REFLECTION_MAP_NV", + }; + + for (i = 0 ; i < Elements(test) ; i++) { + int d = gl_lookup_enum_by_name( test[i] ); + printf("%s --> %d --> %s\n", test[i], d, gl_lookup_enum_by_nr( d )); + } +} +#endif diff --git a/src/mesa/main/enums.h b/src/mesa/main/enums.h new file mode 100644 index 00000000000..028c9b4654b --- /dev/null +++ b/src/mesa/main/enums.h @@ -0,0 +1,34 @@ +/* $Id: enums.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 _ENUMS_H_ +#define _ENUMS_H_ + +extern const char *gl_lookup_enum_by_nr( int nr ); +extern int gl_lookup_enum_by_name( const char *symbol ); + +#endif diff --git a/src/mesa/main/eval.c b/src/mesa/main/eval.c new file mode 100644 index 00000000000..74604a21c4d --- /dev/null +++ b/src/mesa/main/eval.c @@ -0,0 +1,2725 @@ +/* $Id: eval.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +/* + * eval.c was written by + * Bernd Barsuhn ([email protected]) and + * Volker Weiss ([email protected]). + * + * My original implementation of evaluators was simplistic and didn't + * compute surface normal vectors properly. Bernd and Volker applied + * used more sophisticated methods to get better results. + * + * Thanks guys! + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include "context.h" +#include "eval.h" +#include "macros.h" +#include "mmath.h" +#include "types.h" +#include "vbcull.h" +#include "vbfill.h" +#include "vbxform.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +static GLfloat inv_tab[MAX_EVAL_ORDER]; + +/* + * Do one-time initialization for evaluators. + */ +void gl_init_eval( void ) +{ + static int init_flag = 0; + GLuint i; + + /* Compute a table of nCr (combination) values used by the + * Bernstein polynomial generator. + */ + + /* KW: precompute 1/x for useful x. + */ + if (init_flag==0) + { + for (i = 1 ; i < MAX_EVAL_ORDER ; i++) + inv_tab[i] = 1.0 / i; + } + + init_flag = 1; +} + + + +/* + * Horner scheme for Bezier curves + * + * Bezier curves can be computed via a Horner scheme. + * Horner is numerically less stable than the de Casteljau + * algorithm, but it is faster. For curves of degree n + * the complexity of Horner is O(n) and de Casteljau is O(n^2). + * Since stability is not important for displaying curve + * points I decided to use the Horner scheme. + * + * A cubic Bezier curve with control points b0, b1, b2, b3 can be + * written as + * + * (([3] [3] ) [3] ) [3] + * c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3 + * + * [n] + * where s=1-t and the binomial coefficients [i]. These can + * be computed iteratively using the identity: + * + * [n] [n ] [n] + * [i] = (n-i+1)/i * [i-1] and [0] = 1 + */ + + +static void +horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t, + GLuint dim, GLuint order) +{ + GLfloat s, powert; + GLuint i, k, bincoeff; + + if(order >= 2) + { + bincoeff = order-1; + s = 1.0-t; + + for(k=0; k<dim; k++) + out[k] = s*cp[k] + bincoeff*t*cp[dim+k]; + + for(i=2, cp+=2*dim, powert=t*t; i<order; i++, powert*=t, cp +=dim) + { + bincoeff *= order-i; + bincoeff *= inv_tab[i]; + + for(k=0; k<dim; k++) + out[k] = s*out[k] + bincoeff*powert*cp[k]; + } + } + else /* order=1 -> constant curve */ + { + for(k=0; k<dim; k++) + out[k] = cp[k]; + } +} + +/* + * Tensor product Bezier surfaces + * + * Again the Horner scheme is used to compute a point on a + * TP Bezier surface. First a control polygon for a curve + * on the surface in one parameter direction is computed, + * then the point on the curve for the other parameter + * direction is evaluated. + * + * To store the curve control polygon additional storage + * for max(uorder,vorder) points is needed in the + * control net cn. + */ + +static void +horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v, + GLuint dim, GLuint uorder, GLuint vorder) +{ + GLfloat *cp = cn + uorder*vorder*dim; + GLuint i, uinc = vorder*dim; + + if(vorder > uorder) + { + if(uorder >= 2) + { + GLfloat s, poweru; + GLuint j, k, bincoeff; + + /* Compute the control polygon for the surface-curve in u-direction */ + for(j=0; j<vorder; j++) + { + GLfloat *ucp = &cn[j*dim]; + + /* Each control point is the point for parameter u on a */ + /* curve defined by the control polygons in u-direction */ + bincoeff = uorder-1; + s = 1.0-u; + + for(k=0; k<dim; k++) + cp[j*dim+k] = s*ucp[k] + bincoeff*u*ucp[uinc+k]; + + for(i=2, ucp+=2*uinc, poweru=u*u; i<uorder; + i++, poweru*=u, ucp +=uinc) + { + bincoeff *= uorder-i; + bincoeff *= inv_tab[i]; + + for(k=0; k<dim; k++) + cp[j*dim+k] = s*cp[j*dim+k] + bincoeff*poweru*ucp[k]; + } + } + + /* Evaluate curve point in v */ + horner_bezier_curve(cp, out, v, dim, vorder); + } + else /* uorder=1 -> cn defines a curve in v */ + horner_bezier_curve(cn, out, v, dim, vorder); + } + else /* vorder <= uorder */ + { + if(vorder > 1) + { + GLuint i; + + /* Compute the control polygon for the surface-curve in u-direction */ + for(i=0; i<uorder; i++, cn += uinc) + { + /* For constant i all cn[i][j] (j=0..vorder) are located */ + /* on consecutive memory locations, so we can use */ + /* horner_bezier_curve to compute the control points */ + + horner_bezier_curve(cn, &cp[i*dim], v, dim, vorder); + } + + /* Evaluate curve point in u */ + horner_bezier_curve(cp, out, u, dim, uorder); + } + else /* vorder=1 -> cn defines a curve in u */ + horner_bezier_curve(cn, out, u, dim, uorder); + } +} + +/* + * The direct de Casteljau algorithm is used when a point on the + * surface and the tangent directions spanning the tangent plane + * should be computed (this is needed to compute normals to the + * surface). In this case the de Casteljau algorithm approach is + * nicer because a point and the partial derivatives can be computed + * at the same time. To get the correct tangent length du and dv + * must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1. + * Since only the directions are needed, this scaling step is omitted. + * + * De Casteljau needs additional storage for uorder*vorder + * values in the control net cn. + */ + +static void +de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv, + GLfloat u, GLfloat v, GLuint dim, + GLuint uorder, GLuint vorder) +{ + GLfloat *dcn = cn + uorder*vorder*dim; + GLfloat us = 1.0-u, vs = 1.0-v; + GLuint h, i, j, k; + GLuint minorder = uorder < vorder ? uorder : vorder; + GLuint uinc = vorder*dim; + GLuint dcuinc = vorder; + + /* Each component is evaluated separately to save buffer space */ + /* This does not drasticaly decrease the performance of the */ + /* algorithm. If additional storage for (uorder-1)*(vorder-1) */ + /* points would be available, the components could be accessed */ + /* in the innermost loop which could lead to less cache misses. */ + +#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)] +#define DCN(I, J) dcn[(I)*dcuinc+(J)] + if(minorder < 3) + { + if(uorder==vorder) + { + for(k=0; k<dim; k++) + { + /* Derivative direction in u */ + du[k] = vs*(CN(1,0,k) - CN(0,0,k)) + + v*(CN(1,1,k) - CN(0,1,k)); + + /* Derivative direction in v */ + dv[k] = us*(CN(0,1,k) - CN(0,0,k)) + + u*(CN(1,1,k) - CN(1,0,k)); + + /* bilinear de Casteljau step */ + out[k] = us*(vs*CN(0,0,k) + v*CN(0,1,k)) + + u*(vs*CN(1,0,k) + v*CN(1,1,k)); + } + } + else if(minorder == uorder) + { + for(k=0; k<dim; k++) + { + /* bilinear de Casteljau step */ + DCN(1,0) = CN(1,0,k) - CN(0,0,k); + DCN(0,0) = us*CN(0,0,k) + u*CN(1,0,k); + + for(j=0; j<vorder-1; j++) + { + /* for the derivative in u */ + DCN(1,j+1) = CN(1,j+1,k) - CN(0,j+1,k); + DCN(1,j) = vs*DCN(1,j) + v*DCN(1,j+1); + + /* for the `point' */ + DCN(0,j+1) = us*CN(0,j+1,k) + u*CN(1,j+1,k); + DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1); + } + + /* remaining linear de Casteljau steps until the second last step */ + for(h=minorder; h<vorder-1; h++) + for(j=0; j<vorder-h; j++) + { + /* for the derivative in u */ + DCN(1,j) = vs*DCN(1,j) + v*DCN(1,j+1); + + /* for the `point' */ + DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1); + } + + /* derivative direction in v */ + dv[k] = DCN(0,1) - DCN(0,0); + + /* derivative direction in u */ + du[k] = vs*DCN(1,0) + v*DCN(1,1); + + /* last linear de Casteljau step */ + out[k] = vs*DCN(0,0) + v*DCN(0,1); + } + } + else /* minorder == vorder */ + { + for(k=0; k<dim; k++) + { + /* bilinear de Casteljau step */ + DCN(0,1) = CN(0,1,k) - CN(0,0,k); + DCN(0,0) = vs*CN(0,0,k) + v*CN(0,1,k); + for(i=0; i<uorder-1; i++) + { + /* for the derivative in v */ + DCN(i+1,1) = CN(i+1,1,k) - CN(i+1,0,k); + DCN(i,1) = us*DCN(i,1) + u*DCN(i+1,1); + + /* for the `point' */ + DCN(i+1,0) = vs*CN(i+1,0,k) + v*CN(i+1,1,k); + DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0); + } + + /* remaining linear de Casteljau steps until the second last step */ + for(h=minorder; h<uorder-1; h++) + for(i=0; i<uorder-h; i++) + { + /* for the derivative in v */ + DCN(i,1) = us*DCN(i,1) + u*DCN(i+1,1); + + /* for the `point' */ + DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0); + } + + /* derivative direction in u */ + du[k] = DCN(1,0) - DCN(0,0); + + /* derivative direction in v */ + dv[k] = us*DCN(0,1) + u*DCN(1,1); + + /* last linear de Casteljau step */ + out[k] = us*DCN(0,0) + u*DCN(1,0); + } + } + } + else if(uorder == vorder) + { + for(k=0; k<dim; k++) + { + /* first bilinear de Casteljau step */ + for(i=0; i<uorder-1; i++) + { + DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k); + for(j=0; j<vorder-1; j++) + { + DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k); + DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1); + } + } + + /* remaining bilinear de Casteljau steps until the second last step */ + for(h=2; h<minorder-1; h++) + for(i=0; i<uorder-h; i++) + { + DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0); + for(j=0; j<vorder-h; j++) + { + DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1); + DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1); + } + } + + /* derivative direction in u */ + du[k] = vs*(DCN(1,0) - DCN(0,0)) + + v*(DCN(1,1) - DCN(0,1)); + + /* derivative direction in v */ + dv[k] = us*(DCN(0,1) - DCN(0,0)) + + u*(DCN(1,1) - DCN(1,0)); + + /* last bilinear de Casteljau step */ + out[k] = us*(vs*DCN(0,0) + v*DCN(0,1)) + + u*(vs*DCN(1,0) + v*DCN(1,1)); + } + } + else if(minorder == uorder) + { + for(k=0; k<dim; k++) + { + /* first bilinear de Casteljau step */ + for(i=0; i<uorder-1; i++) + { + DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k); + for(j=0; j<vorder-1; j++) + { + DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k); + DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1); + } + } + + /* remaining bilinear de Casteljau steps until the second last step */ + for(h=2; h<minorder-1; h++) + for(i=0; i<uorder-h; i++) + { + DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0); + for(j=0; j<vorder-h; j++) + { + DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1); + DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1); + } + } + + /* last bilinear de Casteljau step */ + DCN(2,0) = DCN(1,0) - DCN(0,0); + DCN(0,0) = us*DCN(0,0) + u*DCN(1,0); + for(j=0; j<vorder-1; j++) + { + /* for the derivative in u */ + DCN(2,j+1) = DCN(1,j+1) - DCN(0,j+1); + DCN(2,j) = vs*DCN(2,j) + v*DCN(2,j+1); + + /* for the `point' */ + DCN(0,j+1) = us*DCN(0,j+1 ) + u*DCN(1,j+1); + DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1); + } + + /* remaining linear de Casteljau steps until the second last step */ + for(h=minorder; h<vorder-1; h++) + for(j=0; j<vorder-h; j++) + { + /* for the derivative in u */ + DCN(2,j) = vs*DCN(2,j) + v*DCN(2,j+1); + + /* for the `point' */ + DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1); + } + + /* derivative direction in v */ + dv[k] = DCN(0,1) - DCN(0,0); + + /* derivative direction in u */ + du[k] = vs*DCN(2,0) + v*DCN(2,1); + + /* last linear de Casteljau step */ + out[k] = vs*DCN(0,0) + v*DCN(0,1); + } + } + else /* minorder == vorder */ + { + for(k=0; k<dim; k++) + { + /* first bilinear de Casteljau step */ + for(i=0; i<uorder-1; i++) + { + DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k); + for(j=0; j<vorder-1; j++) + { + DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k); + DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1); + } + } + + /* remaining bilinear de Casteljau steps until the second last step */ + for(h=2; h<minorder-1; h++) + for(i=0; i<uorder-h; i++) + { + DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0); + for(j=0; j<vorder-h; j++) + { + DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1); + DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1); + } + } + + /* last bilinear de Casteljau step */ + DCN(0,2) = DCN(0,1) - DCN(0,0); + DCN(0,0) = vs*DCN(0,0) + v*DCN(0,1); + for(i=0; i<uorder-1; i++) + { + /* for the derivative in v */ + DCN(i+1,2) = DCN(i+1,1) - DCN(i+1,0); + DCN(i,2) = us*DCN(i,2) + u*DCN(i+1,2); + + /* for the `point' */ + DCN(i+1,0) = vs*DCN(i+1,0) + v*DCN(i+1,1); + DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0); + } + + /* remaining linear de Casteljau steps until the second last step */ + for(h=minorder; h<uorder-1; h++) + for(i=0; i<uorder-h; i++) + { + /* for the derivative in v */ + DCN(i,2) = us*DCN(i,2) + u*DCN(i+1,2); + + /* for the `point' */ + DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0); + } + + /* derivative direction in u */ + du[k] = DCN(1,0) - DCN(0,0); + + /* derivative direction in v */ + dv[k] = us*DCN(0,2) + u*DCN(1,2); + + /* last linear de Casteljau step */ + out[k] = us*DCN(0,0) + u*DCN(1,0); + } + } +#undef DCN +#undef CN +} + +/* + * Return the number of components per control point for any type of + * evaluator. Return 0 if bad target. + */ + +static GLint components( GLenum target ) +{ + switch (target) { + case GL_MAP1_VERTEX_3: return 3; + case GL_MAP1_VERTEX_4: return 4; + case GL_MAP1_INDEX: return 1; + case GL_MAP1_COLOR_4: return 4; + case GL_MAP1_NORMAL: return 3; + case GL_MAP1_TEXTURE_COORD_1: return 1; + case GL_MAP1_TEXTURE_COORD_2: return 2; + case GL_MAP1_TEXTURE_COORD_3: return 3; + case GL_MAP1_TEXTURE_COORD_4: return 4; + case GL_MAP2_VERTEX_3: return 3; + case GL_MAP2_VERTEX_4: return 4; + case GL_MAP2_INDEX: return 1; + case GL_MAP2_COLOR_4: return 4; + case GL_MAP2_NORMAL: return 3; + case GL_MAP2_TEXTURE_COORD_1: return 1; + case GL_MAP2_TEXTURE_COORD_2: return 2; + case GL_MAP2_TEXTURE_COORD_3: return 3; + case GL_MAP2_TEXTURE_COORD_4: return 4; + default: return 0; + } +} + + +/**********************************************************************/ +/*** Copy and deallocate control points ***/ +/**********************************************************************/ + + +/* + * Copy 1-parametric evaluator control points from user-specified + * memory space to a buffer of contiguous control points. + * Input: see glMap1f for details + * Return: pointer to buffer of contiguous control points or NULL if out + * of memory. + */ +GLfloat *gl_copy_map_points1f( GLenum target, + GLint ustride, GLint uorder, + const GLfloat *points ) +{ + GLfloat *buffer, *p; + GLint i, k, size = components(target); + + if (!points || size==0) { + return NULL; + } + + buffer = (GLfloat *) malloc(uorder * size * sizeof(GLfloat)); + + if(buffer) + for(i=0, p=buffer; i<uorder; i++, points+=ustride) + for(k=0; k<size; k++) + *p++ = points[k]; + + return buffer; +} + + + +/* + * Same as above but convert doubles to floats. + */ +GLfloat *gl_copy_map_points1d( GLenum target, + GLint ustride, GLint uorder, + const GLdouble *points ) +{ + GLfloat *buffer, *p; + GLint i, k, size = components(target); + + if (!points || size==0) { + return NULL; + } + + buffer = (GLfloat *) malloc(uorder * size * sizeof(GLfloat)); + + if(buffer) + for(i=0, p=buffer; i<uorder; i++, points+=ustride) + for(k=0; k<size; k++) + *p++ = (GLfloat) points[k]; + + return buffer; +} + + + +/* + * Copy 2-parametric evaluator control points from user-specified + * memory space to a buffer of contiguous control points. + * Additional memory is allocated to be used by the horner and + * de Casteljau evaluation schemes. + * + * Input: see glMap2f for details + * Return: pointer to buffer of contiguous control points or NULL if out + * of memory. + */ +GLfloat *gl_copy_map_points2f( GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLfloat *points ) +{ + GLfloat *buffer, *p; + GLint i, j, k, size, dsize, hsize; + GLint uinc; + + size = components(target); + + if (!points || size==0) { + return NULL; + } + + /* max(uorder, vorder) additional points are used in */ + /* horner evaluation and uorder*vorder additional */ + /* values are needed for de Casteljau */ + dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder; + hsize = (uorder > vorder ? uorder : vorder)*size; + + if(hsize>dsize) + buffer = (GLfloat *) malloc((uorder*vorder*size+hsize)*sizeof(GLfloat)); + else + buffer = (GLfloat *) malloc((uorder*vorder*size+dsize)*sizeof(GLfloat)); + + /* compute the increment value for the u-loop */ + uinc = ustride - vorder*vstride; + + if (buffer) + for (i=0, p=buffer; i<uorder; i++, points += uinc) + for (j=0; j<vorder; j++, points += vstride) + for (k=0; k<size; k++) + *p++ = points[k]; + + return buffer; +} + + + +/* + * Same as above but convert doubles to floats. + */ +GLfloat *gl_copy_map_points2d(GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLdouble *points ) +{ + GLfloat *buffer, *p; + GLint i, j, k, size, hsize, dsize; + GLint uinc; + + size = components(target); + + if (!points || size==0) { + return NULL; + } + + /* max(uorder, vorder) additional points are used in */ + /* horner evaluation and uorder*vorder additional */ + /* values are needed for de Casteljau */ + dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder; + hsize = (uorder > vorder ? uorder : vorder)*size; + + if(hsize>dsize) + buffer = (GLfloat *) malloc((uorder*vorder*size+hsize)*sizeof(GLfloat)); + else + buffer = (GLfloat *) malloc((uorder*vorder*size+dsize)*sizeof(GLfloat)); + + /* compute the increment value for the u-loop */ + uinc = ustride - vorder*vstride; + + if (buffer) + for (i=0, p=buffer; i<uorder; i++, points += uinc) + for (j=0; j<vorder; j++, points += vstride) + for (k=0; k<size; k++) + *p++ = (GLfloat) points[k]; + + return buffer; +} + + +/* + * This function is called by the display list deallocator function to + * specify that a given set of control points are no longer needed. + */ +void gl_free_control_points( GLcontext* ctx, GLenum target, GLfloat *data ) +{ + struct gl_1d_map *map1 = NULL; + struct gl_2d_map *map2 = NULL; + + switch (target) { + case GL_MAP1_VERTEX_3: + map1 = &ctx->EvalMap.Map1Vertex3; + break; + case GL_MAP1_VERTEX_4: + map1 = &ctx->EvalMap.Map1Vertex4; + break; + case GL_MAP1_INDEX: + map1 = &ctx->EvalMap.Map1Index; + break; + case GL_MAP1_COLOR_4: + map1 = &ctx->EvalMap.Map1Color4; + break; + case GL_MAP1_NORMAL: + map1 = &ctx->EvalMap.Map1Normal; + break; + case GL_MAP1_TEXTURE_COORD_1: + map1 = &ctx->EvalMap.Map1Texture1; + break; + case GL_MAP1_TEXTURE_COORD_2: + map1 = &ctx->EvalMap.Map1Texture2; + break; + case GL_MAP1_TEXTURE_COORD_3: + map1 = &ctx->EvalMap.Map1Texture3; + break; + case GL_MAP1_TEXTURE_COORD_4: + map1 = &ctx->EvalMap.Map1Texture4; + break; + case GL_MAP2_VERTEX_3: + map2 = &ctx->EvalMap.Map2Vertex3; + break; + case GL_MAP2_VERTEX_4: + map2 = &ctx->EvalMap.Map2Vertex4; + break; + case GL_MAP2_INDEX: + map2 = &ctx->EvalMap.Map2Index; + break; + case GL_MAP2_COLOR_4: + map2 = &ctx->EvalMap.Map2Color4; + break; + case GL_MAP2_NORMAL: + map2 = &ctx->EvalMap.Map2Normal; + break; + case GL_MAP2_TEXTURE_COORD_1: + map2 = &ctx->EvalMap.Map2Texture1; + break; + case GL_MAP2_TEXTURE_COORD_2: + map2 = &ctx->EvalMap.Map2Texture2; + break; + case GL_MAP2_TEXTURE_COORD_3: + map2 = &ctx->EvalMap.Map2Texture3; + break; + case GL_MAP2_TEXTURE_COORD_4: + map2 = &ctx->EvalMap.Map2Texture4; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "gl_free_control_points" ); + return; + } + + if (map1) { + if (data==map1->Points) { + /* The control points in the display list are currently */ + /* being used so we can mark them as discard-able. */ + map1->Retain = GL_FALSE; + } + else { + /* The control points in the display list are not currently */ + /* being used. */ + free( data ); + } + } + if (map2) { + if (data==map2->Points) { + /* The control points in the display list are currently */ + /* being used so we can mark them as discard-able. */ + map2->Retain = GL_FALSE; + } + else { + /* The control points in the display list are not currently */ + /* being used. */ + free( data ); + } + } + +} + + + +/**********************************************************************/ +/*** API entry points ***/ +/**********************************************************************/ + + +/* + * Note that the array of control points must be 'unpacked' at this time. + * Input: retain - if TRUE, this control point data is also in a display + * list and can't be freed until the list is freed. + */ +void gl_Map1f( GLcontext* ctx, GLenum target, + GLfloat u1, GLfloat u2, GLint stride, + GLint order, const GLfloat *points, GLboolean retain ) +{ + GLint k; + + if (!points) { + gl_error( ctx, GL_OUT_OF_MEMORY, "glMap1f" ); + return; + } + + /* may be a new stride after copying control points */ + stride = components( target ); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMap1"); + + if (u1==u2) { + gl_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" ); + return; + } + + if (order<1 || order>MAX_EVAL_ORDER) { + gl_error( ctx, GL_INVALID_VALUE, "glMap1(order)" ); + return; + } + + k = components( target ); + if (k==0) { + gl_error( ctx, GL_INVALID_ENUM, "glMap1(target)" ); + } + + if (stride < k) { + gl_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" ); + return; + } + + switch (target) { + case GL_MAP1_VERTEX_3: + ctx->EvalMap.Map1Vertex3.Order = order; + ctx->EvalMap.Map1Vertex3.u1 = u1; + ctx->EvalMap.Map1Vertex3.u2 = u2; + ctx->EvalMap.Map1Vertex3.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Vertex3.Points + && !ctx->EvalMap.Map1Vertex3.Retain) { + free( ctx->EvalMap.Map1Vertex3.Points ); + } + ctx->EvalMap.Map1Vertex3.Points = (GLfloat *) points; + ctx->EvalMap.Map1Vertex3.Retain = retain; + break; + case GL_MAP1_VERTEX_4: + ctx->EvalMap.Map1Vertex4.Order = order; + ctx->EvalMap.Map1Vertex4.u1 = u1; + ctx->EvalMap.Map1Vertex4.u2 = u2; + ctx->EvalMap.Map1Vertex4.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Vertex4.Points + && !ctx->EvalMap.Map1Vertex4.Retain) { + free( ctx->EvalMap.Map1Vertex4.Points ); + } + ctx->EvalMap.Map1Vertex4.Points = (GLfloat *) points; + ctx->EvalMap.Map1Vertex4.Retain = retain; + break; + case GL_MAP1_INDEX: + ctx->EvalMap.Map1Index.Order = order; + ctx->EvalMap.Map1Index.u1 = u1; + ctx->EvalMap.Map1Index.u2 = u2; + ctx->EvalMap.Map1Index.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Index.Points + && !ctx->EvalMap.Map1Index.Retain) { + free( ctx->EvalMap.Map1Index.Points ); + } + ctx->EvalMap.Map1Index.Points = (GLfloat *) points; + ctx->EvalMap.Map1Index.Retain = retain; + break; + case GL_MAP1_COLOR_4: + ctx->EvalMap.Map1Color4.Order = order; + ctx->EvalMap.Map1Color4.u1 = u1; + ctx->EvalMap.Map1Color4.u2 = u2; + ctx->EvalMap.Map1Color4.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Color4.Points + && !ctx->EvalMap.Map1Color4.Retain) { + free( ctx->EvalMap.Map1Color4.Points ); + } + ctx->EvalMap.Map1Color4.Points = (GLfloat *) points; + ctx->EvalMap.Map1Color4.Retain = retain; + break; + case GL_MAP1_NORMAL: + ctx->EvalMap.Map1Normal.Order = order; + ctx->EvalMap.Map1Normal.u1 = u1; + ctx->EvalMap.Map1Normal.u2 = u2; + ctx->EvalMap.Map1Normal.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Normal.Points + && !ctx->EvalMap.Map1Normal.Retain) { + free( ctx->EvalMap.Map1Normal.Points ); + } + ctx->EvalMap.Map1Normal.Points = (GLfloat *) points; + ctx->EvalMap.Map1Normal.Retain = retain; + break; + case GL_MAP1_TEXTURE_COORD_1: + ctx->EvalMap.Map1Texture1.Order = order; + ctx->EvalMap.Map1Texture1.u1 = u1; + ctx->EvalMap.Map1Texture1.u2 = u2; + ctx->EvalMap.Map1Texture1.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Texture1.Points + && !ctx->EvalMap.Map1Texture1.Retain) { + free( ctx->EvalMap.Map1Texture1.Points ); + } + ctx->EvalMap.Map1Texture1.Points = (GLfloat *) points; + ctx->EvalMap.Map1Texture1.Retain = retain; + break; + case GL_MAP1_TEXTURE_COORD_2: + ctx->EvalMap.Map1Texture2.Order = order; + ctx->EvalMap.Map1Texture2.u1 = u1; + ctx->EvalMap.Map1Texture2.u2 = u2; + ctx->EvalMap.Map1Texture2.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Texture2.Points + && !ctx->EvalMap.Map1Texture2.Retain) { + free( ctx->EvalMap.Map1Texture2.Points ); + } + ctx->EvalMap.Map1Texture2.Points = (GLfloat *) points; + ctx->EvalMap.Map1Texture2.Retain = retain; + break; + case GL_MAP1_TEXTURE_COORD_3: + ctx->EvalMap.Map1Texture3.Order = order; + ctx->EvalMap.Map1Texture3.u1 = u1; + ctx->EvalMap.Map1Texture3.u2 = u2; + ctx->EvalMap.Map1Texture3.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Texture3.Points + && !ctx->EvalMap.Map1Texture3.Retain) { + free( ctx->EvalMap.Map1Texture3.Points ); + } + ctx->EvalMap.Map1Texture3.Points = (GLfloat *) points; + ctx->EvalMap.Map1Texture3.Retain = retain; + break; + case GL_MAP1_TEXTURE_COORD_4: + ctx->EvalMap.Map1Texture4.Order = order; + ctx->EvalMap.Map1Texture4.u1 = u1; + ctx->EvalMap.Map1Texture4.u2 = u2; + ctx->EvalMap.Map1Texture4.du = 1.0 / (u2 - u1); + if (ctx->EvalMap.Map1Texture4.Points + && !ctx->EvalMap.Map1Texture4.Retain) { + free( ctx->EvalMap.Map1Texture4.Points ); + } + ctx->EvalMap.Map1Texture4.Points = (GLfloat *) points; + ctx->EvalMap.Map1Texture4.Retain = retain; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glMap1(target)" ); + } +} + + + + +/* + * Note that the array of control points must be 'unpacked' at this time. + * Input: retain - if TRUE, this control point data is also in a display + * list and can't be freed until the list is freed. + */ +void gl_Map2f( GLcontext* ctx, GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points, GLboolean retain ) +{ + GLint k; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMap2"); + + if (u1==u2) { + gl_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" ); + return; + } + + if (v1==v2) { + gl_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" ); + return; + } + + if (uorder<1 || uorder>MAX_EVAL_ORDER) { + gl_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" ); + return; + } + + if (vorder<1 || vorder>MAX_EVAL_ORDER) { + gl_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" ); + return; + } + + k = components( target ); + if (k==0) { + gl_error( ctx, GL_INVALID_ENUM, "glMap2(target)" ); + } + + if (ustride < k) { + gl_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" ); + return; + } + if (vstride < k) { + gl_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" ); + return; + } + + switch (target) { + case GL_MAP2_VERTEX_3: + ctx->EvalMap.Map2Vertex3.Uorder = uorder; + ctx->EvalMap.Map2Vertex3.u1 = u1; + ctx->EvalMap.Map2Vertex3.u2 = u2; + ctx->EvalMap.Map2Vertex3.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Vertex3.Vorder = vorder; + ctx->EvalMap.Map2Vertex3.v1 = v1; + ctx->EvalMap.Map2Vertex3.v2 = v2; + ctx->EvalMap.Map2Vertex3.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Vertex3.Points + && !ctx->EvalMap.Map2Vertex3.Retain) { + free( ctx->EvalMap.Map2Vertex3.Points ); + } + ctx->EvalMap.Map2Vertex3.Retain = retain; + ctx->EvalMap.Map2Vertex3.Points = (GLfloat *) points; + break; + case GL_MAP2_VERTEX_4: + ctx->EvalMap.Map2Vertex4.Uorder = uorder; + ctx->EvalMap.Map2Vertex4.u1 = u1; + ctx->EvalMap.Map2Vertex4.u2 = u2; + ctx->EvalMap.Map2Vertex4.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Vertex4.Vorder = vorder; + ctx->EvalMap.Map2Vertex4.v1 = v1; + ctx->EvalMap.Map2Vertex4.v2 = v2; + ctx->EvalMap.Map2Vertex4.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Vertex4.Points + && !ctx->EvalMap.Map2Vertex4.Retain) { + free( ctx->EvalMap.Map2Vertex4.Points ); + } + ctx->EvalMap.Map2Vertex4.Points = (GLfloat *) points; + ctx->EvalMap.Map2Vertex4.Retain = retain; + break; + case GL_MAP2_INDEX: + ctx->EvalMap.Map2Index.Uorder = uorder; + ctx->EvalMap.Map2Index.u1 = u1; + ctx->EvalMap.Map2Index.u2 = u2; + ctx->EvalMap.Map2Index.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Index.Vorder = vorder; + ctx->EvalMap.Map2Index.v1 = v1; + ctx->EvalMap.Map2Index.v2 = v2; + ctx->EvalMap.Map2Index.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Index.Points + && !ctx->EvalMap.Map2Index.Retain) { + free( ctx->EvalMap.Map2Index.Points ); + } + ctx->EvalMap.Map2Index.Retain = retain; + ctx->EvalMap.Map2Index.Points = (GLfloat *) points; + break; + case GL_MAP2_COLOR_4: + ctx->EvalMap.Map2Color4.Uorder = uorder; + ctx->EvalMap.Map2Color4.u1 = u1; + ctx->EvalMap.Map2Color4.u2 = u2; + ctx->EvalMap.Map2Color4.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Color4.Vorder = vorder; + ctx->EvalMap.Map2Color4.v1 = v1; + ctx->EvalMap.Map2Color4.v2 = v2; + ctx->EvalMap.Map2Color4.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Color4.Points + && !ctx->EvalMap.Map2Color4.Retain) { + free( ctx->EvalMap.Map2Color4.Points ); + } + ctx->EvalMap.Map2Color4.Retain = retain; + ctx->EvalMap.Map2Color4.Points = (GLfloat *) points; + break; + case GL_MAP2_NORMAL: + ctx->EvalMap.Map2Normal.Uorder = uorder; + ctx->EvalMap.Map2Normal.u1 = u1; + ctx->EvalMap.Map2Normal.u2 = u2; + ctx->EvalMap.Map2Normal.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Normal.Vorder = vorder; + ctx->EvalMap.Map2Normal.v1 = v1; + ctx->EvalMap.Map2Normal.v2 = v2; + ctx->EvalMap.Map2Normal.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Normal.Points + && !ctx->EvalMap.Map2Normal.Retain) { + free( ctx->EvalMap.Map2Normal.Points ); + } + ctx->EvalMap.Map2Normal.Retain = retain; + ctx->EvalMap.Map2Normal.Points = (GLfloat *) points; + break; + case GL_MAP2_TEXTURE_COORD_1: + ctx->EvalMap.Map2Texture1.Uorder = uorder; + ctx->EvalMap.Map2Texture1.u1 = u1; + ctx->EvalMap.Map2Texture1.u2 = u2; + ctx->EvalMap.Map2Texture1.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Texture1.Vorder = vorder; + ctx->EvalMap.Map2Texture1.v1 = v1; + ctx->EvalMap.Map2Texture1.v2 = v2; + ctx->EvalMap.Map2Texture1.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Texture1.Points + && !ctx->EvalMap.Map2Texture1.Retain) { + free( ctx->EvalMap.Map2Texture1.Points ); + } + ctx->EvalMap.Map2Texture1.Retain = retain; + ctx->EvalMap.Map2Texture1.Points = (GLfloat *) points; + break; + case GL_MAP2_TEXTURE_COORD_2: + ctx->EvalMap.Map2Texture2.Uorder = uorder; + ctx->EvalMap.Map2Texture2.u1 = u1; + ctx->EvalMap.Map2Texture2.u2 = u2; + ctx->EvalMap.Map2Texture2.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Texture2.Vorder = vorder; + ctx->EvalMap.Map2Texture2.v1 = v1; + ctx->EvalMap.Map2Texture2.v2 = v2; + ctx->EvalMap.Map2Texture2.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Texture2.Points + && !ctx->EvalMap.Map2Texture2.Retain) { + free( ctx->EvalMap.Map2Texture2.Points ); + } + ctx->EvalMap.Map2Texture2.Retain = retain; + ctx->EvalMap.Map2Texture2.Points = (GLfloat *) points; + break; + case GL_MAP2_TEXTURE_COORD_3: + ctx->EvalMap.Map2Texture3.Uorder = uorder; + ctx->EvalMap.Map2Texture3.u1 = u1; + ctx->EvalMap.Map2Texture3.u2 = u2; + ctx->EvalMap.Map2Texture3.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Texture3.Vorder = vorder; + ctx->EvalMap.Map2Texture3.v1 = v1; + ctx->EvalMap.Map2Texture3.v2 = v2; + ctx->EvalMap.Map2Texture3.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Texture3.Points + && !ctx->EvalMap.Map2Texture3.Retain) { + free( ctx->EvalMap.Map2Texture3.Points ); + } + ctx->EvalMap.Map2Texture3.Retain = retain; + ctx->EvalMap.Map2Texture3.Points = (GLfloat *) points; + break; + case GL_MAP2_TEXTURE_COORD_4: + ctx->EvalMap.Map2Texture4.Uorder = uorder; + ctx->EvalMap.Map2Texture4.u1 = u1; + ctx->EvalMap.Map2Texture4.u2 = u2; + ctx->EvalMap.Map2Texture4.du = 1.0 / (u2 - u1); + ctx->EvalMap.Map2Texture4.Vorder = vorder; + ctx->EvalMap.Map2Texture4.v1 = v1; + ctx->EvalMap.Map2Texture4.v2 = v2; + ctx->EvalMap.Map2Texture4.dv = 1.0 / (v2 - v1); + if (ctx->EvalMap.Map2Texture4.Points + && !ctx->EvalMap.Map2Texture4.Retain) { + free( ctx->EvalMap.Map2Texture4.Points ); + } + ctx->EvalMap.Map2Texture4.Retain = retain; + ctx->EvalMap.Map2Texture4.Points = (GLfloat *) points; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glMap2(target)" ); + } +} + + + + + +void gl_GetMapdv( GLcontext* ctx, GLenum target, GLenum query, GLdouble *v ) +{ + GLint i, n; + GLfloat *data; + + switch (query) { + case GL_COEFF: + switch (target) { + case GL_MAP1_COLOR_4: + data = ctx->EvalMap.Map1Color4.Points; + n = ctx->EvalMap.Map1Color4.Order * 4; + break; + case GL_MAP1_INDEX: + data = ctx->EvalMap.Map1Index.Points; + n = ctx->EvalMap.Map1Index.Order; + break; + case GL_MAP1_NORMAL: + data = ctx->EvalMap.Map1Normal.Points; + n = ctx->EvalMap.Map1Normal.Order * 3; + break; + case GL_MAP1_TEXTURE_COORD_1: + data = ctx->EvalMap.Map1Texture1.Points; + n = ctx->EvalMap.Map1Texture1.Order * 1; + break; + case GL_MAP1_TEXTURE_COORD_2: + data = ctx->EvalMap.Map1Texture2.Points; + n = ctx->EvalMap.Map1Texture2.Order * 2; + break; + case GL_MAP1_TEXTURE_COORD_3: + data = ctx->EvalMap.Map1Texture3.Points; + n = ctx->EvalMap.Map1Texture3.Order * 3; + break; + case GL_MAP1_TEXTURE_COORD_4: + data = ctx->EvalMap.Map1Texture4.Points; + n = ctx->EvalMap.Map1Texture4.Order * 4; + break; + case GL_MAP1_VERTEX_3: + data = ctx->EvalMap.Map1Vertex3.Points; + n = ctx->EvalMap.Map1Vertex3.Order * 3; + break; + case GL_MAP1_VERTEX_4: + data = ctx->EvalMap.Map1Vertex4.Points; + n = ctx->EvalMap.Map1Vertex4.Order * 4; + break; + case GL_MAP2_COLOR_4: + data = ctx->EvalMap.Map2Color4.Points; + n = ctx->EvalMap.Map2Color4.Uorder + * ctx->EvalMap.Map2Color4.Vorder * 4; + break; + case GL_MAP2_INDEX: + data = ctx->EvalMap.Map2Index.Points; + n = ctx->EvalMap.Map2Index.Uorder + * ctx->EvalMap.Map2Index.Vorder; + break; + case GL_MAP2_NORMAL: + data = ctx->EvalMap.Map2Normal.Points; + n = ctx->EvalMap.Map2Normal.Uorder + * ctx->EvalMap.Map2Normal.Vorder * 3; + break; + case GL_MAP2_TEXTURE_COORD_1: + data = ctx->EvalMap.Map2Texture1.Points; + n = ctx->EvalMap.Map2Texture1.Uorder + * ctx->EvalMap.Map2Texture1.Vorder * 1; + break; + case GL_MAP2_TEXTURE_COORD_2: + data = ctx->EvalMap.Map2Texture2.Points; + n = ctx->EvalMap.Map2Texture2.Uorder + * ctx->EvalMap.Map2Texture2.Vorder * 2; + break; + case GL_MAP2_TEXTURE_COORD_3: + data = ctx->EvalMap.Map2Texture3.Points; + n = ctx->EvalMap.Map2Texture3.Uorder + * ctx->EvalMap.Map2Texture3.Vorder * 3; + break; + case GL_MAP2_TEXTURE_COORD_4: + data = ctx->EvalMap.Map2Texture4.Points; + n = ctx->EvalMap.Map2Texture4.Uorder + * ctx->EvalMap.Map2Texture4.Vorder * 4; + break; + case GL_MAP2_VERTEX_3: + data = ctx->EvalMap.Map2Vertex3.Points; + n = ctx->EvalMap.Map2Vertex3.Uorder + * ctx->EvalMap.Map2Vertex3.Vorder * 3; + break; + case GL_MAP2_VERTEX_4: + data = ctx->EvalMap.Map2Vertex4.Points; + n = ctx->EvalMap.Map2Vertex4.Uorder + * ctx->EvalMap.Map2Vertex4.Vorder * 4; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" ); + return; + } + if (data) { + for (i=0;i<n;i++) { + v[i] = data[i]; + } + } + break; + case GL_ORDER: + switch (target) { + case GL_MAP1_COLOR_4: + *v = ctx->EvalMap.Map1Color4.Order; + break; + case GL_MAP1_INDEX: + *v = ctx->EvalMap.Map1Index.Order; + break; + case GL_MAP1_NORMAL: + *v = ctx->EvalMap.Map1Normal.Order; + break; + case GL_MAP1_TEXTURE_COORD_1: + *v = ctx->EvalMap.Map1Texture1.Order; + break; + case GL_MAP1_TEXTURE_COORD_2: + *v = ctx->EvalMap.Map1Texture2.Order; + break; + case GL_MAP1_TEXTURE_COORD_3: + *v = ctx->EvalMap.Map1Texture3.Order; + break; + case GL_MAP1_TEXTURE_COORD_4: + *v = ctx->EvalMap.Map1Texture4.Order; + break; + case GL_MAP1_VERTEX_3: + *v = ctx->EvalMap.Map1Vertex3.Order; + break; + case GL_MAP1_VERTEX_4: + *v = ctx->EvalMap.Map1Vertex4.Order; + break; + case GL_MAP2_COLOR_4: + v[0] = ctx->EvalMap.Map2Color4.Uorder; + v[1] = ctx->EvalMap.Map2Color4.Vorder; + break; + case GL_MAP2_INDEX: + v[0] = ctx->EvalMap.Map2Index.Uorder; + v[1] = ctx->EvalMap.Map2Index.Vorder; + break; + case GL_MAP2_NORMAL: + v[0] = ctx->EvalMap.Map2Normal.Uorder; + v[1] = ctx->EvalMap.Map2Normal.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_1: + v[0] = ctx->EvalMap.Map2Texture1.Uorder; + v[1] = ctx->EvalMap.Map2Texture1.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_2: + v[0] = ctx->EvalMap.Map2Texture2.Uorder; + v[1] = ctx->EvalMap.Map2Texture2.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_3: + v[0] = ctx->EvalMap.Map2Texture3.Uorder; + v[1] = ctx->EvalMap.Map2Texture3.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_4: + v[0] = ctx->EvalMap.Map2Texture4.Uorder; + v[1] = ctx->EvalMap.Map2Texture4.Vorder; + break; + case GL_MAP2_VERTEX_3: + v[0] = ctx->EvalMap.Map2Vertex3.Uorder; + v[1] = ctx->EvalMap.Map2Vertex3.Vorder; + break; + case GL_MAP2_VERTEX_4: + v[0] = ctx->EvalMap.Map2Vertex4.Uorder; + v[1] = ctx->EvalMap.Map2Vertex4.Vorder; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" ); + return; + } + break; + case GL_DOMAIN: + switch (target) { + case GL_MAP1_COLOR_4: + v[0] = ctx->EvalMap.Map1Color4.u1; + v[1] = ctx->EvalMap.Map1Color4.u2; + break; + case GL_MAP1_INDEX: + v[0] = ctx->EvalMap.Map1Index.u1; + v[1] = ctx->EvalMap.Map1Index.u2; + break; + case GL_MAP1_NORMAL: + v[0] = ctx->EvalMap.Map1Normal.u1; + v[1] = ctx->EvalMap.Map1Normal.u2; + break; + case GL_MAP1_TEXTURE_COORD_1: + v[0] = ctx->EvalMap.Map1Texture1.u1; + v[1] = ctx->EvalMap.Map1Texture1.u2; + break; + case GL_MAP1_TEXTURE_COORD_2: + v[0] = ctx->EvalMap.Map1Texture2.u1; + v[1] = ctx->EvalMap.Map1Texture2.u2; + break; + case GL_MAP1_TEXTURE_COORD_3: + v[0] = ctx->EvalMap.Map1Texture3.u1; + v[1] = ctx->EvalMap.Map1Texture3.u2; + break; + case GL_MAP1_TEXTURE_COORD_4: + v[0] = ctx->EvalMap.Map1Texture4.u1; + v[1] = ctx->EvalMap.Map1Texture4.u2; + break; + case GL_MAP1_VERTEX_3: + v[0] = ctx->EvalMap.Map1Vertex3.u1; + v[1] = ctx->EvalMap.Map1Vertex3.u2; + break; + case GL_MAP1_VERTEX_4: + v[0] = ctx->EvalMap.Map1Vertex4.u1; + v[1] = ctx->EvalMap.Map1Vertex4.u2; + break; + case GL_MAP2_COLOR_4: + v[0] = ctx->EvalMap.Map2Color4.u1; + v[1] = ctx->EvalMap.Map2Color4.u2; + v[2] = ctx->EvalMap.Map2Color4.v1; + v[3] = ctx->EvalMap.Map2Color4.v2; + break; + case GL_MAP2_INDEX: + v[0] = ctx->EvalMap.Map2Index.u1; + v[1] = ctx->EvalMap.Map2Index.u2; + v[2] = ctx->EvalMap.Map2Index.v1; + v[3] = ctx->EvalMap.Map2Index.v2; + break; + case GL_MAP2_NORMAL: + v[0] = ctx->EvalMap.Map2Normal.u1; + v[1] = ctx->EvalMap.Map2Normal.u2; + v[2] = ctx->EvalMap.Map2Normal.v1; + v[3] = ctx->EvalMap.Map2Normal.v2; + break; + case GL_MAP2_TEXTURE_COORD_1: + v[0] = ctx->EvalMap.Map2Texture1.u1; + v[1] = ctx->EvalMap.Map2Texture1.u2; + v[2] = ctx->EvalMap.Map2Texture1.v1; + v[3] = ctx->EvalMap.Map2Texture1.v2; + break; + case GL_MAP2_TEXTURE_COORD_2: + v[0] = ctx->EvalMap.Map2Texture2.u1; + v[1] = ctx->EvalMap.Map2Texture2.u2; + v[2] = ctx->EvalMap.Map2Texture2.v1; + v[3] = ctx->EvalMap.Map2Texture2.v2; + break; + case GL_MAP2_TEXTURE_COORD_3: + v[0] = ctx->EvalMap.Map2Texture3.u1; + v[1] = ctx->EvalMap.Map2Texture3.u2; + v[2] = ctx->EvalMap.Map2Texture3.v1; + v[3] = ctx->EvalMap.Map2Texture3.v2; + break; + case GL_MAP2_TEXTURE_COORD_4: + v[0] = ctx->EvalMap.Map2Texture4.u1; + v[1] = ctx->EvalMap.Map2Texture4.u2; + v[2] = ctx->EvalMap.Map2Texture4.v1; + v[3] = ctx->EvalMap.Map2Texture4.v2; + break; + case GL_MAP2_VERTEX_3: + v[0] = ctx->EvalMap.Map2Vertex3.u1; + v[1] = ctx->EvalMap.Map2Vertex3.u2; + v[2] = ctx->EvalMap.Map2Vertex3.v1; + v[3] = ctx->EvalMap.Map2Vertex3.v2; + break; + case GL_MAP2_VERTEX_4: + v[0] = ctx->EvalMap.Map2Vertex4.u1; + v[1] = ctx->EvalMap.Map2Vertex4.u2; + v[2] = ctx->EvalMap.Map2Vertex4.v1; + v[3] = ctx->EvalMap.Map2Vertex4.v2; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" ); + } +} + + +void gl_GetMapfv( GLcontext* ctx, GLenum target, GLenum query, GLfloat *v ) +{ + GLint i, n; + GLfloat *data; + + switch (query) { + case GL_COEFF: + switch (target) { + case GL_MAP1_COLOR_4: + data = ctx->EvalMap.Map1Color4.Points; + n = ctx->EvalMap.Map1Color4.Order * 4; + break; + case GL_MAP1_INDEX: + data = ctx->EvalMap.Map1Index.Points; + n = ctx->EvalMap.Map1Index.Order; + break; + case GL_MAP1_NORMAL: + data = ctx->EvalMap.Map1Normal.Points; + n = ctx->EvalMap.Map1Normal.Order * 3; + break; + case GL_MAP1_TEXTURE_COORD_1: + data = ctx->EvalMap.Map1Texture1.Points; + n = ctx->EvalMap.Map1Texture1.Order * 1; + break; + case GL_MAP1_TEXTURE_COORD_2: + data = ctx->EvalMap.Map1Texture2.Points; + n = ctx->EvalMap.Map1Texture2.Order * 2; + break; + case GL_MAP1_TEXTURE_COORD_3: + data = ctx->EvalMap.Map1Texture3.Points; + n = ctx->EvalMap.Map1Texture3.Order * 3; + break; + case GL_MAP1_TEXTURE_COORD_4: + data = ctx->EvalMap.Map1Texture4.Points; + n = ctx->EvalMap.Map1Texture4.Order * 4; + break; + case GL_MAP1_VERTEX_3: + data = ctx->EvalMap.Map1Vertex3.Points; + n = ctx->EvalMap.Map1Vertex3.Order * 3; + break; + case GL_MAP1_VERTEX_4: + data = ctx->EvalMap.Map1Vertex4.Points; + n = ctx->EvalMap.Map1Vertex4.Order * 4; + break; + case GL_MAP2_COLOR_4: + data = ctx->EvalMap.Map2Color4.Points; + n = ctx->EvalMap.Map2Color4.Uorder + * ctx->EvalMap.Map2Color4.Vorder * 4; + break; + case GL_MAP2_INDEX: + data = ctx->EvalMap.Map2Index.Points; + n = ctx->EvalMap.Map2Index.Uorder + * ctx->EvalMap.Map2Index.Vorder; + break; + case GL_MAP2_NORMAL: + data = ctx->EvalMap.Map2Normal.Points; + n = ctx->EvalMap.Map2Normal.Uorder + * ctx->EvalMap.Map2Normal.Vorder * 3; + break; + case GL_MAP2_TEXTURE_COORD_1: + data = ctx->EvalMap.Map2Texture1.Points; + n = ctx->EvalMap.Map2Texture1.Uorder + * ctx->EvalMap.Map2Texture1.Vorder * 1; + break; + case GL_MAP2_TEXTURE_COORD_2: + data = ctx->EvalMap.Map2Texture2.Points; + n = ctx->EvalMap.Map2Texture2.Uorder + * ctx->EvalMap.Map2Texture2.Vorder * 2; + break; + case GL_MAP2_TEXTURE_COORD_3: + data = ctx->EvalMap.Map2Texture3.Points; + n = ctx->EvalMap.Map2Texture3.Uorder + * ctx->EvalMap.Map2Texture3.Vorder * 3; + break; + case GL_MAP2_TEXTURE_COORD_4: + data = ctx->EvalMap.Map2Texture4.Points; + n = ctx->EvalMap.Map2Texture4.Uorder + * ctx->EvalMap.Map2Texture4.Vorder * 4; + break; + case GL_MAP2_VERTEX_3: + data = ctx->EvalMap.Map2Vertex3.Points; + n = ctx->EvalMap.Map2Vertex3.Uorder + * ctx->EvalMap.Map2Vertex3.Vorder * 3; + break; + case GL_MAP2_VERTEX_4: + data = ctx->EvalMap.Map2Vertex4.Points; + n = ctx->EvalMap.Map2Vertex4.Uorder + * ctx->EvalMap.Map2Vertex4.Vorder * 4; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" ); + return; + } + if (data) { + for (i=0;i<n;i++) { + v[i] = data[i]; + } + } + break; + case GL_ORDER: + switch (target) { + case GL_MAP1_COLOR_4: + *v = ctx->EvalMap.Map1Color4.Order; + break; + case GL_MAP1_INDEX: + *v = ctx->EvalMap.Map1Index.Order; + break; + case GL_MAP1_NORMAL: + *v = ctx->EvalMap.Map1Normal.Order; + break; + case GL_MAP1_TEXTURE_COORD_1: + *v = ctx->EvalMap.Map1Texture1.Order; + break; + case GL_MAP1_TEXTURE_COORD_2: + *v = ctx->EvalMap.Map1Texture2.Order; + break; + case GL_MAP1_TEXTURE_COORD_3: + *v = ctx->EvalMap.Map1Texture3.Order; + break; + case GL_MAP1_TEXTURE_COORD_4: + *v = ctx->EvalMap.Map1Texture4.Order; + break; + case GL_MAP1_VERTEX_3: + *v = ctx->EvalMap.Map1Vertex3.Order; + break; + case GL_MAP1_VERTEX_4: + *v = ctx->EvalMap.Map1Vertex4.Order; + break; + case GL_MAP2_COLOR_4: + v[0] = ctx->EvalMap.Map2Color4.Uorder; + v[1] = ctx->EvalMap.Map2Color4.Vorder; + break; + case GL_MAP2_INDEX: + v[0] = ctx->EvalMap.Map2Index.Uorder; + v[1] = ctx->EvalMap.Map2Index.Vorder; + break; + case GL_MAP2_NORMAL: + v[0] = ctx->EvalMap.Map2Normal.Uorder; + v[1] = ctx->EvalMap.Map2Normal.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_1: + v[0] = ctx->EvalMap.Map2Texture1.Uorder; + v[1] = ctx->EvalMap.Map2Texture1.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_2: + v[0] = ctx->EvalMap.Map2Texture2.Uorder; + v[1] = ctx->EvalMap.Map2Texture2.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_3: + v[0] = ctx->EvalMap.Map2Texture3.Uorder; + v[1] = ctx->EvalMap.Map2Texture3.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_4: + v[0] = ctx->EvalMap.Map2Texture4.Uorder; + v[1] = ctx->EvalMap.Map2Texture4.Vorder; + break; + case GL_MAP2_VERTEX_3: + v[0] = ctx->EvalMap.Map2Vertex3.Uorder; + v[1] = ctx->EvalMap.Map2Vertex3.Vorder; + break; + case GL_MAP2_VERTEX_4: + v[0] = ctx->EvalMap.Map2Vertex4.Uorder; + v[1] = ctx->EvalMap.Map2Vertex4.Vorder; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" ); + return; + } + break; + case GL_DOMAIN: + switch (target) { + case GL_MAP1_COLOR_4: + v[0] = ctx->EvalMap.Map1Color4.u1; + v[1] = ctx->EvalMap.Map1Color4.u2; + break; + case GL_MAP1_INDEX: + v[0] = ctx->EvalMap.Map1Index.u1; + v[1] = ctx->EvalMap.Map1Index.u2; + break; + case GL_MAP1_NORMAL: + v[0] = ctx->EvalMap.Map1Normal.u1; + v[1] = ctx->EvalMap.Map1Normal.u2; + break; + case GL_MAP1_TEXTURE_COORD_1: + v[0] = ctx->EvalMap.Map1Texture1.u1; + v[1] = ctx->EvalMap.Map1Texture1.u2; + break; + case GL_MAP1_TEXTURE_COORD_2: + v[0] = ctx->EvalMap.Map1Texture2.u1; + v[1] = ctx->EvalMap.Map1Texture2.u2; + break; + case GL_MAP1_TEXTURE_COORD_3: + v[0] = ctx->EvalMap.Map1Texture3.u1; + v[1] = ctx->EvalMap.Map1Texture3.u2; + break; + case GL_MAP1_TEXTURE_COORD_4: + v[0] = ctx->EvalMap.Map1Texture4.u1; + v[1] = ctx->EvalMap.Map1Texture4.u2; + break; + case GL_MAP1_VERTEX_3: + v[0] = ctx->EvalMap.Map1Vertex3.u1; + v[1] = ctx->EvalMap.Map1Vertex3.u2; + break; + case GL_MAP1_VERTEX_4: + v[0] = ctx->EvalMap.Map1Vertex4.u1; + v[1] = ctx->EvalMap.Map1Vertex4.u2; + break; + case GL_MAP2_COLOR_4: + v[0] = ctx->EvalMap.Map2Color4.u1; + v[1] = ctx->EvalMap.Map2Color4.u2; + v[2] = ctx->EvalMap.Map2Color4.v1; + v[3] = ctx->EvalMap.Map2Color4.v2; + break; + case GL_MAP2_INDEX: + v[0] = ctx->EvalMap.Map2Index.u1; + v[1] = ctx->EvalMap.Map2Index.u2; + v[2] = ctx->EvalMap.Map2Index.v1; + v[3] = ctx->EvalMap.Map2Index.v2; + break; + case GL_MAP2_NORMAL: + v[0] = ctx->EvalMap.Map2Normal.u1; + v[1] = ctx->EvalMap.Map2Normal.u2; + v[2] = ctx->EvalMap.Map2Normal.v1; + v[3] = ctx->EvalMap.Map2Normal.v2; + break; + case GL_MAP2_TEXTURE_COORD_1: + v[0] = ctx->EvalMap.Map2Texture1.u1; + v[1] = ctx->EvalMap.Map2Texture1.u2; + v[2] = ctx->EvalMap.Map2Texture1.v1; + v[3] = ctx->EvalMap.Map2Texture1.v2; + break; + case GL_MAP2_TEXTURE_COORD_2: + v[0] = ctx->EvalMap.Map2Texture2.u1; + v[1] = ctx->EvalMap.Map2Texture2.u2; + v[2] = ctx->EvalMap.Map2Texture2.v1; + v[3] = ctx->EvalMap.Map2Texture2.v2; + break; + case GL_MAP2_TEXTURE_COORD_3: + v[0] = ctx->EvalMap.Map2Texture3.u1; + v[1] = ctx->EvalMap.Map2Texture3.u2; + v[2] = ctx->EvalMap.Map2Texture3.v1; + v[3] = ctx->EvalMap.Map2Texture3.v2; + break; + case GL_MAP2_TEXTURE_COORD_4: + v[0] = ctx->EvalMap.Map2Texture4.u1; + v[1] = ctx->EvalMap.Map2Texture4.u2; + v[2] = ctx->EvalMap.Map2Texture4.v1; + v[3] = ctx->EvalMap.Map2Texture4.v2; + break; + case GL_MAP2_VERTEX_3: + v[0] = ctx->EvalMap.Map2Vertex3.u1; + v[1] = ctx->EvalMap.Map2Vertex3.u2; + v[2] = ctx->EvalMap.Map2Vertex3.v1; + v[3] = ctx->EvalMap.Map2Vertex3.v2; + break; + case GL_MAP2_VERTEX_4: + v[0] = ctx->EvalMap.Map2Vertex4.u1; + v[1] = ctx->EvalMap.Map2Vertex4.u2; + v[2] = ctx->EvalMap.Map2Vertex4.v1; + v[3] = ctx->EvalMap.Map2Vertex4.v2; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" ); + } +} + + +void gl_GetMapiv( GLcontext* ctx, GLenum target, GLenum query, GLint *v ) +{ + GLuint i, n; + GLfloat *data; + + switch (query) { + case GL_COEFF: + switch (target) { + case GL_MAP1_COLOR_4: + data = ctx->EvalMap.Map1Color4.Points; + n = ctx->EvalMap.Map1Color4.Order * 4; + break; + case GL_MAP1_INDEX: + data = ctx->EvalMap.Map1Index.Points; + n = ctx->EvalMap.Map1Index.Order; + break; + case GL_MAP1_NORMAL: + data = ctx->EvalMap.Map1Normal.Points; + n = ctx->EvalMap.Map1Normal.Order * 3; + break; + case GL_MAP1_TEXTURE_COORD_1: + data = ctx->EvalMap.Map1Texture1.Points; + n = ctx->EvalMap.Map1Texture1.Order * 1; + break; + case GL_MAP1_TEXTURE_COORD_2: + data = ctx->EvalMap.Map1Texture2.Points; + n = ctx->EvalMap.Map1Texture2.Order * 2; + break; + case GL_MAP1_TEXTURE_COORD_3: + data = ctx->EvalMap.Map1Texture3.Points; + n = ctx->EvalMap.Map1Texture3.Order * 3; + break; + case GL_MAP1_TEXTURE_COORD_4: + data = ctx->EvalMap.Map1Texture4.Points; + n = ctx->EvalMap.Map1Texture4.Order * 4; + break; + case GL_MAP1_VERTEX_3: + data = ctx->EvalMap.Map1Vertex3.Points; + n = ctx->EvalMap.Map1Vertex3.Order * 3; + break; + case GL_MAP1_VERTEX_4: + data = ctx->EvalMap.Map1Vertex4.Points; + n = ctx->EvalMap.Map1Vertex4.Order * 4; + break; + case GL_MAP2_COLOR_4: + data = ctx->EvalMap.Map2Color4.Points; + n = ctx->EvalMap.Map2Color4.Uorder + * ctx->EvalMap.Map2Color4.Vorder * 4; + break; + case GL_MAP2_INDEX: + data = ctx->EvalMap.Map2Index.Points; + n = ctx->EvalMap.Map2Index.Uorder + * ctx->EvalMap.Map2Index.Vorder; + break; + case GL_MAP2_NORMAL: + data = ctx->EvalMap.Map2Normal.Points; + n = ctx->EvalMap.Map2Normal.Uorder + * ctx->EvalMap.Map2Normal.Vorder * 3; + break; + case GL_MAP2_TEXTURE_COORD_1: + data = ctx->EvalMap.Map2Texture1.Points; + n = ctx->EvalMap.Map2Texture1.Uorder + * ctx->EvalMap.Map2Texture1.Vorder * 1; + break; + case GL_MAP2_TEXTURE_COORD_2: + data = ctx->EvalMap.Map2Texture2.Points; + n = ctx->EvalMap.Map2Texture2.Uorder + * ctx->EvalMap.Map2Texture2.Vorder * 2; + break; + case GL_MAP2_TEXTURE_COORD_3: + data = ctx->EvalMap.Map2Texture3.Points; + n = ctx->EvalMap.Map2Texture3.Uorder + * ctx->EvalMap.Map2Texture3.Vorder * 3; + break; + case GL_MAP2_TEXTURE_COORD_4: + data = ctx->EvalMap.Map2Texture4.Points; + n = ctx->EvalMap.Map2Texture4.Uorder + * ctx->EvalMap.Map2Texture4.Vorder * 4; + break; + case GL_MAP2_VERTEX_3: + data = ctx->EvalMap.Map2Vertex3.Points; + n = ctx->EvalMap.Map2Vertex3.Uorder + * ctx->EvalMap.Map2Vertex3.Vorder * 3; + break; + case GL_MAP2_VERTEX_4: + data = ctx->EvalMap.Map2Vertex4.Points; + n = ctx->EvalMap.Map2Vertex4.Uorder + * ctx->EvalMap.Map2Vertex4.Vorder * 4; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" ); + return; + } + if (data) { + for (i=0;i<n;i++) { + v[i] = ROUNDF(data[i]); + } + } + break; + case GL_ORDER: + switch (target) { + case GL_MAP1_COLOR_4: + *v = ctx->EvalMap.Map1Color4.Order; + break; + case GL_MAP1_INDEX: + *v = ctx->EvalMap.Map1Index.Order; + break; + case GL_MAP1_NORMAL: + *v = ctx->EvalMap.Map1Normal.Order; + break; + case GL_MAP1_TEXTURE_COORD_1: + *v = ctx->EvalMap.Map1Texture1.Order; + break; + case GL_MAP1_TEXTURE_COORD_2: + *v = ctx->EvalMap.Map1Texture2.Order; + break; + case GL_MAP1_TEXTURE_COORD_3: + *v = ctx->EvalMap.Map1Texture3.Order; + break; + case GL_MAP1_TEXTURE_COORD_4: + *v = ctx->EvalMap.Map1Texture4.Order; + break; + case GL_MAP1_VERTEX_3: + *v = ctx->EvalMap.Map1Vertex3.Order; + break; + case GL_MAP1_VERTEX_4: + *v = ctx->EvalMap.Map1Vertex4.Order; + break; + case GL_MAP2_COLOR_4: + v[0] = ctx->EvalMap.Map2Color4.Uorder; + v[1] = ctx->EvalMap.Map2Color4.Vorder; + break; + case GL_MAP2_INDEX: + v[0] = ctx->EvalMap.Map2Index.Uorder; + v[1] = ctx->EvalMap.Map2Index.Vorder; + break; + case GL_MAP2_NORMAL: + v[0] = ctx->EvalMap.Map2Normal.Uorder; + v[1] = ctx->EvalMap.Map2Normal.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_1: + v[0] = ctx->EvalMap.Map2Texture1.Uorder; + v[1] = ctx->EvalMap.Map2Texture1.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_2: + v[0] = ctx->EvalMap.Map2Texture2.Uorder; + v[1] = ctx->EvalMap.Map2Texture2.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_3: + v[0] = ctx->EvalMap.Map2Texture3.Uorder; + v[1] = ctx->EvalMap.Map2Texture3.Vorder; + break; + case GL_MAP2_TEXTURE_COORD_4: + v[0] = ctx->EvalMap.Map2Texture4.Uorder; + v[1] = ctx->EvalMap.Map2Texture4.Vorder; + break; + case GL_MAP2_VERTEX_3: + v[0] = ctx->EvalMap.Map2Vertex3.Uorder; + v[1] = ctx->EvalMap.Map2Vertex3.Vorder; + break; + case GL_MAP2_VERTEX_4: + v[0] = ctx->EvalMap.Map2Vertex4.Uorder; + v[1] = ctx->EvalMap.Map2Vertex4.Vorder; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" ); + return; + } + break; + case GL_DOMAIN: + switch (target) { + case GL_MAP1_COLOR_4: + v[0] = ROUNDF(ctx->EvalMap.Map1Color4.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Color4.u2); + break; + case GL_MAP1_INDEX: + v[0] = ROUNDF(ctx->EvalMap.Map1Index.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Index.u2); + break; + case GL_MAP1_NORMAL: + v[0] = ROUNDF(ctx->EvalMap.Map1Normal.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Normal.u2); + break; + case GL_MAP1_TEXTURE_COORD_1: + v[0] = ROUNDF(ctx->EvalMap.Map1Texture1.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Texture1.u2); + break; + case GL_MAP1_TEXTURE_COORD_2: + v[0] = ROUNDF(ctx->EvalMap.Map1Texture2.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Texture2.u2); + break; + case GL_MAP1_TEXTURE_COORD_3: + v[0] = ROUNDF(ctx->EvalMap.Map1Texture3.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Texture3.u2); + break; + case GL_MAP1_TEXTURE_COORD_4: + v[0] = ROUNDF(ctx->EvalMap.Map1Texture4.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Texture4.u2); + break; + case GL_MAP1_VERTEX_3: + v[0] = ROUNDF(ctx->EvalMap.Map1Vertex3.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Vertex3.u2); + break; + case GL_MAP1_VERTEX_4: + v[0] = ROUNDF(ctx->EvalMap.Map1Vertex4.u1); + v[1] = ROUNDF(ctx->EvalMap.Map1Vertex4.u2); + break; + case GL_MAP2_COLOR_4: + v[0] = ROUNDF(ctx->EvalMap.Map2Color4.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Color4.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Color4.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Color4.v2); + break; + case GL_MAP2_INDEX: + v[0] = ROUNDF(ctx->EvalMap.Map2Index.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Index.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Index.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Index.v2); + break; + case GL_MAP2_NORMAL: + v[0] = ROUNDF(ctx->EvalMap.Map2Normal.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Normal.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Normal.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Normal.v2); + break; + case GL_MAP2_TEXTURE_COORD_1: + v[0] = ROUNDF(ctx->EvalMap.Map2Texture1.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Texture1.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Texture1.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Texture1.v2); + break; + case GL_MAP2_TEXTURE_COORD_2: + v[0] = ROUNDF(ctx->EvalMap.Map2Texture2.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Texture2.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Texture2.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Texture2.v2); + break; + case GL_MAP2_TEXTURE_COORD_3: + v[0] = ROUNDF(ctx->EvalMap.Map2Texture3.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Texture3.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Texture3.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Texture3.v2); + break; + case GL_MAP2_TEXTURE_COORD_4: + v[0] = ROUNDF(ctx->EvalMap.Map2Texture4.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Texture4.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Texture4.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Texture4.v2); + break; + case GL_MAP2_VERTEX_3: + v[0] = ROUNDF(ctx->EvalMap.Map2Vertex3.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Vertex3.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Vertex3.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Vertex3.v2); + break; + case GL_MAP2_VERTEX_4: + v[0] = ROUNDF(ctx->EvalMap.Map2Vertex4.u1); + v[1] = ROUNDF(ctx->EvalMap.Map2Vertex4.u2); + v[2] = ROUNDF(ctx->EvalMap.Map2Vertex4.v1); + v[3] = ROUNDF(ctx->EvalMap.Map2Vertex4.v2); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" ); + } +} + + + +void eval_points1( GLfloat outcoord[][4], + GLfloat coord[][4], + const GLuint *flags, + GLfloat du, GLfloat u1 ) +{ + GLuint i; + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & VERT_EVAL_P1) + outcoord[i][0] = coord[i][0] * du + u1; + else if (flags[i] & VERT_EVAL_ANY) { + outcoord[i][0] = coord[i][0]; + outcoord[i][1] = coord[i][1]; + } +} + +void eval_points2( GLfloat outcoord[][4], + GLfloat coord[][4], + const GLuint *flags, + GLfloat du, GLfloat u1, + GLfloat dv, GLfloat v1 ) +{ + GLuint i; + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & VERT_EVAL_P2) { + outcoord[i][0] = coord[i][0] * du + u1; + outcoord[i][1] = coord[i][1] * dv + v1; + } else if (flags[i] & VERT_EVAL_ANY) { + outcoord[i][0] = coord[i][0]; + outcoord[i][1] = coord[i][1]; + } +} + + +static const GLubyte dirty_flags[5] = { + 0, /* not possible */ + VEC_DIRTY_0, + VEC_DIRTY_1, + VEC_DIRTY_2, + VEC_DIRTY_3 +}; + + +GLvector4f *eval1_4f( GLvector4f *dest, + GLfloat coord[][4], + const GLuint *flags, + GLuint dimension, + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLfloat (*to)[4] = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + ASSIGN_4V(to[i], 0,0,0,1); + horner_bezier_curve(map->Points, to[i], u, dimension, map->Order); + } + + dest->count = i; + dest->size = MAX2(dest->size, dimension); + dest->flags |= dirty_flags[dimension]; + return dest; +} + + +GLvector1ui *eval1_1ui( GLvector1ui *dest, + GLfloat coord[][4], + const GLuint *flags, + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLuint *to = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat tmp; + horner_bezier_curve(map->Points, &tmp, u, 1, map->Order); + to[i] = (GLuint) (GLint) tmp; + } + + dest->count = i; + return dest; +} + +GLvector3f *eval1_norm( GLvector3f *dest, + GLfloat coord[][4], + GLuint *flags, /* not const */ + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLfloat (*to)[3] = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + horner_bezier_curve(map->Points, to[i], u, 3, map->Order); + flags[i+1] |= VERT_NORM; /* reset */ + } + + dest->count = i; + return dest; +} + +GLvector4ub *eval1_color( GLvector4ub *dest, + GLfloat coord[][4], + GLuint *flags, /* not const */ + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLubyte (*to)[4] = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat fcolor[4]; + horner_bezier_curve(map->Points, fcolor, u, 4, map->Order); + FLOAT_RGBA_TO_UBYTE_RGBA(to[i], fcolor); + flags[i+1] |= VERT_RGBA; /* reset */ + } + + dest->count = i; + return dest; +} + + + + +GLvector4f *eval2_obj_norm( GLvector4f *obj_ptr, + GLvector3f *norm_ptr, + GLfloat coord[][4], + GLuint *flags, + GLuint dimension, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLfloat (*obj)[4] = obj_ptr->data; + GLfloat (*normal)[3] = norm_ptr->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + GLfloat du[4], dv[4]; + + ASSIGN_4V(obj[i], 0,0,0,1); + de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension, + map->Uorder, map->Vorder); + + CROSS3(normal[i], du, dv); + NORMALIZE_3FV(normal[i]); + flags[i+1] |= VERT_NORM; + } + + obj_ptr->count = i; + obj_ptr->size = MAX2(obj_ptr->size, dimension); + obj_ptr->flags |= dirty_flags[dimension]; + return obj_ptr; +} + + +GLvector4f *eval2_4f( GLvector4f *dest, + GLfloat coord[][4], + const GLuint *flags, + GLuint dimension, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLfloat (*to)[4] = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + horner_bezier_surf(map->Points, to[i], u, v, dimension, + map->Uorder, map->Vorder); + } + + dest->count = i; + dest->size = MAX2(dest->size, dimension); + dest->flags |= dirty_flags[dimension]; + return dest; +} + + +GLvector3f *eval2_norm( GLvector3f *dest, + GLfloat coord[][4], + GLuint *flags, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLfloat (*to)[3] = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + horner_bezier_surf(map->Points, to[i], u, v, 3, + map->Uorder, map->Vorder); + flags[i+1] |= VERT_NORM; /* reset */ + } + + dest->count = i; + return dest; +} + + +GLvector1ui *eval2_1ui( GLvector1ui *dest, + GLfloat coord[][4], + const GLuint *flags, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLuint *to = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + GLfloat tmp; + horner_bezier_surf(map->Points, &tmp, u, v, 1, + map->Uorder, map->Vorder); + + to[i] = (GLuint) (GLint) tmp; + } + + dest->count = i; + return dest; +} + + + +GLvector4ub *eval2_color( GLvector4ub *dest, + GLfloat coord[][4], + GLuint *flags, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLubyte (*to)[4] = dest->data; + GLuint i; + + for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + GLfloat fcolor[4]; + horner_bezier_surf(map->Points, fcolor, u, v, 4, + map->Uorder, map->Vorder); + FLOAT_RGBA_TO_UBYTE_RGBA(to[i], fcolor); + flags[i+1] |= VERT_RGBA; /* reset */ + } + + dest->count = i; + return dest; +} + + +GLvector4f *copy_4f( GLvector4f *out, CONST GLvector4f *in, + const GLuint *flags) +{ + GLfloat (*to)[4] = out->data; + GLfloat (*from)[4] = in->data; + GLuint i; + + for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (!(flags[i] & VERT_EVAL_ANY)) + COPY_4FV( to[i], from[i] ); + + return out; +} + +GLvector3f *copy_3f( GLvector3f *out, CONST GLvector3f *in, + const GLuint *flags) +{ + GLfloat (*to)[3] = out->data; + GLfloat (*from)[3] = in->data; + GLuint i; + + for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (!(flags[i] & VERT_EVAL_ANY)) + COPY_3V( to[i], from[i] ); + + return out; +} + +GLvector4ub *copy_4ub( GLvector4ub *out, CONST GLvector4ub *in, + const GLuint *flags ) +{ + GLubyte (*to)[4] = out->data; + GLubyte (*from)[4] = in->data; + GLuint i; + + for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (!(flags[i] & VERT_EVAL_ANY)) + COPY_4UBV( to[i], from[i] ); + + return out; +} + +GLvector1ui *copy_1ui( GLvector1ui *out, CONST GLvector1ui *in, + const GLuint *flags ) +{ + GLuint *to = out->data; + CONST GLuint *from = in->data; + GLuint i; + + for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++) + if (!(flags[i] & VERT_EVAL_ANY)) + to[i] = from[i]; + + return out; +} + + +/* KW: Rewrote this to perform eval on a whole buffer at once. + * Only evaluates active data items, and avoids scribbling + * the source buffer if we are running from a display list. + * + * If the user (in this case looser) sends eval coordinates + * or runs a display list containing eval coords with no + * vertex maps enabled, we have to either copy all non-eval + * data to a new buffer, or find a way of working around + * the eval data. I choose the second option. + * + * KW: This code not reached by cva - use IM to access storage. + */ +void gl_eval_vb( struct vertex_buffer *VB ) +{ + struct immediate *IM = VB->IM; + GLcontext *ctx = VB->ctx; + GLuint req = ctx->CVA.elt.inputs; + GLfloat (*coord)[4] = VB->ObjPtr->data; + GLuint *flags = VB->Flag; + GLuint new_flags = 0; + + + GLuint any_eval1 = VB->OrFlag & (VERT_EVAL_C1|VERT_EVAL_P1); + GLuint any_eval2 = VB->OrFlag & (VERT_EVAL_C2|VERT_EVAL_P2); + GLuint all_eval = VB->AndFlag & VERT_EVAL_ANY; + + /* Handle the degenerate cases. + */ + if (any_eval1 && !ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3) { + VB->PurgeFlags |= (VERT_EVAL_C1|VERT_EVAL_P1); + VB->EarlyCull = 0; + any_eval1 = GL_FALSE; + } + + if (any_eval2 && !ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3) { + VB->PurgeFlags |= (VERT_EVAL_C2|VERT_EVAL_P2); + VB->EarlyCull = 0; + any_eval2 = GL_FALSE; + } + + /* KW: This really is a degenerate case - doing this disables + * culling, and causes dummy values for the missing vertices to be + * transformed and clip tested. It also forces the individual + * cliptesting of each primitive in vb_render. I wish there was a + * nice alternative, but I can't say I want to put effort into + * optimizing such a bad usage of the library - I'd much rather + * work on useful changes. + */ + if (VB->PurgeFlags) { + if (!any_eval1 && !any_eval2 && all_eval) VB->Count = VB_START; + gl_purge_vertices( VB ); + if (!any_eval1 && !any_eval2) return; + } else + VB->IndirectCount = VB->Count; + + /* Translate points into coords. + */ + if (any_eval1 && (VB->OrFlag & VERT_EVAL_P1)) + { + eval_points1( IM->Obj, coord, flags, + ctx->Eval.MapGrid1du, + ctx->Eval.MapGrid1u1); + + coord = IM->Obj; + } + + if (any_eval2 && (VB->OrFlag & VERT_EVAL_P2)) + { + eval_points2( IM->Obj, coord, flags, + ctx->Eval.MapGrid2du, + ctx->Eval.MapGrid2u1, + ctx->Eval.MapGrid2dv, + ctx->Eval.MapGrid2v1 ); + + coord = IM->Obj; + } + + /* Perform the evaluations on active data elements. + */ + if (req & VERT_INDEX) + { + GLvector1ui *in_index = VB->IndexPtr; + GLvector1ui *out_index = &IM->v.Index; + + if (ctx->Eval.Map1Index && any_eval1) + VB->IndexPtr = eval1_1ui( out_index, coord, flags, + &ctx->EvalMap.Map1Index ); + + if (ctx->Eval.Map2Index && any_eval2) + VB->IndexPtr = eval2_1ui( out_index, coord, flags, + &ctx->EvalMap.Map2Index ); + + if (VB->IndexPtr != in_index) { + new_flags |= VERT_INDEX; + if (!all_eval) + VB->IndexPtr = copy_1ui( out_index, in_index, flags ); + } + } + + if (req & VERT_RGBA) + { + GLvector4ub *in_color = VB->ColorPtr; + GLvector4ub *out_color = &IM->v.Color; + + if (ctx->Eval.Map1Color4 && any_eval1) + VB->ColorPtr = eval1_color( out_color, coord, flags, + &ctx->EvalMap.Map1Color4 ); + + if (ctx->Eval.Map2Color4 && any_eval2) + VB->ColorPtr = eval2_color( out_color, coord, flags, + &ctx->EvalMap.Map2Color4 ); + + if (VB->ColorPtr != in_color) { + new_flags |= VERT_RGBA; + if (!all_eval) + VB->ColorPtr = copy_4ub( out_color, in_color, flags ); + } + + VB->Color[0] = VB->Color[1] = VB->ColorPtr; + } + + + if (req & VERT_NORM) + { + GLvector3f *in_normal = VB->NormalPtr; + GLvector3f *out_normal = &IM->v.Normal; + + if (ctx->Eval.Map1Normal && any_eval1) + VB->NormalPtr = eval1_norm( out_normal, coord, flags, + &ctx->EvalMap.Map1Normal ); + + if (ctx->Eval.Map2Normal && any_eval2) + VB->NormalPtr = eval2_norm( out_normal, coord, flags, + &ctx->EvalMap.Map2Normal ); + + if (VB->NormalPtr != in_normal) { + new_flags |= VERT_NORM; + if (!all_eval) + VB->NormalPtr = copy_3f( out_normal, in_normal, flags ); + } + } + + + if (req & VERT_TEX_ANY(0)) + { + GLvector4f *tc = VB->TexCoordPtr[0]; + GLvector4f *in = tc; + GLvector4f *out = &IM->v.TexCoord[0]; + + if (any_eval1) { + if (ctx->Eval.Map1TextureCoord4) + tc = eval1_4f( out, coord, flags, 4, &ctx->EvalMap.Map1Texture4); + else if (ctx->Eval.Map1TextureCoord3) + tc = eval1_4f( out, coord, flags, 3, &ctx->EvalMap.Map1Texture3); + else if (ctx->Eval.Map1TextureCoord2) + tc = eval1_4f( out, coord, flags, 2, &ctx->EvalMap.Map1Texture2); + else if (ctx->Eval.Map1TextureCoord1) + tc = eval1_4f( out, coord, flags, 1, &ctx->EvalMap.Map1Texture1); + } + + if (any_eval2) { + if (ctx->Eval.Map2TextureCoord4) + tc = eval2_4f( out, coord, flags, 4, &ctx->EvalMap.Map2Texture4); + else if (ctx->Eval.Map2TextureCoord3) + tc = eval2_4f( out, coord, flags, 3, &ctx->EvalMap.Map2Texture3); + else if (ctx->Eval.Map2TextureCoord2) + tc = eval2_4f( out, coord, flags, 2, &ctx->EvalMap.Map2Texture2); + else if (ctx->Eval.Map2TextureCoord1) + tc = eval2_4f( out, coord, flags, 1, &ctx->EvalMap.Map2Texture1); + } + + if (tc != in) { + new_flags |= VERT_TEX_ANY(0); /* fix for sizes.. */ + if (!all_eval) + tc = copy_4f( out, in, flags ); + } + + VB->TexCoordPtr[0] = tc; + } + + + { + GLvector4f *in = VB->ObjPtr; + GLvector4f *out = &IM->v.Obj; + GLvector4f *obj = in; + + if (any_eval1) { + if (ctx->Eval.Map1Vertex4) + obj = eval1_4f( out, coord, flags, 4, &ctx->EvalMap.Map1Vertex4); + else + obj = eval1_4f( out, coord, flags, 3, &ctx->EvalMap.Map1Vertex3); + } + + if (any_eval2) { + if (ctx->Eval.Map2Vertex4) + { + if (ctx->Eval.AutoNormal && (req & VERT_NORM)) + obj = eval2_obj_norm( out, VB->NormalPtr, coord, flags, 4, + &ctx->EvalMap.Map2Vertex4 ); + else + obj = eval2_4f( out, coord, flags, 4, + &ctx->EvalMap.Map2Vertex4); + } + else if (ctx->Eval.Map2Vertex3) + { + if (ctx->Eval.AutoNormal && (req & VERT_NORM)) + obj = eval2_obj_norm( out, VB->NormalPtr, coord, flags, 3, + &ctx->EvalMap.Map2Vertex3 ); + else + obj = eval2_4f( out, coord, flags, 3, + &ctx->EvalMap.Map2Vertex3 ); + } + } + + if (obj != in && !all_eval) + obj = copy_4f( out, in, flags ); + + VB->ObjPtr = obj; + } + + if (new_flags) { + GLuint *oldflags = VB->Flag; + GLuint *flags = VB->Flag = VB->EvaluatedFlags; + GLuint i; + GLuint count = VB->Count; + + if (!flags) { + VB->EvaluatedFlags = (GLuint *)malloc(VB->Size * sizeof(GLuint)); + flags = VB->Flag = VB->EvaluatedFlags; + } + + if (all_eval) { + for (i = 0 ; i < count ; i++) + flags[i] = oldflags[i] | new_flags; + VB->AndFlag |= new_flags; + } else { + GLuint andflag = ~0; + for (i = 0 ; i < count ; i++) { + if (oldflags[i] & VERT_EVAL_ANY) + flags[i] = oldflags[i] | new_flags; + andflag &= flags[i]; + } + VB->AndFlag = andflag; + } + } +} + + +void gl_MapGrid1f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2 ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMapGrid1f"); + + if (un<1) { + gl_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" ); + return; + } + ctx->Eval.MapGrid1un = un; + ctx->Eval.MapGrid1u1 = u1; + ctx->Eval.MapGrid1u2 = u2; + ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un; +} + + +void gl_MapGrid2f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMapGrid2f"); + if (un<1) { + gl_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" ); + return; + } + if (vn<1) { + gl_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" ); + return; + } + ctx->Eval.MapGrid2un = un; + ctx->Eval.MapGrid2u1 = u1; + ctx->Eval.MapGrid2u2 = u2; + ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un; + ctx->Eval.MapGrid2vn = vn; + ctx->Eval.MapGrid2v1 = v1; + ctx->Eval.MapGrid2v2 = v2; + ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn; +} + + + +void gl_EvalMesh1( GLcontext* ctx, GLenum mode, GLint i1, GLint i2 ) +{ + GLint i; + GLfloat u, du; + GLenum prim; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glEvalMesh1"); + + switch (mode) { + case GL_POINT: + prim = GL_POINTS; + break; + case GL_LINE: + prim = GL_LINE_STRIP; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" ); + return; + } + + /* No effect if vertex maps disabled. + */ + if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3) + return; + + du = ctx->Eval.MapGrid1du; + u = ctx->Eval.MapGrid1u1 + i1 * du; + + /* KW: Could short-circuit this to avoid the immediate mechanism. + */ + RESET_IMMEDIATE(ctx); + + gl_Begin( ctx, prim ); + for (i=i1;i<=i2;i++,u+=du) { + gl_EvalCoord1f( ctx, u ); + } + gl_End(ctx); +} + + + +void gl_EvalMesh2( GLcontext* ctx, + GLenum mode, + GLint i1, GLint i2, + GLint j1, GLint j2 ) +{ + GLint i, j; + GLfloat u, du, v, dv, v1, u1; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glEvalMesh2"); + + /* No effect if vertex maps disabled. + */ + if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3) + return; + + du = ctx->Eval.MapGrid2du; + dv = ctx->Eval.MapGrid2dv; + v1 = ctx->Eval.MapGrid2v1 + j1 * dv; + u1 = ctx->Eval.MapGrid2u1 + i1 * du; + + RESET_IMMEDIATE(ctx); + + switch (mode) { + case GL_POINT: + gl_Begin( ctx, GL_POINTS ); + for (v=v1,j=j1;j<=j2;j++,v+=dv) { + for (u=u1,i=i1;i<=i2;i++,u+=du) { + gl_EvalCoord2f( ctx, u, v ); + } + } + gl_End(ctx); + break; + case GL_LINE: + for (v=v1,j=j1;j<=j2;j++,v+=dv) { + gl_Begin( ctx, GL_LINE_STRIP ); + for (u=u1,i=i1;i<=i2;i++,u+=du) { + gl_EvalCoord2f( ctx, u, v ); + } + gl_End(ctx); + } + for (u=u1,i=i1;i<=i2;i++,u+=du) { + gl_Begin( ctx, GL_LINE_STRIP ); + for (v=v1,j=j1;j<=j2;j++,v+=dv) { + gl_EvalCoord2f( ctx, u, v ); + } + gl_End(ctx); + } + break; + case GL_FILL: + for (v=v1,j=j1;j<j2;j++,v+=dv) { + /* NOTE: a quad strip can't be used because the four */ + /* can't be guaranteed to be coplanar! */ + gl_Begin( ctx, GL_TRIANGLE_STRIP ); + for (u=u1,i=i1;i<=i2;i++,u+=du) { + gl_EvalCoord2f( ctx, u, v ); + gl_EvalCoord2f( ctx, u, v+dv ); + } + gl_End(ctx); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" ); + return; + } +} + diff --git a/src/mesa/main/eval.h b/src/mesa/main/eval.h new file mode 100644 index 00000000000..cde76b08dde --- /dev/null +++ b/src/mesa/main/eval.h @@ -0,0 +1,95 @@ +/* $Id: eval.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 EVAL_H +#define EVAL_H + + +#include "types.h" + + +extern void gl_init_eval( void ); + + +extern void gl_free_control_points( GLcontext *ctx, + GLenum target, GLfloat *data ); + + +extern GLfloat *gl_copy_map_points1f( GLenum target, + GLint ustride, GLint uorder, + const GLfloat *points ); + +extern GLfloat *gl_copy_map_points1d( GLenum target, + GLint ustride, GLint uorder, + const GLdouble *points ); + +extern GLfloat *gl_copy_map_points2f( GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLfloat *points ); + +extern GLfloat *gl_copy_map_points2d(GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLdouble *points ); + + +extern void gl_Map1f( GLcontext* ctx, + GLenum target, GLfloat u1, GLfloat u2, GLint stride, + GLint order, const GLfloat *points, GLboolean retain ); + +extern void gl_Map2f( GLcontext* ctx, GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points, GLboolean retain ); + + + +extern void gl_MapGrid1f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2 ); + +extern void gl_MapGrid2f( GLcontext* ctx, + GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ); + +extern void gl_GetMapdv( GLcontext* ctx, + GLenum target, GLenum query, GLdouble *v ); + +extern void gl_GetMapfv( GLcontext* ctx, + GLenum target, GLenum query, GLfloat *v ); + +extern void gl_GetMapiv( GLcontext* ctx, + GLenum target, GLenum query, GLint *v ); + +extern void gl_EvalMesh1( GLcontext* ctx, GLenum mode, GLint i1, GLint i2 ); + +extern void gl_EvalMesh2( GLcontext* ctx, GLenum mode, + GLint i1, GLint i2, GLint j1, GLint j2 ); + +extern void gl_eval_vb( struct vertex_buffer *VB ); + + +#endif diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c new file mode 100644 index 00000000000..55687294d17 --- /dev/null +++ b/src/mesa/main/extensions.c @@ -0,0 +1,196 @@ +/* $Id: extensions.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 <stdlib.h> +#include "extensions.h" +#include "simple_list.h" +#include "types.h" + +#define MAX_EXT_NAMELEN 80 +#define MALLOC_STRUCT(T) (struct T *) malloc( sizeof(struct T) ) + +struct extension { + struct extension *next, *prev; + int enabled; + char name[MAX_EXT_NAMELEN+1]; + void (*notify)( GLcontext *, GLboolean ); +}; + + + +static struct { int enabled; const char *name; } default_extensions[] = { + { ALWAYS_ENABLED, "GL_EXT_blend_color" }, + { ALWAYS_ENABLED, "GL_EXT_blend_minmax" }, + { ALWAYS_ENABLED, "GL_EXT_blend_logic_op" }, + { ALWAYS_ENABLED, "GL_EXT_blend_subtract" }, + { ALWAYS_ENABLED, "GL_EXT_paletted_texture" }, + { DEFAULT_ON, "GL_EXT_point_parameters" }, + { ALWAYS_ENABLED, "GL_EXT_polygon_offset" }, + { ALWAYS_ENABLED, "GL_EXT_vertex_array" }, + { ALWAYS_ENABLED, "GL_EXT_texture_object" }, + { DEFAULT_ON, "GL_EXT_texture3D" }, + { ALWAYS_ENABLED, "GL_MESA_window_pos" }, + { ALWAYS_ENABLED, "GL_MESA_resize_buffers" }, + { ALWAYS_ENABLED, "GL_EXT_shared_texture_palette" }, + { ALWAYS_ENABLED, "GL_EXT_rescale_normal" }, + { ALWAYS_ENABLED, "GL_EXT_abgr" }, + { ALWAYS_ENABLED, "GL_SGIS_texture_edge_clamp" }, + { ALWAYS_ENABLED, "GL_EXT_stencil_wrap" }, + { ALWAYS_ENABLED, "GL_INGR_blend_func_separate" }, + { DEFAULT_ON, "GL_ARB_multitexture" }, + { ALWAYS_ENABLED, "GL_NV_texgen_reflection" }, + { DEFAULT_ON, "GL_PGI_misc_hints" }, + { DEFAULT_ON, "GL_EXT_compiled_vertex_array" }, + { DEFAULT_OFF, "GL_EXT_vertex_array_set" }, + { DEFAULT_ON, "GL_EXT_clip_volume_hint" }, +}; + + +int gl_extensions_add( GLcontext *ctx, + int state, + const char *name, + void (*notify)() ) +{ + (void) notify; + + if (ctx->Extensions.ext_string == 0) + { + struct extension *t = MALLOC_STRUCT(extension); + t->enabled = state; + strncpy(t->name, name, MAX_EXT_NAMELEN); + t->name[MAX_EXT_NAMELEN] = 0; + t->notify = (void (*)(GLcontext *, GLboolean)) notify; + insert_at_tail( ctx->Extensions.ext_list, t ); + return 0; + } + return 1; +} + + +static int set_extension( GLcontext *ctx, const char *name, GLuint state ) +{ + struct extension *i; + foreach( i, ctx->Extensions.ext_list ) + if (strncmp(i->name, name, MAX_EXT_NAMELEN) == 0) + break; + + if (i == ctx->Extensions.ext_list) return 1; + + if (i->enabled && !(i->enabled & ALWAYS_ENABLED)) + { + if (i->notify) i->notify( ctx, state ); + i->enabled = state; + } + + return 0; +} + + +int gl_extensions_enable( GLcontext *ctx, const char *name ) +{ + if (ctx->Extensions.ext_string == 0) + return set_extension( ctx, name, 1 ); + return 1; +} + + +int gl_extensions_disable( GLcontext *ctx, const char *name ) +{ + if (ctx->Extensions.ext_string == 0) + return set_extension( ctx, name, 0 ); + return 1; +} + + +void gl_extensions_dtr( GLcontext *ctx ) +{ + struct extension *i, *nexti; + + if (ctx->Extensions.ext_string) { + free( ctx->Extensions.ext_string ); + ctx->Extensions.ext_string = 0; + } + + if (ctx->Extensions.ext_list) { + foreach_s( i, nexti, ctx->Extensions.ext_list ) { + free( i ); + } + + free(ctx->Extensions.ext_list); + ctx->Extensions.ext_list = 0; + } +} + + +void gl_extensions_ctr( GLcontext *ctx ) +{ + GLuint i; + + ctx->Extensions.ext_string = 0; + ctx->Extensions.ext_list = MALLOC_STRUCT(extension); + make_empty_list( ctx->Extensions.ext_list ); + + for (i = 0 ; i < Elements(default_extensions) ; i++) { + gl_extensions_add( ctx, + default_extensions[i].enabled, + default_extensions[i].name, + 0 ); + } +} + + +const char *gl_extensions_get_string( GLcontext *ctx ) +{ + if (ctx->Extensions.ext_string == 0) + { + struct extension *i; + char *str; + GLuint len = 0; + foreach (i, ctx->Extensions.ext_list) + if (i->enabled) + len += strlen(i->name) + 1; + + if (len == 0) + return ""; + + str = (char *)malloc(len * sizeof(char)); + ctx->Extensions.ext_string = str; + + foreach (i, ctx->Extensions.ext_list) + if (i->enabled) { + strcpy(str, i->name); + str += strlen(str); + *str++ = ' '; + } + + *(str-1) = 0; + } + + return ctx->Extensions.ext_string; +} + + diff --git a/src/mesa/main/extensions.h b/src/mesa/main/extensions.h new file mode 100644 index 00000000000..a19dc479208 --- /dev/null +++ b/src/mesa/main/extensions.h @@ -0,0 +1,56 @@ +/* $Id: extensions.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 _EXTENSIONS_H_ +#define _EXTENSIONS_H_ + +struct gl_context; +struct extension; + +struct gl_extensions { + char *ext_string; + struct extension *ext_list; +}; + +#define DEFAULT_OFF 0x0 +#define DEFAULT_ON 0x1 +#define ALWAYS_ENABLED 0x2 + +/* Return 0 on success. + */ +extern int gl_extensions_add( struct gl_context *ctx, int state, + const char *name, void (*notify)() ); + +extern int gl_extensions_enable( struct gl_context *ctx, const char *name ); +extern int gl_extensions_disable( struct gl_context *ctx, const char *name ); +extern void gl_extensions_dtr( struct gl_context *ctx ); +extern void gl_extensions_ctr( struct gl_context *ctx ); +extern const char *gl_extensions_get_string( struct gl_context *ctx ); + +#endif + + diff --git a/src/mesa/main/feedback.c b/src/mesa/main/feedback.c new file mode 100644 index 00000000000..4251aae01a3 --- /dev/null +++ b/src/mesa/main/feedback.c @@ -0,0 +1,395 @@ +/* $Id: feedback.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdio.h> +#include "context.h" +#include "enums.h" +#include "feedback.h" +#include "macros.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +#define FB_3D 0x01 +#define FB_4D 0x02 +#define FB_INDEX 0x04 +#define FB_COLOR 0x08 +#define FB_TEXTURE 0X10 + + + +void +gl_FeedbackBuffer( GLcontext *ctx, GLsizei size, GLenum type, GLfloat *buffer ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glFeedbackBuffer" ); + + if (ctx->RenderMode==GL_FEEDBACK) { + gl_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" ); + return; + } + + if (size<0) { + gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" ); + return; + } + if (!buffer) { + gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" ); + ctx->Feedback.BufferSize = 0; + return; + } + + switch (type) { + case GL_2D: + ctx->Feedback.Mask = 0; + ctx->Feedback.Type = type; + break; + case GL_3D: + ctx->Feedback.Mask = FB_3D; + ctx->Feedback.Type = type; + break; + case GL_3D_COLOR: + ctx->Feedback.Mask = FB_3D + | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX); + ctx->Feedback.Type = type; + break; + case GL_3D_COLOR_TEXTURE: + ctx->Feedback.Mask = FB_3D + | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX) + | FB_TEXTURE; + ctx->Feedback.Type = type; + break; + case GL_4D_COLOR_TEXTURE: + ctx->Feedback.Mask = FB_3D | FB_4D + | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX) + | FB_TEXTURE; + ctx->Feedback.Type = type; + break; + default: + ctx->Feedback.Mask = 0; + gl_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" ); + } + + ctx->Feedback.BufferSize = size; + ctx->Feedback.Buffer = buffer; + ctx->Feedback.Count = 0; +} + + + +void gl_PassThrough( GLcontext *ctx, GLfloat token ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPassThrough"); + + if (ctx->RenderMode==GL_FEEDBACK) { + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN ); + FEEDBACK_TOKEN( ctx, token ); + } +} + + + +/* + * Put a vertex into the feedback buffer. + */ +void gl_feedback_vertex( GLcontext *ctx, + GLfloat x, GLfloat y, GLfloat z, GLfloat w, + const GLfloat color[4], GLfloat index, + const GLfloat texcoord[4] ) +{ + FEEDBACK_TOKEN( ctx, x ); + FEEDBACK_TOKEN( ctx, y ); + if (ctx->Feedback.Mask & FB_3D) { + FEEDBACK_TOKEN( ctx, z ); + } + if (ctx->Feedback.Mask & FB_4D) { + FEEDBACK_TOKEN( ctx, w ); + } + if (ctx->Feedback.Mask & FB_INDEX) { + FEEDBACK_TOKEN( ctx, index ); + } + if (ctx->Feedback.Mask & FB_COLOR) { + FEEDBACK_TOKEN( ctx, color[0] ); + FEEDBACK_TOKEN( ctx, color[1] ); + FEEDBACK_TOKEN( ctx, color[2] ); + FEEDBACK_TOKEN( ctx, color[3] ); + } + if (ctx->Feedback.Mask & FB_TEXTURE) { + FEEDBACK_TOKEN( ctx, texcoord[0] ); + FEEDBACK_TOKEN( ctx, texcoord[1] ); + FEEDBACK_TOKEN( ctx, texcoord[2] ); + FEEDBACK_TOKEN( ctx, texcoord[3] ); + } +} + + + +/**********************************************************************/ +/* Selection */ +/**********************************************************************/ + + +/* + * NOTE: this function can't be put in a display list. + */ +void gl_SelectBuffer( GLcontext *ctx, GLsizei size, GLuint *buffer ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glSelectBuffer"); + if (ctx->RenderMode==GL_SELECT) { + gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" ); + } + ctx->Select.Buffer = buffer; + ctx->Select.BufferSize = size; + ctx->Select.BufferCount = 0; + + ctx->Select.HitFlag = GL_FALSE; + ctx->Select.HitMinZ = 1.0; + ctx->Select.HitMaxZ = 0.0; +} + + +#define WRITE_RECORD( CTX, V ) \ + if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \ + CTX->Select.Buffer[CTX->Select.BufferCount] = (V); \ + } \ + CTX->Select.BufferCount++; + + + +void gl_update_hitflag( GLcontext *ctx, GLfloat z ) +{ + ctx->Select.HitFlag = GL_TRUE; + if (z < ctx->Select.HitMinZ) { + ctx->Select.HitMinZ = z; + } + if (z > ctx->Select.HitMaxZ) { + ctx->Select.HitMaxZ = z; + } +} + + + +static void write_hit_record( GLcontext *ctx ) +{ + GLuint i; + GLuint zmin, zmax, zscale = (~0u); + + /* HitMinZ and HitMaxZ are in [0,1]. Multiply these values by */ + /* 2^32-1 and round to nearest unsigned integer. */ + + assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */ + zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ); + zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ); + + WRITE_RECORD( ctx, ctx->Select.NameStackDepth ); + WRITE_RECORD( ctx, zmin ); + WRITE_RECORD( ctx, zmax ); + for (i=0;i<ctx->Select.NameStackDepth;i++) { + WRITE_RECORD( ctx, ctx->Select.NameStack[i] ); + } + + ctx->Select.Hits++; + ctx->Select.HitFlag = GL_FALSE; + ctx->Select.HitMinZ = 1.0; + ctx->Select.HitMaxZ = -1.0; +} + + + +void gl_InitNames( GLcontext *ctx ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glInitNames"); + /* Record the hit before the HitFlag is wiped out again. */ + if (ctx->RenderMode==GL_SELECT) { + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + } + ctx->Select.NameStackDepth = 0; + ctx->Select.HitFlag = GL_FALSE; + ctx->Select.HitMinZ = 1.0; + ctx->Select.HitMaxZ = 0.0; +} + + + +void gl_LoadName( GLcontext *ctx, GLuint name ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLoadName"); + if (ctx->RenderMode!=GL_SELECT) { + return; + } + if (ctx->Select.NameStackDepth==0) { + gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" ); + return; + } + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) { + ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name; + } + else { + ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name; + } +} + + +void gl_PushName( GLcontext *ctx, GLuint name ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushName"); + if (ctx->RenderMode!=GL_SELECT) { + return; + } + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) { + ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name; + } + else { + gl_error( ctx, GL_STACK_OVERFLOW, "glPushName" ); + } +} + + + +void gl_PopName( GLcontext *ctx ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopName"); + if (ctx->RenderMode!=GL_SELECT) { + return; + } + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.NameStackDepth>0) { + ctx->Select.NameStackDepth--; + } + else { + gl_error( ctx, GL_STACK_UNDERFLOW, "glPopName" ); + } +} + + + +/**********************************************************************/ +/* Render Mode */ +/**********************************************************************/ + + + +/* + * NOTE: this function can't be put in a display list. + */ +GLint gl_RenderMode( GLcontext *ctx, GLenum mode ) +{ + GLint result; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glRenderMode", 0); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glRenderMode %s\n", gl_lookup_enum_by_nr(mode)); + + ctx->TriangleCaps &= ~(DD_FEEDBACK|DD_SELECT); + + switch (ctx->RenderMode) { + case GL_RENDER: + result = 0; + break; + case GL_SELECT: + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.BufferCount > ctx->Select.BufferSize) { + /* overflow */ +#ifdef DEBUG + gl_warning(ctx, "Feedback buffer overflow"); +#endif + result = -1; + } + else { + result = ctx->Select.Hits; + } + ctx->Select.BufferCount = 0; + ctx->Select.Hits = 0; + ctx->Select.NameStackDepth = 0; + break; + case GL_FEEDBACK: + if (ctx->Feedback.Count > ctx->Feedback.BufferSize) { + /* overflow */ + result = -1; + } + else { + result = ctx->Feedback.Count; + } + ctx->Feedback.Count = 0; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" ); + return 0; + } + + switch (mode) { + case GL_RENDER: + break; + case GL_SELECT: + ctx->TriangleCaps |= DD_SELECT; + if (ctx->Select.BufferSize==0) { + /* haven't called glSelectBuffer yet */ + gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" ); + } + break; + case GL_FEEDBACK: + ctx->TriangleCaps |= DD_FEEDBACK; + if (ctx->Feedback.BufferSize==0) { + /* haven't called glFeedbackBuffer yet */ + gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" ); + return 0; + } + + + ctx->RenderMode = mode; + ctx->NewState |= NEW_ALL; + + return result; +} + diff --git a/src/mesa/main/feedback.h b/src/mesa/main/feedback.h new file mode 100644 index 00000000000..99a4b7aeb15 --- /dev/null +++ b/src/mesa/main/feedback.h @@ -0,0 +1,74 @@ +/* $Id: feedback.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 FEEDBACK_H +#define FEEDBACK_H + + +#include "types.h" + + +#define FEEDBACK_TOKEN( CTX, T ) \ + if (CTX->Feedback.Count < CTX->Feedback.BufferSize) { \ + CTX->Feedback.Buffer[CTX->Feedback.Count] = (T); \ + } \ + CTX->Feedback.Count++; + + +extern void gl_feedback_vertex( GLcontext *ctx, + GLfloat x, GLfloat y, GLfloat z, GLfloat w, + const GLfloat color[4], GLfloat index, + const GLfloat texcoord[4] ); + + +extern void gl_update_hitflag( GLcontext *ctx, GLfloat z ); + + +extern void gl_PassThrough( GLcontext *ctx, GLfloat token ); + +extern void gl_FeedbackBuffer( GLcontext *ctx, GLsizei size, + GLenum type, GLfloat *buffer ); + +extern void gl_SelectBuffer( GLcontext *ctx, GLsizei size, GLuint *buffer ); + +extern void gl_InitNames( GLcontext *ctx ); + +extern void gl_LoadName( GLcontext *ctx, GLuint name ); + +extern void gl_PushName( GLcontext *ctx, GLuint name ); + +extern void gl_PopName( GLcontext *ctx ); + +extern GLint gl_RenderMode( GLcontext *ctx, GLenum mode ); + + + +#endif + diff --git a/src/mesa/main/fog.c b/src/mesa/main/fog.c new file mode 100644 index 00000000000..1579c8c47ca --- /dev/null +++ b/src/mesa/main/fog.c @@ -0,0 +1,327 @@ +/* $Id: fog.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <math.h> +#include <stdlib.h> +#include "context.h" +#include "fog.h" +#include "macros.h" +#include "mmath.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params ) +{ + GLenum m; + + switch (pname) { + case GL_FOG_MODE: + m = (GLenum) (GLint) *params; + if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) { + ctx->Fog.Mode = m; + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glFog" ); + return; + } + break; + case GL_FOG_DENSITY: + if (*params<0.0) { + gl_error( ctx, GL_INVALID_VALUE, "glFog" ); + return; + } + else { + ctx->Fog.Density = *params; + } + break; + case GL_FOG_START: +#if 0 + /* Prior to OpenGL 1.1, this was an error */ + if (*params<0.0F) { + gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" ); + return; + } +#endif + ctx->Fog.Start = *params; + break; + case GL_FOG_END: +#if 0 + /* Prior to OpenGL 1.1, this was an error */ + if (*params<0.0F) { + gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" ); + return; + } +#endif + ctx->Fog.End = *params; + break; + case GL_FOG_INDEX: + ctx->Fog.Index = *params; + break; + case GL_FOG_COLOR: + ctx->Fog.Color[0] = params[0]; + ctx->Fog.Color[1] = params[1]; + ctx->Fog.Color[2] = params[2]; + ctx->Fog.Color[3] = params[3]; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glFog" ); + return; + } + + if (ctx->Driver.Fogfv) { + (*ctx->Driver.Fogfv)( ctx, pname, params ); + } + + ctx->NewState |= NEW_FOG; +} + + +typedef void (*fog_func)( struct vertex_buffer *VB, GLuint side, + GLubyte flag ); + + +static fog_func fog_ci_tab[2]; +static fog_func fog_rgba_tab[2]; + +/* + * Compute the fogged color for an array of vertices. + * Input: n - number of vertices + * v - array of vertices + * color - the original vertex colors + * Output: color - the fogged colors + * + */ +#define TAG(x) x##_raw +#define CULLCHECK +#define IDX 0 +#include "fog_tmp.h" + +#define TAG(x) x##_masked +#define CULLCHECK if (cullmask[i]&flag) +#define IDX 1 +#include "fog_tmp.h" + +void gl_init_fog( void ) +{ + init_fog_tab_masked(); + init_fog_tab_raw(); +} + +/* + * Compute fog for the vertices in the vertex buffer. + */ +void gl_fog_vertices( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + GLuint i = VB->CullMode & 1; + + if (ctx->Visual->RGBAflag) { + /* Fog RGB colors */ + if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { + fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT ); + fog_rgba_tab[i]( VB, 1, VERT_FACE_REAR ); + } else { + fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR ); + } + } + else { + /* Fog color indexes */ + if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { + fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT ); + fog_ci_tab[i]( VB, 1, VERT_FACE_REAR ); + } else { + fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR ); + } + } +} + +/* + * Apply fog to an array of RGBA pixels. + * 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 + */ +void gl_fog_rgba_pixels( const GLcontext *ctx, + GLuint n, const GLdepth z[], GLubyte rgba[][4] ) +{ + GLfloat c = ctx->ProjectionMatrix.m[10]; + GLfloat d = ctx->ProjectionMatrix.m[14]; + GLuint i; + + GLfloat rFog = ctx->Fog.Color[0] * 255.0F; + GLfloat gFog = ctx->Fog.Color[1] * 255.0F; + GLfloat bFog = ctx->Fog.Color[2] * 255.0F; + + GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ]; + GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ]; + + switch (ctx->Fog.Mode) { + case GL_LINEAR: + { + GLfloat fogEnd = ctx->Fog.End; + GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = -d / (c+ndcz); + GLfloat f, g; + if (eyez < 0.0) eyez = -eyez; + f = (fogEnd - eyez) * fogScale; + f = CLAMP( f, 0.0F, 1.0F ); + g = 1.0F - f; + rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog); + rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog); + rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog); + } + } + break; + case GL_EXP: + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = d / (c+ndcz); + GLfloat f, g; + if (eyez < 0.0) + eyez = -eyez; + f = exp( -ctx->Fog.Density * eyez ); + g = 1.0F - f; + rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog); + rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog); + rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog); + } + break; + case GL_EXP2: + { + GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = d / (c+ndcz); + GLfloat f, g; + GLfloat tmp = negDensitySquared * eyez * eyez; +#ifdef __alpha__ + /* XXX this underflow check may be needed for other systems */ + if (tmp < FLT_MIN_10_EXP) + f = exp( FLT_MIN_10_EXP ); + else +#endif + f = exp( tmp ); + g = 1.0F - f; + rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog); + rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog); + rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog); + } + } + break; + default: + gl_problem(ctx, "Bad fog mode in gl_fog_rgba_pixels"); + return; + } +} + + + + +/* + * Apply fog to an array of color index pixels. + * Input: n - number of pixels + * z - array of integer depth values + * index - pixel color indexes + * Output: index - fogged pixel color indexes + */ +void gl_fog_ci_pixels( const GLcontext *ctx, + GLuint n, const GLdepth z[], GLuint index[] ) +{ + GLfloat c = ctx->ProjectionMatrix.m[10]; + GLfloat d = ctx->ProjectionMatrix.m[14]; + GLuint i; + + GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ]; + GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ]; + + switch (ctx->Fog.Mode) { + case GL_LINEAR: + { + GLfloat fogEnd = ctx->Fog.End; + GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = -d / (c+ndcz); + GLfloat f; + if (eyez < 0.0) eyez = -eyez; + f = (fogEnd - eyez) * fogScale; + f = CLAMP( f, 0.0F, 1.0F ); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index); + } + } + break; + case GL_EXP: + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = -d / (c+ndcz); + GLfloat f; + if (eyez < 0.0) + eyez = -eyez; + f = exp( -ctx->Fog.Density * eyez ); + f = CLAMP( f, 0.0F, 1.0F ); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index); + } + break; + case GL_EXP2: + { + GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; + for (i=0;i<n;i++) { + GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; + GLfloat eyez = -d / (c+ndcz); + GLfloat tmp, f; + if (eyez < 0.0) + eyez = -eyez; + tmp = negDensitySquared * eyez * eyez; +#ifdef __alpha__ + /* XXX this underflow check may be needed for other systems */ + if (tmp < FLT_MIN_10_EXP) + f = exp( FLT_MIN_10_EXP ); + else +#endif + f = exp( tmp ); + f = CLAMP( f, 0.0F, 1.0F ); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index); + } + } + break; + default: + gl_problem(ctx, "Bad fog mode in gl_fog_ci_pixels"); + return; + } +} + diff --git a/src/mesa/main/fog.h b/src/mesa/main/fog.h new file mode 100644 index 00000000000..cf9dcebaf7d --- /dev/null +++ b/src/mesa/main/fog.h @@ -0,0 +1,51 @@ +/* $Id: fog.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 FOG_H +#define FOG_H + + +#include "types.h" + + +extern void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params ); + + +extern void gl_fog_vertices( struct vertex_buffer *VB ); + +extern void gl_fog_rgba_pixels( const GLcontext *ctx, + GLuint n, const GLdepth z[], + GLubyte rgba[][4] ); + +extern void gl_fog_ci_pixels( const GLcontext *ctx, + GLuint n, const GLdepth z[], GLuint indx[] ); + + +extern void gl_init_fog( void ); + +#endif diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c new file mode 100644 index 00000000000..65a682c5472 --- /dev/null +++ b/src/mesa/main/get.c @@ -0,0 +1,3692 @@ +/* $Id: get.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include "context.h" +#include "enable.h" +#include "enums.h" +#include "get.h" +#include "macros.h" +#include "mmath.h" +#include "types.h" +#include "vb.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +#define FLOAT_TO_BOOL(X) ( (X)==0.0F ? GL_FALSE : GL_TRUE ) +#define INT_TO_BOOL(I) ( (I)==0 ? GL_FALSE : GL_TRUE ) +#define ENUM_TO_BOOL(E) ( (E)==0 ? GL_FALSE : GL_TRUE ) + +#ifdef SPECIALCAST +/* Needed for an Amiga compiler */ +#define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X)) +#define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X)) +#else +/* all other compilers */ +#define ENUM_TO_FLOAT(X) ((GLfloat)(X)) +#define ENUM_TO_DOUBLE(X) ((GLdouble)(X)) +#endif + + + +void gl_GetBooleanv( GLcontext *ctx, GLenum pname, GLboolean *params ) +{ + GLuint i; + GLuint texUnit = ctx->Texture.CurrentUnit; + GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit; + const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetBooleanv"); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glGetBooleanv %s\n", gl_lookup_enum_by_nr(pname)); + + switch (pname) { + case GL_ACCUM_RED_BITS: + case GL_ACCUM_GREEN_BITS: + case GL_ACCUM_BLUE_BITS: + case GL_ACCUM_ALPHA_BITS: + *params = INT_TO_BOOL(ctx->Visual->AccumBits); + break; + case GL_ACCUM_CLEAR_VALUE: + params[0] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[0]); + params[1] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[1]); + params[2] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[2]); + params[3] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[3]); + break; + case GL_ALPHA_BIAS: + *params = FLOAT_TO_BOOL(ctx->Pixel.AlphaBias); + break; + case GL_ALPHA_BITS: + *params = INT_TO_BOOL(ctx->Visual->AlphaBits); + break; + case GL_ALPHA_SCALE: + *params = FLOAT_TO_BOOL(ctx->Pixel.AlphaScale); + break; + case GL_ALPHA_TEST: + *params = ctx->Color.AlphaEnabled; + break; + case GL_ALPHA_TEST_FUNC: + *params = ENUM_TO_BOOL(ctx->Color.AlphaFunc); + break; + case GL_ALPHA_TEST_REF: + *params = FLOAT_TO_BOOL((GLfloat) ctx->Color.AlphaRef / 255.0); + break; + case GL_ATTRIB_STACK_DEPTH: + *params = INT_TO_BOOL(ctx->AttribStackDepth); + break; + case GL_AUTO_NORMAL: + *params = ctx->Eval.AutoNormal; + break; + case GL_AUX_BUFFERS: + *params = (NUM_AUX_BUFFERS) ? GL_TRUE : GL_FALSE; + break; + case GL_BLEND: + *params = ctx->Color.BlendEnabled; + break; + case GL_BLEND_DST: + *params = ENUM_TO_BOOL(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC: + *params = ENUM_TO_BOOL(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_SRC_RGB_INGR: + *params = ENUM_TO_BOOL(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_DST_RGB_INGR: + *params = ENUM_TO_BOOL(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC_ALPHA_INGR: + *params = ENUM_TO_BOOL(ctx->Color.BlendSrcA); + break; + case GL_BLEND_DST_ALPHA_INGR: + *params = ENUM_TO_BOOL(ctx->Color.BlendDstA); + break; + case GL_BLEND_EQUATION_EXT: + *params = ENUM_TO_BOOL( ctx->Color.BlendEquation ); + break; + case GL_BLEND_COLOR_EXT: + params[0] = FLOAT_TO_BOOL( ctx->Color.BlendColor[0] ); + params[1] = FLOAT_TO_BOOL( ctx->Color.BlendColor[1] ); + params[2] = FLOAT_TO_BOOL( ctx->Color.BlendColor[2] ); + params[3] = FLOAT_TO_BOOL( ctx->Color.BlendColor[3] ); + break; + case GL_BLUE_BIAS: + *params = FLOAT_TO_BOOL(ctx->Pixel.BlueBias); + break; + case GL_BLUE_BITS: + *params = INT_TO_BOOL( ctx->Visual->BlueBits ); + break; + case GL_BLUE_SCALE: + *params = FLOAT_TO_BOOL(ctx->Pixel.BlueScale); + break; + case GL_CLIENT_ATTRIB_STACK_DEPTH: + *params = INT_TO_BOOL(ctx->ClientAttribStackDepth); + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + *params = ctx->Transform.ClipEnabled[pname-GL_CLIP_PLANE0]; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = FLOAT_TO_BOOL(ctx->Color.ClearColor[0]); + params[1] = FLOAT_TO_BOOL(ctx->Color.ClearColor[1]); + params[2] = FLOAT_TO_BOOL(ctx->Color.ClearColor[2]); + params[3] = FLOAT_TO_BOOL(ctx->Color.ClearColor[3]); + break; + case GL_COLOR_MATERIAL: + *params = ctx->Light.ColorMaterialEnabled; + break; + case GL_COLOR_MATERIAL_FACE: + *params = ENUM_TO_BOOL(ctx->Light.ColorMaterialFace); + break; + case GL_COLOR_MATERIAL_PARAMETER: + *params = ENUM_TO_BOOL(ctx->Light.ColorMaterialMode); + break; + case GL_COLOR_WRITEMASK: + params[0] = ctx->Color.ColorMask[RCOMP] ? GL_TRUE : GL_FALSE; + params[1] = ctx->Color.ColorMask[GCOMP] ? GL_TRUE : GL_FALSE; + params[2] = ctx->Color.ColorMask[BCOMP] ? GL_TRUE : GL_FALSE; + params[3] = ctx->Color.ColorMask[ACOMP] ? GL_TRUE : GL_FALSE; + break; + case GL_CULL_FACE: + *params = ctx->Polygon.CullFlag; + break; + case GL_CULL_FACE_MODE: + *params = ENUM_TO_BOOL(ctx->Polygon.CullFaceMode); + break; + case GL_CURRENT_COLOR: + params[0] = INT_TO_BOOL(ctx->Current.ByteColor[0]); + params[1] = INT_TO_BOOL(ctx->Current.ByteColor[1]); + params[2] = INT_TO_BOOL(ctx->Current.ByteColor[2]); + params[3] = INT_TO_BOOL(ctx->Current.ByteColor[3]); + break; + case GL_CURRENT_INDEX: + *params = INT_TO_BOOL(ctx->Current.Index); + break; + case GL_CURRENT_NORMAL: + params[0] = FLOAT_TO_BOOL(ctx->Current.Normal[0]); + params[1] = FLOAT_TO_BOOL(ctx->Current.Normal[1]); + params[2] = FLOAT_TO_BOOL(ctx->Current.Normal[2]); + break; + case GL_CURRENT_RASTER_COLOR: + params[0] = FLOAT_TO_BOOL(ctx->Current.RasterColor[0]); + params[1] = FLOAT_TO_BOOL(ctx->Current.RasterColor[1]); + params[2] = FLOAT_TO_BOOL(ctx->Current.RasterColor[2]); + params[3] = FLOAT_TO_BOOL(ctx->Current.RasterColor[3]); + break; + case GL_CURRENT_RASTER_DISTANCE: + *params = FLOAT_TO_BOOL(ctx->Current.RasterDistance); + break; + case GL_CURRENT_RASTER_INDEX: + *params = FLOAT_TO_BOOL(ctx->Current.RasterIndex); + break; + case GL_CURRENT_RASTER_POSITION: + params[0] = FLOAT_TO_BOOL(ctx->Current.RasterPos[0]); + params[1] = FLOAT_TO_BOOL(ctx->Current.RasterPos[1]); + params[2] = FLOAT_TO_BOOL(ctx->Current.RasterPos[2]); + params[3] = FLOAT_TO_BOOL(ctx->Current.RasterPos[3]); + break; + case GL_CURRENT_RASTER_TEXTURE_COORDS: + params[0] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][0]); + params[1] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][1]); + params[2] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][2]); + params[3] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][3]); + break; + case GL_CURRENT_RASTER_POSITION_VALID: + *params = ctx->Current.RasterPosValid; + break; + case GL_CURRENT_TEXTURE_COORDS: + params[0] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][0]); + params[1] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][1]); + params[2] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][2]); + params[3] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][3]); + break; + case GL_DEPTH_BIAS: + *params = FLOAT_TO_BOOL(ctx->Pixel.DepthBias); + break; + case GL_DEPTH_BITS: + *params = INT_TO_BOOL(ctx->Visual->DepthBits); + break; + case GL_DEPTH_CLEAR_VALUE: + *params = FLOAT_TO_BOOL(ctx->Depth.Clear); + break; + case GL_DEPTH_FUNC: + *params = ENUM_TO_BOOL(ctx->Depth.Func); + break; + case GL_DEPTH_RANGE: + params[0] = FLOAT_TO_BOOL(ctx->Viewport.Near); + params[1] = FLOAT_TO_BOOL(ctx->Viewport.Far); + break; + case GL_DEPTH_SCALE: + *params = FLOAT_TO_BOOL(ctx->Pixel.DepthScale); + break; + case GL_DEPTH_TEST: + *params = ctx->Depth.Test; + break; + case GL_DEPTH_WRITEMASK: + *params = ctx->Depth.Mask; + break; + case GL_DITHER: + *params = ctx->Color.DitherFlag; + break; + case GL_DOUBLEBUFFER: + *params = ctx->Visual->DBflag; + break; + case GL_DRAW_BUFFER: + *params = ENUM_TO_BOOL(ctx->Color.DrawBuffer); + break; + case GL_EDGE_FLAG: + *params = ctx->Current.EdgeFlag; + break; + case GL_FEEDBACK_BUFFER_SIZE: + /* TODO: is this right? Or, return number of entries in buffer? */ + *params = INT_TO_BOOL(ctx->Feedback.BufferSize); + break; + case GL_FEEDBACK_BUFFER_TYPE: + *params = INT_TO_BOOL(ctx->Feedback.Type); + break; + case GL_FOG: + *params = ctx->Fog.Enabled; + break; + case GL_FOG_COLOR: + params[0] = FLOAT_TO_BOOL(ctx->Fog.Color[0]); + params[1] = FLOAT_TO_BOOL(ctx->Fog.Color[1]); + params[2] = FLOAT_TO_BOOL(ctx->Fog.Color[2]); + params[3] = FLOAT_TO_BOOL(ctx->Fog.Color[3]); + break; + case GL_FOG_DENSITY: + *params = FLOAT_TO_BOOL(ctx->Fog.Density); + break; + case GL_FOG_END: + *params = FLOAT_TO_BOOL(ctx->Fog.End); + break; + case GL_FOG_HINT: + *params = ENUM_TO_BOOL(ctx->Hint.Fog); + break; + case GL_FOG_INDEX: + *params = FLOAT_TO_BOOL(ctx->Fog.Index); + break; + case GL_FOG_MODE: + *params = ENUM_TO_BOOL(ctx->Fog.Mode); + break; + case GL_FOG_START: + *params = FLOAT_TO_BOOL(ctx->Fog.End); + break; + case GL_FRONT_FACE: + *params = ENUM_TO_BOOL(ctx->Polygon.FrontFace); + break; + case GL_GREEN_BIAS: + *params = FLOAT_TO_BOOL(ctx->Pixel.GreenBias); + break; + case GL_GREEN_BITS: + *params = INT_TO_BOOL( ctx->Visual->GreenBits ); + break; + case GL_GREEN_SCALE: + *params = FLOAT_TO_BOOL(ctx->Pixel.GreenScale); + break; + case GL_INDEX_BITS: + *params = INT_TO_BOOL( ctx->Visual->IndexBits ); + break; + case GL_INDEX_CLEAR_VALUE: + *params = INT_TO_BOOL(ctx->Color.ClearIndex); + break; + case GL_INDEX_MODE: + *params = ctx->Visual->RGBAflag ? GL_FALSE : GL_TRUE; + break; + case GL_INDEX_OFFSET: + *params = INT_TO_BOOL(ctx->Pixel.IndexOffset); + break; + case GL_INDEX_SHIFT: + *params = INT_TO_BOOL(ctx->Pixel.IndexShift); + break; + case GL_INDEX_WRITEMASK: + *params = INT_TO_BOOL(ctx->Color.IndexMask); + break; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + *params = ctx->Light.Light[pname-GL_LIGHT0].Enabled; + break; + case GL_LIGHTING: + *params = ctx->Light.Enabled; + break; + case GL_LIGHT_MODEL_AMBIENT: + params[0] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[0]); + params[1] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[1]); + params[2] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[2]); + params[3] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[3]); + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + params[0] = ENUM_TO_BOOL(ctx->Light.Model.ColorControl); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + *params = ctx->Light.Model.LocalViewer; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + *params = ctx->Light.Model.TwoSide; + break; + case GL_LINE_SMOOTH: + *params = ctx->Line.SmoothFlag; + break; + case GL_LINE_SMOOTH_HINT: + *params = ENUM_TO_BOOL(ctx->Hint.LineSmooth); + break; + case GL_LINE_STIPPLE: + *params = ctx->Line.StippleFlag; + break; + case GL_LINE_STIPPLE_PATTERN: + *params = INT_TO_BOOL(ctx->Line.StipplePattern); + break; + case GL_LINE_STIPPLE_REPEAT: + *params = INT_TO_BOOL(ctx->Line.StippleFactor); + break; + case GL_LINE_WIDTH: + *params = FLOAT_TO_BOOL(ctx->Line.Width); + break; + case GL_LINE_WIDTH_GRANULARITY: + *params = FLOAT_TO_BOOL(LINE_WIDTH_GRANULARITY); + break; + case GL_LINE_WIDTH_RANGE: + params[0] = FLOAT_TO_BOOL(MIN_LINE_WIDTH); + params[1] = FLOAT_TO_BOOL(MAX_LINE_WIDTH); + break; + case GL_LIST_BASE: + *params = INT_TO_BOOL(ctx->List.ListBase); + break; + case GL_LIST_INDEX: + *params = INT_TO_BOOL( ctx->CurrentListNum ); + break; + case GL_LIST_MODE: + *params = ENUM_TO_BOOL( ctx->ExecuteFlag + ? GL_COMPILE_AND_EXECUTE : GL_COMPILE ); + break; + case GL_INDEX_LOGIC_OP: + *params = ctx->Color.IndexLogicOpEnabled; + break; + case GL_COLOR_LOGIC_OP: + *params = ctx->Color.ColorLogicOpEnabled; + break; + case GL_LOGIC_OP_MODE: + *params = ENUM_TO_BOOL(ctx->Color.LogicOp); + break; + case GL_MAP1_COLOR_4: + *params = ctx->Eval.Map1Color4; + break; + case GL_MAP1_GRID_DOMAIN: + params[0] = FLOAT_TO_BOOL(ctx->Eval.MapGrid1u1); + params[1] = FLOAT_TO_BOOL(ctx->Eval.MapGrid1u2); + break; + case GL_MAP1_GRID_SEGMENTS: + *params = INT_TO_BOOL(ctx->Eval.MapGrid1un); + break; + case GL_MAP1_INDEX: + *params = ctx->Eval.Map1Index; + break; + case GL_MAP1_NORMAL: + *params = ctx->Eval.Map1Normal; + break; + case GL_MAP1_TEXTURE_COORD_1: + *params = ctx->Eval.Map1TextureCoord1; + break; + case GL_MAP1_TEXTURE_COORD_2: + *params = ctx->Eval.Map1TextureCoord2; + break; + case GL_MAP1_TEXTURE_COORD_3: + *params = ctx->Eval.Map1TextureCoord3; + break; + case GL_MAP1_TEXTURE_COORD_4: + *params = ctx->Eval.Map1TextureCoord4; + break; + case GL_MAP1_VERTEX_3: + *params = ctx->Eval.Map1Vertex3; + break; + case GL_MAP1_VERTEX_4: + *params = ctx->Eval.Map1Vertex4; + break; + case GL_MAP2_COLOR_4: + *params = ctx->Eval.Map2Color4; + break; + case GL_MAP2_GRID_DOMAIN: + params[0] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2u1); + params[1] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2u2); + params[2] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2v1); + params[3] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2v2); + break; + case GL_MAP2_GRID_SEGMENTS: + params[0] = INT_TO_BOOL(ctx->Eval.MapGrid2un); + params[1] = INT_TO_BOOL(ctx->Eval.MapGrid2vn); + break; + case GL_MAP2_INDEX: + *params = ctx->Eval.Map2Index; + break; + case GL_MAP2_NORMAL: + *params = ctx->Eval.Map2Normal; + break; + case GL_MAP2_TEXTURE_COORD_1: + *params = ctx->Eval.Map2TextureCoord1; + break; + case GL_MAP2_TEXTURE_COORD_2: + *params = ctx->Eval.Map2TextureCoord2; + break; + case GL_MAP2_TEXTURE_COORD_3: + *params = ctx->Eval.Map2TextureCoord3; + break; + case GL_MAP2_TEXTURE_COORD_4: + *params = ctx->Eval.Map2TextureCoord4; + break; + case GL_MAP2_VERTEX_3: + *params = ctx->Eval.Map2Vertex3; + break; + case GL_MAP2_VERTEX_4: + *params = ctx->Eval.Map2Vertex4; + break; + case GL_MAP_COLOR: + *params = ctx->Pixel.MapColorFlag; + break; + case GL_MAP_STENCIL: + *params = ctx->Pixel.MapStencilFlag; + break; + case GL_MATRIX_MODE: + *params = ENUM_TO_BOOL( ctx->Transform.MatrixMode ); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + *params = INT_TO_BOOL(MAX_ATTRIB_STACK_DEPTH); + break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: + *params = INT_TO_BOOL( MAX_CLIENT_ATTRIB_STACK_DEPTH); + break; + case GL_MAX_CLIP_PLANES: + *params = INT_TO_BOOL(MAX_CLIP_PLANES); + break; + case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */ + *params = INT_TO_BOOL(VB_MAX); + break; + case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */ + *params = INT_TO_BOOL(VB_MAX); + break; + case GL_MAX_EVAL_ORDER: + *params = INT_TO_BOOL(MAX_EVAL_ORDER); + break; + case GL_MAX_LIGHTS: + *params = INT_TO_BOOL(MAX_LIGHTS); + break; + case GL_MAX_LIST_NESTING: + *params = INT_TO_BOOL(MAX_LIST_NESTING); + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + *params = INT_TO_BOOL(MAX_MODELVIEW_STACK_DEPTH); + break; + case GL_MAX_NAME_STACK_DEPTH: + *params = INT_TO_BOOL(MAX_NAME_STACK_DEPTH); + break; + case GL_MAX_PIXEL_MAP_TABLE: + *params = INT_TO_BOOL(MAX_PIXEL_MAP_TABLE); + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + *params = INT_TO_BOOL(MAX_PROJECTION_STACK_DEPTH); + break; + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_3D_TEXTURE_SIZE: + *params = INT_TO_BOOL(ctx->Const.MaxTextureSize); + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + *params = INT_TO_BOOL(MAX_TEXTURE_STACK_DEPTH); + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = INT_TO_BOOL(MAX_WIDTH); + params[1] = INT_TO_BOOL(MAX_HEIGHT); + break; + case GL_MODELVIEW_MATRIX: + for (i=0;i<16;i++) { + params[i] = FLOAT_TO_BOOL(ctx->ModelView.m[i]); + } + break; + case GL_MODELVIEW_STACK_DEPTH: + *params = INT_TO_BOOL(ctx->ModelViewStackDepth + 1); + break; + case GL_NAME_STACK_DEPTH: + *params = INT_TO_BOOL(ctx->Select.NameStackDepth); + break; + case GL_NORMALIZE: + *params = ctx->Transform.Normalize; + break; + case GL_PACK_ALIGNMENT: + *params = INT_TO_BOOL(ctx->Pack.Alignment); + break; + case GL_PACK_LSB_FIRST: + *params = ctx->Pack.LsbFirst; + break; + case GL_PACK_ROW_LENGTH: + *params = INT_TO_BOOL(ctx->Pack.RowLength); + break; + case GL_PACK_SKIP_PIXELS: + *params = INT_TO_BOOL(ctx->Pack.SkipPixels); + break; + case GL_PACK_SKIP_ROWS: + *params = INT_TO_BOOL(ctx->Pack.SkipRows); + break; + case GL_PACK_SWAP_BYTES: + *params = ctx->Pack.SwapBytes; + break; + case GL_PACK_SKIP_IMAGES_EXT: + *params = ctx->Pack.SkipImages; + break; + case GL_PACK_IMAGE_HEIGHT_EXT: + *params = ctx->Pack.ImageHeight; + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + *params = ENUM_TO_BOOL(ctx->Hint.PerspectiveCorrection); + break; + case GL_PIXEL_MAP_A_TO_A_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapAtoAsize); + break; + case GL_PIXEL_MAP_B_TO_B_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapBtoBsize); + break; + case GL_PIXEL_MAP_G_TO_G_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapGtoGsize); + break; + case GL_PIXEL_MAP_I_TO_A_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapItoAsize); + break; + case GL_PIXEL_MAP_I_TO_B_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapItoBsize); + break; + case GL_PIXEL_MAP_I_TO_G_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapItoGsize); + break; + case GL_PIXEL_MAP_I_TO_I_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapItoIsize); + break; + case GL_PIXEL_MAP_I_TO_R_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapItoRsize); + break; + case GL_PIXEL_MAP_R_TO_R_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapRtoRsize); + break; + case GL_PIXEL_MAP_S_TO_S_SIZE: + *params = INT_TO_BOOL(ctx->Pixel.MapStoSsize); + break; + case GL_POINT_SIZE: + *params = FLOAT_TO_BOOL(ctx->Point.Size ); + break; + case GL_POINT_SIZE_GRANULARITY: + *params = FLOAT_TO_BOOL(POINT_SIZE_GRANULARITY ); + break; + case GL_POINT_SIZE_RANGE: + params[0] = FLOAT_TO_BOOL(MIN_POINT_SIZE ); + params[1] = FLOAT_TO_BOOL(MAX_POINT_SIZE ); + break; + case GL_POINT_SMOOTH: + *params = ctx->Point.SmoothFlag; + break; + case GL_POINT_SMOOTH_HINT: + *params = ENUM_TO_BOOL(ctx->Hint.PointSmooth); + break; + case GL_POINT_SIZE_MIN_EXT: + *params = FLOAT_TO_BOOL(ctx->Point.MinSize); + break; + case GL_POINT_SIZE_MAX_EXT: + *params = FLOAT_TO_BOOL(ctx->Point.MaxSize); + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + *params = FLOAT_TO_BOOL(ctx->Point.Threshold); + break; + case GL_DISTANCE_ATTENUATION_EXT: + params[0] = FLOAT_TO_BOOL(ctx->Point.Params[0]); + params[1] = FLOAT_TO_BOOL(ctx->Point.Params[1]); + params[2] = FLOAT_TO_BOOL(ctx->Point.Params[2]); + break; + case GL_POLYGON_MODE: + params[0] = ENUM_TO_BOOL(ctx->Polygon.FrontMode); + params[1] = ENUM_TO_BOOL(ctx->Polygon.BackMode); + break; +#ifdef GL_EXT_polygon_offset + case GL_POLYGON_OFFSET_BIAS_EXT: + *params = FLOAT_TO_BOOL( ctx->Polygon.OffsetUnits ); + break; +#endif + case GL_POLYGON_OFFSET_FACTOR: + *params = FLOAT_TO_BOOL( ctx->Polygon.OffsetFactor ); + break; + case GL_POLYGON_OFFSET_UNITS: + *params = FLOAT_TO_BOOL( ctx->Polygon.OffsetUnits ); + break; + case GL_POLYGON_SMOOTH: + *params = ctx->Polygon.SmoothFlag; + break; + case GL_POLYGON_SMOOTH_HINT: + *params = ENUM_TO_BOOL(ctx->Hint.PolygonSmooth); + break; + case GL_POLYGON_STIPPLE: + *params = ctx->Polygon.StippleFlag; + break; + case GL_PROJECTION_MATRIX: + for (i=0;i<16;i++) { + params[i] = FLOAT_TO_BOOL(ctx->ProjectionMatrix.m[i]); + } + break; + case GL_PROJECTION_STACK_DEPTH: + *params = INT_TO_BOOL(ctx->ProjectionStackDepth + 1); + break; + case GL_READ_BUFFER: + *params = ENUM_TO_BOOL(ctx->Pixel.ReadBuffer); + break; + case GL_RED_BIAS: + *params = FLOAT_TO_BOOL(ctx->Pixel.RedBias); + break; + case GL_RED_BITS: + *params = INT_TO_BOOL( ctx->Visual->RedBits ); + break; + case GL_RED_SCALE: + *params = FLOAT_TO_BOOL(ctx->Pixel.RedScale); + break; + case GL_RENDER_MODE: + *params = ENUM_TO_BOOL(ctx->RenderMode); + break; + case GL_RGBA_MODE: + *params = ctx->Visual->RGBAflag; + break; + case GL_SCISSOR_BOX: + params[0] = INT_TO_BOOL(ctx->Scissor.X); + params[1] = INT_TO_BOOL(ctx->Scissor.Y); + params[2] = INT_TO_BOOL(ctx->Scissor.Width); + params[3] = INT_TO_BOOL(ctx->Scissor.Height); + break; + case GL_SCISSOR_TEST: + *params = ctx->Scissor.Enabled; + break; + case GL_SELECTION_BUFFER_SIZE: + *params = INT_TO_BOOL(ctx->Select.BufferSize); + break; + case GL_SHADE_MODEL: + *params = ENUM_TO_BOOL(ctx->Light.ShadeModel); + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + *params = ctx->Texture.SharedPalette; + break; + case GL_STENCIL_BITS: + *params = INT_TO_BOOL(ctx->Visual->StencilBits); + break; + case GL_STENCIL_CLEAR_VALUE: + *params = INT_TO_BOOL(ctx->Stencil.Clear); + break; + case GL_STENCIL_FAIL: + *params = ENUM_TO_BOOL(ctx->Stencil.FailFunc); + break; + case GL_STENCIL_FUNC: + *params = ENUM_TO_BOOL(ctx->Stencil.Function); + break; + case GL_STENCIL_PASS_DEPTH_FAIL: + *params = ENUM_TO_BOOL(ctx->Stencil.ZFailFunc); + break; + case GL_STENCIL_PASS_DEPTH_PASS: + *params = ENUM_TO_BOOL(ctx->Stencil.ZPassFunc); + break; + case GL_STENCIL_REF: + *params = INT_TO_BOOL(ctx->Stencil.Ref); + break; + case GL_STENCIL_TEST: + *params = ctx->Stencil.Enabled; + break; + case GL_STENCIL_VALUE_MASK: + *params = INT_TO_BOOL(ctx->Stencil.ValueMask); + break; + case GL_STENCIL_WRITEMASK: + *params = INT_TO_BOOL(ctx->Stencil.WriteMask); + break; + case GL_STEREO: + *params = ctx->Visual->StereoFlag; + break; + case GL_SUBPIXEL_BITS: + *params = INT_TO_BOOL(0); /* TODO */ + break; + case GL_TEXTURE_1D: + *params = gl_IsEnabled( ctx, GL_TEXTURE_1D ); + break; + case GL_TEXTURE_2D: + *params = gl_IsEnabled( ctx, GL_TEXTURE_2D ); + break; + case GL_TEXTURE_3D: + *params = gl_IsEnabled( ctx, GL_TEXTURE_3D ); + break; + case GL_TEXTURE_BINDING_1D: + *params = INT_TO_BOOL(textureUnit->CurrentD[1]->Name); + break; + case GL_TEXTURE_BINDING_2D: + *params = INT_TO_BOOL(textureUnit->CurrentD[2]->Name); + break; + case GL_TEXTURE_BINDING_3D: + *params = INT_TO_BOOL(textureUnit->CurrentD[3]->Name); + break; + case GL_TEXTURE_ENV_COLOR: + { + params[0] = FLOAT_TO_BOOL(textureUnit->EnvColor[0]); + params[1] = FLOAT_TO_BOOL(textureUnit->EnvColor[1]); + params[2] = FLOAT_TO_BOOL(textureUnit->EnvColor[2]); + params[3] = FLOAT_TO_BOOL(textureUnit->EnvColor[3]); + } + break; + case GL_TEXTURE_ENV_MODE: + *params = ENUM_TO_BOOL(textureUnit->EnvMode); + break; + case GL_TEXTURE_GEN_S: + *params = (textureUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_GEN_T: + *params = (textureUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_GEN_R: + *params = (textureUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_GEN_Q: + *params = (textureUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_MATRIX: + for (i=0;i<16;i++) { + params[i] = + FLOAT_TO_BOOL(ctx->TextureMatrix[texTransformUnit].m[i]); + } + break; + case GL_TEXTURE_STACK_DEPTH: + *params = INT_TO_BOOL(ctx->TextureStackDepth[texTransformUnit] + 1); + break; + case GL_UNPACK_ALIGNMENT: + *params = INT_TO_BOOL(ctx->Unpack.Alignment); + break; + case GL_UNPACK_LSB_FIRST: + *params = ctx->Unpack.LsbFirst; + break; + case GL_UNPACK_ROW_LENGTH: + *params = INT_TO_BOOL(ctx->Unpack.RowLength); + break; + case GL_UNPACK_SKIP_PIXELS: + *params = INT_TO_BOOL(ctx->Unpack.SkipPixels); + break; + case GL_UNPACK_SKIP_ROWS: + *params = INT_TO_BOOL(ctx->Unpack.SkipRows); + break; + case GL_UNPACK_SWAP_BYTES: + *params = ctx->Unpack.SwapBytes; + break; + case GL_UNPACK_SKIP_IMAGES_EXT: + *params = ctx->Unpack.SkipImages; + break; + case GL_UNPACK_IMAGE_HEIGHT_EXT: + *params = ctx->Unpack.ImageHeight; + break; + case GL_VIEWPORT: + params[0] = INT_TO_BOOL(ctx->Viewport.X); + params[1] = INT_TO_BOOL(ctx->Viewport.Y); + params[2] = INT_TO_BOOL(ctx->Viewport.Width); + params[3] = INT_TO_BOOL(ctx->Viewport.Height); + break; + case GL_ZOOM_X: + *params = FLOAT_TO_BOOL(ctx->Pixel.ZoomX); + break; + case GL_ZOOM_Y: + *params = FLOAT_TO_BOOL(ctx->Pixel.ZoomY); + break; + case GL_VERTEX_ARRAY_SIZE: + *params = INT_TO_BOOL(ctx->Array.Vertex.Size); + break; + case GL_VERTEX_ARRAY_TYPE: + *params = ENUM_TO_BOOL(ctx->Array.Vertex.Type); + break; + case GL_VERTEX_ARRAY_STRIDE: + *params = INT_TO_BOOL(ctx->Array.Vertex.Stride); + break; + case GL_VERTEX_ARRAY_COUNT_EXT: + *params = INT_TO_BOOL(0); + break; + case GL_NORMAL_ARRAY_TYPE: + *params = ENUM_TO_BOOL(ctx->Array.Normal.Type); + break; + case GL_NORMAL_ARRAY_STRIDE: + *params = INT_TO_BOOL(ctx->Array.Normal.Stride); + break; + case GL_NORMAL_ARRAY_COUNT_EXT: + *params = INT_TO_BOOL(0); + break; + case GL_COLOR_ARRAY_SIZE: + *params = INT_TO_BOOL(ctx->Array.Color.Size); + break; + case GL_COLOR_ARRAY_TYPE: + *params = ENUM_TO_BOOL(ctx->Array.Color.Type); + break; + case GL_COLOR_ARRAY_STRIDE: + *params = INT_TO_BOOL(ctx->Array.Color.Stride); + break; + case GL_COLOR_ARRAY_COUNT_EXT: + *params = INT_TO_BOOL(0); + break; + case GL_INDEX_ARRAY_TYPE: + *params = ENUM_TO_BOOL(ctx->Array.Index.Type); + break; + case GL_INDEX_ARRAY_STRIDE: + *params = INT_TO_BOOL(ctx->Array.Index.Stride); + break; + case GL_INDEX_ARRAY_COUNT_EXT: + *params = INT_TO_BOOL(0); + break; + case GL_TEXTURE_COORD_ARRAY_SIZE: + *params = INT_TO_BOOL(ctx->Array.TexCoord[texUnit].Size); + break; + case GL_TEXTURE_COORD_ARRAY_TYPE: + *params = ENUM_TO_BOOL(ctx->Array.TexCoord[texUnit].Type); + break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: + *params = INT_TO_BOOL(ctx->Array.TexCoord[texUnit].Stride); + break; + case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: + *params = INT_TO_BOOL(0); + break; + case GL_EDGE_FLAG_ARRAY_STRIDE: + *params = INT_TO_BOOL(ctx->Array.EdgeFlag.Stride); + break; + case GL_EDGE_FLAG_ARRAY_EXT: + *params = INT_TO_BOOL(0); + break; + + case GL_MAX_TEXTURE_UNITS_ARB: + *params = ctx->Const.MaxTextureUnits; + break; + case GL_ACTIVE_TEXTURE_ARB: + *params = INT_TO_BOOL(GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit); + break; + case GL_CLIENT_ACTIVE_TEXTURE_ARB: + *params = INT_TO_BOOL(GL_TEXTURE0_ARB + ctx->Array.ActiveTexture); + break; + + + /* GL_PGI_misc_hints */ + case GL_STRICT_DEPTHFUNC_HINT_PGI: + *params = ENUM_TO_BOOL(GL_NICEST); + break; + case GL_STRICT_LIGHTING_HINT_PGI: + *params = ENUM_TO_BOOL(ctx->Hint.StrictLighting); + break; + case GL_STRICT_SCISSOR_HINT_PGI: + case GL_FULL_STIPPLE_HINT_PGI: + *params = ENUM_TO_BOOL(GL_TRUE); + break; + case GL_CONSERVE_MEMORY_HINT_PGI: + *params = ENUM_TO_BOOL(GL_FALSE); + break; + case GL_ALWAYS_FAST_HINT_PGI: + *params = (GLboolean) (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_FALSE && + ctx->Hint.AllowDrawMem == GL_FALSE); + break; + case GL_ALWAYS_SOFT_HINT_PGI: + *params = (GLboolean) (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_TRUE && + ctx->Hint.AllowDrawMem == GL_TRUE); + break; + case GL_ALLOW_DRAW_OBJ_HINT_PGI: + *params = (GLboolean) GL_TRUE; + break; + case GL_ALLOW_DRAW_WIN_HINT_PGI: + *params = (GLboolean) ctx->Hint.AllowDrawWin; + break; + case GL_ALLOW_DRAW_SPN_HINT_PGI: + *params = (GLboolean) ctx->Hint.AllowDrawSpn; + break; + case GL_ALLOW_DRAW_MEM_HINT_PGI: + *params = (GLboolean) ctx->Hint.AllowDrawMem; + break; + case GL_CLIP_NEAR_HINT_PGI: + case GL_CLIP_FAR_HINT_PGI: + *params = ENUM_TO_BOOL(GL_TRUE); + break; + case GL_WIDE_LINE_HINT_PGI: + *params = ENUM_TO_BOOL(GL_DONT_CARE); + break; + case GL_BACK_NORMALS_HINT_PGI: + *params = ENUM_TO_BOOL(GL_TRUE); + break; + case GL_NATIVE_GRAPHICS_HANDLE_PGI: + *params = 0; + break; + default: + printf("invalid enum: %x\n", pname); + gl_error( ctx, GL_INVALID_ENUM, "glGetBooleanv" ); + } +} + + + + +void gl_GetDoublev( GLcontext *ctx, GLenum pname, GLdouble *params ) +{ + GLuint i; + GLuint texUnit = ctx->Texture.CurrentUnit; + GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit; + const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetDoublev"); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glGetDoublev %s\n", gl_lookup_enum_by_nr(pname)); + + switch (pname) { + case GL_ACCUM_RED_BITS: + case GL_ACCUM_GREEN_BITS: + case GL_ACCUM_BLUE_BITS: + case GL_ACCUM_ALPHA_BITS: + *params = (GLdouble) ctx->Visual->AccumBits; + break; + case GL_ACCUM_CLEAR_VALUE: + params[0] = (GLdouble) ctx->Accum.ClearColor[0]; + params[1] = (GLdouble) ctx->Accum.ClearColor[1]; + params[2] = (GLdouble) ctx->Accum.ClearColor[2]; + params[3] = (GLdouble) ctx->Accum.ClearColor[3]; + break; + case GL_ALPHA_BIAS: + *params = (GLdouble) ctx->Pixel.AlphaBias; + break; + case GL_ALPHA_BITS: + *params = (GLdouble) ctx->Visual->AlphaBits; + break; + case GL_ALPHA_SCALE: + *params = (GLdouble) ctx->Pixel.AlphaScale; + break; + case GL_ALPHA_TEST: + *params = (GLdouble) ctx->Color.AlphaEnabled; + break; + case GL_ALPHA_TEST_FUNC: + *params = ENUM_TO_DOUBLE(ctx->Color.AlphaFunc); + break; + case GL_ALPHA_TEST_REF: + *params = (GLdouble) ctx->Color.AlphaRef / 255.0; + break; + case GL_ATTRIB_STACK_DEPTH: + *params = (GLdouble ) (ctx->AttribStackDepth); + break; + case GL_AUTO_NORMAL: + *params = (GLdouble) ctx->Eval.AutoNormal; + break; + case GL_AUX_BUFFERS: + *params = (GLdouble) NUM_AUX_BUFFERS; + break; + case GL_BLEND: + *params = (GLdouble) ctx->Color.BlendEnabled; + break; + case GL_BLEND_DST: + *params = ENUM_TO_DOUBLE(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC: + *params = ENUM_TO_DOUBLE(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_SRC_RGB_INGR: + *params = ENUM_TO_DOUBLE(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_DST_RGB_INGR: + *params = ENUM_TO_DOUBLE(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC_ALPHA_INGR: + *params = ENUM_TO_DOUBLE(ctx->Color.BlendSrcA); + break; + case GL_BLEND_DST_ALPHA_INGR: + *params = ENUM_TO_DOUBLE(ctx->Color.BlendDstA); + break; + case GL_BLEND_EQUATION_EXT: + *params = ENUM_TO_DOUBLE(ctx->Color.BlendEquation); + break; + case GL_BLEND_COLOR_EXT: + params[0] = (GLdouble) ctx->Color.BlendColor[0]; + params[1] = (GLdouble) ctx->Color.BlendColor[1]; + params[2] = (GLdouble) ctx->Color.BlendColor[2]; + params[3] = (GLdouble) ctx->Color.BlendColor[3]; + break; + case GL_BLUE_BIAS: + *params = (GLdouble) ctx->Pixel.BlueBias; + break; + case GL_BLUE_BITS: + *params = (GLdouble) ctx->Visual->BlueBits; + break; + case GL_BLUE_SCALE: + *params = (GLdouble) ctx->Pixel.BlueScale; + break; + case GL_CLIENT_ATTRIB_STACK_DEPTH: + *params = (GLdouble) (ctx->ClientAttribStackDepth); + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + *params = (GLdouble) ctx->Transform.ClipEnabled[pname-GL_CLIP_PLANE0]; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = (GLdouble) ctx->Color.ClearColor[0]; + params[1] = (GLdouble) ctx->Color.ClearColor[1]; + params[2] = (GLdouble) ctx->Color.ClearColor[2]; + params[3] = (GLdouble) ctx->Color.ClearColor[3]; + break; + case GL_COLOR_MATERIAL: + *params = (GLdouble) ctx->Light.ColorMaterialEnabled; + break; + case GL_COLOR_MATERIAL_FACE: + *params = ENUM_TO_DOUBLE(ctx->Light.ColorMaterialFace); + break; + case GL_COLOR_MATERIAL_PARAMETER: + *params = ENUM_TO_DOUBLE(ctx->Light.ColorMaterialMode); + break; + case GL_COLOR_WRITEMASK: + params[0] = ctx->Color.ColorMask[RCOMP] ? 1.0 : 0.0; + params[1] = ctx->Color.ColorMask[GCOMP] ? 1.0 : 0.0; + params[2] = ctx->Color.ColorMask[BCOMP] ? 1.0 : 0.0; + params[3] = ctx->Color.ColorMask[ACOMP] ? 1.0 : 0.0; + break; + case GL_CULL_FACE: + *params = (GLdouble) ctx->Polygon.CullFlag; + break; + case GL_CULL_FACE_MODE: + *params = ENUM_TO_DOUBLE(ctx->Polygon.CullFaceMode); + break; + case GL_CURRENT_COLOR: + params[0] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[0]); + params[1] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[1]); + params[2] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[2]); + params[3] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[3]); + break; + case GL_CURRENT_INDEX: + *params = (GLdouble) ctx->Current.Index; + break; + case GL_CURRENT_NORMAL: + params[0] = (GLdouble) ctx->Current.Normal[0]; + params[1] = (GLdouble) ctx->Current.Normal[1]; + params[2] = (GLdouble) ctx->Current.Normal[2]; + break; + case GL_CURRENT_RASTER_COLOR: + params[0] = (GLdouble) ctx->Current.RasterColor[0]; + params[1] = (GLdouble) ctx->Current.RasterColor[1]; + params[2] = (GLdouble) ctx->Current.RasterColor[2]; + params[3] = (GLdouble) ctx->Current.RasterColor[3]; + break; + case GL_CURRENT_RASTER_DISTANCE: + params[0] = (GLdouble) ctx->Current.RasterDistance; + break; + case GL_CURRENT_RASTER_INDEX: + *params = (GLdouble) ctx->Current.RasterIndex; + break; + case GL_CURRENT_RASTER_POSITION: + params[0] = (GLdouble) ctx->Current.RasterPos[0]; + params[1] = (GLdouble) ctx->Current.RasterPos[1]; + params[2] = (GLdouble) ctx->Current.RasterPos[2]; + params[3] = (GLdouble) ctx->Current.RasterPos[3]; + break; + case GL_CURRENT_RASTER_TEXTURE_COORDS: + params[0] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][0]; + params[1] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][1]; + params[2] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][2]; + params[3] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][3]; + break; + case GL_CURRENT_RASTER_POSITION_VALID: + *params = (GLdouble) ctx->Current.RasterPosValid; + break; + case GL_CURRENT_TEXTURE_COORDS: + params[0] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][0]; + params[1] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][1]; + params[2] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][2]; + params[3] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][3]; + break; + case GL_DEPTH_BIAS: + *params = (GLdouble) ctx->Pixel.DepthBias; + break; + case GL_DEPTH_BITS: + *params = (GLdouble) ctx->Visual->DepthBits; + break; + case GL_DEPTH_CLEAR_VALUE: + *params = (GLdouble) ctx->Depth.Clear; + break; + case GL_DEPTH_FUNC: + *params = ENUM_TO_DOUBLE(ctx->Depth.Func); + break; + case GL_DEPTH_RANGE: + params[0] = (GLdouble) ctx->Viewport.Near; + params[1] = (GLdouble) ctx->Viewport.Far; + break; + case GL_DEPTH_SCALE: + *params = (GLdouble) ctx->Pixel.DepthScale; + break; + case GL_DEPTH_TEST: + *params = (GLdouble) ctx->Depth.Test; + break; + case GL_DEPTH_WRITEMASK: + *params = (GLdouble) ctx->Depth.Mask; + break; + case GL_DITHER: + *params = (GLdouble) ctx->Color.DitherFlag; + break; + case GL_DOUBLEBUFFER: + *params = (GLdouble) ctx->Visual->DBflag; + break; + case GL_DRAW_BUFFER: + *params = ENUM_TO_DOUBLE(ctx->Color.DrawBuffer); + break; + case GL_EDGE_FLAG: + *params = (GLdouble) ctx->Current.EdgeFlag; + break; + case GL_FEEDBACK_BUFFER_SIZE: + /* TODO: is this right? Or, return number of entries in buffer? */ + *params = (GLdouble) ctx->Feedback.BufferSize; + break; + case GL_FEEDBACK_BUFFER_TYPE: + *params = ENUM_TO_DOUBLE(ctx->Feedback.Type); + break; + case GL_FOG: + *params = (GLdouble) ctx->Fog.Enabled; + break; + case GL_FOG_COLOR: + params[0] = (GLdouble) ctx->Fog.Color[0]; + params[1] = (GLdouble) ctx->Fog.Color[1]; + params[2] = (GLdouble) ctx->Fog.Color[2]; + params[3] = (GLdouble) ctx->Fog.Color[3]; + break; + case GL_FOG_DENSITY: + *params = (GLdouble) ctx->Fog.Density; + break; + case GL_FOG_END: + *params = (GLdouble) ctx->Fog.End; + break; + case GL_FOG_HINT: + *params = ENUM_TO_DOUBLE(ctx->Hint.Fog); + break; + case GL_FOG_INDEX: + *params = (GLdouble) ctx->Fog.Index; + break; + case GL_FOG_MODE: + *params = ENUM_TO_DOUBLE(ctx->Fog.Mode); + break; + case GL_FOG_START: + *params = (GLdouble) ctx->Fog.Start; + break; + case GL_FRONT_FACE: + *params = ENUM_TO_DOUBLE(ctx->Polygon.FrontFace); + break; + case GL_GREEN_BIAS: + *params = (GLdouble) ctx->Pixel.GreenBias; + break; + case GL_GREEN_BITS: + *params = (GLdouble) ctx->Visual->GreenBits; + break; + case GL_GREEN_SCALE: + *params = (GLdouble) ctx->Pixel.GreenScale; + break; + case GL_INDEX_BITS: + *params = (GLdouble) ctx->Visual->IndexBits; + break; + case GL_INDEX_CLEAR_VALUE: + *params = (GLdouble) ctx->Color.ClearIndex; + break; + case GL_INDEX_MODE: + *params = ctx->Visual->RGBAflag ? 0.0 : 1.0; + break; + case GL_INDEX_OFFSET: + *params = (GLdouble) ctx->Pixel.IndexOffset; + break; + case GL_INDEX_SHIFT: + *params = (GLdouble) ctx->Pixel.IndexShift; + break; + case GL_INDEX_WRITEMASK: + *params = (GLdouble) ctx->Color.IndexMask; + break; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + *params = (GLdouble) ctx->Light.Light[pname-GL_LIGHT0].Enabled; + break; + case GL_LIGHTING: + *params = (GLdouble) ctx->Light.Enabled; + break; + case GL_LIGHT_MODEL_AMBIENT: + params[0] = (GLdouble) ctx->Light.Model.Ambient[0]; + params[1] = (GLdouble) ctx->Light.Model.Ambient[1]; + params[2] = (GLdouble) ctx->Light.Model.Ambient[2]; + params[3] = (GLdouble) ctx->Light.Model.Ambient[3]; + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + params[0] = (GLdouble) ctx->Light.Model.ColorControl; + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + *params = (GLdouble) ctx->Light.Model.LocalViewer; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + *params = (GLdouble) ctx->Light.Model.TwoSide; + break; + case GL_LINE_SMOOTH: + *params = (GLdouble) ctx->Line.SmoothFlag; + break; + case GL_LINE_SMOOTH_HINT: + *params = ENUM_TO_DOUBLE(ctx->Hint.LineSmooth); + break; + case GL_LINE_STIPPLE: + *params = (GLdouble) ctx->Line.StippleFlag; + break; + case GL_LINE_STIPPLE_PATTERN: + *params = (GLdouble) ctx->Line.StipplePattern; + break; + case GL_LINE_STIPPLE_REPEAT: + *params = (GLdouble) ctx->Line.StippleFactor; + break; + case GL_LINE_WIDTH: + *params = (GLdouble) ctx->Line.Width; + break; + case GL_LINE_WIDTH_GRANULARITY: + *params = (GLdouble) LINE_WIDTH_GRANULARITY; + break; + case GL_LINE_WIDTH_RANGE: + params[0] = (GLdouble) MIN_LINE_WIDTH; + params[1] = (GLdouble) MAX_LINE_WIDTH; + break; + case GL_LIST_BASE: + *params = (GLdouble) ctx->List.ListBase; + break; + case GL_LIST_INDEX: + *params = (GLdouble) ctx->CurrentListNum; + break; + case GL_LIST_MODE: + *params = ctx->ExecuteFlag ? ENUM_TO_DOUBLE(GL_COMPILE_AND_EXECUTE) + : ENUM_TO_DOUBLE(GL_COMPILE); + break; + case GL_INDEX_LOGIC_OP: + *params = (GLdouble) ctx->Color.IndexLogicOpEnabled; + break; + case GL_COLOR_LOGIC_OP: + *params = (GLdouble) ctx->Color.ColorLogicOpEnabled; + break; + case GL_LOGIC_OP_MODE: + *params = ENUM_TO_DOUBLE(ctx->Color.LogicOp); + break; + case GL_MAP1_COLOR_4: + *params = (GLdouble) ctx->Eval.Map1Color4; + break; + case GL_MAP1_GRID_DOMAIN: + params[0] = (GLdouble) ctx->Eval.MapGrid1u1; + params[1] = (GLdouble) ctx->Eval.MapGrid1u2; + break; + case GL_MAP1_GRID_SEGMENTS: + *params = (GLdouble) ctx->Eval.MapGrid1un; + break; + case GL_MAP1_INDEX: + *params = (GLdouble) ctx->Eval.Map1Index; + break; + case GL_MAP1_NORMAL: + *params = (GLdouble) ctx->Eval.Map1Normal; + break; + case GL_MAP1_TEXTURE_COORD_1: + *params = (GLdouble) ctx->Eval.Map1TextureCoord1; + break; + case GL_MAP1_TEXTURE_COORD_2: + *params = (GLdouble) ctx->Eval.Map1TextureCoord2; + break; + case GL_MAP1_TEXTURE_COORD_3: + *params = (GLdouble) ctx->Eval.Map1TextureCoord3; + break; + case GL_MAP1_TEXTURE_COORD_4: + *params = (GLdouble) ctx->Eval.Map1TextureCoord4; + break; + case GL_MAP1_VERTEX_3: + *params = (GLdouble) ctx->Eval.Map1Vertex3; + break; + case GL_MAP1_VERTEX_4: + *params = (GLdouble) ctx->Eval.Map1Vertex4; + break; + case GL_MAP2_COLOR_4: + *params = (GLdouble) ctx->Eval.Map2Color4; + break; + case GL_MAP2_GRID_DOMAIN: + params[0] = (GLdouble) ctx->Eval.MapGrid2u1; + params[1] = (GLdouble) ctx->Eval.MapGrid2u2; + params[2] = (GLdouble) ctx->Eval.MapGrid2v1; + params[3] = (GLdouble) ctx->Eval.MapGrid2v2; + break; + case GL_MAP2_GRID_SEGMENTS: + params[0] = (GLdouble) ctx->Eval.MapGrid2un; + params[1] = (GLdouble) ctx->Eval.MapGrid2vn; + break; + case GL_MAP2_INDEX: + *params = (GLdouble) ctx->Eval.Map2Index; + break; + case GL_MAP2_NORMAL: + *params = (GLdouble) ctx->Eval.Map2Normal; + break; + case GL_MAP2_TEXTURE_COORD_1: + *params = (GLdouble) ctx->Eval.Map2TextureCoord1; + break; + case GL_MAP2_TEXTURE_COORD_2: + *params = (GLdouble) ctx->Eval.Map2TextureCoord2; + break; + case GL_MAP2_TEXTURE_COORD_3: + *params = (GLdouble) ctx->Eval.Map2TextureCoord3; + break; + case GL_MAP2_TEXTURE_COORD_4: + *params = (GLdouble) ctx->Eval.Map2TextureCoord4; + break; + case GL_MAP2_VERTEX_3: + *params = (GLdouble) ctx->Eval.Map2Vertex3; + break; + case GL_MAP2_VERTEX_4: + *params = (GLdouble) ctx->Eval.Map2Vertex4; + break; + case GL_MAP_COLOR: + *params = (GLdouble) ctx->Pixel.MapColorFlag; + break; + case GL_MAP_STENCIL: + *params = (GLdouble) ctx->Pixel.MapStencilFlag; + break; + case GL_MATRIX_MODE: + *params = ENUM_TO_DOUBLE(ctx->Transform.MatrixMode); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + *params = (GLdouble) MAX_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: + *params = (GLdouble) MAX_CLIENT_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIP_PLANES: + *params = (GLdouble) MAX_CLIP_PLANES; + break; + case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */ + *params = (GLdouble) VB_MAX; + break; + case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */ + *params = (GLdouble) VB_MAX; + break; + case GL_MAX_EVAL_ORDER: + *params = (GLdouble) MAX_EVAL_ORDER; + break; + case GL_MAX_LIGHTS: + *params = (GLdouble) MAX_LIGHTS; + break; + case GL_MAX_LIST_NESTING: + *params = (GLdouble) MAX_LIST_NESTING; + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + *params = (GLdouble) MAX_MODELVIEW_STACK_DEPTH; + break; + case GL_MAX_NAME_STACK_DEPTH: + *params = (GLdouble) MAX_NAME_STACK_DEPTH; + break; + case GL_MAX_PIXEL_MAP_TABLE: + *params = (GLdouble) MAX_PIXEL_MAP_TABLE; + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + *params = (GLdouble) MAX_PROJECTION_STACK_DEPTH; + break; + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_3D_TEXTURE_SIZE: + *params = (GLdouble) ctx->Const.MaxTextureSize; + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + *params = (GLdouble) MAX_TEXTURE_STACK_DEPTH; + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = (GLdouble) MAX_WIDTH; + params[1] = (GLdouble) MAX_HEIGHT; + break; + case GL_MODELVIEW_MATRIX: + for (i=0;i<16;i++) { + params[i] = (GLdouble) ctx->ModelView.m[i]; + } + break; + case GL_MODELVIEW_STACK_DEPTH: + *params = (GLdouble) (ctx->ModelViewStackDepth + 1); + break; + case GL_NAME_STACK_DEPTH: + *params = (GLdouble) ctx->Select.NameStackDepth; + break; + case GL_NORMALIZE: + *params = (GLdouble) ctx->Transform.Normalize; + break; + case GL_PACK_ALIGNMENT: + *params = (GLdouble) ctx->Pack.Alignment; + break; + case GL_PACK_LSB_FIRST: + *params = (GLdouble) ctx->Pack.LsbFirst; + break; + case GL_PACK_ROW_LENGTH: + *params = (GLdouble) ctx->Pack.RowLength; + break; + case GL_PACK_SKIP_PIXELS: + *params = (GLdouble) ctx->Pack.SkipPixels; + break; + case GL_PACK_SKIP_ROWS: + *params = (GLdouble) ctx->Pack.SkipRows; + break; + case GL_PACK_SWAP_BYTES: + *params = (GLdouble) ctx->Pack.SwapBytes; + break; + case GL_PACK_SKIP_IMAGES_EXT: + *params = (GLdouble) ctx->Pack.SkipImages; + break; + case GL_PACK_IMAGE_HEIGHT_EXT: + *params = (GLdouble) ctx->Pack.ImageHeight; + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + *params = ENUM_TO_DOUBLE(ctx->Hint.PerspectiveCorrection); + break; + case GL_PIXEL_MAP_A_TO_A_SIZE: + *params = (GLdouble) ctx->Pixel.MapAtoAsize; + break; + case GL_PIXEL_MAP_B_TO_B_SIZE: + *params = (GLdouble) ctx->Pixel.MapBtoBsize; + break; + case GL_PIXEL_MAP_G_TO_G_SIZE: + *params = (GLdouble) ctx->Pixel.MapGtoGsize; + break; + case GL_PIXEL_MAP_I_TO_A_SIZE: + *params = (GLdouble) ctx->Pixel.MapItoAsize; + break; + case GL_PIXEL_MAP_I_TO_B_SIZE: + *params = (GLdouble) ctx->Pixel.MapItoBsize; + break; + case GL_PIXEL_MAP_I_TO_G_SIZE: + *params = (GLdouble) ctx->Pixel.MapItoGsize; + break; + case GL_PIXEL_MAP_I_TO_I_SIZE: + *params = (GLdouble) ctx->Pixel.MapItoIsize; + break; + case GL_PIXEL_MAP_I_TO_R_SIZE: + *params = (GLdouble) ctx->Pixel.MapItoRsize; + break; + case GL_PIXEL_MAP_R_TO_R_SIZE: + *params = (GLdouble) ctx->Pixel.MapRtoRsize; + break; + case GL_PIXEL_MAP_S_TO_S_SIZE: + *params = (GLdouble) ctx->Pixel.MapStoSsize; + break; + case GL_POINT_SIZE: + *params = (GLdouble) ctx->Point.Size; + break; + case GL_POINT_SIZE_GRANULARITY: + *params = (GLdouble) POINT_SIZE_GRANULARITY; + break; + case GL_POINT_SIZE_RANGE: + params[0] = (GLdouble) MIN_POINT_SIZE; + params[1] = (GLdouble) MAX_POINT_SIZE; + break; + case GL_POINT_SMOOTH: + *params = (GLdouble) ctx->Point.SmoothFlag; + break; + case GL_POINT_SMOOTH_HINT: + *params = ENUM_TO_DOUBLE(ctx->Hint.PointSmooth); + break; + case GL_POINT_SIZE_MIN_EXT: + *params = (GLdouble) (ctx->Point.MinSize); + break; + case GL_POINT_SIZE_MAX_EXT: + *params = (GLdouble) (ctx->Point.MaxSize); + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + *params = (GLdouble) (ctx->Point.Threshold); + break; + case GL_DISTANCE_ATTENUATION_EXT: + params[0] = (GLdouble) (ctx->Point.Params[0]); + params[1] = (GLdouble) (ctx->Point.Params[1]); + params[2] = (GLdouble) (ctx->Point.Params[2]); + break; + case GL_POLYGON_MODE: + params[0] = ENUM_TO_DOUBLE(ctx->Polygon.FrontMode); + params[1] = ENUM_TO_DOUBLE(ctx->Polygon.BackMode); + break; +#ifdef GL_EXT_polygon_offset + case GL_POLYGON_OFFSET_BIAS_EXT: + *params = (GLdouble) ctx->Polygon.OffsetUnits; + break; +#endif + case GL_POLYGON_OFFSET_FACTOR: + *params = (GLdouble) ctx->Polygon.OffsetFactor; + break; + case GL_POLYGON_OFFSET_UNITS: + *params = (GLdouble) ctx->Polygon.OffsetUnits; + break; + case GL_POLYGON_SMOOTH: + *params = (GLdouble) ctx->Polygon.SmoothFlag; + break; + case GL_POLYGON_SMOOTH_HINT: + *params = ENUM_TO_DOUBLE(ctx->Hint.PolygonSmooth); + break; + case GL_POLYGON_STIPPLE: + *params = (GLdouble) ctx->Polygon.StippleFlag; + break; + case GL_PROJECTION_MATRIX: + for (i=0;i<16;i++) { + params[i] = (GLdouble) ctx->ProjectionMatrix.m[i]; + } + break; + case GL_PROJECTION_STACK_DEPTH: + *params = (GLdouble) (ctx->ProjectionStackDepth + 1); + break; + case GL_READ_BUFFER: + *params = ENUM_TO_DOUBLE(ctx->Pixel.ReadBuffer); + break; + case GL_RED_BIAS: + *params = (GLdouble) ctx->Pixel.RedBias; + break; + case GL_RED_BITS: + *params = (GLdouble) ctx->Visual->RedBits; + break; + case GL_RED_SCALE: + *params = (GLdouble) ctx->Pixel.RedScale; + break; + case GL_RENDER_MODE: + *params = ENUM_TO_DOUBLE(ctx->RenderMode); + break; + case GL_RGBA_MODE: + *params = (GLdouble) ctx->Visual->RGBAflag; + break; + case GL_SCISSOR_BOX: + params[0] = (GLdouble) ctx->Scissor.X; + params[1] = (GLdouble) ctx->Scissor.Y; + params[2] = (GLdouble) ctx->Scissor.Width; + params[3] = (GLdouble) ctx->Scissor.Height; + break; + case GL_SCISSOR_TEST: + *params = (GLdouble) ctx->Scissor.Enabled; + break; + case GL_SELECTION_BUFFER_SIZE: + *params = (GLdouble) ctx->Select.BufferSize; + break; + case GL_SHADE_MODEL: + *params = ENUM_TO_DOUBLE(ctx->Light.ShadeModel); + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + *params = (GLdouble) ctx->Texture.SharedPalette; + break; + case GL_STENCIL_BITS: + *params = (GLdouble) ctx->Visual->StencilBits; + break; + case GL_STENCIL_CLEAR_VALUE: + *params = (GLdouble) ctx->Stencil.Clear; + break; + case GL_STENCIL_FAIL: + *params = ENUM_TO_DOUBLE(ctx->Stencil.FailFunc); + break; + case GL_STENCIL_FUNC: + *params = ENUM_TO_DOUBLE(ctx->Stencil.Function); + break; + case GL_STENCIL_PASS_DEPTH_FAIL: + *params = ENUM_TO_DOUBLE(ctx->Stencil.ZFailFunc); + break; + case GL_STENCIL_PASS_DEPTH_PASS: + *params = ENUM_TO_DOUBLE(ctx->Stencil.ZPassFunc); + break; + case GL_STENCIL_REF: + *params = (GLdouble) ctx->Stencil.Ref; + break; + case GL_STENCIL_TEST: + *params = (GLdouble) ctx->Stencil.Enabled; + break; + case GL_STENCIL_VALUE_MASK: + *params = (GLdouble) ctx->Stencil.ValueMask; + break; + case GL_STENCIL_WRITEMASK: + *params = (GLdouble) ctx->Stencil.WriteMask; + break; + case GL_STEREO: + *params = (GLdouble) ctx->Visual->StereoFlag; + break; + case GL_SUBPIXEL_BITS: + *params = 0.0; /* TODO */ + break; + case GL_TEXTURE_1D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_1D) ? 1.0 : 0.0; + break; + case GL_TEXTURE_2D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_2D) ? 1.0 : 0.0; + break; + case GL_TEXTURE_3D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_3D) ? 1.0 : 0.0; + break; + case GL_TEXTURE_BINDING_1D: + *params = (GLdouble) textureUnit->CurrentD[1]->Name; + break; + case GL_TEXTURE_BINDING_2D: + *params = (GLdouble) textureUnit->CurrentD[2]->Name; + break; + case GL_TEXTURE_BINDING_3D: + *params = (GLdouble) textureUnit->CurrentD[3]->Name; + break; + case GL_TEXTURE_ENV_COLOR: + params[0] = (GLdouble) textureUnit->EnvColor[0]; + params[1] = (GLdouble) textureUnit->EnvColor[1]; + params[2] = (GLdouble) textureUnit->EnvColor[2]; + params[3] = (GLdouble) textureUnit->EnvColor[3]; + break; + case GL_TEXTURE_ENV_MODE: + *params = ENUM_TO_DOUBLE(textureUnit->EnvMode); + break; + case GL_TEXTURE_GEN_S: + *params = (textureUnit->TexGenEnabled & S_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_GEN_T: + *params = (textureUnit->TexGenEnabled & T_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_GEN_R: + *params = (textureUnit->TexGenEnabled & R_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_GEN_Q: + *params = (textureUnit->TexGenEnabled & Q_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_MATRIX: + for (i=0;i<16;i++) { + params[i] = (GLdouble) ctx->TextureMatrix[texTransformUnit].m[i]; + } + break; + case GL_TEXTURE_STACK_DEPTH: + *params = (GLdouble) (ctx->TextureStackDepth[texTransformUnit] + 1); + break; + case GL_UNPACK_ALIGNMENT: + *params = (GLdouble) ctx->Unpack.Alignment; + break; + case GL_UNPACK_LSB_FIRST: + *params = (GLdouble) ctx->Unpack.LsbFirst; + break; + case GL_UNPACK_ROW_LENGTH: + *params = (GLdouble) ctx->Unpack.RowLength; + break; + case GL_UNPACK_SKIP_PIXELS: + *params = (GLdouble) ctx->Unpack.SkipPixels; + break; + case GL_UNPACK_SKIP_ROWS: + *params = (GLdouble) ctx->Unpack.SkipRows; + break; + case GL_UNPACK_SWAP_BYTES: + *params = (GLdouble) ctx->Unpack.SwapBytes; + break; + case GL_UNPACK_SKIP_IMAGES_EXT: + *params = (GLdouble) ctx->Unpack.SkipImages; + break; + case GL_UNPACK_IMAGE_HEIGHT_EXT: + *params = (GLdouble) ctx->Unpack.ImageHeight; + break; + case GL_VIEWPORT: + params[0] = (GLdouble) ctx->Viewport.X; + params[1] = (GLdouble) ctx->Viewport.Y; + params[2] = (GLdouble) ctx->Viewport.Width; + params[3] = (GLdouble) ctx->Viewport.Height; + break; + case GL_ZOOM_X: + *params = (GLdouble) ctx->Pixel.ZoomX; + break; + case GL_ZOOM_Y: + *params = (GLdouble) ctx->Pixel.ZoomY; + break; + case GL_VERTEX_ARRAY_SIZE: + *params = (GLdouble) ctx->Array.Vertex.Size; + break; + case GL_VERTEX_ARRAY_TYPE: + *params = ENUM_TO_DOUBLE(ctx->Array.Vertex.Type); + break; + case GL_VERTEX_ARRAY_STRIDE: + *params = (GLdouble) ctx->Array.Vertex.Stride; + break; + case GL_VERTEX_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_NORMAL_ARRAY_TYPE: + *params = ENUM_TO_DOUBLE(ctx->Array.Normal.Type); + break; + case GL_NORMAL_ARRAY_STRIDE: + *params = (GLdouble) ctx->Array.Normal.Stride; + break; + case GL_NORMAL_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_COLOR_ARRAY_SIZE: + *params = (GLdouble) ctx->Array.Color.Size; + break; + case GL_COLOR_ARRAY_TYPE: + *params = ENUM_TO_DOUBLE(ctx->Array.Color.Type); + break; + case GL_COLOR_ARRAY_STRIDE: + *params = (GLdouble) ctx->Array.Color.Stride; + break; + case GL_COLOR_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_INDEX_ARRAY_TYPE: + *params = ENUM_TO_DOUBLE(ctx->Array.Index.Type); + break; + case GL_INDEX_ARRAY_STRIDE: + *params = (GLdouble) ctx->Array.Index.Stride; + break; + case GL_INDEX_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_TEXTURE_COORD_ARRAY_SIZE: + *params = (GLdouble) ctx->Array.TexCoord[texUnit].Size; + break; + case GL_TEXTURE_COORD_ARRAY_TYPE: + *params = ENUM_TO_DOUBLE(ctx->Array.TexCoord[texUnit].Type); + break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: + *params = (GLdouble) ctx->Array.TexCoord[texUnit].Stride; + break; + case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_EDGE_FLAG_ARRAY_STRIDE: + *params = (GLdouble) ctx->Array.EdgeFlag.Stride; + break; + case GL_EDGE_FLAG_ARRAY_COUNT_EXT: + *params = 0.0; + break; + + case GL_MAX_TEXTURE_UNITS_ARB: + *params = (GLdouble) ctx->Const.MaxTextureUnits; + break; + case GL_ACTIVE_TEXTURE_ARB: + *params = (GLdouble) (GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit); + break; + case GL_CLIENT_ACTIVE_TEXTURE_ARB: + *params = (GLdouble) (GL_TEXTURE0_ARB + ctx->Array.ActiveTexture); + break; + + + /* GL_PGI_misc_hints */ + case GL_STRICT_DEPTHFUNC_HINT_PGI: + *params = ENUM_TO_DOUBLE(GL_NICEST); + break; + case GL_STRICT_LIGHTING_HINT_PGI: + *params = ENUM_TO_DOUBLE(ctx->Hint.StrictLighting); + break; + case GL_STRICT_SCISSOR_HINT_PGI: + case GL_FULL_STIPPLE_HINT_PGI: + *params = ENUM_TO_DOUBLE(GL_TRUE); + break; + case GL_CONSERVE_MEMORY_HINT_PGI: + *params = ENUM_TO_DOUBLE(GL_FALSE); + break; + case GL_ALWAYS_FAST_HINT_PGI: + *params = (GLdouble) (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_FALSE && + ctx->Hint.AllowDrawMem == GL_FALSE); + break; + case GL_ALWAYS_SOFT_HINT_PGI: + *params = (GLdouble) (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_TRUE && + ctx->Hint.AllowDrawMem == GL_TRUE); + break; + case GL_ALLOW_DRAW_OBJ_HINT_PGI: + *params = (GLdouble) GL_TRUE; + break; + case GL_ALLOW_DRAW_WIN_HINT_PGI: + *params = (GLdouble) ctx->Hint.AllowDrawWin; + break; + case GL_ALLOW_DRAW_SPN_HINT_PGI: + *params = (GLdouble) ctx->Hint.AllowDrawSpn; + break; + case GL_ALLOW_DRAW_MEM_HINT_PGI: + *params = (GLdouble) ctx->Hint.AllowDrawMem; + break; + case GL_CLIP_NEAR_HINT_PGI: + case GL_CLIP_FAR_HINT_PGI: + *params = ENUM_TO_DOUBLE(GL_TRUE); + break; + case GL_WIDE_LINE_HINT_PGI: + *params = ENUM_TO_DOUBLE(GL_DONT_CARE); + break; + case GL_BACK_NORMALS_HINT_PGI: + *params = ENUM_TO_DOUBLE(GL_TRUE); + break; + case GL_NATIVE_GRAPHICS_HANDLE_PGI: + *params = 0; + break; + + + + default: + printf("invalid enum: %x\n", pname); + gl_error( ctx, GL_INVALID_ENUM, "glGetDoublev" ); + } +} + + + + +void gl_GetFloatv( GLcontext *ctx, GLenum pname, GLfloat *params ) +{ + GLuint i; + GLuint texUnit = ctx->Texture.CurrentUnit; + GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit; + const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetFloatv"); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glGetFloatv %s\n", gl_lookup_enum_by_nr(pname)); + + switch (pname) { + case GL_ACCUM_RED_BITS: + case GL_ACCUM_GREEN_BITS: + case GL_ACCUM_BLUE_BITS: + case GL_ACCUM_ALPHA_BITS: + *params = (GLfloat) ctx->Visual->AccumBits; + break; + case GL_ACCUM_CLEAR_VALUE: + params[0] = ctx->Accum.ClearColor[0]; + params[1] = ctx->Accum.ClearColor[1]; + params[2] = ctx->Accum.ClearColor[2]; + params[3] = ctx->Accum.ClearColor[3]; + break; + case GL_ALPHA_BIAS: + *params = ctx->Pixel.AlphaBias; + break; + case GL_ALPHA_BITS: + *params = (GLfloat) ctx->Visual->AlphaBits; + break; + case GL_ALPHA_SCALE: + *params = ctx->Pixel.AlphaScale; + break; + case GL_ALPHA_TEST: + *params = (GLfloat) ctx->Color.AlphaEnabled; + break; + case GL_ALPHA_TEST_FUNC: + *params = ENUM_TO_FLOAT(ctx->Color.AlphaFunc); + break; + case GL_ALPHA_TEST_REF: + *params = (GLfloat) ctx->Color.AlphaRef / 255.0; + break; + case GL_ATTRIB_STACK_DEPTH: + *params = (GLfloat) (ctx->AttribStackDepth); + break; + case GL_AUTO_NORMAL: + *params = (GLfloat) ctx->Eval.AutoNormal; + break; + case GL_AUX_BUFFERS: + *params = (GLfloat) NUM_AUX_BUFFERS; + break; + case GL_BLEND: + *params = (GLfloat) ctx->Color.BlendEnabled; + break; + case GL_BLEND_DST: + *params = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC: + *params = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_SRC_RGB_INGR: + *params = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_DST_RGB_INGR: + *params = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC_ALPHA_INGR: + *params = ENUM_TO_FLOAT(ctx->Color.BlendSrcA); + break; + case GL_BLEND_DST_ALPHA_INGR: + *params = ENUM_TO_FLOAT(ctx->Color.BlendDstA); + break; + case GL_BLEND_EQUATION_EXT: + *params = ENUM_TO_FLOAT(ctx->Color.BlendEquation); + break; + case GL_BLEND_COLOR_EXT: + params[0] = ctx->Color.BlendColor[0]; + params[1] = ctx->Color.BlendColor[1]; + params[2] = ctx->Color.BlendColor[2]; + params[3] = ctx->Color.BlendColor[3]; + break; + case GL_BLUE_BIAS: + *params = ctx->Pixel.BlueBias; + break; + case GL_BLUE_BITS: + *params = (GLfloat) ctx->Visual->BlueBits; + break; + case GL_BLUE_SCALE: + *params = ctx->Pixel.BlueScale; + break; + case GL_CLIENT_ATTRIB_STACK_DEPTH: + *params = (GLfloat) (ctx->ClientAttribStackDepth); + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + *params = (GLfloat) ctx->Transform.ClipEnabled[pname-GL_CLIP_PLANE0]; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = (GLfloat) ctx->Color.ClearColor[0]; + params[1] = (GLfloat) ctx->Color.ClearColor[1]; + params[2] = (GLfloat) ctx->Color.ClearColor[2]; + params[3] = (GLfloat) ctx->Color.ClearColor[3]; + break; + case GL_COLOR_MATERIAL: + *params = (GLfloat) ctx->Light.ColorMaterialEnabled; + break; + case GL_COLOR_MATERIAL_FACE: + *params = ENUM_TO_FLOAT(ctx->Light.ColorMaterialFace); + break; + case GL_COLOR_MATERIAL_PARAMETER: + *params = ENUM_TO_FLOAT(ctx->Light.ColorMaterialMode); + break; + case GL_COLOR_WRITEMASK: + params[0] = ctx->Color.ColorMask[RCOMP] ? 1.0F : 0.0F; + params[1] = ctx->Color.ColorMask[GCOMP] ? 1.0F : 0.0F; + params[2] = ctx->Color.ColorMask[BCOMP] ? 1.0F : 0.0F; + params[3] = ctx->Color.ColorMask[ACOMP] ? 1.0F : 0.0F; + break; + case GL_CULL_FACE: + *params = (GLfloat) ctx->Polygon.CullFlag; + break; + case GL_CULL_FACE_MODE: + *params = ENUM_TO_FLOAT(ctx->Polygon.CullFaceMode); + break; + case GL_CURRENT_COLOR: + UBYTE_RGBA_TO_FLOAT_RGBA(params, ctx->Current.ByteColor); + break; + case GL_CURRENT_INDEX: + *params = (GLfloat) ctx->Current.Index; + break; + case GL_CURRENT_NORMAL: + params[0] = ctx->Current.Normal[0]; + params[1] = ctx->Current.Normal[1]; + params[2] = ctx->Current.Normal[2]; + break; + case GL_CURRENT_RASTER_COLOR: + params[0] = ctx->Current.RasterColor[0]; + params[1] = ctx->Current.RasterColor[1]; + params[2] = ctx->Current.RasterColor[2]; + params[3] = ctx->Current.RasterColor[3]; + break; + case GL_CURRENT_RASTER_DISTANCE: + params[0] = ctx->Current.RasterDistance; + break; + case GL_CURRENT_RASTER_INDEX: + *params = (GLfloat) ctx->Current.RasterIndex; + break; + case GL_CURRENT_RASTER_POSITION: + params[0] = ctx->Current.RasterPos[0]; + params[1] = ctx->Current.RasterPos[1]; + params[2] = ctx->Current.RasterPos[2]; + params[3] = ctx->Current.RasterPos[3]; + break; + case GL_CURRENT_RASTER_TEXTURE_COORDS: + params[0] = ctx->Current.RasterMultiTexCoord[texTransformUnit][0]; + params[1] = ctx->Current.RasterMultiTexCoord[texTransformUnit][1]; + params[2] = ctx->Current.RasterMultiTexCoord[texTransformUnit][2]; + params[3] = ctx->Current.RasterMultiTexCoord[texTransformUnit][3]; + break; + case GL_CURRENT_RASTER_POSITION_VALID: + *params = (GLfloat) ctx->Current.RasterPosValid; + break; + case GL_CURRENT_TEXTURE_COORDS: + params[0] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][0]; + params[1] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][1]; + params[2] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][2]; + params[3] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][3]; + break; + case GL_DEPTH_BIAS: + *params = (GLfloat) ctx->Pixel.DepthBias; + break; + case GL_DEPTH_BITS: + *params = (GLfloat) ctx->Visual->DepthBits; + break; + case GL_DEPTH_CLEAR_VALUE: + *params = (GLfloat) ctx->Depth.Clear; + break; + case GL_DEPTH_FUNC: + *params = ENUM_TO_FLOAT(ctx->Depth.Func); + break; + case GL_DEPTH_RANGE: + params[0] = (GLfloat) ctx->Viewport.Near; + params[1] = (GLfloat) ctx->Viewport.Far; + break; + case GL_DEPTH_SCALE: + *params = (GLfloat) ctx->Pixel.DepthScale; + break; + case GL_DEPTH_TEST: + *params = (GLfloat) ctx->Depth.Test; + break; + case GL_DEPTH_WRITEMASK: + *params = (GLfloat) ctx->Depth.Mask; + break; + case GL_DITHER: + *params = (GLfloat) ctx->Color.DitherFlag; + break; + case GL_DOUBLEBUFFER: + *params = (GLfloat) ctx->Visual->DBflag; + break; + case GL_DRAW_BUFFER: + *params = ENUM_TO_FLOAT(ctx->Color.DrawBuffer); + break; + case GL_EDGE_FLAG: + *params = (GLfloat) ctx->Current.EdgeFlag; + break; + case GL_FEEDBACK_BUFFER_SIZE: + /* TODO: is this right? Or, return number of entries in buffer? */ + *params = (GLfloat) ctx->Feedback.BufferSize; + break; + case GL_FEEDBACK_BUFFER_TYPE: + *params = ENUM_TO_FLOAT(ctx->Feedback.Type); + break; + case GL_FOG: + *params = (GLfloat) ctx->Fog.Enabled; + break; + case GL_FOG_COLOR: + params[0] = ctx->Fog.Color[0]; + params[1] = ctx->Fog.Color[1]; + params[2] = ctx->Fog.Color[2]; + params[3] = ctx->Fog.Color[3]; + break; + case GL_FOG_DENSITY: + *params = ctx->Fog.Density; + break; + case GL_FOG_END: + *params = ctx->Fog.End; + break; + case GL_FOG_HINT: + *params = ENUM_TO_FLOAT(ctx->Hint.Fog); + break; + case GL_FOG_INDEX: + *params = ctx->Fog.Index; + break; + case GL_FOG_MODE: + *params = ENUM_TO_FLOAT(ctx->Fog.Mode); + break; + case GL_FOG_START: + *params = ctx->Fog.Start; + break; + case GL_FRONT_FACE: + *params = ENUM_TO_FLOAT(ctx->Polygon.FrontFace); + break; + case GL_GREEN_BIAS: + *params = (GLfloat) ctx->Pixel.GreenBias; + break; + case GL_GREEN_BITS: + *params = (GLfloat) ctx->Visual->GreenBits; + break; + case GL_GREEN_SCALE: + *params = (GLfloat) ctx->Pixel.GreenScale; + break; + case GL_INDEX_BITS: + *params = (GLfloat) ctx->Visual->IndexBits; + break; + case GL_INDEX_CLEAR_VALUE: + *params = (GLfloat) ctx->Color.ClearIndex; + break; + case GL_INDEX_MODE: + *params = ctx->Visual->RGBAflag ? 0.0F : 1.0F; + break; + case GL_INDEX_OFFSET: + *params = (GLfloat) ctx->Pixel.IndexOffset; + break; + case GL_INDEX_SHIFT: + *params = (GLfloat) ctx->Pixel.IndexShift; + break; + case GL_INDEX_WRITEMASK: + *params = (GLfloat) ctx->Color.IndexMask; + break; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + *params = (GLfloat) ctx->Light.Light[pname-GL_LIGHT0].Enabled; + break; + case GL_LIGHTING: + *params = (GLfloat) ctx->Light.Enabled; + break; + case GL_LIGHT_MODEL_AMBIENT: + params[0] = ctx->Light.Model.Ambient[0]; + params[1] = ctx->Light.Model.Ambient[1]; + params[2] = ctx->Light.Model.Ambient[2]; + params[3] = ctx->Light.Model.Ambient[3]; + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + params[0] = ENUM_TO_FLOAT(ctx->Light.Model.ColorControl); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + *params = (GLfloat) ctx->Light.Model.LocalViewer; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + *params = (GLfloat) ctx->Light.Model.TwoSide; + break; + case GL_LINE_SMOOTH: + *params = (GLfloat) ctx->Line.SmoothFlag; + break; + case GL_LINE_SMOOTH_HINT: + *params = ENUM_TO_FLOAT(ctx->Hint.LineSmooth); + break; + case GL_LINE_STIPPLE: + *params = (GLfloat) ctx->Line.StippleFlag; + break; + case GL_LINE_STIPPLE_PATTERN: + *params = (GLfloat) ctx->Line.StipplePattern; + break; + case GL_LINE_STIPPLE_REPEAT: + *params = (GLfloat) ctx->Line.StippleFactor; + break; + case GL_LINE_WIDTH: + *params = (GLfloat) ctx->Line.Width; + break; + case GL_LINE_WIDTH_GRANULARITY: + *params = (GLfloat) LINE_WIDTH_GRANULARITY; + break; + case GL_LINE_WIDTH_RANGE: + params[0] = (GLfloat) MIN_LINE_WIDTH; + params[1] = (GLfloat) MAX_LINE_WIDTH; + break; + case GL_LIST_BASE: + *params = (GLfloat) ctx->List.ListBase; + break; + case GL_LIST_INDEX: + *params = (GLfloat) ctx->CurrentListNum; + break; + case GL_LIST_MODE: + *params = ctx->ExecuteFlag ? ENUM_TO_FLOAT(GL_COMPILE_AND_EXECUTE) + : ENUM_TO_FLOAT(GL_COMPILE); + break; + case GL_INDEX_LOGIC_OP: + *params = (GLfloat) ctx->Color.IndexLogicOpEnabled; + break; + case GL_COLOR_LOGIC_OP: + *params = (GLfloat) ctx->Color.ColorLogicOpEnabled; + break; + case GL_LOGIC_OP_MODE: + *params = ENUM_TO_FLOAT(ctx->Color.LogicOp); + break; + case GL_MAP1_COLOR_4: + *params = (GLfloat) ctx->Eval.Map1Color4; + break; + case GL_MAP1_GRID_DOMAIN: + params[0] = ctx->Eval.MapGrid1u1; + params[1] = ctx->Eval.MapGrid1u2; + break; + case GL_MAP1_GRID_SEGMENTS: + *params = (GLfloat) ctx->Eval.MapGrid1un; + break; + case GL_MAP1_INDEX: + *params = (GLfloat) ctx->Eval.Map1Index; + break; + case GL_MAP1_NORMAL: + *params = (GLfloat) ctx->Eval.Map1Normal; + break; + case GL_MAP1_TEXTURE_COORD_1: + *params = (GLfloat) ctx->Eval.Map1TextureCoord1; + break; + case GL_MAP1_TEXTURE_COORD_2: + *params = (GLfloat) ctx->Eval.Map1TextureCoord2; + break; + case GL_MAP1_TEXTURE_COORD_3: + *params = (GLfloat) ctx->Eval.Map1TextureCoord3; + break; + case GL_MAP1_TEXTURE_COORD_4: + *params = (GLfloat) ctx->Eval.Map1TextureCoord4; + break; + case GL_MAP1_VERTEX_3: + *params = (GLfloat) ctx->Eval.Map1Vertex3; + break; + case GL_MAP1_VERTEX_4: + *params = (GLfloat) ctx->Eval.Map1Vertex4; + break; + case GL_MAP2_COLOR_4: + *params = (GLfloat) ctx->Eval.Map2Color4; + break; + case GL_MAP2_GRID_DOMAIN: + params[0] = ctx->Eval.MapGrid2u1; + params[1] = ctx->Eval.MapGrid2u2; + params[2] = ctx->Eval.MapGrid2v1; + params[3] = ctx->Eval.MapGrid2v2; + break; + case GL_MAP2_GRID_SEGMENTS: + params[0] = (GLfloat) ctx->Eval.MapGrid2un; + params[1] = (GLfloat) ctx->Eval.MapGrid2vn; + break; + case GL_MAP2_INDEX: + *params = (GLfloat) ctx->Eval.Map2Index; + break; + case GL_MAP2_NORMAL: + *params = (GLfloat) ctx->Eval.Map2Normal; + break; + case GL_MAP2_TEXTURE_COORD_1: + *params = ctx->Eval.Map2TextureCoord1; + break; + case GL_MAP2_TEXTURE_COORD_2: + *params = ctx->Eval.Map2TextureCoord2; + break; + case GL_MAP2_TEXTURE_COORD_3: + *params = ctx->Eval.Map2TextureCoord3; + break; + case GL_MAP2_TEXTURE_COORD_4: + *params = ctx->Eval.Map2TextureCoord4; + break; + case GL_MAP2_VERTEX_3: + *params = (GLfloat) ctx->Eval.Map2Vertex3; + break; + case GL_MAP2_VERTEX_4: + *params = (GLfloat) ctx->Eval.Map2Vertex4; + break; + case GL_MAP_COLOR: + *params = (GLfloat) ctx->Pixel.MapColorFlag; + break; + case GL_MAP_STENCIL: + *params = (GLfloat) ctx->Pixel.MapStencilFlag; + break; + case GL_MATRIX_MODE: + *params = ENUM_TO_FLOAT(ctx->Transform.MatrixMode); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + *params = (GLfloat) MAX_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: + *params = (GLfloat) MAX_CLIENT_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIP_PLANES: + *params = (GLfloat) MAX_CLIP_PLANES; + break; + case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */ + *params = (GLfloat) VB_MAX; + break; + case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */ + *params = (GLfloat) VB_MAX; + break; + case GL_MAX_EVAL_ORDER: + *params = (GLfloat) MAX_EVAL_ORDER; + break; + case GL_MAX_LIGHTS: + *params = (GLfloat) MAX_LIGHTS; + break; + case GL_MAX_LIST_NESTING: + *params = (GLfloat) MAX_LIST_NESTING; + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + *params = (GLfloat) MAX_MODELVIEW_STACK_DEPTH; + break; + case GL_MAX_NAME_STACK_DEPTH: + *params = (GLfloat) MAX_NAME_STACK_DEPTH; + break; + case GL_MAX_PIXEL_MAP_TABLE: + *params = (GLfloat) MAX_PIXEL_MAP_TABLE; + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + *params = (GLfloat) MAX_PROJECTION_STACK_DEPTH; + break; + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_3D_TEXTURE_SIZE: + *params = (GLfloat) ctx->Const.MaxTextureSize; + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + *params = (GLfloat) MAX_TEXTURE_STACK_DEPTH; + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = (GLfloat) MAX_WIDTH; + params[1] = (GLfloat) MAX_HEIGHT; + break; + case GL_MODELVIEW_MATRIX: + for (i=0;i<16;i++) { + params[i] = ctx->ModelView.m[i]; + } + break; + case GL_MODELVIEW_STACK_DEPTH: + *params = (GLfloat) (ctx->ModelViewStackDepth + 1); + break; + case GL_NAME_STACK_DEPTH: + *params = (GLfloat) ctx->Select.NameStackDepth; + break; + case GL_NORMALIZE: + *params = (GLfloat) ctx->Transform.Normalize; + break; + case GL_PACK_ALIGNMENT: + *params = (GLfloat) ctx->Pack.Alignment; + break; + case GL_PACK_LSB_FIRST: + *params = (GLfloat) ctx->Pack.LsbFirst; + break; + case GL_PACK_ROW_LENGTH: + *params = (GLfloat) ctx->Pack.RowLength; + break; + case GL_PACK_SKIP_PIXELS: + *params = (GLfloat) ctx->Pack.SkipPixels; + break; + case GL_PACK_SKIP_ROWS: + *params = (GLfloat) ctx->Pack.SkipRows; + break; + case GL_PACK_SWAP_BYTES: + *params = (GLfloat) ctx->Pack.SwapBytes; + break; + case GL_PACK_SKIP_IMAGES_EXT: + *params = (GLfloat) ctx->Pack.SkipImages; + break; + case GL_PACK_IMAGE_HEIGHT_EXT: + *params = (GLfloat) ctx->Pack.ImageHeight; + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + *params = ENUM_TO_FLOAT(ctx->Hint.PerspectiveCorrection); + break; + case GL_PIXEL_MAP_A_TO_A_SIZE: + *params = (GLfloat) ctx->Pixel.MapAtoAsize; + break; + case GL_PIXEL_MAP_B_TO_B_SIZE: + *params = (GLfloat) ctx->Pixel.MapBtoBsize; + break; + case GL_PIXEL_MAP_G_TO_G_SIZE: + *params = (GLfloat) ctx->Pixel.MapGtoGsize; + break; + case GL_PIXEL_MAP_I_TO_A_SIZE: + *params = (GLfloat) ctx->Pixel.MapItoAsize; + break; + case GL_PIXEL_MAP_I_TO_B_SIZE: + *params = (GLfloat) ctx->Pixel.MapItoBsize; + break; + case GL_PIXEL_MAP_I_TO_G_SIZE: + *params = (GLfloat) ctx->Pixel.MapItoGsize; + break; + case GL_PIXEL_MAP_I_TO_I_SIZE: + *params = (GLfloat) ctx->Pixel.MapItoIsize; + break; + case GL_PIXEL_MAP_I_TO_R_SIZE: + *params = (GLfloat) ctx->Pixel.MapItoRsize; + break; + case GL_PIXEL_MAP_R_TO_R_SIZE: + *params = (GLfloat) ctx->Pixel.MapRtoRsize; + break; + case GL_PIXEL_MAP_S_TO_S_SIZE: + *params = (GLfloat) ctx->Pixel.MapStoSsize; + break; + case GL_POINT_SIZE: + *params = (GLfloat) ctx->Point.Size; + break; + case GL_POINT_SIZE_GRANULARITY: + *params = (GLfloat) POINT_SIZE_GRANULARITY; + break; + case GL_POINT_SIZE_RANGE: + params[0] = (GLfloat) MIN_POINT_SIZE; + params[1] = (GLfloat) MAX_POINT_SIZE; + break; + case GL_POINT_SMOOTH: + *params = (GLfloat) ctx->Point.SmoothFlag; + break; + case GL_POINT_SMOOTH_HINT: + *params = ENUM_TO_FLOAT(ctx->Hint.PointSmooth); + break; + case GL_POINT_SIZE_MIN_EXT: + *params = (GLfloat) (ctx->Point.MinSize); + break; + case GL_POINT_SIZE_MAX_EXT: + *params = (GLfloat) (ctx->Point.MaxSize); + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + *params = (GLfloat) (ctx->Point.Threshold); + break; + case GL_DISTANCE_ATTENUATION_EXT: + params[0] = (GLfloat) (ctx->Point.Params[0]); + params[1] = (GLfloat) (ctx->Point.Params[1]); + params[2] = (GLfloat) (ctx->Point.Params[2]); + break; + case GL_POLYGON_MODE: + params[0] = ENUM_TO_FLOAT(ctx->Polygon.FrontMode); + params[1] = ENUM_TO_FLOAT(ctx->Polygon.BackMode); + break; +#ifdef GL_EXT_polygon_offset + case GL_POLYGON_OFFSET_BIAS_EXT: + *params = ctx->Polygon.OffsetUnits; + break; +#endif + case GL_POLYGON_OFFSET_FACTOR: + *params = ctx->Polygon.OffsetFactor; + break; + case GL_POLYGON_OFFSET_UNITS: + *params = ctx->Polygon.OffsetUnits; + break; + case GL_POLYGON_SMOOTH: + *params = (GLfloat) ctx->Polygon.SmoothFlag; + break; + case GL_POLYGON_SMOOTH_HINT: + *params = ENUM_TO_FLOAT(ctx->Hint.PolygonSmooth); + break; + case GL_POLYGON_STIPPLE: + *params = (GLfloat) ctx->Polygon.StippleFlag; + break; + case GL_PROJECTION_MATRIX: + for (i=0;i<16;i++) { + params[i] = ctx->ProjectionMatrix.m[i]; + } + break; + case GL_PROJECTION_STACK_DEPTH: + *params = (GLfloat) (ctx->ProjectionStackDepth + 1); + break; + case GL_READ_BUFFER: + *params = ENUM_TO_FLOAT(ctx->Pixel.ReadBuffer); + break; + case GL_RED_BIAS: + *params = ctx->Pixel.RedBias; + break; + case GL_RED_BITS: + *params = (GLfloat) ctx->Visual->RedBits; + break; + case GL_RED_SCALE: + *params = ctx->Pixel.RedScale; + break; + case GL_RENDER_MODE: + *params = ENUM_TO_FLOAT(ctx->RenderMode); + break; + case GL_RGBA_MODE: + *params = (GLfloat) ctx->Visual->RGBAflag; + break; + case GL_SCISSOR_BOX: + params[0] = (GLfloat) ctx->Scissor.X; + params[1] = (GLfloat) ctx->Scissor.Y; + params[2] = (GLfloat) ctx->Scissor.Width; + params[3] = (GLfloat) ctx->Scissor.Height; + break; + case GL_SCISSOR_TEST: + *params = (GLfloat) ctx->Scissor.Enabled; + break; + case GL_SELECTION_BUFFER_SIZE: + *params = (GLfloat) ctx->Select.BufferSize; + break; + case GL_SHADE_MODEL: + *params = ENUM_TO_FLOAT(ctx->Light.ShadeModel); + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + *params = (GLfloat) ctx->Texture.SharedPalette; + break; + case GL_STENCIL_BITS: + *params = (GLfloat) ctx->Visual->StencilBits; + break; + case GL_STENCIL_CLEAR_VALUE: + *params = (GLfloat) ctx->Stencil.Clear; + break; + case GL_STENCIL_FAIL: + *params = ENUM_TO_FLOAT(ctx->Stencil.FailFunc); + break; + case GL_STENCIL_FUNC: + *params = ENUM_TO_FLOAT(ctx->Stencil.Function); + break; + case GL_STENCIL_PASS_DEPTH_FAIL: + *params = ENUM_TO_FLOAT(ctx->Stencil.ZFailFunc); + break; + case GL_STENCIL_PASS_DEPTH_PASS: + *params = ENUM_TO_FLOAT(ctx->Stencil.ZPassFunc); + break; + case GL_STENCIL_REF: + *params = (GLfloat) ctx->Stencil.Ref; + break; + case GL_STENCIL_TEST: + *params = (GLfloat) ctx->Stencil.Enabled; + break; + case GL_STENCIL_VALUE_MASK: + *params = (GLfloat) ctx->Stencil.ValueMask; + break; + case GL_STENCIL_WRITEMASK: + *params = (GLfloat) ctx->Stencil.WriteMask; + break; + case GL_STEREO: + *params = (GLfloat) ctx->Visual->StereoFlag; + break; + case GL_SUBPIXEL_BITS: + *params = 0.0F; /* TODO */ + break; + case GL_TEXTURE_1D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_1D) ? 1.0 : 0.0; + break; + case GL_TEXTURE_2D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_2D) ? 1.0 : 0.0; + break; + case GL_TEXTURE_3D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_3D) ? 1.0 : 0.0; + break; + case GL_TEXTURE_BINDING_1D: + *params = (GLfloat) textureUnit->CurrentD[1]->Name; + break; + case GL_TEXTURE_BINDING_2D: + *params = (GLfloat) textureUnit->CurrentD[2]->Name; + break; + case GL_TEXTURE_BINDING_3D: + *params = (GLfloat) textureUnit->CurrentD[2]->Name; + break; + case GL_TEXTURE_ENV_COLOR: + params[0] = textureUnit->EnvColor[0]; + params[1] = textureUnit->EnvColor[1]; + params[2] = textureUnit->EnvColor[2]; + params[3] = textureUnit->EnvColor[3]; + break; + case GL_TEXTURE_ENV_MODE: + *params = ENUM_TO_FLOAT(textureUnit->EnvMode); + break; + case GL_TEXTURE_GEN_S: + *params = (textureUnit->TexGenEnabled & S_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_GEN_T: + *params = (textureUnit->TexGenEnabled & T_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_GEN_R: + *params = (textureUnit->TexGenEnabled & R_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_GEN_Q: + *params = (textureUnit->TexGenEnabled & Q_BIT) ? 1.0 : 0.0; + break; + case GL_TEXTURE_MATRIX: + for (i=0;i<16;i++) { + params[i] = ctx->TextureMatrix[texTransformUnit].m[i]; + } + break; + case GL_TEXTURE_STACK_DEPTH: + *params = (GLfloat) (ctx->TextureStackDepth[texTransformUnit] + 1); + break; + case GL_UNPACK_ALIGNMENT: + *params = (GLfloat) ctx->Unpack.Alignment; + break; + case GL_UNPACK_LSB_FIRST: + *params = (GLfloat) ctx->Unpack.LsbFirst; + break; + case GL_UNPACK_ROW_LENGTH: + *params = (GLfloat) ctx->Unpack.RowLength; + break; + case GL_UNPACK_SKIP_PIXELS: + *params = (GLfloat) ctx->Unpack.SkipPixels; + break; + case GL_UNPACK_SKIP_ROWS: + *params = (GLfloat) ctx->Unpack.SkipRows; + break; + case GL_UNPACK_SWAP_BYTES: + *params = (GLfloat) ctx->Unpack.SwapBytes; + break; + case GL_UNPACK_SKIP_IMAGES_EXT: + *params = (GLfloat) ctx->Unpack.SkipImages; + break; + case GL_UNPACK_IMAGE_HEIGHT_EXT: + *params = (GLfloat) ctx->Unpack.ImageHeight; + break; + case GL_VIEWPORT: + params[0] = (GLfloat) ctx->Viewport.X; + params[1] = (GLfloat) ctx->Viewport.Y; + params[2] = (GLfloat) ctx->Viewport.Width; + params[3] = (GLfloat) ctx->Viewport.Height; + break; + case GL_ZOOM_X: + *params = (GLfloat) ctx->Pixel.ZoomX; + break; + case GL_ZOOM_Y: + *params = (GLfloat) ctx->Pixel.ZoomY; + break; + case GL_VERTEX_ARRAY_SIZE: + *params = (GLfloat) ctx->Array.Vertex.Size; + break; + case GL_VERTEX_ARRAY_TYPE: + *params = ENUM_TO_FLOAT(ctx->Array.Vertex.Type); + break; + case GL_VERTEX_ARRAY_STRIDE: + *params = (GLfloat) ctx->Array.Vertex.Stride; + break; + case GL_VERTEX_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_NORMAL_ARRAY_TYPE: + *params = ENUM_TO_FLOAT(ctx->Array.Normal.Type); + break; + case GL_NORMAL_ARRAY_STRIDE: + *params = (GLfloat) ctx->Array.Normal.Stride; + break; + case GL_NORMAL_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_COLOR_ARRAY_SIZE: + *params = (GLfloat) ctx->Array.Color.Size; + break; + case GL_COLOR_ARRAY_TYPE: + *params = ENUM_TO_FLOAT(ctx->Array.Color.Type); + break; + case GL_COLOR_ARRAY_STRIDE: + *params = (GLfloat) ctx->Array.Color.Stride; + break; + case GL_COLOR_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_INDEX_ARRAY_TYPE: + *params = ENUM_TO_FLOAT(ctx->Array.Index.Type); + break; + case GL_INDEX_ARRAY_STRIDE: + *params = (GLfloat) ctx->Array.Index.Stride; + break; + case GL_INDEX_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_TEXTURE_COORD_ARRAY_SIZE: + *params = (GLfloat) ctx->Array.TexCoord[texUnit].Size; + break; + case GL_TEXTURE_COORD_ARRAY_TYPE: + *params = ENUM_TO_FLOAT(ctx->Array.TexCoord[texUnit].Type); + break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: + *params = (GLfloat) ctx->Array.TexCoord[texUnit].Stride; + break; + case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: + *params = 0.0; + break; + case GL_EDGE_FLAG_ARRAY_STRIDE: + *params = (GLfloat) ctx->Array.EdgeFlag.Stride; + break; + case GL_EDGE_FLAG_ARRAY_COUNT_EXT: + *params = 0.0; + break; + + case GL_MAX_TEXTURE_UNITS_ARB: + *params = (GLfloat) ctx->Const.MaxTextureUnits; + break; + case GL_ACTIVE_TEXTURE_ARB: + *params = (GLfloat) (GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit); + break; + case GL_CLIENT_ACTIVE_TEXTURE_ARB: + *params = (GLfloat) (GL_TEXTURE0_ARB + ctx->Array.ActiveTexture); + break; + + /* GL_PGI_misc_hints */ + case GL_STRICT_DEPTHFUNC_HINT_PGI: + *params = ENUM_TO_FLOAT(GL_NICEST); + break; + case GL_STRICT_LIGHTING_HINT_PGI: + *params = ENUM_TO_FLOAT(ctx->Hint.StrictLighting); + break; + case GL_STRICT_SCISSOR_HINT_PGI: + case GL_FULL_STIPPLE_HINT_PGI: + *params = ENUM_TO_FLOAT(GL_TRUE); + break; + case GL_CONSERVE_MEMORY_HINT_PGI: + *params = ENUM_TO_FLOAT(GL_FALSE); + break; + case GL_ALWAYS_FAST_HINT_PGI: + *params = (GLfloat) (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_FALSE && + ctx->Hint.AllowDrawMem == GL_FALSE); + break; + case GL_ALWAYS_SOFT_HINT_PGI: + *params = (GLfloat) (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_TRUE && + ctx->Hint.AllowDrawMem == GL_TRUE); + break; + case GL_ALLOW_DRAW_OBJ_HINT_PGI: + *params = (GLfloat) GL_TRUE; + break; + case GL_ALLOW_DRAW_WIN_HINT_PGI: + *params = (GLfloat) ctx->Hint.AllowDrawWin; + break; + case GL_ALLOW_DRAW_SPN_HINT_PGI: + *params = (GLfloat) ctx->Hint.AllowDrawSpn; + break; + case GL_ALLOW_DRAW_MEM_HINT_PGI: + *params = (GLfloat) ctx->Hint.AllowDrawMem; + break; + case GL_CLIP_NEAR_HINT_PGI: + case GL_CLIP_FAR_HINT_PGI: + *params = ENUM_TO_FLOAT(GL_TRUE); + break; + case GL_WIDE_LINE_HINT_PGI: + *params = ENUM_TO_FLOAT(GL_DONT_CARE); + break; + case GL_BACK_NORMALS_HINT_PGI: + *params = ENUM_TO_FLOAT(GL_TRUE); + break; + case GL_NATIVE_GRAPHICS_HANDLE_PGI: + *params = 0; + break; + + default: + printf("invalid enum: %x\n", pname); + gl_error( ctx, GL_INVALID_ENUM, "glGetFloatv" ); + } +} + + + + +void gl_GetIntegerv( GLcontext *ctx, GLenum pname, GLint *params ) +{ + GLuint i; + GLuint texUnit = ctx->Texture.CurrentUnit; + GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit; + const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetIntegerv"); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glGetIntegerv %s\n", gl_lookup_enum_by_nr(pname)); + + switch (pname) { + case GL_ACCUM_RED_BITS: + case GL_ACCUM_GREEN_BITS: + case GL_ACCUM_BLUE_BITS: + case GL_ACCUM_ALPHA_BITS: + *params = (GLint) ctx->Visual->AccumBits; + break; + case GL_ACCUM_CLEAR_VALUE: + params[0] = FLOAT_TO_INT( ctx->Accum.ClearColor[0] ); + params[1] = FLOAT_TO_INT( ctx->Accum.ClearColor[1] ); + params[2] = FLOAT_TO_INT( ctx->Accum.ClearColor[2] ); + params[3] = FLOAT_TO_INT( ctx->Accum.ClearColor[3] ); + break; + case GL_ALPHA_BIAS: + *params = (GLint) ctx->Pixel.AlphaBias; + break; + case GL_ALPHA_BITS: + *params = ctx->Visual->AlphaBits; + break; + case GL_ALPHA_SCALE: + *params = (GLint) ctx->Pixel.AlphaScale; + break; + case GL_ALPHA_TEST: + *params = (GLint) ctx->Color.AlphaEnabled; + break; + case GL_ALPHA_TEST_REF: + *params = FLOAT_TO_INT( (GLfloat) ctx->Color.AlphaRef / 255.0 ); + break; + case GL_ALPHA_TEST_FUNC: + *params = (GLint) ctx->Color.AlphaFunc; + break; + case GL_ATTRIB_STACK_DEPTH: + *params = (GLint) (ctx->AttribStackDepth); + break; + case GL_AUTO_NORMAL: + *params = (GLint) ctx->Eval.AutoNormal; + break; + case GL_AUX_BUFFERS: + *params = (GLint) NUM_AUX_BUFFERS; + break; + case GL_BLEND: + *params = (GLint) ctx->Color.BlendEnabled; + break; + case GL_BLEND_DST: + *params = (GLint) ctx->Color.BlendDstRGB; + break; + case GL_BLEND_SRC: + *params = (GLint) ctx->Color.BlendSrcRGB; + break; + case GL_BLEND_SRC_RGB_INGR: + *params = (GLint) ctx->Color.BlendSrcRGB; + break; + case GL_BLEND_DST_RGB_INGR: + *params = (GLint) ctx->Color.BlendDstRGB; + break; + case GL_BLEND_SRC_ALPHA_INGR: + *params = (GLint) ctx->Color.BlendSrcA; + break; + case GL_BLEND_DST_ALPHA_INGR: + *params = (GLint) ctx->Color.BlendDstA; + break; + case GL_BLEND_EQUATION_EXT: + *params = (GLint) ctx->Color.BlendEquation; + break; + case GL_BLEND_COLOR_EXT: + params[0] = FLOAT_TO_INT( ctx->Color.BlendColor[0] ); + params[1] = FLOAT_TO_INT( ctx->Color.BlendColor[1] ); + params[2] = FLOAT_TO_INT( ctx->Color.BlendColor[2] ); + params[3] = FLOAT_TO_INT( ctx->Color.BlendColor[3] ); + break; + case GL_BLUE_BIAS: + *params = (GLint) ctx->Pixel.BlueBias; + break; + case GL_BLUE_BITS: + *params = (GLint) ctx->Visual->BlueBits; + break; + case GL_BLUE_SCALE: + *params = (GLint) ctx->Pixel.BlueScale; + break; + case GL_CLIENT_ATTRIB_STACK_DEPTH: + *params = (GLint) (ctx->ClientAttribStackDepth); + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + i = (GLint) (pname - GL_CLIP_PLANE0); + *params = (GLint) ctx->Transform.ClipEnabled[i]; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = FLOAT_TO_INT( ctx->Color.ClearColor[0] ); + params[1] = FLOAT_TO_INT( ctx->Color.ClearColor[1] ); + params[2] = FLOAT_TO_INT( ctx->Color.ClearColor[2] ); + params[3] = FLOAT_TO_INT( ctx->Color.ClearColor[3] ); + break; + case GL_COLOR_MATERIAL: + *params = (GLint) ctx->Light.ColorMaterialEnabled; + break; + case GL_COLOR_MATERIAL_FACE: + *params = (GLint) ctx->Light.ColorMaterialFace; + break; + case GL_COLOR_MATERIAL_PARAMETER: + *params = (GLint) ctx->Light.ColorMaterialMode; + break; + case GL_COLOR_WRITEMASK: + params[0] = ctx->Color.ColorMask[RCOMP] ? 1 : 0; + params[1] = ctx->Color.ColorMask[GCOMP] ? 1 : 0; + params[2] = ctx->Color.ColorMask[BCOMP] ? 1 : 0; + params[3] = ctx->Color.ColorMask[ACOMP] ? 1 : 0; + break; + case GL_CULL_FACE: + *params = (GLint) ctx->Polygon.CullFlag; + break; + case GL_CULL_FACE_MODE: + *params = (GLint) ctx->Polygon.CullFaceMode; + break; + case GL_CURRENT_COLOR: + params[0] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[0] ) ); + params[1] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[1] ) ); + params[2] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[2] ) ); + params[3] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[3] ) ); + break; + case GL_CURRENT_INDEX: + *params = (GLint) ctx->Current.Index; + break; + case GL_CURRENT_NORMAL: + params[0] = FLOAT_TO_INT( ctx->Current.Normal[0] ); + params[1] = FLOAT_TO_INT( ctx->Current.Normal[1] ); + params[2] = FLOAT_TO_INT( ctx->Current.Normal[2] ); + break; + case GL_CURRENT_RASTER_COLOR: + params[0] = FLOAT_TO_INT( ctx->Current.RasterColor[0] ); + params[1] = FLOAT_TO_INT( ctx->Current.RasterColor[1] ); + params[2] = FLOAT_TO_INT( ctx->Current.RasterColor[2] ); + params[3] = FLOAT_TO_INT( ctx->Current.RasterColor[3] ); + break; + case GL_CURRENT_RASTER_DISTANCE: + params[0] = (GLint) ctx->Current.RasterDistance; + break; + case GL_CURRENT_RASTER_INDEX: + *params = (GLint) ctx->Current.RasterIndex; + break; + case GL_CURRENT_RASTER_POSITION: + params[0] = (GLint) ctx->Current.RasterPos[0]; + params[1] = (GLint) ctx->Current.RasterPos[1]; + params[2] = (GLint) ctx->Current.RasterPos[2]; + params[3] = (GLint) ctx->Current.RasterPos[3]; + break; + case GL_CURRENT_RASTER_TEXTURE_COORDS: + params[0] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][0]; + params[1] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][1]; + params[2] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][2]; + params[3] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][3]; + break; + case GL_CURRENT_RASTER_POSITION_VALID: + *params = (GLint) ctx->Current.RasterPosValid; + break; + case GL_CURRENT_TEXTURE_COORDS: + params[0] = (GLint) ctx->Current.Texcoord[texTransformUnit][0]; + params[1] = (GLint) ctx->Current.Texcoord[texTransformUnit][1]; + params[2] = (GLint) ctx->Current.Texcoord[texTransformUnit][2]; + params[3] = (GLint) ctx->Current.Texcoord[texTransformUnit][3]; + break; + case GL_DEPTH_BIAS: + *params = (GLint) ctx->Pixel.DepthBias; + break; + case GL_DEPTH_BITS: + *params = ctx->Visual->DepthBits; + break; + case GL_DEPTH_CLEAR_VALUE: + *params = (GLint) ctx->Depth.Clear; + break; + case GL_DEPTH_FUNC: + *params = (GLint) ctx->Depth.Func; + break; + case GL_DEPTH_RANGE: + params[0] = (GLint) ctx->Viewport.Near; + params[1] = (GLint) ctx->Viewport.Far; + break; + case GL_DEPTH_SCALE: + *params = (GLint) ctx->Pixel.DepthScale; + break; + case GL_DEPTH_TEST: + *params = (GLint) ctx->Depth.Test; + break; + case GL_DEPTH_WRITEMASK: + *params = (GLint) ctx->Depth.Mask; + break; + case GL_DITHER: + *params = (GLint) ctx->Color.DitherFlag; + break; + case GL_DOUBLEBUFFER: + *params = (GLint) ctx->Visual->DBflag; + break; + case GL_DRAW_BUFFER: + *params = (GLint) ctx->Color.DrawBuffer; + break; + case GL_EDGE_FLAG: + *params = (GLint) ctx->Current.EdgeFlag; + break; + case GL_FEEDBACK_BUFFER_SIZE: + /* TODO: is this right? Or, return number of entries in buffer? */ + *params = ctx->Feedback.BufferSize; + break; + case GL_FEEDBACK_BUFFER_TYPE: + *params = ctx->Feedback.Type; + break; + case GL_FOG: + *params = (GLint) ctx->Fog.Enabled; + break; + case GL_FOG_COLOR: + params[0] = FLOAT_TO_INT( ctx->Fog.Color[0] ); + params[1] = FLOAT_TO_INT( ctx->Fog.Color[1] ); + params[2] = FLOAT_TO_INT( ctx->Fog.Color[2] ); + params[3] = FLOAT_TO_INT( ctx->Fog.Color[3] ); + break; + case GL_FOG_DENSITY: + *params = (GLint) ctx->Fog.Density; + break; + case GL_FOG_END: + *params = (GLint) ctx->Fog.End; + break; + case GL_FOG_HINT: + *params = (GLint) ctx->Hint.Fog; + break; + case GL_FOG_INDEX: + *params = (GLint) ctx->Fog.Index; + break; + case GL_FOG_MODE: + *params = (GLint) ctx->Fog.Mode; + break; + case GL_FOG_START: + *params = (GLint) ctx->Fog.Start; + break; + case GL_FRONT_FACE: + *params = (GLint) ctx->Polygon.FrontFace; + break; + case GL_GREEN_BIAS: + *params = (GLint) ctx->Pixel.GreenBias; + break; + case GL_GREEN_BITS: + *params = (GLint) ctx->Visual->GreenBits; + break; + case GL_GREEN_SCALE: + *params = (GLint) ctx->Pixel.GreenScale; + break; + case GL_INDEX_BITS: + *params = (GLint) ctx->Visual->IndexBits; + break; + case GL_INDEX_CLEAR_VALUE: + *params = (GLint) ctx->Color.ClearIndex; + break; + case GL_INDEX_MODE: + *params = ctx->Visual->RGBAflag ? 0 : 1; + break; + case GL_INDEX_OFFSET: + *params = ctx->Pixel.IndexOffset; + break; + case GL_INDEX_SHIFT: + *params = ctx->Pixel.IndexShift; + break; + case GL_INDEX_WRITEMASK: + *params = (GLint) ctx->Color.IndexMask; + break; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + *params = (GLint) ctx->Light.Light[pname-GL_LIGHT0].Enabled; + break; + case GL_LIGHTING: + *params = (GLint) ctx->Light.Enabled; + break; + case GL_LIGHT_MODEL_AMBIENT: + params[0] = FLOAT_TO_INT( ctx->Light.Model.Ambient[0] ); + params[1] = FLOAT_TO_INT( ctx->Light.Model.Ambient[1] ); + params[2] = FLOAT_TO_INT( ctx->Light.Model.Ambient[2] ); + params[3] = FLOAT_TO_INT( ctx->Light.Model.Ambient[3] ); + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + params[0] = (GLint) ctx->Light.Model.ColorControl; + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + *params = (GLint) ctx->Light.Model.LocalViewer; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + *params = (GLint) ctx->Light.Model.TwoSide; + break; + case GL_LINE_SMOOTH: + *params = (GLint) ctx->Line.SmoothFlag; + break; + case GL_LINE_SMOOTH_HINT: + *params = (GLint) ctx->Hint.LineSmooth; + break; + case GL_LINE_STIPPLE: + *params = (GLint) ctx->Line.StippleFlag; + break; + case GL_LINE_STIPPLE_PATTERN: + *params = (GLint) ctx->Line.StipplePattern; + break; + case GL_LINE_STIPPLE_REPEAT: + *params = (GLint) ctx->Line.StippleFactor; + break; + case GL_LINE_WIDTH: + *params = (GLint) ctx->Line.Width; + break; + case GL_LINE_WIDTH_GRANULARITY: + *params = (GLint) LINE_WIDTH_GRANULARITY; + break; + case GL_LINE_WIDTH_RANGE: + params[0] = (GLint) MIN_LINE_WIDTH; + params[1] = (GLint) MAX_LINE_WIDTH; + break; + case GL_LIST_BASE: + *params = (GLint) ctx->List.ListBase; + break; + case GL_LIST_INDEX: + *params = (GLint) ctx->CurrentListNum; + break; + case GL_LIST_MODE: + *params = ctx->ExecuteFlag ? (GLint) GL_COMPILE_AND_EXECUTE + : (GLint) GL_COMPILE; + break; + case GL_INDEX_LOGIC_OP: + *params = (GLint) ctx->Color.IndexLogicOpEnabled; + break; + case GL_COLOR_LOGIC_OP: + *params = (GLint) ctx->Color.ColorLogicOpEnabled; + break; + case GL_LOGIC_OP_MODE: + *params = (GLint) ctx->Color.LogicOp; + break; + case GL_MAP1_COLOR_4: + *params = (GLint) ctx->Eval.Map1Color4; + break; + case GL_MAP1_GRID_DOMAIN: + params[0] = (GLint) ctx->Eval.MapGrid1u1; + params[1] = (GLint) ctx->Eval.MapGrid1u2; + break; + case GL_MAP1_GRID_SEGMENTS: + *params = (GLint) ctx->Eval.MapGrid1un; + break; + case GL_MAP1_INDEX: + *params = (GLint) ctx->Eval.Map1Index; + break; + case GL_MAP1_NORMAL: + *params = (GLint) ctx->Eval.Map1Normal; + break; + case GL_MAP1_TEXTURE_COORD_1: + *params = (GLint) ctx->Eval.Map1TextureCoord1; + break; + case GL_MAP1_TEXTURE_COORD_2: + *params = (GLint) ctx->Eval.Map1TextureCoord2; + break; + case GL_MAP1_TEXTURE_COORD_3: + *params = (GLint) ctx->Eval.Map1TextureCoord3; + break; + case GL_MAP1_TEXTURE_COORD_4: + *params = (GLint) ctx->Eval.Map1TextureCoord4; + break; + case GL_MAP1_VERTEX_3: + *params = (GLint) ctx->Eval.Map1Vertex3; + break; + case GL_MAP1_VERTEX_4: + *params = (GLint) ctx->Eval.Map1Vertex4; + break; + case GL_MAP2_COLOR_4: + *params = (GLint) ctx->Eval.Map2Color4; + break; + case GL_MAP2_GRID_DOMAIN: + params[0] = (GLint) ctx->Eval.MapGrid2u1; + params[1] = (GLint) ctx->Eval.MapGrid2u2; + params[2] = (GLint) ctx->Eval.MapGrid2v1; + params[3] = (GLint) ctx->Eval.MapGrid2v2; + break; + case GL_MAP2_GRID_SEGMENTS: + params[0] = (GLint) ctx->Eval.MapGrid2un; + params[1] = (GLint) ctx->Eval.MapGrid2vn; + break; + case GL_MAP2_INDEX: + *params = (GLint) ctx->Eval.Map2Index; + break; + case GL_MAP2_NORMAL: + *params = (GLint) ctx->Eval.Map2Normal; + break; + case GL_MAP2_TEXTURE_COORD_1: + *params = (GLint) ctx->Eval.Map2TextureCoord1; + break; + case GL_MAP2_TEXTURE_COORD_2: + *params = (GLint) ctx->Eval.Map2TextureCoord2; + break; + case GL_MAP2_TEXTURE_COORD_3: + *params = (GLint) ctx->Eval.Map2TextureCoord3; + break; + case GL_MAP2_TEXTURE_COORD_4: + *params = (GLint) ctx->Eval.Map2TextureCoord4; + break; + case GL_MAP2_VERTEX_3: + *params = (GLint) ctx->Eval.Map2Vertex3; + break; + case GL_MAP2_VERTEX_4: + *params = (GLint) ctx->Eval.Map2Vertex4; + break; + case GL_MAP_COLOR: + *params = (GLint) ctx->Pixel.MapColorFlag; + break; + case GL_MAP_STENCIL: + *params = (GLint) ctx->Pixel.MapStencilFlag; + break; + case GL_MATRIX_MODE: + *params = (GLint) ctx->Transform.MatrixMode; + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + *params = (GLint) MAX_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: + *params = (GLint) MAX_CLIENT_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIP_PLANES: + *params = (GLint) MAX_CLIP_PLANES; + break; + case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */ + *params = VB_MAX; + break; + case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */ + *params = VB_MAX; + break; + case GL_MAX_EVAL_ORDER: + *params = (GLint) MAX_EVAL_ORDER; + break; + case GL_MAX_LIGHTS: + *params = (GLint) MAX_LIGHTS; + break; + case GL_MAX_LIST_NESTING: + *params = (GLint) MAX_LIST_NESTING; + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + *params = (GLint) MAX_MODELVIEW_STACK_DEPTH; + break; + case GL_MAX_NAME_STACK_DEPTH: + *params = (GLint) MAX_NAME_STACK_DEPTH; + break; + case GL_MAX_PIXEL_MAP_TABLE: + *params = (GLint) MAX_PIXEL_MAP_TABLE; + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + *params = (GLint) MAX_PROJECTION_STACK_DEPTH; + break; + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_3D_TEXTURE_SIZE: + *params = ctx->Const.MaxTextureSize; + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + *params = (GLint) MAX_TEXTURE_STACK_DEPTH; + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = (GLint) MAX_WIDTH; + params[1] = (GLint) MAX_HEIGHT; + break; + case GL_MODELVIEW_MATRIX: + for (i=0;i<16;i++) { + params[i] = (GLint) ctx->ModelView.m[i]; + } + break; + case GL_MODELVIEW_STACK_DEPTH: + *params = (GLint) (ctx->ModelViewStackDepth + 1); + break; + case GL_NAME_STACK_DEPTH: + *params = (GLint) ctx->Select.NameStackDepth; + break; + case GL_NORMALIZE: + *params = (GLint) ctx->Transform.Normalize; + break; + case GL_PACK_ALIGNMENT: + *params = ctx->Pack.Alignment; + break; + case GL_PACK_LSB_FIRST: + *params = (GLint) ctx->Pack.LsbFirst; + break; + case GL_PACK_ROW_LENGTH: + *params = ctx->Pack.RowLength; + break; + case GL_PACK_SKIP_PIXELS: + *params = ctx->Pack.SkipPixels; + break; + case GL_PACK_SKIP_ROWS: + *params = ctx->Pack.SkipRows; + break; + case GL_PACK_SWAP_BYTES: + *params = (GLint) ctx->Pack.SwapBytes; + break; + case GL_PACK_SKIP_IMAGES_EXT: + *params = ctx->Pack.SkipImages; + break; + case GL_PACK_IMAGE_HEIGHT_EXT: + *params = ctx->Pack.ImageHeight; + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + *params = (GLint) ctx->Hint.PerspectiveCorrection; + break; + case GL_PIXEL_MAP_A_TO_A_SIZE: + *params = ctx->Pixel.MapAtoAsize; + break; + case GL_PIXEL_MAP_B_TO_B_SIZE: + *params = ctx->Pixel.MapBtoBsize; + break; + case GL_PIXEL_MAP_G_TO_G_SIZE: + *params = ctx->Pixel.MapGtoGsize; + break; + case GL_PIXEL_MAP_I_TO_A_SIZE: + *params = ctx->Pixel.MapItoAsize; + break; + case GL_PIXEL_MAP_I_TO_B_SIZE: + *params = ctx->Pixel.MapItoBsize; + break; + case GL_PIXEL_MAP_I_TO_G_SIZE: + *params = ctx->Pixel.MapItoGsize; + break; + case GL_PIXEL_MAP_I_TO_I_SIZE: + *params = ctx->Pixel.MapItoIsize; + break; + case GL_PIXEL_MAP_I_TO_R_SIZE: + *params = ctx->Pixel.MapItoRsize; + break; + case GL_PIXEL_MAP_R_TO_R_SIZE: + *params = ctx->Pixel.MapRtoRsize; + break; + case GL_PIXEL_MAP_S_TO_S_SIZE: + *params = ctx->Pixel.MapStoSsize; + break; + case GL_POINT_SIZE: + *params = (GLint) ctx->Point.Size; + break; + case GL_POINT_SIZE_GRANULARITY: + *params = (GLint) POINT_SIZE_GRANULARITY; + break; + case GL_POINT_SIZE_RANGE: + params[0] = (GLint) MIN_POINT_SIZE; + params[1] = (GLint) MAX_POINT_SIZE; + break; + case GL_POINT_SMOOTH: + *params = (GLint) ctx->Point.SmoothFlag; + break; + case GL_POINT_SMOOTH_HINT: + *params = (GLint) ctx->Hint.PointSmooth; + break; + case GL_POINT_SIZE_MIN_EXT: + *params = (GLint) (ctx->Point.MinSize); + break; + case GL_POINT_SIZE_MAX_EXT: + *params = (GLint) (ctx->Point.MaxSize); + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + *params = (GLint) (ctx->Point.Threshold); + break; + case GL_DISTANCE_ATTENUATION_EXT: + params[0] = (GLint) (ctx->Point.Params[0]); + params[1] = (GLint) (ctx->Point.Params[1]); + params[2] = (GLint) (ctx->Point.Params[2]); + break; + case GL_POLYGON_MODE: + params[0] = (GLint) ctx->Polygon.FrontMode; + params[1] = (GLint) ctx->Polygon.BackMode; + break; +#ifdef GL_EXT_polygon_offset + case GL_POLYGON_OFFSET_BIAS_EXT: + *params = (GLint) ctx->Polygon.OffsetUnits; + break; +#endif + case GL_POLYGON_OFFSET_FACTOR: + *params = (GLint) ctx->Polygon.OffsetFactor; + break; + case GL_POLYGON_OFFSET_UNITS: + *params = (GLint) ctx->Polygon.OffsetUnits; + break; + case GL_POLYGON_SMOOTH: + *params = (GLint) ctx->Polygon.SmoothFlag; + break; + case GL_POLYGON_SMOOTH_HINT: + *params = (GLint) ctx->Hint.PolygonSmooth; + break; + case GL_POLYGON_STIPPLE: + *params = (GLint) ctx->Polygon.StippleFlag; + break; + case GL_PROJECTION_MATRIX: + for (i=0;i<16;i++) { + params[i] = (GLint) ctx->ProjectionMatrix.m[i]; + } + break; + case GL_PROJECTION_STACK_DEPTH: + *params = (GLint) (ctx->ProjectionStackDepth + 1); + break; + case GL_READ_BUFFER: + *params = (GLint) ctx->Pixel.ReadBuffer; + break; + case GL_RED_BIAS: + *params = (GLint) ctx->Pixel.RedBias; + break; + case GL_RED_BITS: + *params = (GLint) ctx->Visual->RedBits; + break; + case GL_RED_SCALE: + *params = (GLint) ctx->Pixel.RedScale; + break; + case GL_RENDER_MODE: + *params = (GLint) ctx->RenderMode; + break; + case GL_RGBA_MODE: + *params = (GLint) ctx->Visual->RGBAflag; + break; + case GL_SCISSOR_BOX: + params[0] = (GLint) ctx->Scissor.X; + params[1] = (GLint) ctx->Scissor.Y; + params[2] = (GLint) ctx->Scissor.Width; + params[3] = (GLint) ctx->Scissor.Height; + break; + case GL_SCISSOR_TEST: + *params = (GLint) ctx->Scissor.Enabled; + break; + case GL_SELECTION_BUFFER_SIZE: + *params = (GLint) ctx->Select.BufferSize; + break; + case GL_SHADE_MODEL: + *params = (GLint) ctx->Light.ShadeModel; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + *params = (GLint) ctx->Texture.SharedPalette; + break; + case GL_STENCIL_BITS: + *params = ctx->Visual->StencilBits; + break; + case GL_STENCIL_CLEAR_VALUE: + *params = (GLint) ctx->Stencil.Clear; + break; + case GL_STENCIL_FAIL: + *params = (GLint) ctx->Stencil.FailFunc; + break; + case GL_STENCIL_FUNC: + *params = (GLint) ctx->Stencil.Function; + break; + case GL_STENCIL_PASS_DEPTH_FAIL: + *params = (GLint) ctx->Stencil.ZFailFunc; + break; + case GL_STENCIL_PASS_DEPTH_PASS: + *params = (GLint) ctx->Stencil.ZPassFunc; + break; + case GL_STENCIL_REF: + *params = (GLint) ctx->Stencil.Ref; + break; + case GL_STENCIL_TEST: + *params = (GLint) ctx->Stencil.Enabled; + break; + case GL_STENCIL_VALUE_MASK: + *params = (GLint) ctx->Stencil.ValueMask; + break; + case GL_STENCIL_WRITEMASK: + *params = (GLint) ctx->Stencil.WriteMask; + break; + case GL_STEREO: + *params = (GLint) ctx->Visual->StereoFlag; + break; + case GL_SUBPIXEL_BITS: + *params = 0; /* TODO */ + break; + case GL_TEXTURE_1D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_1D) ? 1 : 0; + break; + case GL_TEXTURE_2D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_2D) ? 1 : 0; + break; + case GL_TEXTURE_3D: + *params = gl_IsEnabled(ctx, GL_TEXTURE_3D) ? 1 : 0; + break; + case GL_TEXTURE_BINDING_1D: + *params = textureUnit->CurrentD[1]->Name; + break; + case GL_TEXTURE_BINDING_2D: + *params = textureUnit->CurrentD[2]->Name; + break; + case GL_TEXTURE_BINDING_3D: + *params = textureUnit->CurrentD[3]->Name; + break; + case GL_TEXTURE_ENV_COLOR: + params[0] = FLOAT_TO_INT( textureUnit->EnvColor[0] ); + params[1] = FLOAT_TO_INT( textureUnit->EnvColor[1] ); + params[2] = FLOAT_TO_INT( textureUnit->EnvColor[2] ); + params[3] = FLOAT_TO_INT( textureUnit->EnvColor[3] ); + break; + case GL_TEXTURE_ENV_MODE: + *params = (GLint) textureUnit->EnvMode; + break; + case GL_TEXTURE_GEN_S: + *params = (textureUnit->TexGenEnabled & S_BIT) ? 1 : 0; + break; + case GL_TEXTURE_GEN_T: + *params = (textureUnit->TexGenEnabled & T_BIT) ? 1 : 0; + break; + case GL_TEXTURE_GEN_R: + *params = (textureUnit->TexGenEnabled & R_BIT) ? 1 : 0; + break; + case GL_TEXTURE_GEN_Q: + *params = (textureUnit->TexGenEnabled & Q_BIT) ? 1 : 0; + break; + case GL_TEXTURE_MATRIX: + for (i=0;i<16;i++) { + params[i] = (GLint) ctx->TextureMatrix[texTransformUnit].m[i]; + } + break; + case GL_TEXTURE_STACK_DEPTH: + *params = (GLint) (ctx->TextureStackDepth[texTransformUnit] + 1); + break; + case GL_UNPACK_ALIGNMENT: + *params = ctx->Unpack.Alignment; + break; + case GL_UNPACK_LSB_FIRST: + *params = (GLint) ctx->Unpack.LsbFirst; + break; + case GL_UNPACK_ROW_LENGTH: + *params = ctx->Unpack.RowLength; + break; + case GL_UNPACK_SKIP_PIXELS: + *params = ctx->Unpack.SkipPixels; + break; + case GL_UNPACK_SKIP_ROWS: + *params = ctx->Unpack.SkipRows; + break; + case GL_UNPACK_SWAP_BYTES: + *params = (GLint) ctx->Unpack.SwapBytes; + break; + case GL_UNPACK_SKIP_IMAGES_EXT: + *params = ctx->Unpack.SkipImages; + break; + case GL_UNPACK_IMAGE_HEIGHT_EXT: + *params = ctx->Unpack.ImageHeight; + break; + case GL_VIEWPORT: + params[0] = (GLint) ctx->Viewport.X; + params[1] = (GLint) ctx->Viewport.Y; + params[2] = (GLint) ctx->Viewport.Width; + params[3] = (GLint) ctx->Viewport.Height; + break; + case GL_ZOOM_X: + *params = (GLint) ctx->Pixel.ZoomX; + break; + case GL_ZOOM_Y: + *params = (GLint) ctx->Pixel.ZoomY; + break; + case GL_VERTEX_ARRAY_SIZE: + *params = ctx->Array.Vertex.Size; + break; + case GL_VERTEX_ARRAY_TYPE: + *params = ctx->Array.Vertex.Type; + break; + case GL_VERTEX_ARRAY_STRIDE: + *params = ctx->Array.Vertex.Stride; + break; + case GL_VERTEX_ARRAY_COUNT_EXT: + *params = 0; + break; + case GL_NORMAL_ARRAY_TYPE: + *params = ctx->Array.Normal.Type; + break; + case GL_NORMAL_ARRAY_STRIDE: + *params = ctx->Array.Normal.Stride; + break; + case GL_NORMAL_ARRAY_COUNT_EXT: + *params = 0; + break; + case GL_COLOR_ARRAY_SIZE: + *params = ctx->Array.Color.Size; + break; + case GL_COLOR_ARRAY_TYPE: + *params = ctx->Array.Color.Type; + break; + case GL_COLOR_ARRAY_STRIDE: + *params = ctx->Array.Color.Stride; + break; + case GL_COLOR_ARRAY_COUNT_EXT: + *params = 0; + break; + case GL_INDEX_ARRAY_TYPE: + *params = ctx->Array.Index.Type; + break; + case GL_INDEX_ARRAY_STRIDE: + *params = ctx->Array.Index.Stride; + break; + case GL_INDEX_ARRAY_COUNT_EXT: + *params = 0; + break; + case GL_TEXTURE_COORD_ARRAY_SIZE: + *params = ctx->Array.TexCoord[texUnit].Size; + break; + case GL_TEXTURE_COORD_ARRAY_TYPE: + *params = ctx->Array.TexCoord[texUnit].Type; + break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: + *params = ctx->Array.TexCoord[texUnit].Stride; + break; + case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: + *params = 0; + break; + case GL_EDGE_FLAG_ARRAY_STRIDE: + *params = ctx->Array.EdgeFlag.Stride; + break; + case GL_EDGE_FLAG_ARRAY_COUNT_EXT: + *params = 0; + break; + + case GL_MAX_TEXTURE_UNITS_ARB: + *params = ctx->Const.MaxTextureUnits; + break; + case GL_ACTIVE_TEXTURE_ARB: + *params = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit; + break; + case GL_CLIENT_ACTIVE_TEXTURE_ARB: + *params = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture; + break; + + + /* GL_PGI_misc_hints */ + case GL_STRICT_DEPTHFUNC_HINT_PGI: + *params = (GL_NICEST); + break; + case GL_STRICT_LIGHTING_HINT_PGI: + *params = (ctx->Hint.StrictLighting); + break; + case GL_STRICT_SCISSOR_HINT_PGI: + case GL_FULL_STIPPLE_HINT_PGI: + *params = (GL_TRUE); + break; + case GL_CONSERVE_MEMORY_HINT_PGI: + *params = (GL_FALSE); + break; + case GL_ALWAYS_FAST_HINT_PGI: + *params = (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_FALSE && + ctx->Hint.AllowDrawMem == GL_FALSE); + break; + case GL_ALWAYS_SOFT_HINT_PGI: + *params = (ctx->Hint.AllowDrawWin == GL_TRUE && + ctx->Hint.AllowDrawSpn == GL_TRUE && + ctx->Hint.AllowDrawMem == GL_TRUE); + break; + case GL_ALLOW_DRAW_OBJ_HINT_PGI: + *params = GL_TRUE; + break; + case GL_ALLOW_DRAW_WIN_HINT_PGI: + *params = ctx->Hint.AllowDrawWin; + break; + case GL_ALLOW_DRAW_SPN_HINT_PGI: + *params = ctx->Hint.AllowDrawSpn; + break; + case GL_ALLOW_DRAW_MEM_HINT_PGI: + *params = ctx->Hint.AllowDrawMem; + break; + case GL_CLIP_NEAR_HINT_PGI: + case GL_CLIP_FAR_HINT_PGI: + *params = GL_TRUE; + break; + case GL_WIDE_LINE_HINT_PGI: + *params = GL_DONT_CARE; + break; + case GL_BACK_NORMALS_HINT_PGI: + *params = (GL_TRUE); + break; + case GL_NATIVE_GRAPHICS_HANDLE_PGI: + *params = 0; + break; + + /* GL_EXT_compiled_vertex_array + */ + case GL_ARRAY_ELEMENT_LOCK_FIRST_SGI: + *params = ctx->Array.LockFirst; + break; + + case GL_ARRAY_ELEMENT_LOCK_COUNT_SGI: + *params = ctx->Array.LockCount; + break; + + default: + printf("invalid enum: %x\n", pname); + gl_error( ctx, GL_INVALID_ENUM, "glGetIntegerv" ); + } +} + + + +void gl_GetPointerv( GLcontext *ctx, GLenum pname, GLvoid **params ) +{ + GLuint texUnit = ctx->Texture.CurrentUnit; + /*GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit;*/ + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glGetPointerv %s\n", gl_lookup_enum_by_nr(pname)); + + switch (pname) { + case GL_VERTEX_ARRAY_POINTER: + *params = ctx->Array.Vertex.Ptr; + break; + case GL_NORMAL_ARRAY_POINTER: + *params = ctx->Array.Normal.Ptr; + break; + case GL_COLOR_ARRAY_POINTER: + *params = ctx->Array.Color.Ptr; + break; + case GL_INDEX_ARRAY_POINTER: + *params = ctx->Array.Index.Ptr; + break; + case GL_TEXTURE_COORD_ARRAY_POINTER: + *params = ctx->Array.TexCoord[texUnit].Ptr; + break; + case GL_EDGE_FLAG_ARRAY_POINTER: + *params = ctx->Array.EdgeFlag.Ptr; + break; + case GL_FEEDBACK_BUFFER_POINTER: + *params = ctx->Feedback.Buffer; + break; + case GL_SELECTION_BUFFER_POINTER: + *params = ctx->Select.Buffer; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetPointerv" ); + return; + } +} diff --git a/src/mesa/main/get.h b/src/mesa/main/get.h new file mode 100644 index 00000000000..c4e55041f66 --- /dev/null +++ b/src/mesa/main/get.h @@ -0,0 +1,48 @@ +/* $Id: get.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 GET_H +#define GET_H + + +#include "types.h" + + +extern void gl_GetBooleanv( GLcontext *ctx, GLenum pname, GLboolean *params ); + +extern void gl_GetDoublev( GLcontext *ctx, GLenum pname, GLdouble *params ); + +extern void gl_GetFloatv( GLcontext *ctx, GLenum pname, GLfloat *params ); + +extern void gl_GetIntegerv( GLcontext *ctx, GLenum pname, GLint *params ); + + +#endif + diff --git a/src/mesa/main/hash.c b/src/mesa/main/hash.c new file mode 100644 index 00000000000..3d533c82e8e --- /dev/null +++ b/src/mesa/main/hash.c @@ -0,0 +1,295 @@ +/* $Id: hash.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include "hash.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +/* + * Generic hash table. Only dependency is the GLuint datatype. + * + * This is used to implement display list and texture object lookup. + * NOTE: key=0 is illegal. + */ + + +#define TABLE_SIZE 1024 + +struct HashEntry { + GLuint Key; + void *Data; + struct HashEntry *Next; +}; + +struct HashTable { + struct HashEntry *Table[TABLE_SIZE]; + GLuint MaxKey; +}; + + + +/* + * Return pointer to a new, empty hash table. + */ +struct HashTable *NewHashTable(void) +{ + return (struct HashTable *) calloc(sizeof (struct HashTable), 1); +} + + + +/* + * Delete a hash table. + */ +void DeleteHashTable(struct HashTable *table) +{ + GLuint i; + assert(table); + for (i=0;i<TABLE_SIZE;i++) { + struct HashEntry *entry = table->Table[i]; + while (entry) { + struct HashEntry *next = entry->Next; + free(entry); + entry = next; + } + } + free(table); +} + + + +/* + * Lookup an entry in the hash table. + * Input: table - the hash table + * key - the key + * Return: user data pointer or NULL if key not in table + */ +void *HashLookup(const struct HashTable *table, GLuint key) +{ + GLuint pos; + const struct HashEntry *entry; + + assert(table); + assert(key); + + pos = key & (TABLE_SIZE-1); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + return entry->Data; + } + entry = entry->Next; + } + return NULL; +} + + + +/* + * Insert into the hash table. If an entry with this key already exists + * we'll replace the existing entry. + * Input: table - the hash table + * key - the key (not zero) + * data - pointer to user data + */ +void HashInsert(struct HashTable *table, GLuint key, void *data) +{ + /* search for existing entry with this key */ + GLuint pos; + struct HashEntry *entry; + + assert(table); + assert(key); + + if (key > table->MaxKey) + table->MaxKey = key; + + pos = key & (TABLE_SIZE-1); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + /* replace entry's data */ + entry->Data = data; + return; + } + entry = entry->Next; + } + + /* alloc and insert new table entry */ + entry = (struct HashEntry *) calloc(sizeof(struct HashEntry), 1); + entry->Key = key; + entry->Data = data; + entry->Next = table->Table[pos]; + table->Table[pos] = entry; +} + + + +/* + * Remove an entry from the hash table. + * Input: table - the hash table + * key - key of entry to remove + */ +void HashRemove(struct HashTable *table, GLuint key) +{ + GLuint pos; + struct HashEntry *entry, *prev; + + assert(table); + assert(key); + + pos = key & (TABLE_SIZE-1); + prev = NULL; + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + /* found it! */ + if (prev) { + prev->Next = entry->Next; + } + else { + table->Table[pos] = entry->Next; + } + free(entry); + return; + } + prev = entry; + entry = entry->Next; + } +} + + + +/* + * Return the key of the "first" entry in the hash table. + * By calling this function until zero is returned we can get + * the keys of all entries in the table. + */ +GLuint HashFirstEntry(const struct HashTable *table) +{ + GLuint pos; + assert(table); + for (pos=0; pos < TABLE_SIZE; pos++) { + if (table->Table[pos]) + return table->Table[pos]->Key; + } + return 0; +} + + + +/* + * Dump contents of hash table for debugging. + */ +void HashPrint(const struct HashTable *table) +{ + GLuint i; + assert(table); + for (i=0;i<TABLE_SIZE;i++) { + const struct HashEntry *entry = table->Table[i]; + while (entry) { + printf("%u %p\n", entry->Key, entry->Data); + entry = entry->Next; + } + } +} + + + +/* + * Find a block of 'numKeys' adjacent unused hash keys. + * Input: table - the hash table + * numKeys - number of keys needed + * Return: startint key of free block or 0 if failure + */ +GLuint HashFindFreeKeyBlock(const struct HashTable *table, GLuint numKeys) +{ + GLuint maxKey = ~((GLuint) 0); + if (maxKey - numKeys > table->MaxKey) { + /* the quick solution */ + return table->MaxKey + 1; + } + else { + /* the slow solution */ + GLuint freeCount = 0; + GLuint freeStart = 0; + GLuint key; + for (key=0; key!=maxKey; key++) { + if (HashLookup(table, key)) { + /* darn, this key is already in use */ + freeCount = 0; + freeStart = key+1; + } + else { + /* this key not in use, check if we've found enough */ + freeCount++; + if (freeCount == numKeys) { + return freeStart; + } + } + } + /* cannot allocate a block of numKeys consecutive keys */ + return 0; + } +} + + + +#ifdef HASH_TEST_HARNESS +int main(int argc, char *argv[]) +{ + int a, b, c; + struct HashTable *t; + + printf("&a = %p\n", &a); + printf("&b = %p\n", &b); + + t = NewHashTable(); + HashInsert(t, 501, &a); + HashInsert(t, 10, &c); + HashInsert(t, 0xfffffff8, &b); + HashPrint(t); + printf("Find 501: %p\n", HashLookup(t,501)); + printf("Find 1313: %p\n", HashLookup(t,1313)); + printf("Find block of 100: %d\n", HashFindFreeKeyBlock(t, 100)); + DeleteHashTable(t); + + return 0; +} +#endif diff --git a/src/mesa/main/hash.h b/src/mesa/main/hash.h new file mode 100644 index 00000000000..a38159ce090 --- /dev/null +++ b/src/mesa/main/hash.h @@ -0,0 +1,59 @@ +/* $Id: hash.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 HASH_H +#define HASH_H + + +#include "GL/gl.h" + + +struct HashTable; + + + +extern struct HashTable *NewHashTable(void); + +extern void DeleteHashTable(struct HashTable *table); + +extern void *HashLookup(const struct HashTable *table, GLuint key); + +extern void HashInsert(struct HashTable *table, GLuint key, void *data); + +extern void HashRemove(struct HashTable *table, GLuint key); + +extern GLuint HashFirstEntry(const struct HashTable *table); + +extern void HashPrint(const struct HashTable *table); + +extern GLuint HashFindFreeKeyBlock(const struct HashTable *table, GLuint numKeys); + + +#endif diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c new file mode 100644 index 00000000000..46c33a67d90 --- /dev/null +++ b/src/mesa/main/image.c @@ -0,0 +1,2417 @@ +/* $Id: image.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include "context.h" +#include "image.h" +#include "macros.h" +#include "mmath.h" +#include "pixel.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/* + * Flip the 8 bits in each byte of the given array. + */ +void gl_flip_bytes( GLubyte *p, GLuint n ) +{ + register GLuint i, a, b; + + for (i=0;i<n;i++) { + b = (GLuint) p[i]; + a = ((b & 0x01) << 7) | + ((b & 0x02) << 5) | + ((b & 0x04) << 3) | + ((b & 0x08) << 1) | + ((b & 0x10) >> 1) | + ((b & 0x20) >> 3) | + ((b & 0x40) >> 5) | + ((b & 0x80) >> 7); + p[i] = (GLubyte) a; + } +} + + +/* + * Flip the order of the 2 bytes in each word in the given array. + */ +void gl_swap2( GLushort *p, GLuint n ) +{ + register GLuint i; + + for (i=0;i<n;i++) { + p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); + } +} + + + +/* + * Flip the order of the 4 bytes in each word in the given array. + */ +void gl_swap4( GLuint *p, GLuint n ) +{ + register GLuint i, a, b; + + for (i=0;i<n;i++) { + b = p[i]; + a = (b >> 24) + | ((b >> 8) & 0xff00) + | ((b << 8) & 0xff0000) + | ((b << 24) & 0xff000000); + p[i] = a; + } +} + + + + +/* + * Return the size, in bytes, of the given GL datatype. + * Return 0 if GL_BITMAP. + * Return -1 if invalid type enum. + */ +GLint gl_sizeof_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + default: + return -1; + } +} + + +/* + * Same as gl_sizeof_packed_type() but we also accept the + * packed pixel format datatypes. + */ +GLint gl_sizeof_packed_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_UNSIGNED_BYTE_3_3_2: + return sizeof(GLubyte); + case GL_UNSIGNED_BYTE_2_3_3_REV: + return sizeof(GLubyte); + case GL_UNSIGNED_SHORT_5_6_5: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT_5_6_5_REV: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT_4_4_4_4: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT_5_5_5_1: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return sizeof(GLshort); + case GL_UNSIGNED_INT_8_8_8_8: + return sizeof(GLuint); + case GL_UNSIGNED_INT_8_8_8_8_REV: + return sizeof(GLuint); + case GL_UNSIGNED_INT_10_10_10_2: + return sizeof(GLuint); + case GL_UNSIGNED_INT_2_10_10_10_REV: + return sizeof(GLuint); + default: + return -1; + } +} + + + +/* + * Return the number of components in a GL enum pixel type. + * Return -1 if bad format. + */ +GLint gl_components_in_format( GLenum format ) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + return 1; + case GL_LUMINANCE_ALPHA: + return 2; + case GL_RGB: + return 3; + case GL_RGBA: + return 4; + case GL_BGR: + return 3; + case GL_BGRA: + return 4; + case GL_ABGR_EXT: + return 4; + default: + return -1; + } +} + + +/* + * Return bytes per pixel for given format and type + * Return -1 if bad format or type. + */ +GLint gl_bytes_per_pixel( GLenum format, GLenum type ) +{ + GLint comps = gl_components_in_format( format ); + if (comps < 0) + return -1; + + switch (type) { + case GL_BITMAP: + return 0; /* special case */ + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return comps * sizeof(GLubyte); + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return comps * sizeof(GLshort); + case GL_INT: + case GL_UNSIGNED_INT: + return comps * sizeof(GLint); + case GL_FLOAT: + return comps * sizeof(GLfloat); + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + if (format == GL_RGB || format == GL_BGR) + return sizeof(GLubyte); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (format == GL_RGB || format == GL_BGR) + return sizeof(GLshort); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT) + return sizeof(GLushort); + else + return -1; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT) + return sizeof(GLuint); + else + return -1; + default: + return -1; + } +} + + +/* + * Test if the given pixel format and type are legal. + * Return GL_TRUE for legal, GL_FALSE for illegal. + */ +GLboolean gl_is_legal_format_and_type( GLenum format, GLenum type ) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + switch (type) { + case GL_BITMAP: + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + default: + return GL_FALSE; + } + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_DEPTH_COMPONENT: + case GL_BGR: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + default: + return GL_FALSE; + } + case GL_RGB: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return GL_TRUE; + default: + return GL_FALSE; + } + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return GL_TRUE; + default: + return GL_FALSE; + } + default: + ; /* fall-through */ + } + return GL_FALSE; +} + + + +/* + * Return the address of a pixel in an image (actually a volume). + * Pixel unpacking/packing parameters are observed according to 'packing'. + * Input: image - start of image data + * width, height - size of image + * format - image format + * type - pixel component type + * packing - the pixelstore attributes + * img - which image in the volume (0 for 1D or 2D images) + * row, column - location of pixel in the image + * Return: address of pixel at (image,row,column) in image or NULL if error. + */ +GLvoid *gl_pixel_addr_in_image( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, GLsizei width, + GLsizei height, GLenum format, GLenum type, + GLint img, GLint row, GLint column ) +{ + GLint alignment; /* 1, 2 or 4 */ + GLint pixels_per_row; + GLint rows_per_image; + GLint skiprows; + GLint skippixels; + GLint skipimages; /* for 3-D volume images */ + GLubyte *pixel_addr; + + alignment = packing->Alignment; + if (packing->RowLength > 0) { + pixels_per_row = packing->RowLength; + } + else { + pixels_per_row = width; + } + if (packing->ImageHeight > 0) { + rows_per_image = packing->ImageHeight; + } + else { + rows_per_image = height; + } + skiprows = packing->SkipRows; + skippixels = packing->SkipPixels; + skipimages = packing->SkipImages; + + if (type==GL_BITMAP) { + /* BITMAP data */ + GLint comp_per_pixel; /* components per pixel */ + GLint bytes_per_comp; /* bytes per component */ + GLint bytes_per_row; + GLint bytes_per_image; + + /* Compute bytes per component */ + bytes_per_comp = gl_sizeof_packed_type( type ); + if (bytes_per_comp<0) { + return NULL; + } + + /* Compute number of components per pixel */ + comp_per_pixel = gl_components_in_format( format ); + if (comp_per_pixel<0 && type != GL_BITMAP) { + return NULL; + } + + bytes_per_row = alignment + * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); + + bytes_per_image = bytes_per_row * rows_per_image; + + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + (skiprows + row) * bytes_per_row + + (skippixels + column) / 8; + } + else { + /* Non-BITMAP data */ + GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image; + + bytes_per_pixel = gl_bytes_per_pixel( format, type ); + + /* The pixel type and format should have been error checked earlier */ + assert(bytes_per_pixel > 0); + + bytes_per_row = pixels_per_row * bytes_per_pixel; + remainder = bytes_per_row % alignment; + if (remainder > 0) + bytes_per_row += (alignment - remainder); + + ASSERT(bytes_per_row % alignment == 0); + + bytes_per_image = bytes_per_row * rows_per_image; + + /* compute final pixel address */ + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + (skiprows + row) * bytes_per_row + + (skippixels + column) * bytes_per_pixel; + } + + return (GLvoid *) pixel_addr; +} + + + +/* + * Allocate a new gl_image. All fields are initialized to zero. + */ +static struct gl_image *alloc_image( void ) +{ + return (struct gl_image *) calloc(sizeof(struct gl_image), 1); +} + + + +/* + * Allocate a new gl_image with the error flag set. + */ +static struct gl_image *alloc_error_image( GLint width, GLint height, + GLint depth, GLenum format, + GLenum type ) +{ + struct gl_image *image = alloc_image(); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = depth; + image->Format = format; + image->Type = type; + image->ErrorFlag = GL_TRUE; + } + return image; +} + + + +/* + * Free a gl_image. + */ +void gl_free_image( struct gl_image *image ) +{ + if (image->Data) { + free(image->Data); + } + free(image); +} + + + +/* + * Do error checking on an image. If there's an error, register it and + * return GL_TRUE, else return GL_FALSE. + */ +GLboolean gl_image_error_test( GLcontext *ctx, const struct gl_image *image, + const char *msg ) +{ + if (!image) { + gl_error( ctx, GL_OUT_OF_MEMORY, msg ); + return GL_TRUE; + } + if (image->Width <= 0 || image->Height <= 0 || image->Depth <= 0) { + gl_error( ctx, GL_INVALID_VALUE, msg ); + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + + +/* + * Unpack a depth-buffer image storing values as GLshort, GLuint, or GLfloats. + * Input: type - datatype of src depth image + * Return pointer to a new gl_image structure. + * + * Notes: if the source image type is GLushort then the gl_image will + * also store GLushorts. If the src image type is GLuint then the gl_image + * will also store GLuints. For all other src image types the gl_image + * will store GLfloats. The integer cases can later be optimized. + */ +static struct gl_image * +unpack_depth_image( GLcontext *ctx, GLenum type, GLint width, GLint height, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing) + +{ + struct gl_image *image; + GLfloat *fDst; + GLushort *sDst; + GLuint *iDst; + GLint i, j; + + image = alloc_image(); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = 1; + image->Components = 1; + image->Format = GL_DEPTH_COMPONENT; + if (type==GL_UNSIGNED_SHORT) { + image->Type = GL_UNSIGNED_SHORT; + image->Data = malloc( width * height * sizeof(GLushort)); + } + else if (type==GL_UNSIGNED_INT) { + image->Type = GL_UNSIGNED_INT; + image->Data = malloc( width * height * sizeof(GLuint)); + } + else { + image->Type = GL_FLOAT; + image->Data = malloc( width * height * sizeof(GLfloat)); + } + image->RefCount = 0; + if (!image->Data) + return image; + } + else { + return NULL; + } + + fDst = (GLfloat *) image->Data; + sDst = (GLushort *) image->Data; + iDst = (GLuint *) image->Data; + + for (i=0;i<height;i++) { + GLvoid *src = gl_pixel_addr_in_image( packing, pixels, + width, height, + GL_DEPTH_COMPONENT, type, + 0, i, 0 ); + if (!src) { + return image; + } + + switch (type) { + case GL_BYTE: + assert(image->Type == GL_FLOAT); + for (j=0; j<width; j++) { + *fDst++ = BYTE_TO_FLOAT(((GLbyte*)src)[j]); + } + break; + case GL_UNSIGNED_BYTE: + assert(image->Type == GL_FLOAT); + for (j=0; j<width; j++) { + *fDst++ = UBYTE_TO_FLOAT(((GLubyte*)src)[j]); + } + break; + case GL_UNSIGNED_SHORT: + assert(image->Type == GL_UNSIGNED_SHORT); + MEMCPY( sDst, src, width * sizeof(GLushort) ); + if (packing->SwapBytes) { + gl_swap2( sDst, width ); + } + sDst += width; + break; + case GL_SHORT: + assert(image->Type == GL_FLOAT); + if (packing->SwapBytes) { + for (j=0;j<width;j++) { + GLshort value = ((GLshort*)src)[j]; + value = ((value >> 8) & 0xff) | ((value&0xff) << 8); + *fDst++ = SHORT_TO_FLOAT(value); + } + } + else { + for (j=0;j<width;j++) { + *fDst++ = SHORT_TO_FLOAT(((GLshort*)src)[j]); + } + } + break; + case GL_INT: + assert(image->Type == GL_FLOAT); + if (packing->SwapBytes) { + for (j=0;j<width;j++) { + GLint value = ((GLint*)src)[j]; + value = ((value >> 24) & 0x000000ff) | + ((value >> 8) & 0x0000ff00) | + ((value << 8) & 0x00ff0000) | + ((value << 24) & 0xff000000); + *fDst++ = INT_TO_FLOAT(value); + } + } + else { + for (j=0;j<width;j++) { + *fDst++ = INT_TO_FLOAT(((GLint*)src)[j]); + } + } + iDst += width; + break; + case GL_UNSIGNED_INT: + assert(image->Type == GL_UNSIGNED_INT); + MEMCPY( iDst, src, width * sizeof(GLuint) ); + if (packing->SwapBytes) { + gl_swap4( iDst, width ); + } + iDst += width; + break; + case GL_FLOAT: + assert(image->Type == GL_FLOAT); + MEMCPY( fDst, src, width * sizeof(GLfloat) ); + if (packing->SwapBytes) { + gl_swap4( (GLuint*) fDst, width ); + } + fDst += width; + break; + default: + gl_problem(ctx, "unpack_depth_image type" ); + return image; + } + } + + return image; +} + + + +/* + * Unpack a stencil image. Store as GLubytes in a gl_image structure. + * Return: pointer to new gl_image structure. + */ +static struct gl_image * +unpack_stencil_image( GLcontext *ctx, GLenum type, GLint width, GLint height, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing ) +{ + struct gl_image *image; + GLubyte *dst; + GLint i, j; + + assert(sizeof(GLstencil) == sizeof(GLubyte)); + + image = alloc_image(); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = 1; + image->Components = 1; + image->Format = GL_STENCIL_INDEX; + image->Type = GL_UNSIGNED_BYTE; + image->Data = malloc( width * height * sizeof(GLubyte)); + image->RefCount = 0; + if (!image->Data) + return image; + } + else { + return NULL; + } + + dst = (GLubyte *) image->Data; + + for (i=0;i<height;i++) { + GLvoid *src = gl_pixel_addr_in_image( packing, pixels, + width, height, + GL_STENCIL_INDEX, type, + 0, i, 0 ); + if (!src) { + return image; + } + + switch (type) { + case GL_UNSIGNED_BYTE: + case GL_BYTE: + MEMCPY( dst, src, width * sizeof(GLubyte) ); + dst += width * sizeof(GLubyte); + break; + case GL_UNSIGNED_SHORT: + case GL_SHORT: + if (packing->SwapBytes) { + /* grab upper byte */ + for (j=0; j < width; j++) { + *dst++ = (((GLushort*)src)[j] & 0xff00) >> 8; + } + } + else { + for (j=0; j < width; j++) { + *dst++ = (((GLushort*)src)[j]) & 0xff; + } + } + break; + case GL_INT: + if (packing->SwapBytes) { + /* grab upper byte */ + for (j=0; j < width; j++) { + *dst++ = (((GLuint*)src)[j] & 0xff000000) >> 8; + } + } + else { + for (j=0; j < width; j++) { + *dst++ = (((GLuint*)src)[j]) & 0xff; + } + } + break; + case GL_UNSIGNED_INT: + if (packing->SwapBytes) { + /* grab upper byte */ + for (j=0; j < width; j++) { + *dst++ = (((GLuint*)src)[j] & 0xff000000) >> 8; + } + } + else { + for (j=0; j < width; j++) { + *dst++ = (((GLuint*)src)[j]) & 0xff; + } + } + break; + case GL_FLOAT: + if (packing->SwapBytes) { + for (j=0; j < width; j++) { + GLfloat fvalue; + GLint value = ((GLuint*)src)[j]; + value = ((value & 0xff000000) >> 24) + | ((value & 0x00ff0000) >> 8) + | ((value & 0x0000ff00) << 8) + | ((value & 0x000000ff) << 24); + fvalue = *((GLfloat*) &value); + *dst++ = ((GLint) fvalue) & 0xff; + } + } + else { + for (j=0; j < width; j++) { + GLfloat fvalue = ((GLfloat *)src)[j]; + *dst++ = ((GLint) fvalue) & 0xff; + } + } + break; + default: + gl_problem(ctx, "unpack_stencil_image type" ); + return image; + } + } + + return image; +} + + + +/* + * Unpack a bitmap, return a new gl_image struct. + */ +static struct gl_image * +unpack_bitmap( GLcontext *ctx, GLenum format, GLint width, GLint height, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing ) +{ + struct gl_image *image; + GLint bytes, i, width_in_bytes; + GLubyte *buffer, *dst; + + assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX); + + /* Alloc dest storage */ + bytes = ((width+7)/8 * height); + if (bytes>0 && pixels!=NULL) { + buffer = (GLubyte *) malloc( bytes ); + if (!buffer) { + return NULL; + } + /* Copy/unpack pixel data to buffer */ + width_in_bytes = CEILING( width, 8 ); + dst = buffer; + for (i=0; i<height; i++) { + GLvoid *src = gl_pixel_addr_in_image( packing, pixels, + width, height, + GL_COLOR_INDEX, GL_BITMAP, + 0, i, 0 ); + if (!src) { + free(buffer); + return NULL; + } + MEMCPY( dst, src, width_in_bytes ); + dst += width_in_bytes; + } + /* Bit flipping */ + if (packing->LsbFirst) { + gl_flip_bytes( buffer, bytes ); + } + } + else { + /* a 'null' bitmap */ + buffer = NULL; + } + + image = alloc_image(); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = 1; + image->Components = 0; + image->Format = format; + image->Type = GL_BITMAP; + image->Data = buffer; + image->RefCount = 0; + } + else { + free( buffer ); + return NULL; + } + + return image; +} + + + +/* + * Unpack a 32x32 pixel polygon stipple from user memory using the + * current pixel unpack settings. + */ +void gl_unpack_polygon_stipple( const GLcontext *ctx, + const GLubyte *pattern, GLuint dest[32] ) +{ + GLint i; + for (i = 0; i < 32; i++) { + GLubyte *src = (GLubyte *) gl_pixel_addr_in_image( &ctx->Unpack, pattern, + 32, 32, GL_COLOR_INDEX, GL_BITMAP, 0, i, 0 ); + dest[i] = (src[0] << 24) + | (src[1] << 16) + | (src[2] << 8) + | (src[3] ); + } + + /* Bit flipping within each byte */ + if (ctx->Unpack.LsbFirst) { + gl_flip_bytes( (GLubyte *) dest, 32 * 4 ); + } +} + + + +/* + * Pack polygon stipple into user memory given current pixel packing + * settings. + */ +void gl_pack_polygon_stipple( const GLcontext *ctx, + const GLuint pattern[32], + GLubyte *dest ) +{ + GLint i; + for (i = 0; i < 32; i++) { + GLubyte *dst = (GLubyte *) gl_pixel_addr_in_image( &ctx->Pack, dest, + 32, 32, GL_COLOR_INDEX, GL_BITMAP, 0, i, 0 ); + dst[0] = (pattern[i] >> 24) & 0xff; + dst[1] = (pattern[i] >> 16) & 0xff; + dst[2] = (pattern[i] >> 8) & 0xff; + dst[3] = (pattern[i] ) & 0xff; + + /* Bit flipping within each byte */ + if (ctx->Pack.LsbFirst) { + gl_flip_bytes( (GLubyte *) dst, 4 ); + } + } +} + + + +/* + * Unpack an RGBA or CI image and store it as unsigned bytes + */ +static struct gl_image * +unpack_ubyte_image( GLcontext *ctx, GLint width, GLint height, + GLint depth, GLenum format, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing ) +{ + struct gl_image *image; + GLint width_in_bytes; + GLint components; + GLubyte *buffer, *dst; + GLint i, d; + + components = gl_components_in_format( format ); + + width_in_bytes = width * components * sizeof(GLubyte); + buffer = (GLubyte *) malloc( height * width_in_bytes * depth ); + if (!buffer) { + return NULL; + } + + /* Copy/unpack pixel data to buffer */ + dst = buffer; + for (d=0; d<depth; d++ ) { + for (i=0;i<height;i++) { + GLubyte *src = (GLubyte *) gl_pixel_addr_in_image( packing, + pixels, width, height, format, GL_UNSIGNED_BYTE, + d, i, 0 ); + if (!src) { + free(buffer); + return NULL; + } + MEMCPY( dst, src, width_in_bytes ); + dst += width_in_bytes; + } + } + + if (format == GL_BGR) { + /* swap order of every ubyte triplet from BGR to RGB */ + for (i=0; i<width*height; i++) { + GLubyte b = buffer[i*3+0]; + GLubyte r = buffer[i*3+2]; + buffer[i*3+0] = r; + buffer[i*3+2] = b; + } + } + else if (format == GL_BGRA) { + /* swap order of every ubyte quadruplet from BGRA to RGBA */ + for (i=0; i<width*height; i++) { + GLubyte b = buffer[i*4+0]; + GLubyte r = buffer[i*4+2]; + buffer[i*4+0] = r; + buffer[i*4+2] = b; + } + } + else if (format == GL_ABGR_EXT) { + /* swap order of every ubyte quadruplet from ABGR to RGBA */ + for (i=0; i<width*height; i++) { + GLubyte a = buffer[i*4+0]; + GLubyte b = buffer[i*4+1]; + GLubyte g = buffer[i*4+2]; + GLubyte r = buffer[i*4+3]; + buffer[i*4+0] = r; + buffer[i*4+1] = g; + buffer[i*4+2] = b; + buffer[i*4+3] = a; + } + } + + + image = alloc_image(); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = depth; + image->Components = components; + if (format == GL_BGR) + image->Format = GL_RGB; + else if (format == GL_BGRA) + image->Format = GL_RGBA; + else if (format == GL_ABGR_EXT) + image->Format = GL_RGBA; + else + image->Format = format; + image->Type = GL_UNSIGNED_BYTE; + image->Data = buffer; + image->RefCount = 0; + } + else { + free( buffer ); + } + + return image; +} + + + +/* + * Unpack a color image storing image as GLfloats + */ +static struct gl_image * +unpack_float_image( GLcontext *ctx, GLint width, GLint height, GLint depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing ) +{ + struct gl_image *image; + GLfloat *dst; + GLint elems_per_row; + GLint components; + GLint i, j, d; + GLboolean normalize; + + assert(type != GL_BITMAP); + + components = gl_components_in_format( format ); + assert(components > 0); /* should have been caught earlier */ + + if (!gl_is_legal_format_and_type( format, type )) { + /* bad pixel type for format, make dummy image */ + image = alloc_image(); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = depth; + image->Components = components; + image->Format = format; + image->Type = type; + image->Data = NULL; + image->RefCount = 0; + } + return image; + } + + elems_per_row = width * components; + + image = alloc_image(); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = depth; + image->Components = components; + if (format == GL_BGR) + image->Format = GL_RGB; + else if (format == GL_BGRA) + image->Format = GL_RGBA; + else if (format == GL_ABGR_EXT) + image->Format = GL_RGBA; + else + image->Format = format; + image->Type = GL_FLOAT; + image->Data = malloc( elems_per_row * height * depth * sizeof(GLfloat)); + image->RefCount = 0; + if (!image->Data) + return image; + } + else { + return NULL; + } + + normalize = (format != GL_COLOR_INDEX) && (format != GL_STENCIL_INDEX); + + dst = (GLfloat *) image->Data; + + for (d=0; d<depth; d++) { + for (i=0;i<height;i++) { + GLvoid *src = gl_pixel_addr_in_image( packing, pixels, + width, height, + format, type, + d, i, 0 ); + if (!src) { + return image; + } + + switch (type) { + case GL_UNSIGNED_BYTE: + { + GLubyte *ubsrc = (GLubyte *) src; + if (normalize) { + for (j=0;j<elems_per_row;j++) { + *dst++ = UBYTE_TO_FLOAT(ubsrc[j]); + } + } + else { + for (j=0;j<elems_per_row;j++) { + *dst++ = (GLfloat) ubsrc[j]; + } + } + } + break; + case GL_BYTE: + if (normalize) { + for (j=0;j<elems_per_row;j++) { + *dst++ = BYTE_TO_FLOAT(((GLbyte*)src)[j]); + } + } + else { + for (j=0;j<elems_per_row;j++) { + *dst++ = (GLfloat) ((GLbyte*)src)[j]; + } + } + break; + case GL_UNSIGNED_SHORT: + if (packing->SwapBytes) { + for (j=0;j<elems_per_row;j++) { + GLushort value = ((GLushort*)src)[j]; + value = ((value >> 8) & 0xff) | ((value&0xff) << 8); + if (normalize) { + *dst++ = USHORT_TO_FLOAT(value); + } + else { + *dst++ = (GLfloat) value; + } + } + } + else { + if (normalize) { + for (j=0;j<elems_per_row;j++) { + *dst++ = USHORT_TO_FLOAT(((GLushort*)src)[j]); + } + } + else { + for (j=0;j<elems_per_row;j++) { + *dst++ = (GLfloat) ((GLushort*)src)[j]; + } + } + } + break; + case GL_SHORT: + if (packing->SwapBytes) { + for (j=0;j<elems_per_row;j++) { + GLshort value = ((GLshort*)src)[j]; + value = ((value >> 8) & 0xff) | ((value&0xff) << 8); + if (normalize) { + *dst++ = SHORT_TO_FLOAT(value); + } + else { + *dst++ = (GLfloat) value; + } + } + } + else { + if (normalize) { + for (j=0;j<elems_per_row;j++) { + *dst++ = SHORT_TO_FLOAT(((GLshort*)src)[j]); + } + } + else { + for (j=0;j<elems_per_row;j++) { + *dst++ = (GLfloat) ((GLshort*)src)[j]; + } + } + } + break; + case GL_UNSIGNED_INT: + if (packing->SwapBytes) { + GLuint value; + for (j=0;j<elems_per_row;j++) { + value = ((GLuint*)src)[j]; + value = ((value & 0xff000000) >> 24) + | ((value & 0x00ff0000) >> 8) + | ((value & 0x0000ff00) << 8) + | ((value & 0x000000ff) << 24); + if (normalize) { + *dst++ = UINT_TO_FLOAT(value); + } + else { + *dst++ = (GLfloat) value; + } + } + } + else { + if (normalize) { + for (j=0;j<elems_per_row;j++) { + *dst++ = UINT_TO_FLOAT(((GLuint*)src)[j]); + } + } + else { + for (j=0;j<elems_per_row;j++) { + *dst++ = (GLfloat) ((GLuint*)src)[j]; + } + } + } + break; + case GL_INT: + if (packing->SwapBytes) { + GLint value; + for (j=0;j<elems_per_row;j++) { + value = ((GLint*)src)[j]; + value = ((value & 0xff000000) >> 24) + | ((value & 0x00ff0000) >> 8) + | ((value & 0x0000ff00) << 8) + | ((value & 0x000000ff) << 24); + if (normalize) { + *dst++ = INT_TO_FLOAT(value); + } + else { + *dst++ = (GLfloat) value; + } + } + } + else { + if (normalize) { + for (j=0;j<elems_per_row;j++) { + *dst++ = INT_TO_FLOAT(((GLint*)src)[j]); + } + } + else { + for (j=0;j<elems_per_row;j++) { + *dst++ = (GLfloat) ((GLint*)src)[j]; + } + } + } + break; + case GL_FLOAT: + if (packing->SwapBytes) { + GLint value; + for (j=0;j<elems_per_row;j++) { + value = ((GLuint*)src)[j]; + value = ((value & 0xff000000) >> 24) + | ((value & 0x00ff0000) >> 8) + | ((value & 0x0000ff00) << 8) + | ((value & 0x000000ff) << 24); + *dst++ = *((GLfloat*) &value); + } + } + else { + MEMCPY( dst, src, elems_per_row*sizeof(GLfloat) ); + dst += elems_per_row; + } + break; + case GL_UNSIGNED_BYTE_3_3_2: + { + GLubyte *ubsrc = (GLubyte *) src; + for (j=0;j<width;j++) { + GLubyte p = ubsrc[j]; + *dst++ = ((p >> 5) ) * (1.0F / 7.0F); /* red */ + *dst++ = ((p >> 2) & 0x7) * (1.0F / 7.0F); /* green */ + *dst++ = ((p ) & 0x3) * (1.0F / 3.0F); /* blue */ + } + } + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + { + GLubyte *ubsrc = (GLubyte *) src; + for (j=0;j<width;j++) { + GLubyte p = ubsrc[j]; + *dst++ = ((p ) & 0x7) * (1.0F / 7.0F); /* red */ + *dst++ = ((p >> 3) & 0x7) * (1.0F / 7.0F); /* green */ + *dst++ = ((p >> 6) ) * (1.0F / 3.0F); /* blue */ + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + { + GLushort *ussrc = (GLushort *) src; + for (j=0;j<width;j++) { + GLushort p = ussrc[j]; + *dst++ = ((p >> 11) ) * (1.0F / 31.0F); /* red */ + *dst++ = ((p >> 5) & 0x3f) * (1.0F / 63.0F); /* green */ + *dst++ = ((p ) & 0x1f) * (1.0F / 31.0F); /* blue */ + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + { + GLushort *ussrc = (GLushort *) src; + for (j=0;j<width;j++) { + GLushort p = ussrc[j]; + *dst++ = ((p ) & 0x1f) * (1.0F / 31.0F); /* red */ + *dst++ = ((p >> 5) & 0x3f) * (1.0F / 63.0F); /* green */ + *dst++ = ((p >> 11) ) * (1.0F / 31.0F); /* blue */ + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + { + GLushort *ussrc = (GLushort *) src; + for (j=0;j<width;j++) { + GLushort p = ussrc[j]; + *dst++ = ((p >> 12) ) * (1.0F / 15.0F); /* red */ + *dst++ = ((p >> 8) & 0xf) * (1.0F / 15.0F); /* green */ + *dst++ = ((p >> 4) & 0xf) * (1.0F / 15.0F); /* blue */ + *dst++ = ((p ) & 0xf) * (1.0F / 15.0F); /* alpha */ + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + { + GLushort *ussrc = (GLushort *) src; + for (j=0;j<width;j++) { + GLushort p = ussrc[j]; + *dst++ = ((p ) & 0xf) * (1.0F / 15.0F); /* red */ + *dst++ = ((p >> 4) & 0xf) * (1.0F / 15.0F); /* green */ + *dst++ = ((p >> 8) & 0xf) * (1.0F / 15.0F); /* blue */ + *dst++ = ((p >> 12) ) * (1.0F / 15.0F); /* alpha */ + } + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + { + GLushort *ussrc = (GLushort *) src; + for (j=0;j<width;j++) { + GLushort p = ussrc[j]; + *dst++ = ((p >> 11) ) * (1.0F / 31.0F); /* red */ + *dst++ = ((p >> 6) & 0x1f) * (1.0F / 31.0F); /* green */ + *dst++ = ((p >> 1) & 0x1f) * (1.0F / 31.0F); /* blue */ + *dst++ = ((p ) & 0x1) * (1.0F / 1.0F); /* alpha */ + } + } + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + { + GLushort *ussrc = (GLushort *) src; + for (j=0;j<width;j++) { + GLushort p = ussrc[j]; + *dst++ = ((p ) & 0x1f) * (1.0F / 31.0F); /* red */ + *dst++ = ((p >> 5) & 0x1f) * (1.0F / 31.0F); /* green */ + *dst++ = ((p >> 10) & 0x1f) * (1.0F / 31.0F); /* blue */ + *dst++ = ((p >> 15) ) * (1.0F / 1.0F); /* alpha */ + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8: + { + GLuint *uisrc = (GLuint *) src; + for (j=0;j<width;j++) { + GLuint p = uisrc[j]; + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + { + GLuint *uisrc = (GLuint *) src; + for (j=0;j<width;j++) { + GLuint p = uisrc[j]; + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); + *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + } + } + break; + case GL_UNSIGNED_INT_10_10_10_2: + { + GLuint *uisrc = (GLuint *) src; + for (j=0;j<width;j++) { + GLuint p = uisrc[j]; + *dst++ = ((p >> 22) ) * (1.0F / 1023.0F); /* r */ + *dst++ = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F); /* g */ + *dst++ = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F); /* b */ + *dst++ = ((p ) & 0x3 ) * (1.0F / 3.0F); /* a */ + } + } + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + { + GLuint *uisrc = (GLuint *) src; + for (j=0;j<width;j++) { + GLuint p = uisrc[j]; + *dst++ = ((p ) & 0x3ff) * (1.0F / 1023.0F); /* r*/ + *dst++ = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F); /* g */ + *dst++ = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F); /* b */ + *dst++ = ((p >> 30) ) * (1.0F / 3.0F); /* a */ + } + } + break; + default: + gl_problem(ctx, "unpack_float_image type" ); + return image; + } + } + } + + if (format == GL_BGR) { + /* swap order of every float triplet from BGR to RGBA */ + GLfloat *buffer = (GLfloat *) image->Data; + for (i=0; i<width*height*depth; i++) { + GLfloat b = buffer[i*3+0]; + GLfloat r = buffer[i*3+2]; + buffer[i*3+0] = r; + buffer[i*3+2] = b; + } + } + else if (format == GL_BGRA) { + /* swap order of every float quadruplet from BGRA to RGBA */ + GLfloat *buffer = (GLfloat *) image->Data; + for (i=0; i<width*height*depth; i++) { + GLfloat b = buffer[i*4+0]; + GLfloat r = buffer[i*4+2]; + buffer[i*4+0] = r; + buffer[i*4+2] = b; + } + } + else if (format == GL_ABGR_EXT) { + /* swap order of every float quadruplet from ABGR to RGBA */ + GLfloat *buffer = (GLfloat *) image->Data; + for (i=0; i<width*height*depth; i++) { + GLfloat a = buffer[i*4+0]; + GLfloat b = buffer[i*4+1]; + GLfloat g = buffer[i*4+2]; + GLfloat r = buffer[i*4+3]; + buffer[i*4+0] = r; + buffer[i*4+1] = g; + buffer[i*4+2] = b; + buffer[i*4+3] = a; + } + } + + return image; +} + + + +/* + * Unpack a bitmap image, using current glPixelStore parameters, + * making a new gl_image. + */ +struct gl_image *gl_unpack_bitmap( GLcontext *ctx, + GLsizei width, GLsizei height, + const GLubyte *bitmap, + const struct gl_pixelstore_attrib *packing ) +{ + return gl_unpack_image( ctx, width, height, + GL_COLOR_INDEX, GL_BITMAP, bitmap, packing ); +} + + + +/* + * Unpack a 2-D image from user's buffer. Return pointer to new + * gl_image struct. + * + * Input: width, height - size in pixels + * format - format of incoming pixel data + * type - datatype of incoming pixel data + * pixels - pointer to unpacked image in user buffer + */ +struct gl_image *gl_unpack_image( GLcontext *ctx, + GLint width, GLint height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing ) +{ + return gl_unpack_image3D( ctx, width, height, 1, + format, type, pixels, packing ); +} + + + +/* + * Unpack a 1, 2 or 3-D image from user-supplied address, returning a + * pointer to a new gl_image struct. + * This function is always called by a higher-level unpack function such + * as gl_unpack_texsubimage() or gl_unpack_bitmap(). + * + * Input: width, height, depth - size in pixels + * format - format of incoming pixel data + * type - datatype of incoming pixel data + * pixels - pointer to unpacked image. + */ +struct gl_image *gl_unpack_image3D( GLcontext *ctx, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing) +{ + if (width <= 0 || height <= 0 || depth <= 0) { + return alloc_error_image(width, height, depth, format, type); + } + + if (type==GL_BITMAP) { + if (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX) { + return alloc_error_image(width, height, depth, format, type); + } + else { + return unpack_bitmap( ctx, format, width, height, pixels, packing ); + } + } + else if (format==GL_DEPTH_COMPONENT) { + /* TODO: pack as GLdepth values (GLushort or GLuint) */ + return unpack_depth_image( ctx, type, width, height, pixels, packing ); + } + else if (format==GL_STENCIL_INDEX) { + /* TODO: pack as GLstencil (GLubyte or GLushort) */ + return unpack_stencil_image( ctx, type, width, height, pixels, packing ); + } + else if (type==GL_UNSIGNED_BYTE) { + /* upack, convert to GLubytes */ + return unpack_ubyte_image( ctx, width, height, depth, format, pixels, packing ); + } + else { + /* upack, convert to floats */ + return unpack_float_image( ctx, width, height, depth, + format, type, pixels, packing ); + } + + /* never get here */ + /*return NULL;*/ +} + + +/* + * Apply pixel-transfer operations (scale, bias, mapping) to a single row + * of a gl_image. Put resulting color components into result array. + */ +void gl_scale_bias_map_image_data( const GLcontext *ctx, + const struct gl_image *image, + GLint row, GLubyte result[] ) +{ + GLint start, i; + + assert(ctx); + assert(image); + assert(result); + assert(row >= 0); + + start = row * image->Width * image->Components; + + for (i=0; i < image->Width; i++) { + GLint pos = start+i; + GLfloat red, green, blue, alpha; + if (image->Type == GL_UNSIGNED_BYTE) { + const GLubyte *data = (GLubyte *) image->Data; + switch (image->Format) { + case GL_RED: + red = data[pos] * (1.0F/255.0F); + green = 0; + blue = 0; + alpha = 0; + break; + case GL_RGB: + red = data[pos*3+0] * (1.0F/255.0F); + green = data[pos*3+1] * (1.0F/255.0F); + blue = data[pos*3+2] * (1.0F/255.0F); + alpha = 0; + break; + default: + gl_problem(ctx, "bad image format in gl_scale...image_data"); + return; + } + } + else if (image->Type == GL_FLOAT) { + const GLubyte *data = (GLubyte *) image->Data; + switch (image->Format) { + case GL_RED: + red = data[pos]; + green = 0; + blue = 0; + alpha = 0; + break; + case GL_RGB: + red = data[pos*3+0]; + green = data[pos*3+1]; + blue = data[pos*3+2]; + alpha = 0; + break; + default: + gl_problem(ctx, "bad image format in gl_scale...image_data"); + return; + } + } + else { + gl_problem(ctx, "Bad image type in gl_scale_...image_data"); + return; + } + + assert(red >= 0.0 && red <= 1.0); + assert(green >= 0.0 && green <= 1.0); + assert(blue >= 0.0 && blue <= 1.0); + assert(alpha >= 0.0 && alpha <= 1.0); + + /* + if (scale or bias) { + + + } + if (mapping) { + + } + */ + + result[i*4+0] = (GLubyte) (red * 255.0); + result[i*4+1] = (GLubyte) (green * 255.0); + result[i*4+2] = (GLubyte) (blue * 255.0); + result[i*4+3] = (GLubyte) (alpha * 255.0); + } +} + + + +/* + * Pack the given RGBA span into client memory at 'dest' address + * in the given pixel format and type. + * Optionally apply the enabled pixel transfer ops. + * Pack into memory using the given packing params struct. + * This is used by glReadPixels and glGetTexImage?D() + * Input: ctx - the context + * n - number of pixels in the span + * rgba - the pixels + * format - dest packing format + * type - dest packing datatype + * destination - destination packing address + * packing - pixel packing parameters + * applyTransferOps - apply scale/bias/lookup-table ops? + */ +void gl_pack_rgba_span( const GLcontext *ctx, + GLuint n, CONST GLubyte rgba[][4], + GLenum format, GLenum type, GLvoid *destination, + const struct gl_pixelstore_attrib *packing, + GLboolean applyTransferOps ) +{ + /* Test for optimized case first */ + if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag && + format == GL_RGBA && type == GL_UNSIGNED_BYTE) { + /* simple case */ + MEMCPY( destination, rgba, n * 4 * sizeof(GLubyte) ); + } + else { + GLfloat red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH]; + GLfloat alpha[MAX_WIDTH], luminance[MAX_WIDTH]; + GLfloat rscale = 1.0F / 255.0F; + GLfloat gscale = 1.0F / 255.0F; + GLfloat bscale = 1.0F / 255.0F; + GLfloat ascale = 1.0F / 255.0F; + GLuint i; + + assert( n < MAX_WIDTH ); + + /* convert color components to floating point */ + for (i=0;i<n;i++) { + red[i] = rgba[i][RCOMP] * rscale; + green[i] = rgba[i][GCOMP] * gscale; + blue[i] = rgba[i][BCOMP] * bscale; + alpha[i] = rgba[i][ACOMP] * ascale; + } + + /* + * Apply scale, bias and lookup-tables if enabled. + */ + if (applyTransferOps) { + if (ctx->Pixel.ScaleOrBiasRGBA) { + gl_scale_and_bias_color( ctx, n, red, green, blue, alpha ); + } + if (ctx->Pixel.MapColorFlag) { + gl_map_color( ctx, n, red, green, blue, alpha ); + } + } + + if (format==GL_LUMINANCE || format==GL_LUMINANCE_ALPHA) { + for (i=0;i<n;i++) { + GLfloat sum = red[i] + green[i] + blue[i]; + luminance[i] = CLAMP( sum, 0.0F, 1.0F ); + } + } + + /* + * Pack/store the pixels. Ugh! Lots of cases!!! + */ + switch (type) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) destination; + switch (format) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(red[i]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(green[i]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(blue[i]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(alpha[i]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_UBYTE(luminance[i]); + dst[i*2+1] = FLOAT_TO_UBYTE(alpha[i]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UBYTE(red[i]); + dst[i*3+1] = FLOAT_TO_UBYTE(green[i]); + dst[i*3+2] = FLOAT_TO_UBYTE(blue[i]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UBYTE(red[i]); + dst[i*4+1] = FLOAT_TO_UBYTE(green[i]); + dst[i*4+2] = FLOAT_TO_UBYTE(blue[i]); + dst[i*4+3] = FLOAT_TO_UBYTE(alpha[i]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UBYTE(blue[i]); + dst[i*3+1] = FLOAT_TO_UBYTE(green[i]); + dst[i*3+2] = FLOAT_TO_UBYTE(red[i]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UBYTE(blue[i]); + dst[i*4+1] = FLOAT_TO_UBYTE(green[i]); + dst[i*4+2] = FLOAT_TO_UBYTE(red[i]); + dst[i*4+3] = FLOAT_TO_UBYTE(alpha[i]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UBYTE(alpha[i]); + dst[i*4+1] = FLOAT_TO_UBYTE(blue[i]); + dst[i*4+2] = FLOAT_TO_UBYTE(green[i]); + dst[i*4+3] = FLOAT_TO_UBYTE(red[i]); + } + break; + default: + gl_problem(ctx, "bad format in gl_pack_rgba_span\n"); + } + } + break; + case GL_BYTE: + { + GLbyte *dst = (GLbyte *) destination; + switch (format) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(red[i]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(green[i]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(blue[i]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(alpha[i]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_BYTE(luminance[i]); + dst[i*2+1] = FLOAT_TO_BYTE(alpha[i]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_BYTE(red[i]); + dst[i*3+1] = FLOAT_TO_BYTE(green[i]); + dst[i*3+2] = FLOAT_TO_BYTE(blue[i]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_BYTE(red[i]); + dst[i*4+1] = FLOAT_TO_BYTE(green[i]); + dst[i*4+2] = FLOAT_TO_BYTE(blue[i]); + dst[i*4+3] = FLOAT_TO_BYTE(alpha[i]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_BYTE(blue[i]); + dst[i*3+1] = FLOAT_TO_BYTE(green[i]); + dst[i*3+2] = FLOAT_TO_BYTE(red[i]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_BYTE(blue[i]); + dst[i*4+1] = FLOAT_TO_BYTE(green[i]); + dst[i*4+2] = FLOAT_TO_BYTE(red[i]); + dst[i*4+3] = FLOAT_TO_BYTE(alpha[i]); + } + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_BYTE(alpha[i]); + dst[i*4+1] = FLOAT_TO_BYTE(blue[i]); + dst[i*4+2] = FLOAT_TO_BYTE(green[i]); + dst[i*4+3] = FLOAT_TO_BYTE(red[i]); + } + break; + default: + gl_problem(ctx, "bad format in gl_pack_rgba_span\n"); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLushort *dst = (GLushort *) destination; + switch (format) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(red[i]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(green[i]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(blue[i]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(alpha[i]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_USHORT(luminance[i]); + dst[i*2+1] = FLOAT_TO_USHORT(alpha[i]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_USHORT(red[i]); + dst[i*3+1] = FLOAT_TO_USHORT(green[i]); + dst[i*3+2] = FLOAT_TO_USHORT(blue[i]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_USHORT(red[i]); + dst[i*4+1] = FLOAT_TO_USHORT(green[i]); + dst[i*4+2] = FLOAT_TO_USHORT(blue[i]); + dst[i*4+3] = FLOAT_TO_USHORT(alpha[i]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_USHORT(blue[i]); + dst[i*3+1] = FLOAT_TO_USHORT(green[i]); + dst[i*3+2] = FLOAT_TO_USHORT(red[i]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_USHORT(blue[i]); + dst[i*4+1] = FLOAT_TO_USHORT(green[i]); + dst[i*4+2] = FLOAT_TO_USHORT(red[i]); + dst[i*4+3] = FLOAT_TO_USHORT(alpha[i]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_USHORT(alpha[i]); + dst[i*4+1] = FLOAT_TO_USHORT(blue[i]); + dst[i*4+2] = FLOAT_TO_USHORT(green[i]); + dst[i*4+3] = FLOAT_TO_USHORT(red[i]); + } + break; + default: + gl_problem(ctx, "bad format in gl_pack_rgba_span\n"); + } + if (packing->SwapBytes) { + gl_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_SHORT: + { + GLshort *dst = (GLshort *) destination; + switch (format) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(red[i]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(green[i]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(blue[i]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(alpha[i]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_SHORT(luminance[i]); + dst[i*2+1] = FLOAT_TO_SHORT(alpha[i]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_SHORT(red[i]); + dst[i*3+1] = FLOAT_TO_SHORT(green[i]); + dst[i*3+2] = FLOAT_TO_SHORT(blue[i]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_SHORT(red[i]); + dst[i*4+1] = FLOAT_TO_SHORT(green[i]); + dst[i*4+2] = FLOAT_TO_SHORT(blue[i]); + dst[i*4+3] = FLOAT_TO_SHORT(alpha[i]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_SHORT(blue[i]); + dst[i*3+1] = FLOAT_TO_SHORT(green[i]); + dst[i*3+2] = FLOAT_TO_SHORT(red[i]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_SHORT(blue[i]); + dst[i*4+1] = FLOAT_TO_SHORT(green[i]); + dst[i*4+2] = FLOAT_TO_SHORT(red[i]); + dst[i*4+3] = FLOAT_TO_SHORT(alpha[i]); + } + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_SHORT(alpha[i]); + dst[i*4+1] = FLOAT_TO_SHORT(blue[i]); + dst[i*4+2] = FLOAT_TO_SHORT(green[i]); + dst[i*4+3] = FLOAT_TO_SHORT(red[i]); + } + break; + default: + gl_problem(ctx, "bad format in gl_pack_rgba_span\n"); + } + if (packing->SwapBytes) { + gl_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *dst = (GLuint *) destination; + switch (format) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(red[i]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(green[i]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(blue[i]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(alpha[i]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_UINT(luminance[i]); + dst[i*2+1] = FLOAT_TO_UINT(alpha[i]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UINT(red[i]); + dst[i*3+1] = FLOAT_TO_UINT(green[i]); + dst[i*3+2] = FLOAT_TO_UINT(blue[i]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UINT(red[i]); + dst[i*4+1] = FLOAT_TO_UINT(green[i]); + dst[i*4+2] = FLOAT_TO_UINT(blue[i]); + dst[i*4+3] = FLOAT_TO_UINT(alpha[i]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UINT(blue[i]); + dst[i*3+1] = FLOAT_TO_UINT(green[i]); + dst[i*3+2] = FLOAT_TO_UINT(red[i]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UINT(blue[i]); + dst[i*4+1] = FLOAT_TO_UINT(green[i]); + dst[i*4+2] = FLOAT_TO_UINT(red[i]); + dst[i*4+3] = FLOAT_TO_UINT(alpha[i]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UINT(alpha[i]); + dst[i*4+1] = FLOAT_TO_UINT(blue[i]); + dst[i*4+2] = FLOAT_TO_UINT(green[i]); + dst[i*4+3] = FLOAT_TO_UINT(red[i]); + } + break; + default: + gl_problem(ctx, "bad format in gl_pack_rgba_span\n"); + } + if (packing->SwapBytes) { + gl_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_INT: + { + GLint *dst = (GLint *) destination; + switch (format) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(red[i]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(green[i]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(blue[i]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(alpha[i]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_INT(luminance[i]); + dst[i*2+1] = FLOAT_TO_INT(alpha[i]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_INT(red[i]); + dst[i*3+1] = FLOAT_TO_INT(green[i]); + dst[i*3+2] = FLOAT_TO_INT(blue[i]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_INT(red[i]); + dst[i*4+1] = FLOAT_TO_INT(green[i]); + dst[i*4+2] = FLOAT_TO_INT(blue[i]); + dst[i*4+3] = FLOAT_TO_INT(alpha[i]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_INT(blue[i]); + dst[i*3+1] = FLOAT_TO_INT(green[i]); + dst[i*3+2] = FLOAT_TO_INT(red[i]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_INT(blue[i]); + dst[i*4+1] = FLOAT_TO_INT(green[i]); + dst[i*4+2] = FLOAT_TO_INT(red[i]); + dst[i*4+3] = FLOAT_TO_INT(alpha[i]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_INT(alpha[i]); + dst[i*4+1] = FLOAT_TO_INT(blue[i]); + dst[i*4+2] = FLOAT_TO_INT(green[i]); + dst[i*4+3] = FLOAT_TO_INT(red[i]); + } + break; + default: + gl_problem(ctx, "bad format in gl_pack_rgba_span\n"); + } + if (packing->SwapBytes) { + gl_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_FLOAT: + { + GLfloat *dst = (GLfloat *) destination; + switch (format) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = red[i]; + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = green[i]; + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = blue[i]; + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = alpha[i]; + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = luminance[i]; + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = luminance[i]; + dst[i*2+1] = alpha[i]; + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = red[i]; + dst[i*3+1] = green[i]; + dst[i*3+2] = blue[i]; + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = red[i]; + dst[i*4+1] = green[i]; + dst[i*4+2] = blue[i]; + dst[i*4+3] = alpha[i]; + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = blue[i]; + dst[i*3+1] = green[i]; + dst[i*3+2] = red[i]; + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = blue[i]; + dst[i*4+1] = green[i]; + dst[i*4+2] = red[i]; + dst[i*4+3] = alpha[i]; + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = alpha[i]; + dst[i*4+1] = blue[i]; + dst[i*4+2] = green[i]; + dst[i*4+3] = red[i]; + } + break; + default: + gl_problem(ctx, "bad format in gl_pack_rgba_span\n"); + } + if (packing->SwapBytes) { + gl_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_UNSIGNED_BYTE_3_3_2: + if (format == GL_RGB) { + GLubyte *dst = (GLubyte *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 7.0F)) << 5) + | (((GLint) (green[i] * 7.0F)) << 2) + | (((GLint) (blue[i] * 3.0F)) ); + } + } + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + if (format == GL_RGB) { + GLubyte *dst = (GLubyte *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 7.0F)) ) + | (((GLint) (green[i] * 7.0F)) << 3) + | (((GLint) (blue[i] * 3.0F)) << 5); + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 31.0F)) << 11) + | (((GLint) (green[i] * 63.0F)) << 5) + | (((GLint) (blue[i] * 31.0F)) ); + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 31.0F)) ) + | (((GLint) (green[i] * 63.0F)) << 5) + | (((GLint) (blue[i] * 31.0F)) << 11); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 15.0F)) << 12) + | (((GLint) (green[i] * 15.0F)) << 8) + | (((GLint) (blue[i] * 15.0F)) << 4) + | (((GLint) (alpha[i] * 15.0F)) ); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 15.0F)) ) + | (((GLint) (green[i] * 15.0F)) << 4) + | (((GLint) (blue[i] * 15.0F)) << 8) + | (((GLint) (alpha[i] * 15.0F)) << 12); + } + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 31.0F)) << 11) + | (((GLint) (green[i] * 31.0F)) << 6) + | (((GLint) (blue[i] * 31.0F)) << 1) + | (((GLint) (alpha[i] * 1.0F)) ); + } + } + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (red[i] * 31.0F)) ) + | (((GLint) (green[i] * 31.0F)) << 5) + | (((GLint) (blue[i] * 31.0F)) << 10) + | (((GLint) (alpha[i] * 1.0F)) << 15); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (red[i] * 255.0F)) << 24) + | (((GLuint) (green[i] * 255.0F)) << 16) + | (((GLuint) (blue[i] * 255.0F)) << 8) + | (((GLuint) (alpha[i] * 255.0F)) ); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (blue[i] * 255.0F)) << 24) + | (((GLuint) (green[i] * 255.0F)) << 16) + | (((GLuint) (red[i] * 255.0F)) << 8) + | (((GLuint) (alpha[i] * 255.0F)) ); + } + } + else if (format == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (alpha[i] * 255.0F)) << 24) + | (((GLuint) (blue[i] * 255.0F)) << 16) + | (((GLuint) (green[i] * 255.0F)) << 8) + | (((GLuint) (red[i] * 255.0F)) ); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (red[i] * 255.0F)) ) + | (((GLuint) (green[i] * 255.0F)) << 8) + | (((GLuint) (blue[i] * 255.0F)) << 16) + | (((GLuint) (alpha[i] * 255.0F)) << 24); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (blue[i] * 255.0F)) ) + | (((GLuint) (green[i] * 255.0F)) << 8) + | (((GLuint) (red[i] * 255.0F)) << 16) + | (((GLuint) (alpha[i] * 255.0F)) << 24); + } + } + else if (format == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (alpha[i] * 255.0F)) ) + | (((GLuint) (blue[i] * 255.0F)) << 8) + | (((GLuint) (green[i] * 255.0F)) << 16) + | (((GLuint) (red[i] * 255.0F)) << 24); + } + } + break; + case GL_UNSIGNED_INT_10_10_10_2: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (red[i] * 1023.0F)) << 22) + | (((GLuint) (green[i] * 1023.0F)) << 12) + | (((GLuint) (blue[i] * 1023.0F)) << 2) + | (((GLuint) (alpha[i] * 3.0F)) ); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (blue[i] * 1023.0F)) << 22) + | (((GLuint) (green[i] * 1023.0F)) << 12) + | (((GLuint) (red[i] * 1023.0F)) << 2) + | (((GLuint) (alpha[i] * 3.0F)) ); + } + } + else if (format == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (alpha[i] * 1023.0F)) << 22) + | (((GLuint) (blue[i] * 1023.0F)) << 12) + | (((GLuint) (green[i] * 1023.0F)) << 2) + | (((GLuint) (red[i] * 3.0F)) ); + } + } + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (red[i] * 1023.0F)) ) + | (((GLuint) (green[i] * 1023.0F)) << 10) + | (((GLuint) (blue[i] * 1023.0F)) << 20) + | (((GLuint) (alpha[i] * 3.0F)) << 30); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (blue[i] * 1023.0F)) ) + | (((GLuint) (green[i] * 1023.0F)) << 10) + | (((GLuint) (red[i] * 1023.0F)) << 20) + | (((GLuint) (alpha[i] * 3.0F)) << 30); + } + } + else if (format == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) destination; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (alpha[i] * 1023.0F)) ) + | (((GLuint) (blue[i] * 1023.0F)) << 10) + | (((GLuint) (green[i] * 1023.0F)) << 20) + | (((GLuint) (red[i] * 3.0F)) << 30); + } + } + break; + default: + gl_problem( ctx, "bad type in gl_pack_rgba_span" ); + } + } +} diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h new file mode 100644 index 00000000000..3fd2ca8b338 --- /dev/null +++ b/src/mesa/main/image.h @@ -0,0 +1,109 @@ +/* $Id: image.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 IMAGE_H +#define IMAGE_H + + +#include "types.h" + + +extern void gl_flip_bytes( GLubyte *p, GLuint n ); + + +extern void gl_swap2( GLushort *p, GLuint n ); + +extern void gl_swap4( GLuint *p, GLuint n ); + + +extern GLint gl_sizeof_type( GLenum type ); + +extern GLint gl_sizeof_packed_type( GLenum type ); + +extern GLint gl_components_in_format( GLenum format ); + +extern GLint gl_bytes_per_pixel( GLenum format, GLenum type ); + +extern GLboolean gl_is_legal_format_and_type( GLenum format, GLenum type ); + + +extern GLvoid * +gl_pixel_addr_in_image( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, GLsizei width, + GLsizei height, GLenum format, GLenum type, + GLint img, GLint row, GLint column ); + + +extern struct gl_image * +gl_unpack_bitmap( GLcontext *ctx, GLsizei width, GLsizei height, + const GLubyte *bitmap, + const struct gl_pixelstore_attrib *packing ); + + +extern void gl_unpack_polygon_stipple( const GLcontext *ctx, + const GLubyte *pattern, + GLuint dest[32] ); + + +extern void gl_pack_polygon_stipple( const GLcontext *ctx, + const GLuint pattern[32], + GLubyte *dest ); + + +extern struct gl_image * +gl_unpack_image( GLcontext *ctx, GLint width, GLint height, + GLenum srcFormat, GLenum srcType, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing ); + + + +struct gl_image * +gl_unpack_image3D( GLcontext *ctx, GLint width, GLint height,GLint depth, + GLenum srcFormat, GLenum srcType, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing ); + + +extern void +gl_pack_rgba_span( const GLcontext *ctx, + GLuint n, CONST GLubyte rgba[][4], + GLenum format, GLenum type, GLvoid *dest, + const struct gl_pixelstore_attrib *packing, + GLboolean applyTransferOps ); + + +extern void gl_free_image( struct gl_image *image ); + + +extern GLboolean gl_image_error_test( GLcontext *ctx, + const struct gl_image *image, + const char *msg ); + + +#endif diff --git a/src/mesa/main/light.c b/src/mesa/main/light.c new file mode 100644 index 00000000000..cc396f85a50 --- /dev/null +++ b/src/mesa/main/light.c @@ -0,0 +1,1183 @@ +/* $Id: light.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <float.h> +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include "context.h" +#include "enums.h" +#include "light.h" +#include "macros.h" +#include "matrix.h" +#include "mmath.h" +#include "simple_list.h" +#include "types.h" +#include "vb.h" +#include "xform.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +void gl_ShadeModel( GLcontext *ctx, GLenum mode ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glShadeModel"); + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode)); + + switch (mode) { + case GL_FLAT: + case GL_SMOOTH: + if (ctx->Light.ShadeModel!=mode) { + ctx->Light.ShadeModel = mode; + ctx->TriangleCaps ^= DD_FLATSHADE; + ctx->NewState |= NEW_RASTER_OPS; + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" ); + } + + if (ctx->Driver.ShadeModel) + (*ctx->Driver.ShadeModel)( ctx, mode ); +} + + + +void gl_Lightfv( GLcontext *ctx, + GLenum light, GLenum pname, const GLfloat *params, + GLint nparams ) +{ + GLint l; + + (void) nparams; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLight"); + + l = (GLint) (light - GL_LIGHT0); + + if (l<0 || l>=MAX_LIGHTS) { + gl_error( ctx, GL_INVALID_ENUM, "glLight" ); + return; + } + + switch (pname) { + case GL_AMBIENT: + COPY_4V( ctx->Light.Light[l].Ambient, params ); + break; + case GL_DIFFUSE: + COPY_4V( ctx->Light.Light[l].Diffuse, params ); + break; + case GL_SPECULAR: + COPY_4V( ctx->Light.Light[l].Specular, params ); + break; + case GL_POSITION: + /* transform position by ModelView matrix */ + TRANSFORM_POINT( ctx->Light.Light[l].EyePosition, + ctx->ModelView.m, + params ); + break; + case GL_SPOT_DIRECTION: + /* transform direction by inverse modelview */ + if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) { + gl_matrix_analyze( &ctx->ModelView ); + } + TRANSFORM_NORMAL( ctx->Light.Light[l].EyeDirection, + params, + ctx->ModelView.inv ); + break; + case GL_SPOT_EXPONENT: + if (params[0]<0.0 || params[0]>128.0) { + gl_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + if (ctx->Light.Light[l].SpotExponent != params[0]) { + ctx->Light.Light[l].SpotExponent = params[0]; + gl_compute_spot_exp_table( &ctx->Light.Light[l] ); + } + break; + case GL_SPOT_CUTOFF: + if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) { + gl_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + ctx->Light.Light[l].SpotCutoff = params[0]; + ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD); + if (ctx->Light.Light[l].CosCutoff < 0) + ctx->Light.Light[l].CosCutoff = 0; + break; + case GL_CONSTANT_ATTENUATION: + if (params[0]<0.0) { + gl_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + ctx->Light.Light[l].ConstantAttenuation = params[0]; + break; + case GL_LINEAR_ATTENUATION: + if (params[0]<0.0) { + gl_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + ctx->Light.Light[l].LinearAttenuation = params[0]; + break; + case GL_QUADRATIC_ATTENUATION: + if (params[0]<0.0) { + gl_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + ctx->Light.Light[l].QuadraticAttenuation = params[0]; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glLight" ); + break; + } + + ctx->NewState |= NEW_LIGHTING; +} + + + +void gl_GetLightfv( GLcontext *ctx, + GLenum light, GLenum pname, GLfloat *params ) +{ + GLint l = (GLint) (light - GL_LIGHT0); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight"); + + if (l<0 || l>=MAX_LIGHTS) { + gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); + return; + } + + switch (pname) { + case GL_AMBIENT: + COPY_4V( params, ctx->Light.Light[l].Ambient ); + break; + case GL_DIFFUSE: + COPY_4V( params, ctx->Light.Light[l].Diffuse ); + break; + case GL_SPECULAR: + COPY_4V( params, ctx->Light.Light[l].Specular ); + break; + case GL_POSITION: + COPY_4V( params, ctx->Light.Light[l].EyePosition ); + break; + case GL_SPOT_DIRECTION: + COPY_3V( params, ctx->Light.Light[l].EyeDirection ); + break; + case GL_SPOT_EXPONENT: + params[0] = ctx->Light.Light[l].SpotExponent; + break; + case GL_SPOT_CUTOFF: + params[0] = ctx->Light.Light[l].SpotCutoff; + break; + case GL_CONSTANT_ATTENUATION: + params[0] = ctx->Light.Light[l].ConstantAttenuation; + break; + case GL_LINEAR_ATTENUATION: + params[0] = ctx->Light.Light[l].LinearAttenuation; + break; + case GL_QUADRATIC_ATTENUATION: + params[0] = ctx->Light.Light[l].QuadraticAttenuation; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); + break; + } +} + + + +void gl_GetLightiv( GLcontext *ctx, GLenum light, GLenum pname, GLint *params ) +{ + GLint l = (GLint) (light - GL_LIGHT0); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight"); + + if (l<0 || l>=MAX_LIGHTS) { + gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); + return; + } + + switch (pname) { + case GL_AMBIENT: + params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]); + params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]); + params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]); + params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]); + break; + case GL_DIFFUSE: + params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]); + params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]); + params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]); + params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]); + break; + case GL_SPECULAR: + params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]); + params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]); + params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]); + params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]); + break; + case GL_POSITION: + params[0] = (GLint) ctx->Light.Light[l].EyePosition[0]; + params[1] = (GLint) ctx->Light.Light[l].EyePosition[1]; + params[2] = (GLint) ctx->Light.Light[l].EyePosition[2]; + params[3] = (GLint) ctx->Light.Light[l].EyePosition[3]; + break; + case GL_SPOT_DIRECTION: + params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0]; + params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1]; + params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2]; + break; + case GL_SPOT_EXPONENT: + params[0] = (GLint) ctx->Light.Light[l].SpotExponent; + break; + case GL_SPOT_CUTOFF: + params[0] = (GLint) ctx->Light.Light[l].SpotCutoff; + break; + case GL_CONSTANT_ATTENUATION: + params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation; + break; + case GL_LINEAR_ATTENUATION: + params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation; + break; + case GL_QUADRATIC_ATTENUATION: + params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); + break; + } +} + + + +/**********************************************************************/ +/*** Light Model ***/ +/**********************************************************************/ + + +void gl_LightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *params ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModel"); + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + COPY_4V( ctx->Light.Model.Ambient, params ); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + if (params[0]==0.0) + ctx->Light.Model.LocalViewer = GL_FALSE; + else + ctx->Light.Model.LocalViewer = GL_TRUE; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + if (params[0]==0.0) + ctx->Light.Model.TwoSide = GL_FALSE; + else + ctx->Light.Model.TwoSide = GL_TRUE; + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + ctx->TriangleCaps &= ~DD_SEPERATE_SPECULAR; + if (params[0] == (GLfloat) GL_SINGLE_COLOR) + ctx->Light.Model.ColorControl = GL_SINGLE_COLOR; + else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) { + ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR; + ctx->TriangleCaps |= DD_SEPERATE_SPECULAR; + } else + gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" ); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glLightModel" ); + break; + } + ctx->NewState |= NEW_LIGHTING; +} + + + + +/********** MATERIAL **********/ + + +/* + * Given a face and pname value (ala glColorMaterial), compute a bitmask + * of the targeted material values. + */ +GLuint gl_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname, + GLuint legal, + const char *where ) +{ + GLuint bitmask = 0; + + /* Make a bitmask indicating what material attribute(s) we're updating */ + switch (pname) { + case GL_EMISSION: + bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT; + break; + case GL_AMBIENT: + bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT; + break; + case GL_DIFFUSE: + bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT; + break; + case GL_SPECULAR: + bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT; + break; + case GL_SHININESS: + bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT; + break; + case GL_AMBIENT_AND_DIFFUSE: + bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT; + bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT; + break; + case GL_COLOR_INDEXES: + bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, where ); + return 0; + } + + if (face==GL_FRONT) { + bitmask &= FRONT_MATERIAL_BITS; + } + else if (face==GL_BACK) { + bitmask &= BACK_MATERIAL_BITS; + } + else if (face != GL_FRONT_AND_BACK) { + gl_error( ctx, GL_INVALID_ENUM, where ); + return 0; + } + + if (bitmask & ~legal) { + gl_error( ctx, GL_INVALID_ENUM, where ); + return 0; + } + + return bitmask; +} + + + + + + +/* + * Check if the global material has to be updated with info that was + * associated with a vertex via glMaterial. + * This function is used when any material values get changed between + * glBegin/glEnd either by calling glMaterial() or by calling glColor() + * when GL_COLOR_MATERIAL is enabled. + * + * KW: Added code here to keep the precomputed variables uptodate. + * This means we can use the faster shade functions when using + * GL_COLOR_MATERIAL, and we can also now use the precomputed + * values in the slower shading functions, which further offsets + * the cost of doing this here. + */ +void gl_update_material( GLcontext *ctx, + struct gl_material *src, + GLuint bitmask ) +{ + struct gl_light *light, *list = &ctx->Light.EnabledList; + GLfloat tmp[4]; + + if (ctx->Light.ColorMaterialEnabled) + bitmask &= ~ctx->Light.ColorMaterialBitmask; + + if (!bitmask) + return; + + if (bitmask & FRONT_AMBIENT_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, src[0].Ambient, mat->Ambient ); + ACC_SCALE_3V( ctx->Light.BaseColor[0], ctx->Light.Model.Ambient, tmp); + foreach (light, list) { + ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp ); + } + COPY_4FV( mat->Ambient, src[0].Ambient ); + } + if (bitmask & BACK_AMBIENT_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, src[1].Ambient, mat->Ambient ); + ACC_SCALE_3V( ctx->Light.BaseColor[1], ctx->Light.Model.Ambient, tmp); + foreach (light, list) { + ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp ); + } + COPY_4FV( mat->Ambient, src[1].Ambient ); + } + if (bitmask & FRONT_DIFFUSE_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, src[0].Diffuse, mat->Diffuse ); + foreach (light, list) { + ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp ); + } + COPY_4FV( mat->Diffuse, src[0].Diffuse ); + FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]); + } + if (bitmask & BACK_DIFFUSE_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, src[1].Diffuse, mat->Diffuse ); + foreach (light, list) { + ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp ); + } + COPY_4FV( mat->Diffuse, src[1].Diffuse ); + FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]); + } + if (bitmask & FRONT_SPECULAR_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, src[0].Specular, mat->Specular ); + foreach (light, list) { + if (light->Flags & LIGHT_SPECULAR) { + ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp ); + light->IsMatSpecular[0] = + (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16); + } + } + COPY_4FV( mat->Specular, src[0].Specular ); + } + if (bitmask & BACK_SPECULAR_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, src[1].Specular, mat->Specular ); + foreach (light, list) { + if (light->Flags & LIGHT_SPECULAR) { + ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp ); + light->IsMatSpecular[1] = + (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16); + } + } + COPY_4FV( mat->Specular, src[1].Specular ); + } + if (bitmask & FRONT_EMISSION_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, src[0].Emission, mat->Emission ); + ACC_3V( ctx->Light.BaseColor[0], tmp ); + COPY_4FV( mat->Emission, src[0].Emission ); + } + if (bitmask & BACK_EMISSION_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, src[1].Emission, mat->Emission ); + ACC_3V( ctx->Light.BaseColor[1], tmp ); + COPY_4FV( mat->Emission, src[1].Emission ); + } + if (bitmask & FRONT_SHININESS_BIT) { + GLfloat shininess = ctx->Light.Material[0].Shininess = src[0].Shininess; + gl_compute_shine_table( ctx, 0, shininess ); + gl_compute_shine_table( ctx, 2, shininess * .5 ); + } + if (bitmask & BACK_SHININESS_BIT) { + GLfloat shininess = ctx->Light.Material[1].Shininess = src[1].Shininess; + gl_compute_shine_table( ctx, 1, shininess ); + gl_compute_shine_table( ctx, 3, shininess * .5 ); + } + if (bitmask & FRONT_INDEXES_BIT) { + ctx->Light.Material[0].AmbientIndex = src[0].AmbientIndex; + ctx->Light.Material[0].DiffuseIndex = src[0].DiffuseIndex; + ctx->Light.Material[0].SpecularIndex = src[0].SpecularIndex; + } + if (bitmask & BACK_INDEXES_BIT) { + ctx->Light.Material[1].AmbientIndex = src[1].AmbientIndex; + ctx->Light.Material[1].DiffuseIndex = src[1].DiffuseIndex; + ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex; + } + +} + + + + + + +void gl_update_color_material( GLcontext *ctx, + const GLubyte rgba[4] ) +{ + struct gl_light *light, *list = &ctx->Light.EnabledList; + GLuint bitmask = ctx->Light.ColorMaterialBitmask; + GLfloat tmp[4], color[4]; + + UBYTE_RGBA_TO_FLOAT_RGBA( color, rgba ); + + if (bitmask & FRONT_AMBIENT_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, color, mat->Ambient ); + ACC_SCALE_3V( ctx->Light.BaseColor[0], ctx->Light.Model.Ambient, tmp); + foreach (light, list) { + ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp ); + } + COPY_4FV( mat->Ambient, color ); + } + + if (bitmask & BACK_AMBIENT_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, color, mat->Ambient ); + ACC_SCALE_3V( ctx->Light.BaseColor[1], ctx->Light.Model.Ambient, tmp); + foreach (light, list) { + ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp ); + } + COPY_4FV( mat->Ambient, color ); + } + + if (bitmask & FRONT_DIFFUSE_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, color, mat->Diffuse ); + foreach (light, list) { + ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp ); + } + COPY_4FV( mat->Diffuse, color ); + FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]); + } + + if (bitmask & BACK_DIFFUSE_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, color, mat->Diffuse ); + foreach (light, list) { + ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp ); + } + COPY_4FV( mat->Diffuse, color ); + FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]); + } + + if (bitmask & FRONT_SPECULAR_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, color, mat->Specular ); + foreach (light, list) { + if (light->Flags & LIGHT_SPECULAR) { + ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp ); + light->IsMatSpecular[0] = + (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16); + } + } + COPY_4FV( mat->Specular, color ); + } + if (bitmask & BACK_SPECULAR_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, color, mat->Specular ); + foreach (light, list) { + if (light->Flags & LIGHT_SPECULAR) { + ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp ); + light->IsMatSpecular[1] = + (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16); + } + } + COPY_4FV( mat->Specular, color ); + } + if (bitmask & FRONT_EMISSION_BIT) { + struct gl_material *mat = &ctx->Light.Material[0]; + SUB_3V( tmp, color, mat->Emission ); + ACC_3V( ctx->Light.BaseColor[0], tmp ); + COPY_4FV( mat->Emission, color ); + } + if (bitmask & BACK_EMISSION_BIT) { + struct gl_material *mat = &ctx->Light.Material[1]; + SUB_3V( tmp, color, mat->Emission ); + ACC_3V( ctx->Light.BaseColor[1], tmp ); + COPY_4FV( mat->Emission, color ); + } +} + + + + +void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ) +{ + GLuint bitmask; + GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT | + FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT | + FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT | + FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial"); + + bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" ); + + if (bitmask != 0) { + ctx->Light.ColorMaterialBitmask = bitmask; + ctx->Light.ColorMaterialFace = face; + ctx->Light.ColorMaterialMode = mode; + } +} + + + +/* KW: This is now called directly (ie by name) from the glMaterial* + * API functions. + */ +void gl_Materialfv( GLcontext *ctx, + GLenum face, GLenum pname, const GLfloat *params ) +{ + struct immediate *IM; + struct gl_material *mat; + GLuint bitmask; + GLuint count; + + bitmask = gl_material_bitmask( ctx, face, pname, ~0, "gl_Materialfv" ); + if (bitmask == 0) + return; + + IM = ctx->input; + count = IM->Count; + + if (!(IM->Flag[count] & VERT_MATERIAL)) { + IM->Flag[count] |= VERT_MATERIAL; + IM->MaterialMask[count] = 0; + } + + IM->MaterialMask[count] |= bitmask; + mat = IM->Material[count]; + IM->LastMaterial = count; + + if (bitmask & FRONT_AMBIENT_BIT) { + COPY_4FV( mat[0].Ambient, params ); + } + if (bitmask & BACK_AMBIENT_BIT) { + COPY_4FV( mat[1].Ambient, params ); + } + if (bitmask & FRONT_DIFFUSE_BIT) { + COPY_4FV( mat[0].Diffuse, params ); + } + if (bitmask & BACK_DIFFUSE_BIT) { + COPY_4FV( mat[1].Diffuse, params ); + } + if (bitmask & FRONT_SPECULAR_BIT) { + COPY_4FV( mat[0].Specular, params ); + } + if (bitmask & BACK_SPECULAR_BIT) { + COPY_4FV( mat[1].Specular, params ); + } + if (bitmask & FRONT_EMISSION_BIT) { + COPY_4FV( mat[0].Emission, params ); + } + if (bitmask & BACK_EMISSION_BIT) { + COPY_4FV( mat[1].Emission, params ); + } + if (bitmask & FRONT_SHININESS_BIT) { + GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F ); + mat[0].Shininess = shininess; + } + if (bitmask & BACK_SHININESS_BIT) { + GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F ); + mat[1].Shininess = shininess; + } + if (bitmask & FRONT_INDEXES_BIT) { + mat[0].AmbientIndex = params[0]; + mat[0].DiffuseIndex = params[1]; + mat[0].SpecularIndex = params[2]; + } + if (bitmask & BACK_INDEXES_BIT) { + mat[1].AmbientIndex = params[0]; + mat[1].DiffuseIndex = params[1]; + mat[1].SpecularIndex = params[2]; + } +} + + + + +void gl_GetMaterialfv( GLcontext *ctx, + GLenum face, GLenum pname, GLfloat *params ) +{ + GLuint f; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv"); + + if (face==GL_FRONT) { + f = 0; + } + else if (face==GL_BACK) { + f = 1; + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" ); + return; + } + switch (pname) { + case GL_AMBIENT: + COPY_4FV( params, ctx->Light.Material[f].Ambient ); + break; + case GL_DIFFUSE: + COPY_4FV( params, ctx->Light.Material[f].Diffuse ); + break; + case GL_SPECULAR: + COPY_4FV( params, ctx->Light.Material[f].Specular ); + break; + case GL_EMISSION: + COPY_4FV( params, ctx->Light.Material[f].Emission ); + break; + case GL_SHININESS: + *params = ctx->Light.Material[f].Shininess; + break; + case GL_COLOR_INDEXES: + params[0] = ctx->Light.Material[f].AmbientIndex; + params[1] = ctx->Light.Material[f].DiffuseIndex; + params[2] = ctx->Light.Material[f].SpecularIndex; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); + } +} + + + +void gl_GetMaterialiv( GLcontext *ctx, + GLenum face, GLenum pname, GLint *params ) +{ + GLuint f; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv"); + + if (face==GL_FRONT) { + f = 0; + } + else if (face==GL_BACK) { + f = 1; + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" ); + return; + } + switch (pname) { + case GL_AMBIENT: + params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] ); + params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] ); + params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] ); + params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] ); + break; + case GL_DIFFUSE: + params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] ); + params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] ); + params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] ); + params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] ); + break; + case GL_SPECULAR: + params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] ); + params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] ); + params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] ); + params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] ); + break; + case GL_EMISSION: + params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] ); + params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] ); + params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] ); + params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] ); + break; + case GL_SHININESS: + *params = ROUNDF( ctx->Light.Material[f].Shininess ); + break; + case GL_COLOR_INDEXES: + params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex ); + params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex ); + params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex ); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); + } +} + + + + +/**********************************************************************/ +/***** Lighting computation *****/ +/**********************************************************************/ + + +/* + * Notes: + * When two-sided lighting is enabled we compute the color (or index) + * for both the front and back side of the primitive. Then, when the + * orientation of the facet is later learned, we can determine which + * color (or index) to use for rendering. + * + * KW: We now know orientation in advance and only shade for + * the side or sides which are actually required. + * + * Variables: + * n = normal vector + * V = vertex position + * P = light source position + * Pe = (0,0,0,1) + * + * Precomputed: + * IF P[3]==0 THEN + * // light at infinity + * IF local_viewer THEN + * VP_inf_norm = unit vector from V to P // Precompute + * ELSE + * // eye at infinity + * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute + * ENDIF + * ENDIF + * + * Functions: + * Normalize( v ) = normalized vector v + * Magnitude( v ) = length of vector v + */ + + + +/* + * Whenever the spotlight exponent for a light changes we must call + * this function to recompute the exponent lookup table. + */ +void gl_compute_spot_exp_table( struct gl_light *l ) +{ + int i; + double exponent = l->SpotExponent; + double tmp = 0; + int clamp = 0; + + l->SpotExpTable[0][0] = 0.0; + + for (i=EXP_TABLE_SIZE-1;i>0;i--) { + if (clamp == 0) { + tmp = pow(i/(double)(EXP_TABLE_SIZE-1), exponent); + if (tmp < FLT_MIN*100.0) { + tmp = 0.0; + clamp = 1; + } + } + l->SpotExpTable[i][0] = tmp; + } + for (i=0;i<EXP_TABLE_SIZE-1;i++) { + l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0]; + } + l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0; +} + + + + +/* Calculate a new shine table. Doing this here saves a branch in + * lighting, and the cost of doing it early may be partially offset + * by keeping a MRU cache of shine tables for various shine values. + */ +static void compute_shine_table( struct gl_shine_tab *tab, GLfloat shininess ) +{ + int i; + GLfloat *m = tab->tab; + + m[0] = 0; + if (shininess == 0) { + for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++) + m[i] = 1; + } else { + for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++) { + double t = pow( i/(GLfloat)SHINE_TABLE_SIZE, shininess ); + m[i] = 0; + if (t > 1e-20) m[i] = t; + } + } + + tab->shininess = shininess; +} + +#define DISTSQR(a,b) ((a-b)*(a-b)) + +void gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess ) +{ + struct gl_shine_tab *list = ctx->ShineTabList; + struct gl_shine_tab *s; + + foreach(s, list) + if ( DISTSQR(s->shininess, shininess) < 1e-4 ) + break; + + if (s == list) + { + foreach(s, list) + if (s->refcount == 0) break; + + compute_shine_table( s, shininess ); + } + + ctx->ShineTable[i]->refcount--; + ctx->ShineTable[i] = s; + move_to_tail( list, s ); + s->refcount++; +} + + + + +void gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l ) +{ + GLuint i; + + if (ctx->ShineTable[0]->shininess != l->Material[0].Shininess) { + gl_compute_shine_table( ctx, 0, l->Material[0].Shininess ); + gl_compute_shine_table( ctx, 2, l->Material[0].Shininess * .5 ); + } + + if (ctx->ShineTable[1]->shininess != l->Material[1].Shininess) { + gl_compute_shine_table( ctx, 1, l->Material[1].Shininess ); + gl_compute_shine_table( ctx, 3, l->Material[1].Shininess * .5 ); + } + + make_empty_list( &l->EnabledList ); + for (i = 0 ; i < MAX_LIGHTS ; i++) { + if (l->Light[i].Enabled) + insert_at_tail( &l->EnabledList, &l->Light[i] ); + } +} + + + +/* + * Examine current lighting parameters to determine if the optimized lighting + * function can be used. + * Also, precompute some lighting values such as the products of light + * source and material ambient, diffuse and specular coefficients. + */ +void gl_update_lighting( GLcontext *ctx ) +{ + struct gl_light *light; + + ctx->Light.Flags = 0; + + foreach(light, &ctx->Light.EnabledList) { + + light->Flags = 0; + + if (light->EyePosition[3] != 0.0F) + light->Flags |= LIGHT_POSITIONAL; + + if (LEN_SQUARED_3FV(light->Specular) > 1e-16) + light->Flags |= LIGHT_SPECULAR; + + if (light->SpotCutoff != 180.0F) + light->Flags |= LIGHT_SPOT; + + ctx->Light.Flags |= light->Flags; + } + + ctx->Light.NeedVertices = + ((ctx->Light.Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) || + (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) || + (ctx->Light.Model.LocalViewer && (ctx->Light.Flags & LIGHT_SPECULAR))); + + + /* Precompute some shading values. + */ + if (ctx->Visual->RGBAflag) + { + GLuint sides = ((ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) ? 2 : 1); + GLuint side; + for (side=0; side < sides; side++) { + struct gl_material *mat = &ctx->Light.Material[side]; + + COPY_3V(ctx->Light.BaseColor[side], mat->Emission); + ACC_SCALE_3V(ctx->Light.BaseColor[side], + ctx->Light.Model.Ambient, + mat->Ambient); + + FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[side], + ctx->Light.Material[side].Diffuse[3] ); + } + + foreach (light, &ctx->Light.EnabledList) { + for (side=0; side< sides; side++) { + struct gl_material *mat = &ctx->Light.Material[side]; + SCALE_3V( light->MatDiffuse[side], light->Diffuse, mat->Diffuse ); + SCALE_3V( light->MatAmbient[side], light->Ambient, mat->Ambient ); + ACC_3V( ctx->Light.BaseColor[side], light->MatAmbient[side] ); + if (light->Flags & LIGHT_SPECULAR) + { + SCALE_3V( light->MatSpecular[side], light->Specular, + mat->Specular); + light->IsMatSpecular[side] = + (LEN_SQUARED_3FV(light->MatSpecular[side]) > 1e-16); + } + else + light->IsMatSpecular[side] = 0; + } + } + } + else + { + static GLfloat ci[3] = { .30, .59, .11 }; + + foreach(light, &ctx->Light.EnabledList) { + light->dli = DOT3(ci, light->Diffuse); + light->sli = DOT3(ci, light->Specular); + } + } +} + +/* Need to seriously restrict the circumstances under which these + * calc's are performed. + */ +void gl_compute_light_positions( GLcontext *ctx ) +{ + struct gl_light *light; + + if (ctx->Light.NeedVertices && !ctx->Light.Model.LocalViewer) { + GLfloat eye_z[3] = { 0, 0, 1 }; + if (!ctx->NeedEyeCoords) { + TRANSFORM_NORMAL( ctx->EyeZDir, eye_z, ctx->ModelView.m ); + } else { + COPY_3V( ctx->EyeZDir, eye_z ); + } + } + + foreach (light, &ctx->Light.EnabledList) { + + if (!ctx->NeedEyeCoords) { + TRANSFORM_POINT( light->Position, ctx->ModelView.inv, + light->EyePosition ); + } else { + COPY_4FV( light->Position, light->EyePosition ); + } + + if (!(light->Flags & LIGHT_POSITIONAL)) + { + /* VP (VP) = Normalize( Position ) */ + COPY_3V( light->VP_inf_norm, light->Position ); + NORMALIZE_3FV( light->VP_inf_norm ); + + if (!ctx->Light.Model.LocalViewer) + { + /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */ + ADD_3V( light->h_inf_norm, light->VP_inf_norm, ctx->EyeZDir); + NORMALIZE_3FV( light->h_inf_norm ); + } + + light->VP_inf_spot_attenuation = 1.0; + } + + if (light->Flags & LIGHT_SPOT) + { + if (ctx->NeedEyeNormals) { + COPY_3V( light->NormDirection, light->EyeDirection ); + } else { + TRANSFORM_NORMAL( light->NormDirection, + light->EyeDirection, + ctx->ModelView.m); + } + + NORMALIZE_3FV( light->NormDirection ); + + + /* Unlikely occurrance? + */ + if (!(light->Flags & LIGHT_POSITIONAL)) { + GLfloat PV_dot_dir = - DOT3(light->VP_inf_norm, + light->NormDirection); + + if (PV_dot_dir > light->CosCutoff) { + double x = PV_dot_dir * (EXP_TABLE_SIZE-1); + int k = (int) x; + light->VP_inf_spot_attenuation = + (light->SpotExpTable[k][0] + + (x-k)*light->SpotExpTable[k][1]); + } + else + light->VP_inf_spot_attenuation = 0; + } + } + } +} + + + + + +void gl_update_normal_transform( GLcontext *ctx ) +{ + GLuint new_flag = 0; + normal_func *last = ctx->NormalTransform; + + ctx->vb_rescale_factor = 1.0; + + if (ctx->NeedEyeCoords) { + if (ctx->NeedNormals) { + GLuint transform = NORM_TRANSFORM_NO_ROT; + + if (ctx->ModelView.flags & (MAT_FLAG_GENERAL | + MAT_FLAG_ROTATION | + MAT_FLAG_GENERAL_3D | + MAT_FLAG_PERSPECTIVE)) + transform = NORM_TRANSFORM; + + + new_flag = ctx->NewState & NEW_MODELVIEW; + ctx->vb_rescale_factor = ctx->rescale_factor; + + if (ctx->Transform.Normalize) + { + ctx->NormalTransform = gl_normal_tab[transform | NORM_NORMALIZE]; + } + else if (ctx->Transform.RescaleNormals && + ctx->rescale_factor != 1.0) + { + ctx->NormalTransform = gl_normal_tab[transform | NORM_RESCALE]; + } + else + { + ctx->NormalTransform = gl_normal_tab[transform]; + } + } else { + ctx->NormalTransform = 0; + } + } + else { + if (ctx->NeedNormals) { + ctx->vb_rescale_factor = 1.0/ctx->rescale_factor; + + if (ctx->Transform.Normalize) + { + ctx->NormalTransform = gl_normal_tab[NORM_NORMALIZE]; + } + else if (!ctx->Transform.RescaleNormals && + ctx->rescale_factor != 1.0) + { + ctx->NormalTransform = gl_normal_tab[NORM_RESCALE]; + } + else + { + ctx->NormalTransform = 0; + } + } else { + ctx->NormalTransform = 0; + } + } + + if (last != ctx->NormalTransform || new_flag) + ctx->NewState |= NEW_NORMAL_TRANSFORM; +} + diff --git a/src/mesa/main/light.h b/src/mesa/main/light.h new file mode 100644 index 00000000000..18d25e9828f --- /dev/null +++ b/src/mesa/main/light.h @@ -0,0 +1,103 @@ +/* $Id: light.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 LIGHT_H +#define LIGHT_H + + +#include "types.h" + +struct gl_shine_tab { + struct gl_shine_tab *next, *prev; + GLfloat tab[SHINE_TABLE_SIZE+1]; + GLfloat shininess; + GLuint refcount; +}; + + +extern void gl_ShadeModel( GLcontext *ctx, GLenum mode ); + +extern void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ); + +extern void gl_Lightfv( GLcontext *ctx, + GLenum light, GLenum pname, const GLfloat *params, + GLint nparams ); + +extern void gl_LightModelfv( GLcontext *ctx, + GLenum pname, const GLfloat *params ); + + +extern GLuint gl_material_bitmask( GLcontext *ctx, + GLenum face, GLenum pname, + GLuint legal, + const char * ); + +extern void gl_set_material( GLcontext *ctx, GLuint bitmask, + const GLfloat *params); + +extern void gl_Materialfv( GLcontext *ctx, + GLenum face, GLenum pname, const GLfloat *params ); + + + +extern void gl_GetLightfv( GLcontext *ctx, + GLenum light, GLenum pname, GLfloat *params ); + +extern void gl_GetLightiv( GLcontext *ctx, + GLenum light, GLenum pname, GLint *params ); + + +extern void gl_GetMaterialfv( GLcontext *ctx, + GLenum face, GLenum pname, GLfloat *params ); + +extern void gl_GetMaterialiv( GLcontext *ctx, + GLenum face, GLenum pname, GLint *params ); + + +extern void gl_compute_spot_exp_table( struct gl_light *l ); + +extern void gl_compute_shine_table( GLcontext *ctx, GLuint i, + GLfloat shininess ); + +extern void gl_update_lighting( GLcontext *ctx ); + +extern void gl_compute_light_positions( GLcontext *ctx ); + +extern void gl_update_normal_transform( GLcontext *ctx ); + +extern void gl_update_material( GLcontext *ctx, + struct gl_material *m, + GLuint bitmask ); + +extern void gl_update_color_material( GLcontext *ctx, const GLubyte rgba[4] ); + + +#endif + diff --git a/src/mesa/main/lines.c b/src/mesa/main/lines.c new file mode 100644 index 00000000000..ed671d7a829 --- /dev/null +++ b/src/mesa/main/lines.c @@ -0,0 +1,1146 @@ +/* $Id: lines.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include "context.h" +#include "depth.h" +#include "feedback.h" +#include "lines.h" +#include "macros.h" +#include "mmath.h" +#include "pb.h" +#include "texstate.h" +#include "types.h" +#include "vb.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +void gl_LineWidth( GLcontext *ctx, GLfloat width ) +{ + if (width<=0.0) { + gl_error( ctx, GL_INVALID_VALUE, "glLineWidth" ); + return; + } + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLineWidth"); + + if (ctx->Line.Width != width) { + ctx->Line.Width = width; + ctx->TriangleCaps &= ~DD_LINE_WIDTH; + if (width != 1.0) ctx->TriangleCaps |= DD_LINE_WIDTH; + ctx->NewState |= NEW_RASTER_OPS; + } +} + + + +void gl_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLineStipple"); + ctx->Line.StippleFactor = CLAMP( factor, 1, 256 ); + ctx->Line.StipplePattern = pattern; + ctx->NewState |= NEW_RASTER_OPS; +} + + + +/**********************************************************************/ +/***** Rasterization *****/ +/**********************************************************************/ + + +/* + * There are 4 pairs (RGBA, CI) of line drawing functions: + * 1. simple: width=1 and no special rasterization functions (fastest) + * 2. flat: width=1, non-stippled, flat-shaded, any raster operations + * 3. smooth: width=1, non-stippled, smooth-shaded, any raster operations + * 4. general: any other kind of line (slowest) + */ + + +/* + * All line drawing functions have the same arguments: + * v1, v2 - indexes of first and second endpoints into vertex buffer arrays + * pv - provoking vertex: which vertex color/index to use for flat shading. + */ + + + +static void feedback_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ) +{ + struct vertex_buffer *VB = ctx->VB; + GLfloat x1, y1, z1, w1; + GLfloat x2, y2, z2, w2; + GLfloat tex1[4], tex2[4], invq; + GLuint texUnit = ctx->Texture.CurrentTransformUnit; + + x1 = VB->Win.data[v1][0]; + y1 = VB->Win.data[v1][1]; + z1 = VB->Win.data[v1][2] / DEPTH_SCALE; + w1 = (VB->ClipPtr->size == 4 ? VEC_ELT(VB->ClipPtr, GLfloat, v1)[3] : 1.0); + + x2 = VB->Win.data[v2][0]; + y2 = VB->Win.data[v2][1]; + z2 = VB->Win.data[v2][2] / DEPTH_SCALE; + w2 = (VB->ClipPtr->size == 4 ? VEC_ELT(VB->ClipPtr, GLfloat, v2)[3] : 1.0); + + + if (VB->TexCoordPtr[texUnit]->size == 4) { + invq = (VB->TexCoordPtr[texUnit]->data[v1][3]==0.0 + ? 1.0 + : 1.0F / VB->TexCoordPtr[texUnit]->data[v1][3]); + + tex1[0] = VB->TexCoordPtr[texUnit]->data[v1][0] * invq; + tex1[1] = VB->TexCoordPtr[texUnit]->data[v1][1] * invq; + tex1[2] = VB->TexCoordPtr[texUnit]->data[v1][2] * invq; + tex1[3] = VB->TexCoordPtr[texUnit]->data[v1][3]; + + invq = (VB->TexCoordPtr[texUnit]->data[v2][3]==0.0 + ? 1.0 + : 1.0F / VB->TexCoordPtr[texUnit]->data[v2][3]); + + tex2[0] = VB->TexCoordPtr[texUnit]->data[v2][0] * invq; + tex2[1] = VB->TexCoordPtr[texUnit]->data[v2][1] * invq; + tex2[2] = VB->TexCoordPtr[texUnit]->data[v2][2] * invq; + tex2[3] = VB->TexCoordPtr[texUnit]->data[v2][3]; + } else { + ASSIGN_4V(tex1, 0,0,0,1); + ASSIGN_4V(tex2, 0,0,0,1); + COPY_SZ_4V(tex1, + VB->TexCoordPtr[texUnit]->size, + VB->TexCoordPtr[texUnit]->data[v1]); + COPY_SZ_4V(tex2, + VB->TexCoordPtr[texUnit]->size, + VB->TexCoordPtr[texUnit]->data[v2]); + } + + + if (ctx->StippleCounter==0) { + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_LINE_RESET_TOKEN ); + } + else { + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_LINE_TOKEN ); + } + + { + GLfloat color[4]; + GLubyte *ubc = VB->ColorPtr->data[pv]; + GLuint index = VB->IndexPtr->data[pv]; + + UBYTE_RGBA_TO_FLOAT_RGBA( color, ubc ); + gl_feedback_vertex( ctx, x1,y1,z1,w1, color, (GLfloat) index, tex1 ); + gl_feedback_vertex( ctx, x2,y2,z2,w2, color, (GLfloat) index, tex2 ); + } + + ctx->StippleCounter++; +} + + + +static void select_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ) +{ + (void) pv; + gl_update_hitflag( ctx, ctx->VB->Win.data[v1][2] / DEPTH_SCALE ); + gl_update_hitflag( ctx, ctx->VB->Win.data[v2][2] / DEPTH_SCALE ); +} + + + +#if MAX_WIDTH > MAX_HEIGHT +# define MAXPOINTS MAX_WIDTH +#else +# define MAXPOINTS MAX_HEIGHT +#endif + + +/* Flat, color index line */ +static void flat_ci_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + PB_SET_INDEX( ctx, ctx->PB, ctx->VB->IndexPtr->data[pvert] ); + count = ctx->PB->count; + +#define INTERP_XY 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Flat, color index line with Z interpolation/testing */ +static void flat_ci_z_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + PB_SET_INDEX( ctx, ctx->PB, ctx->VB->IndexPtr->data[pvert] ); + count = ctx->PB->count; + +#define INTERP_XY 1 +#define INTERP_Z 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Flat-shaded, RGBA line */ +static void flat_rgba_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLubyte *color = ctx->VB->ColorPtr->data[pvert]; + PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] ); + count = ctx->PB->count; + +#define INTERP_XY 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Flat-shaded, RGBA line with Z interpolation/testing */ +static void flat_rgba_z_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLubyte *color = ctx->VB->ColorPtr->data[pvert]; + PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] ); + count = ctx->PB->count; + +#define INTERP_XY 1 +#define INTERP_Z 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Smooth shaded, color index line */ +static void smooth_ci_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLuint *pbi = ctx->PB->i; + (void) pvert; + +#define INTERP_XY 1 +#define INTERP_INDEX 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbi[count] = I; \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Smooth shaded, color index line with Z interpolation/testing */ +static void smooth_ci_z_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLuint *pbi = ctx->PB->i; + (void) pvert; + +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_INDEX 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbi[count] = I; \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Smooth-shaded, RGBA line */ +static void smooth_rgba_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLubyte (*pbrgba)[4] = ctx->PB->rgba; + (void) pvert; + +#define INTERP_XY 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Smooth-shaded, RGBA line with Z interpolation/testing */ +static void smooth_rgba_z_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLubyte (*pbrgba)[4] = ctx->PB->rgba; + (void) pvert; + +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 + +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + count++; + +#include "linetemp.h" + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + +#define CHECK_FULL(count) \ + if (count >= PB_SIZE-MAX_WIDTH) { \ + ctx->PB->count = count; \ + gl_flush_pb(ctx); \ + count = ctx->PB->count; \ + } + + + +/* Smooth shaded, color index, any width, maybe stippled */ +static void general_smooth_ci_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLuint *pbi = ctx->PB->i; + (void) pvert; + + if (ctx->Line.StippleFlag) { + /* stippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_INDEX 1 +#define WIDE 1 +#define STIPPLE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbi[count] = I; \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled */ + if (ctx->Line.Width==2.0F) { + /* special case: unstippled and width=2 */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_INDEX 1 +#define XMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X; \ + pby[count] = Y; pby[count+1] = Y+1; \ + pbz[count] = Z; pbz[count+1] = Z; \ + pbi[count] = I; pbi[count+1] = I; \ + count += 2; \ + CHECK_FULL(count); +#define YMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X+1; \ + pby[count] = Y; pby[count+1] = Y; \ + pbz[count] = Z; pbz[count+1] = Z; \ + pbi[count] = I; pbi[count+1] = I; \ + count += 2; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled, any width */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_INDEX 1 +#define WIDE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbi[count] = I; \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + } + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + +/* Flat shaded, color index, any width, maybe stippled */ +static void general_flat_ci_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + PB_SET_INDEX( ctx, ctx->PB, ctx->VB->IndexPtr->data[pvert] ); + count = ctx->PB->count; + + if (ctx->Line.StippleFlag) { + /* stippled, any width */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define WIDE 1 +#define STIPPLE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled */ + if (ctx->Line.Width==2.0F) { + /* special case: unstippled and width=2 */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define XMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X; \ + pby[count] = Y; pby[count+1] = Y+1; \ + pbz[count] = Z; pbz[count+1] = Z; \ + count += 2; \ + CHECK_FULL(count); +#define YMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X+1; \ + pby[count] = Y; pby[count+1] = Y; \ + pbz[count] = Z; pbz[count+1] = Z; \ + count += 2; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled, any width */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define WIDE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + } + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +static void general_smooth_rgba_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLubyte (*pbrgba)[4] = ctx->PB->rgba; + (void) pvert; + + if (ctx->Line.StippleFlag) { + /* stippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 +#define WIDE 1 +#define STIPPLE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled */ + if (ctx->Line.Width==2.0F) { + /* special case: unstippled and width=2 */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 +#define XMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X; \ + pby[count] = Y; pby[count+1] = Y+1; \ + pbz[count] = Z; pbz[count+1] = Z; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + pbrgba[count+1][RCOMP] = FixedToInt(r0); \ + pbrgba[count+1][GCOMP] = FixedToInt(g0); \ + pbrgba[count+1][BCOMP] = FixedToInt(b0); \ + pbrgba[count+1][ACOMP] = FixedToInt(a0); \ + count += 2; \ + CHECK_FULL(count); +#define YMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X+1; \ + pby[count] = Y; pby[count+1] = Y; \ + pbz[count] = Z; pbz[count+1] = Z; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + pbrgba[count+1][RCOMP] = FixedToInt(r0); \ + pbrgba[count+1][GCOMP] = FixedToInt(g0); \ + pbrgba[count+1][BCOMP] = FixedToInt(b0); \ + pbrgba[count+1][ACOMP] = FixedToInt(a0); \ + count += 2; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled, any width */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 +#define WIDE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + } + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + +static void general_flat_rgba_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLubyte *color = ctx->VB->ColorPtr->data[pvert]; + PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] ); + count = ctx->PB->count; + + if (ctx->Line.StippleFlag) { + /* stippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define WIDE 1 +#define STIPPLE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled */ + if (ctx->Line.Width==2.0F) { + /* special case: unstippled and width=2 */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define XMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X; \ + pby[count] = Y; pby[count+1] = Y+1; \ + pbz[count] = Z; pbz[count+1] = Z; \ + count += 2; \ + CHECK_FULL(count); +#define YMAJOR_PLOT(X,Y) \ + pbx[count] = X; pbx[count+1] = X+1; \ + pby[count] = Y; pby[count+1] = Y; \ + pbz[count] = Z; pbz[count+1] = Z; \ + count += 2; \ + CHECK_FULL(count); +#include "linetemp.h" + } + else { + /* unstippled, any width */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define WIDE 1 +#define PLOT(X,Y) \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + count++; \ + CHECK_FULL(count); +#include "linetemp.h" + } + } + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + +/* Flat-shaded, textured, any width, maybe stippled */ +static void flat_textured_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pv ) +{ + GLint count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLfloat *pbs = ctx->PB->s[0]; + GLfloat *pbt = ctx->PB->t[0]; + GLfloat *pbu = ctx->PB->u[0]; + GLubyte *color = ctx->VB->ColorPtr->data[pv]; + PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] ); + count = ctx->PB->count; + + if (ctx->Line.StippleFlag) { + /* stippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_STUV0 1 +#define WIDE 1 +#define STIPPLE 1 +#define PLOT(X,Y) \ + { \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbs[count] = s; \ + pbt[count] = t; \ + pbu[count] = u; \ + count++; \ + CHECK_FULL(count); \ + } +#include "linetemp.h" + } + else { + /* unstippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_STUV0 1 +#define WIDE 1 +#define PLOT(X,Y) \ + { \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbs[count] = s; \ + pbt[count] = t; \ + pbu[count] = u; \ + count++; \ + CHECK_FULL(count); \ + } +#include "linetemp.h" + } + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + + +/* Smooth-shaded, textured, any width, maybe stippled */ +static void smooth_textured_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLfloat *pbs = ctx->PB->s[0]; + GLfloat *pbt = ctx->PB->t[0]; + GLfloat *pbu = ctx->PB->u[0]; + GLubyte (*pbrgba)[4] = ctx->PB->rgba; + (void) pvert; + + if (ctx->Line.StippleFlag) { + /* stippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 +#define INTERP_STUV0 1 +#define WIDE 1 +#define STIPPLE 1 +#define PLOT(X,Y) \ + { \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbs[count] = s; \ + pbt[count] = t; \ + pbu[count] = u; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + count++; \ + CHECK_FULL(count); \ + } +#include "linetemp.h" + } + else { + /* unstippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 +#define INTERP_STUV0 1 +#define WIDE 1 +#define PLOT(X,Y) \ + { \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbs[count] = s; \ + pbt[count] = t; \ + pbu[count] = u; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + count++; \ + CHECK_FULL(count); \ + } +#include "linetemp.h" + } + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + +/* Smooth-shaded, multitextured, any width, maybe stippled, separate specular + * color interpolation. + */ +static void smooth_multitextured_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ + GLint count = ctx->PB->count; + GLint *pbx = ctx->PB->x; + GLint *pby = ctx->PB->y; + GLdepth *pbz = ctx->PB->z; + GLfloat *pbs = ctx->PB->s[0]; + GLfloat *pbt = ctx->PB->t[0]; + GLfloat *pbu = ctx->PB->u[0]; + GLfloat *pbs1 = ctx->PB->s[1]; + GLfloat *pbt1 = ctx->PB->t[1]; + GLfloat *pbu1 = ctx->PB->u[1]; + GLubyte (*pbrgba)[4] = ctx->PB->rgba; + GLubyte (*pbspec)[3] = ctx->PB->spec; + (void) pvert; + + if (ctx->Line.StippleFlag) { + /* stippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_SPEC 1 +#define INTERP_ALPHA 1 +#define INTERP_STUV0 1 +#define INTERP_STUV1 1 +#define WIDE 1 +#define STIPPLE 1 +#define PLOT(X,Y) \ + { \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbs[count] = s; \ + pbt[count] = t; \ + pbu[count] = u; \ + pbs1[count] = s1; \ + pbt1[count] = t1; \ + pbu1[count] = u1; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + pbspec[count][RCOMP] = FixedToInt(sr0); \ + pbspec[count][GCOMP] = FixedToInt(sg0); \ + pbspec[count][BCOMP] = FixedToInt(sb0); \ + count++; \ + CHECK_FULL(count); \ + } +#include "linetemp.h" + } + else { + /* unstippled */ +#define INTERP_XY 1 +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_SPEC 1 +#define INTERP_ALPHA 1 +#define INTERP_STUV0 1 +#define INTERP_STUV1 1 +#define WIDE 1 +#define PLOT(X,Y) \ + { \ + pbx[count] = X; \ + pby[count] = Y; \ + pbz[count] = Z; \ + pbs[count] = s; \ + pbt[count] = t; \ + pbu[count] = u; \ + pbs1[count] = s1; \ + pbt1[count] = t1; \ + pbu1[count] = u1; \ + pbrgba[count][RCOMP] = FixedToInt(r0); \ + pbrgba[count][GCOMP] = FixedToInt(g0); \ + pbrgba[count][BCOMP] = FixedToInt(b0); \ + pbrgba[count][ACOMP] = FixedToInt(a0); \ + pbspec[count][RCOMP] = FixedToInt(sr0); \ + pbspec[count][GCOMP] = FixedToInt(sg0); \ + pbspec[count][BCOMP] = FixedToInt(sb0); \ + count++; \ + CHECK_FULL(count); \ + } +#include "linetemp.h" + } + + ctx->PB->count = count; + PB_CHECK_FLUSH( ctx, ctx->PB ); +} + + +/* + * Antialiased RGBA line + * + * This AA line function isn't terribly efficient but it's pretty + * straight-forward to understand. Also, it doesn't exactly conform + * to the specification. + */ +static void aa_rgba_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ +#define INTERP_RGBA 1 +#define PLOT(x, y) { PB_WRITE_RGBA_PIXEL( pb, (x), (y), z, red, green, blue, coverage ); } +#include "lnaatemp.h" +} + +/* + * Antialiased Textured RGBA line + * + * This AA line function isn't terribly efficient but it's pretty + * straight-forward to understand. Also, it doesn't exactly conform + * to the specification. + */ +static void aa_tex_rgba_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ +#define INTERP_RGBA 1 +#define INTERP_STUV0 1 +#define PLOT(x, y) \ + { \ + PB_WRITE_TEX_PIXEL( pb, (x), (y), z, red, green, blue, coverage, \ + s, t, u ); \ + } +#include "lnaatemp.h" +} + + +/* + * Antialiased Multitextured RGBA line + * + * This AA line function isn't terribly efficient but it's pretty + * straight-forward to understand. Also, it doesn't exactly conform + * to the specification. + */ +static void aa_multitex_rgba_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ +#define INTERP_RGBA 1 +#define INTERP_SPEC 1 +#define INTERP_STUV0 1 +#define INTERP_STUV1 1 +#define PLOT(x, y) \ + { \ + PB_WRITE_MULTITEX_SPEC_PIXEL( pb, (x), (y), z, \ + red, green, blue, coverage, specRed, specGreen, specBlue, \ + s, t, u, s1, t1, u1 ); \ + } +#include "lnaatemp.h" +} + + +/* + * Antialiased CI line. Same comments for RGBA antialiased lines apply. + */ +static void aa_ci_line( GLcontext *ctx, + GLuint vert0, GLuint vert1, GLuint pvert ) +{ +#define INTERP_INDEX 1 +#define PLOT(x, y) \ + { \ + PB_WRITE_CI_PIXEL( pb, (x), (y), z, index + coverage ); \ + } +#include "lnaatemp.h" +} + + +/* + * Null rasterizer for measuring transformation speed. + */ +static void null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ) +{ + (void) ctx; + (void) v1; + (void) v2; + (void) pv; +} + + +/* + * Determine which line drawing function to use given the current + * rendering context. + */ +void gl_set_line_function( GLcontext *ctx ) +{ + GLboolean rgbmode = ctx->Visual->RGBAflag; + /* TODO: antialiased lines */ + + if (ctx->RenderMode==GL_RENDER) { + if (ctx->NoRaster) { + ctx->Driver.LineFunc = null_line; + return; + } + if (ctx->Driver.LineFunc) { + /* Device driver will draw lines. */ + return; + } + + if (ctx->Line.SmoothFlag) { + /* antialiased lines */ + if (rgbmode) { + if (ctx->Texture.ReallyEnabled) { + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D + || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) + /* Multitextured! */ + ctx->Driver.LineFunc = aa_multitex_rgba_line; + else + ctx->Driver.LineFunc = aa_tex_rgba_line; + } else { + ctx->Driver.LineFunc = aa_rgba_line; + } + } + else { + ctx->Driver.LineFunc = aa_ci_line; + } + } + else if (ctx->Texture.ReallyEnabled) { + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D + || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) { + /* multi-texture and/or separate specular color */ + ctx->Driver.LineFunc = smooth_multitextured_line; + } + else { + if (ctx->Light.ShadeModel==GL_SMOOTH) { + ctx->Driver.LineFunc = smooth_textured_line; + } + else { + ctx->Driver.LineFunc = flat_textured_line; + } + } + } + else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag + || ctx->Line.SmoothFlag) { + if (ctx->Light.ShadeModel==GL_SMOOTH) { + if (rgbmode) + ctx->Driver.LineFunc = general_smooth_rgba_line; + else + ctx->Driver.LineFunc = general_smooth_ci_line; + } + else { + if (rgbmode) + ctx->Driver.LineFunc = general_flat_rgba_line; + else + ctx->Driver.LineFunc = general_flat_ci_line; + } + } + else { + if (ctx->Light.ShadeModel==GL_SMOOTH) { + /* Width==1, non-stippled, smooth-shaded */ + if (ctx->Depth.Test + || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) { + if (rgbmode) + ctx->Driver.LineFunc = smooth_rgba_z_line; + else + ctx->Driver.LineFunc = smooth_ci_z_line; + } + else { + if (rgbmode) + ctx->Driver.LineFunc = smooth_rgba_line; + else + ctx->Driver.LineFunc = smooth_ci_line; + } + } + else { + /* Width==1, non-stippled, flat-shaded */ + if (ctx->Depth.Test + || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) { + if (rgbmode) + ctx->Driver.LineFunc = flat_rgba_z_line; + else + ctx->Driver.LineFunc = flat_ci_z_line; + } + else { + if (rgbmode) + ctx->Driver.LineFunc = flat_rgba_line; + else + ctx->Driver.LineFunc = flat_ci_line; + } + } + } + } + else if (ctx->RenderMode==GL_FEEDBACK) { + ctx->Driver.LineFunc = feedback_line; + } + else { + /* GL_SELECT mode */ + ctx->Driver.LineFunc = select_line; + } +} + diff --git a/src/mesa/main/lines.h b/src/mesa/main/lines.h new file mode 100644 index 00000000000..f85a7a49103 --- /dev/null +++ b/src/mesa/main/lines.h @@ -0,0 +1,45 @@ +/* $Id: lines.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 LINES_H +#define LINES_H + + +#include "types.h" + + +extern void gl_LineWidth( GLcontext *ctx, GLfloat width ); + +extern void gl_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern ); + +extern void gl_set_line_function( GLcontext *ctx ); + + +#endif diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h new file mode 100644 index 00000000000..61e89748369 --- /dev/null +++ b/src/mesa/main/macros.h @@ -0,0 +1,546 @@ +/* $Id: macros.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +/* + * A collection of useful macros. + */ + + +#ifndef MACROS_H +#define MACROS_H + + +#include <math.h> +#include <string.h> + + +#ifdef DEBUG +# include <assert.h> +# define ASSERT(X) assert(X) +#else +# define ASSERT(X) +#endif + + +#if defined(__GNUC__) || defined(__MWERKS__) +#define INLINE __inline__ +#elif defined(__MSC__) +#define INLINE __inline +#else +#define INLINE +#endif + + +/* Stepping a GLfloat pointer by a byte stride + */ +#define STRIDE_F(p, i) (p = (GLfloat *)((GLubyte *)p + i)) +#define STRIDE_UI(p, i) (p = (GLuint *)((GLubyte *)p + i)) +#define STRIDE_T(p, t, i) (p = (t *)((GLubyte *)p + i)) + + +/* Limits: */ +#define MAX_GLUSHORT 0xffff +#define MAX_GLUINT 0xffffffff + + +#define ZERO_2V( DST ) (DST)[0] = (DST)[1] = 0 +#define ZERO_3V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = 0 +#define ZERO_4V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = (DST)[3] = 0 + + +/* Copy short vectors: */ +#define COPY_2V( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ +} while (0) + + +#define COPY_3V( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ +} while (0) + +#define COPY_4V( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ + (DST)[3] = (SRC)[3]; \ +} while (0) + + +#define COPY_2FV( DST, SRC ) \ +do { \ + const GLfloat *_tmp = (SRC); \ + (DST)[0] = _tmp[0]; \ + (DST)[1] = _tmp[1]; \ +} while (0) + + +#define COPY_3FV( DST, SRC ) \ +do { \ + const GLfloat *_tmp = (SRC); \ + (DST)[0] = _tmp[0]; \ + (DST)[1] = _tmp[1]; \ + (DST)[2] = _tmp[2]; \ +} while (0) + +#define COPY_4FV( DST, SRC ) \ +do { \ + const GLfloat *_tmp = (SRC); \ + (DST)[0] = _tmp[0]; \ + (DST)[1] = _tmp[1]; \ + (DST)[2] = _tmp[2]; \ + (DST)[3] = _tmp[3]; \ +} while (0) + + + +#define COPY_SZ_4V(DST, SZ, SRC) \ +do { \ + switch (SZ) { \ + case 4: (DST)[3] = (SRC)[3]; \ + case 3: (DST)[2] = (SRC)[2]; \ + case 2: (DST)[1] = (SRC)[1]; \ + case 1: (DST)[0] = (SRC)[0]; \ + } \ +} while(0) + +#define SUB_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ + (DST)[3] = (SRCA)[3] - (SRCB)[3]; \ +} while (0) + +#define ADD_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ + (DST)[3] = (SRCA)[3] + (SRCB)[3]; \ +} while (0) + +#define SCALE_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ + (DST)[3] = (SRCA)[3] * (SRCB)[3]; \ +} while (0) + +#define ACC_4V( DST, SRC ) \ +do { \ + (DST)[0] += (SRC)[0]; \ + (DST)[1] += (SRC)[1]; \ + (DST)[2] += (SRC)[2]; \ + (DST)[3] += (SRC)[3]; \ +} while (0) + +#define ACC_SCALE_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ + (DST)[3] += (SRCA)[3] * (SRCB)[3]; \ +} while (0) + +#define ACC_SCALE_SCALAR_4V( DST, S, SRCB ) \ +do { \ + (DST)[0] += S * (SRCB)[0]; \ + (DST)[1] += S * (SRCB)[1]; \ + (DST)[2] += S * (SRCB)[2]; \ + (DST)[3] += S * (SRCB)[3]; \ +} while (0) + +#define SCALE_SCALAR_4V( DST, S, SRCB ) \ +do { \ + (DST)[0] = S * (SRCB)[0]; \ + (DST)[1] = S * (SRCB)[1]; \ + (DST)[2] = S * (SRCB)[2]; \ + (DST)[3] = S * (SRCB)[3]; \ +} while (0) + + +#define SELF_SCALE_SCALAR_4V( DST, S ) \ +do { \ + (DST)[0] *= S; \ + (DST)[1] *= S; \ + (DST)[2] *= S; \ + (DST)[3] *= S; \ +} while (0) + + +/* + * Similarly for 3-vectors. + */ +#define SUB_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ +} while (0) + +#define ADD_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ +} while (0) + +#define SCALE_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ +} while (0) + +#define ACC_3V( DST, SRC ) \ +do { \ + (DST)[0] += (SRC)[0]; \ + (DST)[1] += (SRC)[1]; \ + (DST)[2] += (SRC)[2]; \ +} while (0) + +#define ACC_SCALE_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ +} while (0) + +#define SCALE_SCALAR_3V( DST, S, SRCB ) \ +do { \ + (DST)[0] = S * (SRCB)[0]; \ + (DST)[1] = S * (SRCB)[1]; \ + (DST)[2] = S * (SRCB)[2]; \ +} while (0) + +#define ACC_SCALE_SCALAR_3V( DST, S, SRCB ) \ +do { \ + (DST)[0] += S * (SRCB)[0]; \ + (DST)[1] += S * (SRCB)[1]; \ + (DST)[2] += S * (SRCB)[2]; \ +} while (0) + +#define SELF_SCALE_SCALAR_3V( DST, S ) \ +do { \ + (DST)[0] *= S; \ + (DST)[1] *= S; \ + (DST)[2] *= S; \ +} while (0) + +#define ACC_SCALAR_3V( DST, S ) \ +do { \ + (DST)[0] += S; \ + (DST)[1] += S; \ + (DST)[2] += S; \ +} while (0) + +/* And also for 2-vectors + */ +#define SUB_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ +} while (0) + +#define ADD_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ +} while (0) + +#define SCALE_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ +} while (0) + +#define ACC_2V( DST, SRC ) \ +do { \ + (DST)[0] += (SRC)[0]; \ + (DST)[1] += (SRC)[1]; \ +} while (0) + +#define ACC_SCALE_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ +} while (0) + +#define SCALE_SCALAR_2V( DST, S, SRCB ) \ +do { \ + (DST)[0] = S * (SRCB)[0]; \ + (DST)[1] = S * (SRCB)[1]; \ +} while (0) + +#define ACC_SCALE_SCALAR_2V( DST, S, SRCB ) \ +do { \ + (DST)[0] += S * (SRCB)[0]; \ + (DST)[1] += S * (SRCB)[1]; \ +} while (0) + +#define SELF_SCALE_SCALAR_2V( DST, S ) \ +do { \ + (DST)[0] *= S; \ + (DST)[1] *= S; \ +} while (0) + +#define ACC_SCALAR_2V( DST, S ) \ +do { \ + (DST)[0] += S; \ + (DST)[1] += S; \ +} while (0) + + + +/* + * Copy a vector of 4 GLubytes from SRC to DST. + */ +#define COPY_4UBV(DST, SRC) \ +do { \ + if (sizeof(GLuint)==4*sizeof(GLubyte)) { \ + *((GLuint*)(DST)) = *((GLuint*)(SRC)); \ + } \ + else { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ + (DST)[3] = (SRC)[3]; \ + } \ +} while (0) + + +/* Assign scalers to short vectors: */ +#define ASSIGN_2V( V, V0, V1 ) \ +do { V[0] = V0; V[1] = V1; } while(0) + +#define ASSIGN_3V( V, V0, V1, V2 ) \ +do { V[0] = V0; V[1] = V1; V[2] = V2; } while(0) + +#define ASSIGN_4V( V, V0, V1, V2, V3 ) \ +do { \ + V[0] = V0; \ + V[1] = V1; \ + V[2] = V2; \ + V[3] = V3; \ +} while(0) + + + + +/* Absolute value (for Int, Float, Double): */ +#define ABSI(X) ((X) < 0 ? -(X) : (X)) +#define ABSF(X) ((X) < 0.0F ? -(X) : (X)) +#define ABSD(X) ((X) < 0.0 ? -(X) : (X)) + + + +/* Round a floating-point value to the nearest integer: */ +#define ROUNDF(X) ( (X)<0.0F ? ((GLint) ((X)-0.5F)) : ((GLint) ((X)+0.5F)) ) + + +/* Compute ceiling of integer quotient of A divided by B: */ +#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) + + +/* Clamp X to [MIN,MAX]: */ +#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) + +/* Assign X to CLAMP(X, MIN, MAX) */ +#define CLAMP_SELF(x, mn, mx) \ + ( (x)<(mn) ? ((x) = (mn)) : ((x)>(mx) ? ((x)=(mx)) : (x)) ) + + + +/* Min of two values: */ +#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) + + +/* MAX of two values: */ +#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) + +/* Dot product of two 2-element vectors */ +#define DOT2( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] ) + +/* Dot product of two 3-element vectors */ +#define DOT3( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] ) + + +/* Dot product of two 4-element vectors */ +#define DOT4( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] + \ + (a)[2]*(b)[2] + (a)[3]*(b)[3] ) + +#define DOT4V(v,a,b,c,d) (v[0]*a + v[1]*b + v[2]*c + v[3]*d) + + +#define CROSS3(n, u, v) \ +do { \ + (n)[0] = (u)[1]*(v)[2] - (u)[2]*(v)[1]; \ + (n)[1] = (u)[2]*(v)[0] - (u)[0]*(v)[2]; \ + (n)[2] = (u)[0]*(v)[1] - (u)[1]*(v)[0]; \ +} while (0) + + +/* + * Integer / float conversion for colors, normals, etc. + */ + + + + +#define BYTE_TO_UBYTE(b) (b < 0 ? 0 : (GLubyte) b) +#define SHORT_TO_UBYTE(s) (s < 0 ? 0 : (GLubyte) (s >> 7)) +#define USHORT_TO_UBYTE(s) (GLubyte) (s >> 8) +#define INT_TO_UBYTE(i) (i < 0 ? 0 : (GLubyte) (i >> 23)) +#define UINT_TO_UBYTE(i) (GLubyte) (i >> 24) + + + + +/* Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */ +#define UBYTE_TO_FLOAT(B) ((GLfloat) (B) * (1.0F / 255.0F)) + +/* Convert GLfloat in [0.0,1.0] to GLubyte in [0,255] */ +#define FLOAT_TO_UBYTE(X) ((GLubyte) (GLint) (((X)) * 255.0F)) + + +/* Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0] */ +#define BYTE_TO_FLOAT(B) ((2.0F * (B) + 1.0F) * (1.0F/255.0F)) + +/* Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127] */ +#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 ) + + +/* Convert GLushort in [0,65536] to GLfloat in [0.0,1.0] */ +#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F)) + +/* Convert GLfloat in [0.0,1.0] to GLushort in [0,65536] */ +#define FLOAT_TO_USHORT(X) ((GLushort) (GLint) ((X) * 65535.0F)) + + +/* Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */ +#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) + +/* Convert GLfloat in [0.0,1.0] to GLshort in [-32768,32767] */ +#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 ) + + +/* Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */ +#define UINT_TO_FLOAT(U) ((GLfloat) (U) * (1.0F / 4294967295.0F)) + +/* Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */ +#define FLOAT_TO_UINT(X) ((GLuint) ((X) * 4294967295.0)) + + +/* Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */ +#define INT_TO_FLOAT(I) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0F)) + +/* Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */ +/* causes overflow: +#define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0F * (X))) - 1) / 2 ) +*/ +/* a close approximation: */ +#define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) ) + + + +/* Memory copy: */ +#ifdef SUNOS4 +#define MEMCPY( DST, SRC, BYTES) \ + memcpy( (char *) (DST), (char *) (SRC), (int) (BYTES) ) +#else +#define MEMCPY( DST, SRC, BYTES) \ + memcpy( (void *) (DST), (void *) (SRC), (size_t) (BYTES) ) +#endif + + +/* Memory set: */ +#ifdef SUNOS4 +#define MEMSET( DST, VAL, N ) \ + memset( (char *) (DST), (int) (VAL), (int) (N) ) +#else +#define MEMSET( DST, VAL, N ) \ + memset( (void *) (DST), (int) (VAL), (size_t) (N) ) +#endif + + +/* MACs and BeOS don't support static larger than 32kb, so... */ +#if defined(macintosh) && !defined(__MRC__) + extern char *AGLAlloc(int size); + extern void AGLFree(char* ptr); +# define DEFARRAY(TYPE,NAME,SIZE) TYPE *NAME = (TYPE*)AGLAlloc(sizeof(TYPE)*(SIZE)) +# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE (*NAME)[SIZE2] = (TYPE(*)[SIZE2])AGLAlloc(sizeof(TYPE)*(SIZE1)*(SIZE2)) +# define CHECKARRAY(NAME,CMD) do {if (!(NAME)) {CMD;}} while (0) +# define UNDEFARRAY(NAME) do {if ((NAME)) {AGLFree((char*)NAME);} }while (0) +#elif defined(__BEOS__) +# define DEFARRAY(TYPE,NAME,SIZE) TYPE *NAME = (TYPE*)malloc(sizeof(TYPE)*(SIZE)) +# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE (*NAME)[SIZE2] = (TYPE(*)[SIZE2])malloc(sizeof(TYPE)*(SIZE1)*(SIZE2)) +# define CHECKARRAY(NAME,CMD) do {if (!(NAME)) {CMD;}} while (0) +# define UNDEFARRAY(NAME) do {if ((NAME)) {free((char*)NAME);} }while (0) +#else +# define DEFARRAY(TYPE,NAME,SIZE) TYPE NAME[SIZE] +# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE NAME[SIZE1][SIZE2] +# define CHECKARRAY(NAME,CMD) do {} while(0) +# define UNDEFARRAY(NAME) +#endif + + +/* Some compilers don't like some of Mesa's const usage */ +#ifdef NO_CONST +# define CONST +#else +# define CONST const +#endif + + + +/* Pi */ +#ifndef M_PI +#define M_PI (3.1415926) +#endif + + +/* Degrees to radians conversion: */ +#define DEG2RAD (M_PI/180.0) + + +#ifndef NULL +#define NULL 0 +#endif + + + +#endif /*MACROS_H*/ diff --git a/src/mesa/main/matrix.c b/src/mesa/main/matrix.c new file mode 100644 index 00000000000..c6459947fe5 --- /dev/null +++ b/src/mesa/main/matrix.c @@ -0,0 +1,1438 @@ +/* $Id: matrix.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +/* + * Matrix operations + * + * + * NOTES: + * 1. 4x4 transformation matrices are stored in memory in column major order. + * 2. Points/vertices are to be thought of as column vectors. + * 3. Transformation of a point p by a matrix M is: p' = M * p + * + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "context.h" +#include "enums.h" +#include "macros.h" +#include "matrix.h" +#include "mmath.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +static const char *types[] = { + "MATRIX_GENERAL", + "MATRIX_IDENTITY", + "MATRIX_3D_NO_ROT", + "MATRIX_PERSPECTIVE", + "MATRIX_2D", + "MATRIX_2D_NO_ROT", + "MATRIX_3D" +}; +static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b ); + + +static GLfloat Identity[16] = { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 +}; + + +static void print_matrix_floats( const GLfloat m[16] ) +{ + int i; + for (i=0;i<4;i++) { + fprintf(stderr,"\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] ); + } +} + +void gl_print_matrix( const GLmatrix *m ) +{ + fprintf(stderr, "Matrix type: %s, flags: %x\n", types[m->type], m->flags); + print_matrix_floats(m->m); +#if 1 + fprintf(stderr, "Inverse: \n"); + if (m->inv) { + GLfloat prod[16]; + print_matrix_floats(m->inv); + matmul4(prod, m->m, m->inv); + fprintf(stderr, "Mat * Inverse:\n"); + print_matrix_floats(prod); + } else + fprintf(stderr, " - not available\n"); +#endif +} + + + +/* + * This matmul was contributed by Thomas Malik + * + * Perform a 4x4 matrix multiplication (product = a x b). + * Input: a, b - matrices to multiply + * Output: product - product of a and b + * WARNING: (product != b) assumed + * NOTE: (product == a) allowed + * + * KW: 4*16 = 64 muls + */ +#define A(row,col) a[(col<<2)+row] +#define B(row,col) b[(col<<2)+row] +#define P(row,col) product[(col<<2)+row] + +static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b ) +{ + GLint i; + for (i = 0; i < 4; i++) { + GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); + P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); + P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); + P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); + P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); + } +} + + + + +/* Multiply two matrices known to occupy only the top three rows, + * such as typical modelling matrices, and ortho matrices. + * + * KW: 3*9 = 27 muls + */ +static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b ) +{ + GLint i; + for (i = 0; i < 3; i++) { + GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); + P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0); + P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1); + P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2); + P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3; + } + P(3,0) = 0; + P(3,1) = 0; + P(3,2) = 0; + P(3,3) = 1; +} + +static void matmul4fd( GLfloat *product, const GLfloat *a, const GLdouble *b ) +{ + GLint i; + for (i = 0; i < 4; i++) { + GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); + P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); + P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); + P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); + P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); + } +} + +#undef A +#undef B +#undef P + + + +#define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; } +#define MAT(m,r,c) (m)[(c)*4+(r)] + +/* + * Compute inverse of 4x4 transformation matrix. + * Code contributed by Jacques Leroy [email protected] + * Return GL_TRUE for success, GL_FALSE for failure (singular matrix) + */ +static GLboolean invert_matrix_general( GLmatrix *mat ) +{ + const GLfloat *m = mat->m; + GLfloat *out = mat->inv; + GLfloat wtmp[4][8]; + GLfloat m0, m1, m2, m3, s; + GLfloat *r0, *r1, *r2, *r3; + + r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3]; + + r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1), + r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3), + r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0, + + r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1), + r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3), + r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0, + + r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1), + r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3), + r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0, + + r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1), + r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3), + r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0; + + /* choose pivot - or die */ + if (fabs(r3[0])>fabs(r2[0])) SWAP_ROWS(r3, r2); + if (fabs(r2[0])>fabs(r1[0])) SWAP_ROWS(r2, r1); + if (fabs(r1[0])>fabs(r0[0])) SWAP_ROWS(r1, r0); + if (0.0 == r0[0]) return GL_FALSE; + + /* eliminate first variable */ + m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0]; + s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s; + s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s; + s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s; + s = r0[4]; + if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; } + s = r0[5]; + if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; } + s = r0[6]; + if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; } + s = r0[7]; + if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; } + + /* choose pivot - or die */ + if (fabs(r3[1])>fabs(r2[1])) SWAP_ROWS(r3, r2); + if (fabs(r2[1])>fabs(r1[1])) SWAP_ROWS(r2, r1); + if (0.0 == r1[1]) return GL_FALSE; + + /* eliminate second variable */ + m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1]; + r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2]; + r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3]; + s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; } + s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; } + s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; } + s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; } + + /* choose pivot - or die */ + if (fabs(r3[2])>fabs(r2[2])) SWAP_ROWS(r3, r2); + if (0.0 == r2[2]) return GL_FALSE; + + /* eliminate third variable */ + m3 = r3[2]/r2[2]; + r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4], + r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], + r3[7] -= m3 * r2[7]; + + /* last check */ + if (0.0 == r3[3]) return GL_FALSE; + + s = 1.0/r3[3]; /* now back substitute row 3 */ + r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s; + + m2 = r2[3]; /* now back substitute row 2 */ + s = 1.0/r2[2]; + r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2), + r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2); + m1 = r1[3]; + r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1, + r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1; + m0 = r0[3]; + r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0, + r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0; + + m1 = r1[2]; /* now back substitute row 1 */ + s = 1.0/r1[1]; + r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1), + r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1); + m0 = r0[2]; + r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0, + r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0; + + m0 = r0[1]; /* now back substitute row 0 */ + s = 1.0/r0[0]; + r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0), + r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0); + + MAT(out,0,0) = r0[4]; MAT(out,0,1) = r0[5], + MAT(out,0,2) = r0[6]; MAT(out,0,3) = r0[7], + MAT(out,1,0) = r1[4]; MAT(out,1,1) = r1[5], + MAT(out,1,2) = r1[6]; MAT(out,1,3) = r1[7], + MAT(out,2,0) = r2[4]; MAT(out,2,1) = r2[5], + MAT(out,2,2) = r2[6]; MAT(out,2,3) = r2[7], + MAT(out,3,0) = r3[4]; MAT(out,3,1) = r3[5], + MAT(out,3,2) = r3[6]; MAT(out,3,3) = r3[7]; + + return GL_TRUE; +} +#undef SWAP_ROWS + +/* Adapted from graphics gems II. + */ +GLboolean invert_matrix_3d_general( GLmatrix *mat ) +{ + const GLfloat *in = mat->m; + GLfloat *out = mat->inv; + GLfloat pos, neg, t; + GLfloat det; + + /* Calculate the determinant of upper left 3x3 submatrix and + * determine if the matrix is singular. + */ + pos = neg = 0.0; + t = MAT(in,0,0) * MAT(in,1,1) * MAT(in,2,2); + if (t >= 0.0) pos += t; else neg += t; + + t = MAT(in,1,0) * MAT(in,2,1) * MAT(in,0,2); + if (t >= 0.0) pos += t; else neg += t; + + t = MAT(in,2,0) * MAT(in,0,1) * MAT(in,1,2); + if (t >= 0.0) pos += t; else neg += t; + + t = -MAT(in,2,0) * MAT(in,1,1) * MAT(in,0,2); + if (t >= 0.0) pos += t; else neg += t; + + t = -MAT(in,1,0) * MAT(in,0,1) * MAT(in,2,2); + if (t >= 0.0) pos += t; else neg += t; + + t = -MAT(in,0,0) * MAT(in,2,1) * MAT(in,1,2); + if (t >= 0.0) pos += t; else neg += t; + + det = pos + neg; + + if (det*det < 1e-25) + return GL_FALSE; + + det = 1.0 / det; + MAT(out,0,0) = ( (MAT(in,1,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,1,2) )*det); + MAT(out,0,1) = (- (MAT(in,0,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,0,2) )*det); + MAT(out,0,2) = ( (MAT(in,0,1)*MAT(in,1,2) - MAT(in,1,1)*MAT(in,0,2) )*det); + MAT(out,1,0) = (- (MAT(in,1,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,1,2) )*det); + MAT(out,1,1) = ( (MAT(in,0,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,0,2) )*det); + MAT(out,1,2) = (- (MAT(in,0,0)*MAT(in,1,2) - MAT(in,1,0)*MAT(in,0,2) )*det); + MAT(out,2,0) = ( (MAT(in,1,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,1,1) )*det); + MAT(out,2,1) = (- (MAT(in,0,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,0,1) )*det); + MAT(out,2,2) = ( (MAT(in,0,0)*MAT(in,1,1) - MAT(in,1,0)*MAT(in,0,1) )*det); + + /* Do the translation part */ + MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) + + MAT(in,1,3) * MAT(out,0,1) + + MAT(in,2,3) * MAT(out,0,2) ); + MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) + + MAT(in,1,3) * MAT(out,1,1) + + MAT(in,2,3) * MAT(out,1,2) ); + MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) + + MAT(in,1,3) * MAT(out,2,1) + + MAT(in,2,3) * MAT(out,2,2) ); + + return GL_TRUE; +} + + +static GLboolean invert_matrix_3d( GLmatrix *mat ) +{ + const GLfloat *in = mat->m; + GLfloat *out = mat->inv; + + if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) + { + return invert_matrix_3d_general( mat ); + } + + if (mat->flags & MAT_FLAG_UNIFORM_SCALE) + { + GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) + + MAT(in,0,1) * MAT(in,0,1) + + MAT(in,0,2) * MAT(in,0,2)); + + if (scale == 0.0) + return GL_FALSE; + + scale = 1.0 / scale; + + /* Transpose and scale the 3 by 3 upper-left submatrix. */ + MAT(out,0,0) = scale * MAT(in,0,0); + MAT(out,1,0) = scale * MAT(in,0,1); + MAT(out,2,0) = scale * MAT(in,0,2); + MAT(out,0,1) = scale * MAT(in,1,0); + MAT(out,1,1) = scale * MAT(in,1,1); + MAT(out,2,1) = scale * MAT(in,1,2); + MAT(out,0,2) = scale * MAT(in,2,0); + MAT(out,1,2) = scale * MAT(in,2,1); + MAT(out,2,2) = scale * MAT(in,2,2); + } + else if (mat->flags & MAT_FLAG_ROTATION) + { + /* Transpose the 3 by 3 upper-left submatrix. */ + MAT(out,0,0) = MAT(in,0,0); + MAT(out,1,0) = MAT(in,0,1); + MAT(out,2,0) = MAT(in,0,2); + MAT(out,0,1) = MAT(in,1,0); + MAT(out,1,1) = MAT(in,1,1); + MAT(out,2,1) = MAT(in,1,2); + MAT(out,0,2) = MAT(in,2,0); + MAT(out,1,2) = MAT(in,2,1); + MAT(out,2,2) = MAT(in,2,2); + } + else /* pure translation */ + { + MEMCPY( out, Identity, sizeof(Identity) ); + MAT(out,0,3) = - MAT(in,0,3); + MAT(out,1,3) = - MAT(in,1,3); + MAT(out,2,3) = - MAT(in,2,3); + return GL_TRUE; + } + + if (mat->flags & MAT_FLAG_TRANSLATION) + { + /* Do the translation part */ + MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) + + MAT(in,1,3) * MAT(out,0,1) + + MAT(in,2,3) * MAT(out,0,2) ); + MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) + + MAT(in,1,3) * MAT(out,1,1) + + MAT(in,2,3) * MAT(out,1,2) ); + MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) + + MAT(in,1,3) * MAT(out,2,1) + + MAT(in,2,3) * MAT(out,2,2) ); + } + else + { + MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0; + } + + return GL_TRUE; +} + + + +static GLboolean invert_matrix_identity( GLmatrix *mat ) +{ + MEMCPY( mat->inv, Identity, sizeof(Identity) ); + return GL_TRUE; +} + + +static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat ) +{ + const GLfloat *in = mat->m; + GLfloat *out = mat->inv; + + if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 ) + return GL_FALSE; + + MEMCPY( out, Identity, 16 * sizeof(GLfloat) ); + MAT(out,0,0) = 1.0 / MAT(in,0,0); + MAT(out,1,1) = 1.0 / MAT(in,1,1); + MAT(out,2,2) = 1.0 / MAT(in,2,2); + + if (mat->flags & MAT_FLAG_TRANSLATION) + { + MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0)); + MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1)); + MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2)); + } + + return GL_TRUE; +} + + +static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat ) +{ + const GLfloat *in = mat->m; + GLfloat *out = mat->inv; + + if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0) + return GL_FALSE; + + MEMCPY( out, Identity, 16 * sizeof(GLfloat) ); + MAT(out,0,0) = 1.0 / MAT(in,0,0); + MAT(out,1,1) = 1.0 / MAT(in,1,1); + + if (mat->flags & MAT_FLAG_TRANSLATION) + { + MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0)); + MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1)); + } + + return GL_TRUE; +} + + +static GLboolean invert_matrix_perspective( GLmatrix *mat ) +{ + const GLfloat *in = mat->m; + GLfloat *out = mat->inv; + + if (MAT(in,2,3) == 0) + return GL_FALSE; + + MEMCPY( out, Identity, 16 * sizeof(GLfloat) ); + + MAT(out,0,0) = 1.0 / MAT(in,0,0); + MAT(out,1,1) = 1.0 / MAT(in,1,1); + + MAT(out,0,3) = MAT(in,0,2); + MAT(out,1,3) = MAT(in,1,2); + + MAT(out,2,2) = 0; + MAT(out,2,3) = -1; + + MAT(out,3,2) = 1.0 / MAT(in,2,3); + MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2); + + return GL_TRUE; +} + + +typedef GLboolean (*inv_mat_func)( GLmatrix *mat ); + +static inv_mat_func inv_mat_tab[7] = { + invert_matrix_general, + invert_matrix_identity, + invert_matrix_3d_no_rot, + invert_matrix_perspective, + invert_matrix_3d, /* lazy! */ + invert_matrix_2d_no_rot, + invert_matrix_3d +}; + + +GLboolean gl_matrix_invert( GLmatrix *mat ) +{ + if (inv_mat_tab[mat->type](mat)) { +#if 0 + GLmatrix m; m.inv = 0; m.type = 0; m.flags = 0; + matmul4( m.m, mat->m, mat->inv ); + printf("inverted matrix of type %s:\n", types[mat->type]); + gl_print_matrix( mat ); + gl_print_matrix( &m ); +#endif + return GL_TRUE; + } else { + MEMCPY( mat->inv, Identity, sizeof(Identity) ); + return GL_FALSE; + } +} + + + +/* + * Generate a 4x4 transformation matrix from glRotate parameters. + */ +void gl_rotation_matrix( GLfloat angle, GLfloat x, GLfloat y, GLfloat z, + GLfloat m[] ) +{ + /* This function contributed by Erich Boleyn ([email protected]) */ + GLfloat mag, s, c; + GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c; + + s = sin( angle * DEG2RAD ); + c = cos( angle * DEG2RAD ); + + mag = GL_SQRT( x*x + y*y + z*z ); + + if (mag == 0.0) { + /* generate an identity matrix and return */ + MEMCPY(m, Identity, sizeof(GLfloat)*16); + return; + } + + x /= mag; + y /= mag; + z /= mag; + +#define M(row,col) m[col*4+row] + + /* + * Arbitrary axis rotation matrix. + * + * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied + * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation + * (which is about the X-axis), and the two composite transforms + * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary + * from the arbitrary axis to the X-axis then back. They are + * all elementary rotations. + * + * Rz' is a rotation about the Z-axis, to bring the axis vector + * into the x-z plane. Then Ry' is applied, rotating about the + * Y-axis to bring the axis vector parallel with the X-axis. The + * rotation about the X-axis is then performed. Ry and Rz are + * simply the respective inverse transforms to bring the arbitrary + * axis back to it's original orientation. The first transforms + * Rz' and Ry' are considered inverses, since the data from the + * arbitrary axis gives you info on how to get to it, not how + * to get away from it, and an inverse must be applied. + * + * The basic calculation used is to recognize that the arbitrary + * axis vector (x, y, z), since it is of unit length, actually + * represents the sines and cosines of the angles to rotate the + * X-axis to the same orientation, with theta being the angle about + * Z and phi the angle about Y (in the order described above) + * as follows: + * + * cos ( theta ) = x / sqrt ( 1 - z^2 ) + * sin ( theta ) = y / sqrt ( 1 - z^2 ) + * + * cos ( phi ) = sqrt ( 1 - z^2 ) + * sin ( phi ) = z + * + * Note that cos ( phi ) can further be inserted to the above + * formulas: + * + * cos ( theta ) = x / cos ( phi ) + * sin ( theta ) = y / sin ( phi ) + * + * ...etc. Because of those relations and the standard trigonometric + * relations, it is pssible to reduce the transforms down to what + * is used below. It may be that any primary axis chosen will give the + * same results (modulo a sign convention) using thie method. + * + * Particularly nice is to notice that all divisions that might + * have caused trouble when parallel to certain planes or + * axis go away with care paid to reducing the expressions. + * After checking, it does perform correctly under all cases, since + * in all the cases of division where the denominator would have + * been zero, the numerator would have been zero as well, giving + * the expected result. + */ + + xx = x * x; + yy = y * y; + zz = z * z; + xy = x * y; + yz = y * z; + zx = z * x; + xs = x * s; + ys = y * s; + zs = z * s; + one_c = 1.0F - c; + + M(0,0) = (one_c * xx) + c; + M(0,1) = (one_c * xy) - zs; + M(0,2) = (one_c * zx) + ys; + M(0,3) = 0.0F; + + M(1,0) = (one_c * xy) + zs; + M(1,1) = (one_c * yy) + c; + M(1,2) = (one_c * yz) - xs; + M(1,3) = 0.0F; + + M(2,0) = (one_c * zx) - ys; + M(2,1) = (one_c * yz) + xs; + M(2,2) = (one_c * zz) + c; + M(2,3) = 0.0F; + + M(3,0) = 0.0F; + M(3,1) = 0.0F; + M(3,2) = 0.0F; + M(3,3) = 1.0F; + +#undef M +} + +#define ZERO(x) (1<<x) +#define ONE(x) (1<<(x+16)) + +#define MASK_NO_TRX (ZERO(12) | ZERO(13) | ZERO(14)) +#define MASK_NO_2D_SCALE ( ONE(0) | ONE(5)) + +#define MASK_IDENTITY ( ONE(0) | ZERO(4) | ZERO(8) | ZERO(12) |\ + ZERO(1) | ONE(5) | ZERO(9) | ZERO(13) |\ + ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ + ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) + +#define MASK_2D_NO_ROT ( ZERO(4) | ZERO(8) | \ + ZERO(1) | ZERO(9) | \ + ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ + ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) + +#define MASK_2D ( ZERO(8) | \ + ZERO(9) | \ + ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ + ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) + + +#define MASK_3D_NO_ROT ( ZERO(4) | ZERO(8) | \ + ZERO(1) | ZERO(9) | \ + ZERO(2) | ZERO(6) | \ + ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) + +#define MASK_3D ( \ + \ + \ + ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) + + +#define MASK_PERSPECTIVE ( ZERO(4) | ZERO(12) |\ + ZERO(1) | ZERO(13) |\ + ZERO(2) | ZERO(6) | \ + ZERO(3) | ZERO(7) | ZERO(15) ) + +#define SQ(x) ((x)*(x)) + +/* Determine type and flags from scratch. This is expensive enough to + * only want to do it once. + */ +static void analyze_from_scratch( GLmatrix *mat ) +{ + const GLfloat *m = mat->m; + GLuint mask = 0; + GLuint i; + + for (i = 0 ; i < 16 ; i++) + { + if (m[i] == 0.0) mask |= (1<<i); + } + + if (m[0] == 1.0F) mask |= (1<<16); + if (m[5] == 1.0F) mask |= (1<<21); + if (m[10] == 1.0F) mask |= (1<<26); + if (m[15] == 1.0F) mask |= (1<<31); + + mat->flags &= ~MAT_FLAGS_GEOMETRY; + + /* Check for translation - no-one really cares + */ + if ((mask & MASK_NO_TRX) != MASK_NO_TRX) + mat->flags |= MAT_FLAG_TRANSLATION; + + /* Do the real work + */ + if (mask == MASK_IDENTITY) { + mat->type = MATRIX_IDENTITY; + } + else if ((mask & MASK_2D_NO_ROT) == MASK_2D_NO_ROT) + { + mat->type = MATRIX_2D_NO_ROT; + + if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE) + mat->flags = MAT_FLAG_GENERAL_SCALE; + } + else if ((mask & MASK_2D) == MASK_2D) + { + GLfloat mm = DOT2(m, m); + GLfloat m4m4 = DOT2(m+4,m+4); + GLfloat mm4 = DOT2(m,m+4); + + mat->type = MATRIX_2D; + + /* Check for scale */ + if (SQ(mm-1) > SQ(1e-6) || + SQ(m4m4-1) > SQ(1e-6)) + mat->flags |= MAT_FLAG_GENERAL_SCALE; + + /* Check for rotation */ + if (SQ(mm4) > SQ(1e-6)) + mat->flags |= MAT_FLAG_GENERAL_3D; + else + mat->flags |= MAT_FLAG_ROTATION; + + } + else if ((mask & MASK_3D_NO_ROT) == MASK_3D_NO_ROT) + { + mat->type = MATRIX_3D_NO_ROT; + + /* Check for scale */ + if (SQ(m[0]-m[5]) < SQ(1e-6) && + SQ(m[0]-m[10]) < SQ(1e-6)) { + if (SQ(m[0]-1.0) > SQ(1e-6)) + mat->flags |= MAT_FLAG_UNIFORM_SCALE; + } else + mat->flags |= MAT_FLAG_GENERAL_SCALE; + } + else if ((mask & MASK_3D) == MASK_3D) + { + GLfloat c1 = DOT3(m,m); + GLfloat c2 = DOT3(m+4,m+4); + GLfloat c3 = DOT3(m+8,m+8); + GLfloat d1 = DOT3(m, m+4); + GLfloat cp[3]; + + mat->type = MATRIX_3D; + + /* Check for scale */ + if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) { + if (SQ(c1-1.0) > SQ(1e-6)) + mat->flags |= MAT_FLAG_UNIFORM_SCALE; + /* else no scale at all */ + } else + mat->flags |= MAT_FLAG_GENERAL_SCALE; + + /* Check for rotation */ + if (SQ(d1) < SQ(1e-6)) { + CROSS3( cp, m, m+4 ); + SUB_3V( cp, cp, (m+8) ); + if (LEN_SQUARED_3FV(cp) < SQ(1e-6)) + mat->flags |= MAT_FLAG_ROTATION; + else + mat->flags |= MAT_FLAG_GENERAL_3D; + } + else + mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */ + } + else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) + { + mat->type = MATRIX_PERSPECTIVE; + mat->flags |= MAT_FLAG_GENERAL; + } + else { + mat->type = MATRIX_GENERAL; + mat->flags |= MAT_FLAG_GENERAL; + } +} + + +/* Analyse a matrix given that its flags are accurate - this is the + * more common operation, hopefully. + */ +static void analyze_from_flags( GLmatrix *mat ) +{ + const GLfloat *m = mat->m; + + if (TEST_MAT_FLAGS(mat, 0)) { + mat->type = MATRIX_IDENTITY; + } + else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION | + MAT_FLAG_UNIFORM_SCALE | + MAT_FLAG_GENERAL_SCALE))) + { + if ( m[10]==1.0F && m[14]==0.0F ) { + mat->type = MATRIX_2D_NO_ROT; + } + else { + mat->type = MATRIX_3D_NO_ROT; + } + } + else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) { + if ( m[ 8]==0.0F + && m[ 9]==0.0F + && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) + { + mat->type = MATRIX_2D; + } + else + { + mat->type = MATRIX_3D; + } + } + else if ( m[4]==0.0F && m[12]==0.0F + && m[1]==0.0F && m[13]==0.0F + && m[2]==0.0F && m[6]==0.0F + && m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) + { + mat->type = MATRIX_PERSPECTIVE; + } + else { + mat->type = MATRIX_GENERAL; + } + +} + + +void gl_matrix_analyze( GLmatrix *mat ) +{ + if (mat->flags & MAT_DIRTY_TYPE) { + if (mat->flags & MAT_DIRTY_FLAGS) + analyze_from_scratch( mat ); + else + analyze_from_flags( mat ); + } + + if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) { + gl_matrix_invert( mat ); + } + + mat->flags &= ~(MAT_DIRTY_FLAGS| + MAT_DIRTY_TYPE| + MAT_DIRTY_INVERSE); +} + + +#define GET_ACTIVE_MATRIX(ctx, mat, flags, where) \ +do { \ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, where); \ + if (MESA_VERBOSE&VERBOSE_API) fprintf(stderr, "%s\n", where); \ + switch (ctx->Transform.MatrixMode) { \ + case GL_MODELVIEW: \ + mat = &ctx->ModelView; \ + flags |= NEW_MODELVIEW; \ + break; \ + case GL_PROJECTION: \ + mat = &ctx->ProjectionMatrix; \ + flags |= NEW_PROJECTION; \ + break; \ + case GL_TEXTURE: \ + mat = &ctx->TextureMatrix[ctx->Texture.CurrentTransformUnit]; \ + flags |= NEW_TEXTURE_MATRIX; \ + break; \ + default: \ + gl_problem(ctx, where); \ + } \ +} while (0) + + +void gl_Frustum( GLcontext *ctx, + GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + GLfloat x, y, a, b, c, d; + GLfloat m[16]; + GLmatrix *mat = 0; + + GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glFrustrum" ); + + if (nearval<=0.0 || farval<=0.0) { + gl_error( ctx, GL_INVALID_VALUE, "glFrustum(near or far)" ); + } + + x = (2.0*nearval) / (right-left); + y = (2.0*nearval) / (top-bottom); + a = (right+left) / (right-left); + b = (top+bottom) / (top-bottom); + c = -(farval+nearval) / ( farval-nearval); + d = -(2.0*farval*nearval) / (farval-nearval); /* error? */ + +#define M(row,col) m[col*4+row] + M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; + M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; + M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; + M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; +#undef M + + + gl_mat_mul_floats( mat, m, MAT_FLAG_PERSPECTIVE ); + + + if (ctx->Transform.MatrixMode == GL_PROJECTION) + { + /* Need to keep a stack of near/far values in case the user push/pops + * the projection matrix stack so that we can call Driver.NearFar() + * after a pop. + */ + ctx->NearFarStack[ctx->ProjectionStackDepth][0] = nearval; + ctx->NearFarStack[ctx->ProjectionStackDepth][1] = farval; + + if (ctx->Driver.NearFar) { + (*ctx->Driver.NearFar)( ctx, nearval, farval ); + } + } +} + + +void gl_Ortho( GLcontext *ctx, + GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + GLfloat x, y, z; + GLfloat tx, ty, tz; + GLfloat m[16]; + GLmatrix *mat = 0; + + GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glOrtho" ); + + x = 2.0 / (right-left); + y = 2.0 / (top-bottom); + z = -2.0 / (farval-nearval); + tx = -(right+left) / (right-left); + ty = -(top+bottom) / (top-bottom); + tz = -(farval+nearval) / (farval-nearval); + +#define M(row,col) m[col*4+row] + M(0,0) = x; M(0,1) = 0.0F; M(0,2) = 0.0F; M(0,3) = tx; + M(1,0) = 0.0F; M(1,1) = y; M(1,2) = 0.0F; M(1,3) = ty; + M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = z; M(2,3) = tz; + M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = 0.0F; M(3,3) = 1.0F; +#undef M + + gl_mat_mul_floats( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION)); + + if (ctx->Driver.NearFar) { + (*ctx->Driver.NearFar)( ctx, nearval, farval ); + } +} + + +void gl_MatrixMode( GLcontext *ctx, GLenum mode ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMatrixMode"); + switch (mode) { + case GL_MODELVIEW: + case GL_PROJECTION: + case GL_TEXTURE: + ctx->Transform.MatrixMode = mode; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glMatrixMode" ); + } +} + + + +void gl_PushMatrix( GLcontext *ctx ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushMatrix"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glPushMatrix %s\n", + gl_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + + switch (ctx->Transform.MatrixMode) { + case GL_MODELVIEW: + if (ctx->ModelViewStackDepth>=MAX_MODELVIEW_STACK_DEPTH-1) { + gl_error( ctx, GL_STACK_OVERFLOW, "glPushMatrix"); + return; + } + gl_matrix_copy( &ctx->ModelViewStack[ctx->ModelViewStackDepth++], + &ctx->ModelView ); + break; + case GL_PROJECTION: + if (ctx->ProjectionStackDepth>=MAX_PROJECTION_STACK_DEPTH) { + gl_error( ctx, GL_STACK_OVERFLOW, "glPushMatrix"); + return; + } + gl_matrix_copy( &ctx->ProjectionStack[ctx->ProjectionStackDepth++], + &ctx->ProjectionMatrix ); + + /* Save near and far projection values */ + ctx->NearFarStack[ctx->ProjectionStackDepth][0] + = ctx->NearFarStack[ctx->ProjectionStackDepth-1][0]; + ctx->NearFarStack[ctx->ProjectionStackDepth][1] + = ctx->NearFarStack[ctx->ProjectionStackDepth-1][1]; + break; + case GL_TEXTURE: + { + GLuint t = ctx->Texture.CurrentTransformUnit; + if (ctx->TextureStackDepth[t] >= MAX_TEXTURE_STACK_DEPTH) { + gl_error( ctx, GL_STACK_OVERFLOW, "glPushMatrix"); + return; + } + gl_matrix_copy( &ctx->TextureStack[t][ctx->TextureStackDepth[t]++], + &ctx->TextureMatrix[t] ); + } + break; + default: + gl_problem(ctx, "Bad matrix mode in gl_PushMatrix"); + } +} + + + +void gl_PopMatrix( GLcontext *ctx ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopMatrix"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glPopMatrix %s\n", + gl_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + + switch (ctx->Transform.MatrixMode) { + case GL_MODELVIEW: + if (ctx->ModelViewStackDepth==0) { + gl_error( ctx, GL_STACK_UNDERFLOW, "glPopMatrix"); + return; + } + gl_matrix_copy( &ctx->ModelView, + &ctx->ModelViewStack[--ctx->ModelViewStackDepth] ); + ctx->NewState |= NEW_MODELVIEW; + break; + case GL_PROJECTION: + if (ctx->ProjectionStackDepth==0) { + gl_error( ctx, GL_STACK_UNDERFLOW, "glPopMatrix"); + return; + } + + gl_matrix_copy( &ctx->ProjectionMatrix, + &ctx->ProjectionStack[--ctx->ProjectionStackDepth] ); + ctx->NewState |= NEW_PROJECTION; + + /* Device driver near/far values */ + { + GLfloat nearVal = ctx->NearFarStack[ctx->ProjectionStackDepth][0]; + GLfloat farVal = ctx->NearFarStack[ctx->ProjectionStackDepth][1]; + if (ctx->Driver.NearFar) { + (*ctx->Driver.NearFar)( ctx, nearVal, farVal ); + } + } + break; + case GL_TEXTURE: + { + GLuint t = ctx->Texture.CurrentTransformUnit; + if (ctx->TextureStackDepth[t]==0) { + gl_error( ctx, GL_STACK_UNDERFLOW, "glPopMatrix"); + return; + } + gl_matrix_copy(&ctx->TextureMatrix[t], + &ctx->TextureStack[t][--ctx->TextureStackDepth[t]]); + } + break; + default: + gl_problem(ctx, "Bad matrix mode in gl_PopMatrix"); + } +} + + + +void gl_LoadIdentity( GLcontext *ctx ) +{ + GLmatrix *mat = 0; + GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadIdentity"); + + MEMCPY( mat->m, Identity, 16*sizeof(GLfloat) ); + + if (mat->inv) + MEMCPY( mat->inv, Identity, 16*sizeof(GLfloat) ); + + mat->type = MATRIX_IDENTITY; + + /* Have to set this to dirty to make sure we recalculate the + * combined matrix later. The update_matrix in this case is a + * shortcircuit anyway... + */ + mat->flags = MAT_DIRTY_DEPENDENTS; +} + + +void gl_LoadMatrixf( GLcontext *ctx, const GLfloat *m ) +{ + GLmatrix *mat = 0; + GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadMatrix"); + + MEMCPY( mat->m, m, 16*sizeof(GLfloat) ); + mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL_OVER); + + if (ctx->Transform.MatrixMode == GL_PROJECTION) { + +#define M(row,col) m[col*4+row] + GLfloat c = M(2,2); + GLfloat d = M(2,3); +#undef M + GLfloat n = (c == 1.0 ? 0.0 : d / (c - 1.0)); + GLfloat f = (c == -1.0 ? 1.0 : d / (c + 1.0)); + + /* Need to keep a stack of near/far values in case the user + * push/pops the projection matrix stack so that we can call + * Driver.NearFar() after a pop. + */ + ctx->NearFarStack[ctx->ProjectionStackDepth][0] = n; + ctx->NearFarStack[ctx->ProjectionStackDepth][1] = f; + + if (ctx->Driver.NearFar) { + (*ctx->Driver.NearFar)( ctx, n, f ); + } + } +} + + + +/* + * Multiply the active matrix by an arbitary matrix. + */ +void gl_MultMatrixf( GLcontext *ctx, const GLfloat *m ) +{ + GLmatrix *mat = 0; + GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glMultMatrix" ); + matmul4( mat->m, mat->m, m ); + mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL_OVER); +} + + +/* + * Multiply the active matrix by an arbitary matrix. + */ +void gl_MultMatrixd( GLcontext *ctx, const GLdouble *m ) +{ + GLmatrix *mat = 0; + GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glMultMatrix" ); + matmul4fd( mat->m, mat->m, m ); + mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL_OVER); +} + + + + +/* + * Multiply a matrix by an array of floats with known properties. + */ +void gl_mat_mul_floats( GLmatrix *mat, const GLfloat *m, GLuint flags ) +{ + mat->flags |= (flags | + MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE | + MAT_DIRTY_DEPENDENTS); + + if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) + matmul34( mat->m, mat->m, m ); + else + matmul4( mat->m, mat->m, m ); + +} + +/* + * Multiply a matrix by an array of floats with known properties. + */ +void gl_mat_mul_mat( GLmatrix *mat, const GLmatrix *m ) +{ + mat->flags |= (m->flags | + MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE | + MAT_DIRTY_DEPENDENTS); + + if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) + matmul34( mat->m, mat->m, m->m ); + else + matmul4( mat->m, mat->m, m->m ); +} + + + +/* + * Execute a glRotate call + */ +void gl_Rotatef( GLcontext *ctx, + GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) +{ + GLfloat m[16]; + if (angle != 0.0F) { + GLmatrix *mat = 0; + GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glRotate" ); + + gl_rotation_matrix( angle, x, y, z, m ); + gl_mat_mul_floats( mat, m, MAT_FLAG_ROTATION ); + } +} + +/* + * Execute a glScale call + */ +void gl_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z ) +{ + GLmatrix *mat = 0; + GLfloat *m; + GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glScale"); + + m = mat->m; + m[0] *= x; m[4] *= y; m[8] *= z; + m[1] *= x; m[5] *= y; m[9] *= z; + m[2] *= x; m[6] *= y; m[10] *= z; + m[3] *= x; m[7] *= y; m[11] *= z; + + if (fabs(x - y) < 1e-8 && fabs(x - z) < 1e-8) + mat->flags |= MAT_FLAG_UNIFORM_SCALE; + else + mat->flags |= MAT_FLAG_GENERAL_SCALE; + + mat->flags |= (MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE | + MAT_DIRTY_DEPENDENTS); +} + +/* + * Execute a glTranslate call + */ +void gl_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z ) +{ + GLmatrix *mat = 0; + GLfloat *m; + GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glTranslate"); + m = mat->m; + m[12] = m[0] * x + m[4] * y + m[8] * z + m[12]; + m[13] = m[1] * x + m[5] * y + m[9] * z + m[13]; + m[14] = m[2] * x + m[6] * y + m[10] * z + m[14]; + m[15] = m[3] * x + m[7] * y + m[11] * z + m[15]; + + mat->flags |= (MAT_FLAG_TRANSLATION | + MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE | + MAT_DIRTY_DEPENDENTS); +} + + +/* + * Define a new viewport and reallocate auxillary buffers if the size of + * the window (color buffer) has changed. + */ +void gl_Viewport( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glViewport"); + + if (width<0 || height<0) { + gl_error( ctx, GL_INVALID_VALUE, "glViewport" ); + return; + } + + if (MESA_VERBOSE & VERBOSE_API) + fprintf(stderr, "glViewport %d %d %d %d\n", x, y, width, height); + + /* clamp width, and height to implementation dependent range */ + width = CLAMP( width, 1, MAX_WIDTH ); + height = CLAMP( height, 1, MAX_HEIGHT ); + + /* Save viewport */ + ctx->Viewport.X = x; + ctx->Viewport.Width = width; + ctx->Viewport.Y = y; + ctx->Viewport.Height = height; + + /* compute scale and bias values */ + ctx->Viewport.WindowMap.m[MAT_SX] = (GLfloat) width / 2.0F; + ctx->Viewport.WindowMap.m[MAT_TX] = ctx->Viewport.WindowMap.m[MAT_SX] + x; + ctx->Viewport.WindowMap.m[MAT_SY] = (GLfloat) height / 2.0F; + ctx->Viewport.WindowMap.m[MAT_TY] = ctx->Viewport.WindowMap.m[MAT_SY] + y; + + ctx->ModelProjectWinMatrixUptodate = GL_FALSE; + ctx->NewState |= NEW_VIEWPORT; + + /* Check if window/buffer has been resized and if so, reallocate the + * ancillary buffers. + */ + gl_ResizeBuffersMESA(ctx); + + + ctx->RasterMask &= WINCLIP_BIT; + + if ( ctx->Viewport.X<0 + || ctx->Viewport.X + ctx->Viewport.Width > ctx->Buffer->Width + || ctx->Viewport.Y<0 + || ctx->Viewport.Y + ctx->Viewport.Height > ctx->Buffer->Height) { + ctx->RasterMask |= WINCLIP_BIT; + } + + + if (ctx->Driver.Viewport) { + (*ctx->Driver.Viewport)( ctx, x, y, width, height ); + } +} + + + +void gl_DepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval ) +{ + /* + * nearval - specifies mapping of the near clipping plane to window + * coordinates, default is 0 + * farval - specifies mapping of the far clipping plane to window + * coordinates, default is 1 + * + * After clipping and div by w, z coords are in -1.0 to 1.0, + * corresponding to near and far clipping planes. glDepthRange + * specifies a linear mapping of the normalized z coords in + * this range to window z coords. + */ + GLfloat n, f; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthRange"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glDepthRange %f %f\n", nearval, farval); + + n = (GLfloat) CLAMP( nearval, 0.0, 1.0 ); + f = (GLfloat) CLAMP( farval, 0.0, 1.0 ); + + ctx->Viewport.Near = n; + ctx->Viewport.Far = f; + ctx->Viewport.WindowMap.m[MAT_SZ] = DEPTH_SCALE * ((f - n) / 2.0); + ctx->Viewport.WindowMap.m[MAT_TZ] = DEPTH_SCALE * ((f - n) / 2.0 + n); + + ctx->ModelProjectWinMatrixUptodate = GL_FALSE; + + if (ctx->Driver.DepthRange) { + (*ctx->Driver.DepthRange)( ctx, nearval, farval ); + } +} + + +void gl_calculate_model_project_matrix( GLcontext *ctx ) +{ + gl_matrix_mul( &ctx->ModelProjectMatrix, + &ctx->ProjectionMatrix, + &ctx->ModelView ); + + gl_matrix_analyze( &ctx->ModelProjectMatrix ); +} + + +void gl_matrix_ctr( GLmatrix *m ) +{ + m->inv = 0; + MEMCPY( m->m, Identity, sizeof(Identity)); + m->type = MATRIX_IDENTITY; + m->flags = MAT_DIRTY_DEPENDENTS; +} + +void gl_matrix_dtr( GLmatrix *m ) +{ + if (m->inv != 0) { + free(m->inv); + m->inv = 0; + } +} + +void gl_matrix_alloc_inv( GLmatrix *m ) +{ + if (m->inv == 0) { + m->inv = (GLfloat *)malloc(16*sizeof(GLfloat)); + MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) ); + } +} + +void gl_matrix_copy( GLmatrix *to, const GLmatrix *from ) +{ + MEMCPY( to->m, from->m, sizeof(Identity)); + to->flags = from->flags | MAT_DIRTY_DEPENDENTS; + to->type = from->type; + + if (to->inv != 0) { + if (from->inv == 0) { + gl_matrix_invert( to ); + } else { + MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16); + } + } +} + +void gl_matrix_mul( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b ) +{ + dest->flags = (a->flags | + b->flags | + MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE | + MAT_DIRTY_DEPENDENTS); + + if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D)) + matmul34( dest->m, a->m, b->m ); + else + matmul4( dest->m, a->m, b->m ); +} diff --git a/src/mesa/main/matrix.h b/src/mesa/main/matrix.h new file mode 100644 index 00000000000..f89993e316a --- /dev/null +++ b/src/mesa/main/matrix.h @@ -0,0 +1,115 @@ +/* $Id: matrix.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 MATRIX_H +#define MATRIX_H + + +#include "GL/gl.h" +#include "config.h" + +typedef struct { + GLfloat m[16]; + GLfloat *inv; /* optional */ + GLuint flags; + GLuint type; +} GLmatrix; + +#ifdef VMS +#define gl_calculate_model_project_matrix gl_calculate_model_project_matr +#endif + + +extern void gl_rotation_matrix( GLfloat angle, GLfloat x, GLfloat y, GLfloat z, + GLfloat m[] ); + + + +extern void gl_Frustum( GLcontext *ctx, + GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ); + +extern void gl_Ortho( GLcontext *ctx, + GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ); + +extern void gl_PushMatrix( GLcontext *ctx ); + +extern void gl_PopMatrix( GLcontext *ctx ); + +extern void gl_LoadIdentity( GLcontext *ctx ); + +extern void gl_LoadMatrixf( GLcontext *ctx, const GLfloat *m ); + +extern void gl_MatrixMode( GLcontext *ctx, GLenum mode ); + +extern void gl_MultMatrixf( GLcontext *ctx, const GLfloat *m ); + +extern void gl_mat_mul_floats( GLmatrix *mat, const GLfloat *m, GLuint flags ); +extern void gl_mat_mul_mat( GLmatrix *mat, const GLmatrix *mat2 ); + +extern void gl_Rotatef( GLcontext *ctx, + GLfloat angle, GLfloat x, GLfloat y, GLfloat z ); + +extern void gl_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z ); + +extern void gl_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z ); + +extern void gl_Viewport( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height ); + +extern void gl_DepthRange( GLcontext* ctx, GLclampd nearval, GLclampd farval ); + + + + + +extern void gl_calculate_model_project_matrix( GLcontext *ctx ); + + +extern void gl_matrix_ctr( GLmatrix *m ); + +extern void gl_matrix_dtr( GLmatrix *m ); + +extern void gl_matrix_alloc_inv( GLmatrix *m ); + +extern void gl_matrix_copy( GLmatrix *to, const GLmatrix *from ); + +extern void gl_matrix_mul( GLmatrix *dest, + const GLmatrix *a, + const GLmatrix *b ); + +extern void gl_matrix_analyze( GLmatrix *mat ); + + + +#endif diff --git a/src/mesa/main/mesa.conf b/src/mesa/main/mesa.conf new file mode 100644 index 00000000000..d24ee6bd9f3 --- /dev/null +++ b/src/mesa/main/mesa.conf @@ -0,0 +1,74 @@ +;; -*-lisp-*- +;; +;; KW: New mesa configuration file, syntax following a lisp style. +;; +;; valid syntax: +;; +;; (include filename) +;; - not implemented +;; +;; (config-mesa version configs) +;; +;; where: +;; version - is the version number of mesa for which the configuration +;; was written. Future versions will use this to check for upwards +;; compatibility. There is however no guarentee that old configurations +;; will continue to be respected. +;; +;; configs - is a list of valid configuration lists, as specified by: +;; +;; (set-var variable value) - not implemented, use to augment env vars +;; (set-env variable value) - not implemented, use to augment env vars +;; (default-hint variable value) +;; (disable-extension name) +;; +;; Mesa will look for an environment variable MESA_CONFIG, and try to +;; execute that profile. Otherwise, it will fallback to the profile +;; with the same name as the current mesa version. As default +;; profiles should normally be empty or near-empty, this should be +;; sufficiently powerful. +;; + + +;; Default profile - should normally be an empty list of +;; configurations. +;; +(config-mesa mesa3.1beta1 ()) + + + +;; Really is an empty config. +;; +(config-mesa empty ()) + + + +;; Turn off some compliance for the sake of speed. +;; +(config-mesa quake2 + ( + ;; Quake2 likes this extension, but it really hurts performance if + ;; you don't also disable software fallbacks, below. (And do + ;; something else to stop the eye-space calculations too...) + ;; + (disable-extension GL_EXT_point_parameters) + + ;; These hints are honoured only by the 3dfx driver - the X driver + ;; continues to function even if you specify hardware-only + ;; rendering. + ;; + ;(default-hint GL_ALLOW_DRAW_OBJ_HINT_PGI GL_TRUE) ; wishful thinking + ;(default-hint GL_ALLOW_DRAW_WIN_HINT_PGI GL_TRUE) ; allow 3dfx hardware... + ;(default-hint GL_ALLOW_DRAW_SPN_HINT_PGI GL_FALSE) ; no software spans + ;(default-hint GL_ALLOW_DRAW_MEM_HINT_PGI GL_FALSE) ; no softare pixels + + ;; Lock in the hints specified above. + ;; + (disable-extension GL_PGI_misc_hints))) + + + + + + + diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c new file mode 100644 index 00000000000..316c357af19 --- /dev/null +++ b/src/mesa/main/pixel.c @@ -0,0 +1,774 @@ +/* $Id: pixel.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +/* + * glPixelStore, glPixelTransfer, glPixelMap, glPixelZoom, etc. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include "context.h" +#include "macros.h" +#include "pixel.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/**********************************************************************/ +/***** glPixelZoom *****/ +/**********************************************************************/ + + + +void gl_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelZoom"); + + ctx->Pixel.ZoomX = xfactor; + ctx->Pixel.ZoomY = yfactor; +} + + + +/**********************************************************************/ +/***** glPixelStore *****/ +/**********************************************************************/ + + +void gl_PixelStorei( GLcontext *ctx, GLenum pname, GLint param ) +{ + /* NOTE: this call can't be compiled into the display list */ + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelStore"); + + + switch (pname) { + case GL_PACK_SWAP_BYTES: + ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE; + break; + case GL_PACK_LSB_FIRST: + ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE; + break; + case GL_PACK_ROW_LENGTH: + if (param<0) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + } + else { + ctx->Pack.RowLength = param; + } + break; + case GL_PACK_IMAGE_HEIGHT: + if (param<0) + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + else + ctx->Pack.ImageHeight = param; + break; + case GL_PACK_SKIP_PIXELS: + if (param<0) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + } + else { + ctx->Pack.SkipPixels = param; + } + break; + case GL_PACK_SKIP_ROWS: + if (param<0) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + } + else { + ctx->Pack.SkipRows = param; + } + break; + case GL_PACK_ALIGNMENT: + if (param==1 || param==2 || param==4 || param==8) { + ctx->Pack.Alignment = param; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + } + break; + case GL_UNPACK_SWAP_BYTES: + ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE; + break; + case GL_UNPACK_LSB_FIRST: + ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE; + break; + case GL_UNPACK_ROW_LENGTH: + if (param<0) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + } + else { + ctx->Unpack.RowLength = param; + } + break; + case GL_UNPACK_IMAGE_HEIGHT: + if (param<0) + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + else + ctx->Unpack.ImageHeight = param; + break; + case GL_UNPACK_SKIP_PIXELS: + if (param<0) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + } + else { + ctx->Unpack.SkipPixels = param; + } + break; + case GL_UNPACK_SKIP_ROWS: + if (param<0) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + } + else { + ctx->Unpack.SkipRows = param; + } + break; + case GL_UNPACK_ALIGNMENT: + if (param==1 || param==2 || param==4 || param==8) { + ctx->Unpack.Alignment = param; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glPixelStore" ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glPixelStore" ); + } +} + + + + + +/**********************************************************************/ +/***** glPixelMap *****/ +/**********************************************************************/ + + + +void gl_PixelMapfv( GLcontext *ctx, + GLenum map, GLint mapsize, const GLfloat *values ) +{ + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelMapfv"); + + + if (mapsize<0 || mapsize>MAX_PIXEL_MAP_TABLE) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); + return; + } + + if (map>=GL_PIXEL_MAP_S_TO_S && map<=GL_PIXEL_MAP_I_TO_A) { + /* test that mapsize is a power of two */ + GLuint p; + GLboolean ok = GL_FALSE; + for (p=1; p<=MAX_PIXEL_MAP_TABLE; p=p<<1) { + if ( (p&mapsize) == p ) { + ok = GL_TRUE; + break; + } + } + if (!ok) { + gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); + return; + } + } + + switch (map) { + case GL_PIXEL_MAP_S_TO_S: + ctx->Pixel.MapStoSsize = mapsize; + for (i=0;i<mapsize;i++) { + ctx->Pixel.MapStoS[i] = (GLint) values[i]; + } + break; + case GL_PIXEL_MAP_I_TO_I: + ctx->Pixel.MapItoIsize = mapsize; + for (i=0;i<mapsize;i++) { + ctx->Pixel.MapItoI[i] = (GLint) values[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + ctx->Pixel.MapItoRsize = mapsize; + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0, 1.0 ); + ctx->Pixel.MapItoR[i] = val; + ctx->Pixel.MapItoR8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_I_TO_G: + ctx->Pixel.MapItoGsize = mapsize; + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0, 1.0 ); + ctx->Pixel.MapItoG[i] = val; + ctx->Pixel.MapItoG8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_I_TO_B: + ctx->Pixel.MapItoBsize = mapsize; + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0, 1.0 ); + ctx->Pixel.MapItoB[i] = val; + ctx->Pixel.MapItoB8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_I_TO_A: + ctx->Pixel.MapItoAsize = mapsize; + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0, 1.0 ); + ctx->Pixel.MapItoA[i] = val; + ctx->Pixel.MapItoA8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_R_TO_R: + ctx->Pixel.MapRtoRsize = mapsize; + for (i=0;i<mapsize;i++) { + ctx->Pixel.MapRtoR[i] = CLAMP( values[i], 0.0, 1.0 ); + } + break; + case GL_PIXEL_MAP_G_TO_G: + ctx->Pixel.MapGtoGsize = mapsize; + for (i=0;i<mapsize;i++) { + ctx->Pixel.MapGtoG[i] = CLAMP( values[i], 0.0, 1.0 ); + } + break; + case GL_PIXEL_MAP_B_TO_B: + ctx->Pixel.MapBtoBsize = mapsize; + for (i=0;i<mapsize;i++) { + ctx->Pixel.MapBtoB[i] = CLAMP( values[i], 0.0, 1.0 ); + } + break; + case GL_PIXEL_MAP_A_TO_A: + ctx->Pixel.MapAtoAsize = mapsize; + for (i=0;i<mapsize;i++) { + ctx->Pixel.MapAtoA[i] = CLAMP( values[i], 0.0, 1.0 ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glPixelMapfv(map)" ); + } +} + + + + + +void gl_GetPixelMapfv( GLcontext *ctx, GLenum map, GLfloat *values ) +{ + GLint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetPixelMapfv"); + + switch (map) { + case GL_PIXEL_MAP_I_TO_I: + for (i=0;i<ctx->Pixel.MapItoIsize;i++) { + values[i] = (GLfloat) ctx->Pixel.MapItoI[i]; + } + break; + case GL_PIXEL_MAP_S_TO_S: + for (i=0;i<ctx->Pixel.MapStoSsize;i++) { + values[i] = (GLfloat) ctx->Pixel.MapStoS[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + MEMCPY(values,ctx->Pixel.MapItoR,ctx->Pixel.MapItoRsize*sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_G: + MEMCPY(values,ctx->Pixel.MapItoG,ctx->Pixel.MapItoGsize*sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_B: + MEMCPY(values,ctx->Pixel.MapItoB,ctx->Pixel.MapItoBsize*sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_A: + MEMCPY(values,ctx->Pixel.MapItoA,ctx->Pixel.MapItoAsize*sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_R_TO_R: + MEMCPY(values,ctx->Pixel.MapRtoR,ctx->Pixel.MapRtoRsize*sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_G_TO_G: + MEMCPY(values,ctx->Pixel.MapGtoG,ctx->Pixel.MapGtoGsize*sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_B_TO_B: + MEMCPY(values,ctx->Pixel.MapBtoB,ctx->Pixel.MapBtoBsize*sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_A_TO_A: + MEMCPY(values,ctx->Pixel.MapAtoA,ctx->Pixel.MapAtoAsize*sizeof(GLfloat)); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); + } +} + + +void gl_GetPixelMapuiv( GLcontext *ctx, GLenum map, GLuint *values ) +{ + GLint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetPixelMapfv"); + + switch (map) { + case GL_PIXEL_MAP_I_TO_I: + MEMCPY(values, ctx->Pixel.MapItoI, ctx->Pixel.MapItoIsize*sizeof(GLint)); + break; + case GL_PIXEL_MAP_S_TO_S: + MEMCPY(values, ctx->Pixel.MapStoS, ctx->Pixel.MapStoSsize*sizeof(GLint)); + break; + case GL_PIXEL_MAP_I_TO_R: + for (i=0;i<ctx->Pixel.MapItoRsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoR[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_G: + for (i=0;i<ctx->Pixel.MapItoGsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoG[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_B: + for (i=0;i<ctx->Pixel.MapItoBsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoB[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_A: + for (i=0;i<ctx->Pixel.MapItoAsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoA[i] ); + } + break; + case GL_PIXEL_MAP_R_TO_R: + for (i=0;i<ctx->Pixel.MapRtoRsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapRtoR[i] ); + } + break; + case GL_PIXEL_MAP_G_TO_G: + for (i=0;i<ctx->Pixel.MapGtoGsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapGtoG[i] ); + } + break; + case GL_PIXEL_MAP_B_TO_B: + for (i=0;i<ctx->Pixel.MapBtoBsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapBtoB[i] ); + } + break; + case GL_PIXEL_MAP_A_TO_A: + for (i=0;i<ctx->Pixel.MapAtoAsize;i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapAtoA[i] ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); + } +} + + +void gl_GetPixelMapusv( GLcontext *ctx, GLenum map, GLushort *values ) +{ + GLint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetPixelMapfv"); + + switch (map) { + case GL_PIXEL_MAP_I_TO_I: + for (i=0;i<ctx->Pixel.MapItoIsize;i++) { + values[i] = (GLushort) ctx->Pixel.MapItoI[i]; + } + break; + case GL_PIXEL_MAP_S_TO_S: + for (i=0;i<ctx->Pixel.MapStoSsize;i++) { + values[i] = (GLushort) ctx->Pixel.MapStoS[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + for (i=0;i<ctx->Pixel.MapItoRsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoR[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_G: + for (i=0;i<ctx->Pixel.MapItoGsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoG[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_B: + for (i=0;i<ctx->Pixel.MapItoBsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoB[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_A: + for (i=0;i<ctx->Pixel.MapItoAsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoA[i] ); + } + break; + case GL_PIXEL_MAP_R_TO_R: + for (i=0;i<ctx->Pixel.MapRtoRsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapRtoR[i] ); + } + break; + case GL_PIXEL_MAP_G_TO_G: + for (i=0;i<ctx->Pixel.MapGtoGsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapGtoG[i] ); + } + break; + case GL_PIXEL_MAP_B_TO_B: + for (i=0;i<ctx->Pixel.MapBtoBsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapBtoB[i] ); + } + break; + case GL_PIXEL_MAP_A_TO_A: + for (i=0;i<ctx->Pixel.MapAtoAsize;i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapAtoA[i] ); + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); + } +} + + + +/**********************************************************************/ +/***** glPixelTransfer *****/ +/**********************************************************************/ + + +/* + * Implements glPixelTransfer[fi] whether called immediately or from a + * display list. + */ +void gl_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelTransfer"); + + + switch (pname) { + case GL_MAP_COLOR: + ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE; + break; + case GL_MAP_STENCIL: + ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE; + break; + case GL_INDEX_SHIFT: + ctx->Pixel.IndexShift = (GLint) param; + break; + case GL_INDEX_OFFSET: + ctx->Pixel.IndexOffset = (GLint) param; + break; + case GL_RED_SCALE: + ctx->Pixel.RedScale = param; + break; + case GL_RED_BIAS: + ctx->Pixel.RedBias = param; + break; + case GL_GREEN_SCALE: + ctx->Pixel.GreenScale = param; + break; + case GL_GREEN_BIAS: + ctx->Pixel.GreenBias = param; + break; + case GL_BLUE_SCALE: + ctx->Pixel.BlueScale = param; + break; + case GL_BLUE_BIAS: + ctx->Pixel.BlueBias = param; + break; + case GL_ALPHA_SCALE: + ctx->Pixel.AlphaScale = param; + break; + case GL_ALPHA_BIAS: + ctx->Pixel.AlphaBias = param; + break; + case GL_DEPTH_SCALE: + ctx->Pixel.DepthScale = param; + break; + case GL_DEPTH_BIAS: + ctx->Pixel.DepthBias = param; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" ); + return; + } + + if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F || + ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F || + ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F || + ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) { + ctx->Pixel.ScaleOrBiasRGBA = GL_TRUE; + } + else { + ctx->Pixel.ScaleOrBiasRGBA = GL_FALSE; + } +} + + + + +/* + * Pixel processing functions + */ + + +/* + * Apply scale and bias factors to an array of RGBA pixels. + */ +void gl_scale_and_bias_color( const GLcontext *ctx, GLuint n, + GLfloat red[], GLfloat green[], + GLfloat blue[], GLfloat alpha[] ) +{ + GLuint i; + for (i=0;i<n;i++) { + GLfloat r = red[i] * ctx->Pixel.RedScale + ctx->Pixel.RedBias; + GLfloat g = green[i] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; + GLfloat b = blue[i] * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; + GLfloat a = alpha[i] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; + red[i] = CLAMP( r, 0.0F, 1.0F ); + green[i] = CLAMP( g, 0.0F, 1.0F ); + blue[i] = CLAMP( b, 0.0F, 1.0F ); + alpha[i] = CLAMP( a, 0.0F, 1.0F ); + } +} + + +/* + * Apply scale and bias factors to an array of RGBA pixels. + */ +void gl_scale_and_bias_rgba( const GLcontext *ctx, GLuint n, GLubyte rgba[][4] ) +{ + GLfloat rbias = ctx->Pixel.RedBias * 255.0F; + GLfloat gbias = ctx->Pixel.GreenBias * 255.0F; + GLfloat bbias = ctx->Pixel.BlueBias * 255.0F; + GLfloat abias = ctx->Pixel.AlphaBias * 255.0F; + GLuint i; + for (i=0;i<n;i++) { + GLint r = (GLint) (rgba[i][RCOMP] * ctx->Pixel.RedScale + rbias); + GLint g = (GLint) (rgba[i][GCOMP] * ctx->Pixel.GreenScale + gbias); + GLint b = (GLint) (rgba[i][BCOMP] * ctx->Pixel.BlueScale + bbias); + GLint a = (GLint) (rgba[i][ACOMP] * ctx->Pixel.AlphaScale + abias); + rgba[i][RCOMP] = CLAMP( r, 0, 255 ); + rgba[i][GCOMP] = CLAMP( g, 0, 255 ); + rgba[i][BCOMP] = CLAMP( b, 0, 255 ); + rgba[i][ACOMP] = CLAMP( a, 0, 255 ); + } +} + + +/* + * Apply pixel mapping to an array of RGBA pixels. + */ +void gl_map_rgba( const GLcontext *ctx, GLuint n, GLubyte rgba[][4] ) +{ + GLfloat rscale = (ctx->Pixel.MapRtoRsize - 1) / 255.0F; + GLfloat gscale = (ctx->Pixel.MapGtoGsize - 1) / 255.0F; + GLfloat bscale = (ctx->Pixel.MapBtoBsize - 1) / 255.0F; + GLfloat ascale = (ctx->Pixel.MapAtoAsize - 1) / 255.0F; + GLuint i; + for (i=0;i<n;i++) { + GLint ir = (GLint) (rgba[i][RCOMP] * rscale); + GLint ig = (GLint) (rgba[i][GCOMP] * gscale); + GLint ib = (GLint) (rgba[i][BCOMP] * bscale); + GLint ia = (GLint) (rgba[i][ACOMP] * ascale); + rgba[i][RCOMP] = (GLint) (ctx->Pixel.MapRtoR[ir] * 255.0F); + rgba[i][GCOMP] = (GLint) (ctx->Pixel.MapGtoG[ig] * 255.0F); + rgba[i][BCOMP] = (GLint) (ctx->Pixel.MapBtoB[ib] * 255.0F); + rgba[i][ACOMP] = (GLint) (ctx->Pixel.MapAtoA[ia] * 255.0F); + } +} + + +/* + * Apply pixel mapping to an array of RGBA pixels. + */ +void gl_map_color( const GLcontext *ctx, GLuint n, + GLfloat red[], GLfloat green[], + GLfloat blue[], GLfloat alpha[] ) +{ + GLfloat rscale = ctx->Pixel.MapRtoRsize-1; + GLfloat gscale = ctx->Pixel.MapGtoGsize-1; + GLfloat bscale = ctx->Pixel.MapBtoBsize-1; + GLfloat ascale = ctx->Pixel.MapAtoAsize-1; + GLuint i; + for (i=0;i<n;i++) { + red[i] = ctx->Pixel.MapRtoR[ (GLint) (red[i] * rscale) ]; + green[i] = ctx->Pixel.MapGtoG[ (GLint) (green[i] * gscale) ]; + blue[i] = ctx->Pixel.MapBtoB[ (GLint) (blue[i] * bscale) ]; + alpha[i] = ctx->Pixel.MapAtoA[ (GLint) (alpha[i] * ascale) ]; + } +} + + + +/* + * Apply color index shift and offset to an array of pixels. + */ +void gl_shift_and_offset_ci( const GLcontext *ctx, GLuint n, GLuint indexes[] ) +{ + GLint shift = ctx->Pixel.IndexShift; + GLint offset = ctx->Pixel.IndexOffset; + GLuint i; + if (shift > 0) { + for (i=0;i<n;i++) { + indexes[i] = (indexes[i] << shift) + offset; + } + } + else if (shift < 0) { + shift = -shift; + for (i=0;i<n;i++) { + indexes[i] = (indexes[i] >> shift) + offset; + } + } + else { + for (i=0;i<n;i++) { + indexes[i] = indexes[i] + offset; + } + } +} + + +/* + * Apply color index mapping to color indexes. + */ +void gl_map_ci( const GLcontext *ctx, GLuint n, GLuint index[] ) +{ + GLuint mask = ctx->Pixel.MapItoIsize - 1; + GLuint i; + for (i=0;i<n;i++) { + index[i] = ctx->Pixel.MapItoI[ index[i] & mask ]; + } +} + + +/* + * Map color indexes to rgb values. + */ +void gl_map_ci_to_rgba( const GLcontext *ctx, GLuint n, const GLuint index[], + GLubyte rgba[][4] ) +{ + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + const GLubyte *rMap = ctx->Pixel.MapItoR8; + const GLubyte *gMap = ctx->Pixel.MapItoG8; + const GLubyte *bMap = ctx->Pixel.MapItoB8; + const GLubyte *aMap = ctx->Pixel.MapItoA8; + GLuint i; + for (i=0;i<n;i++) { + rgba[i][RCOMP] = rMap[index[i] & rmask]; + rgba[i][GCOMP] = gMap[index[i] & gmask]; + rgba[i][BCOMP] = bMap[index[i] & bmask]; + rgba[i][ACOMP] = aMap[index[i] & amask]; + } +} + + +/* + * Map 8-bit color indexes to rgb values. + */ +void gl_map_ci8_to_rgba( const GLcontext *ctx, GLuint n, const GLubyte index[], + GLubyte rgba[][4] ) +{ + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + const GLubyte *rMap = ctx->Pixel.MapItoR8; + const GLubyte *gMap = ctx->Pixel.MapItoG8; + const GLubyte *bMap = ctx->Pixel.MapItoB8; + const GLubyte *aMap = ctx->Pixel.MapItoA8; + GLuint i; + for (i=0;i<n;i++) { + rgba[i][RCOMP] = rMap[index[i] & rmask]; + rgba[i][GCOMP] = gMap[index[i] & gmask]; + rgba[i][BCOMP] = bMap[index[i] & bmask]; + rgba[i][ACOMP] = aMap[index[i] & amask]; + } +} + + +void gl_map_ci_to_color( const GLcontext *ctx, GLuint n, const GLuint index[], + GLfloat r[], GLfloat g[], + GLfloat b[], GLfloat a[] ) +{ + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + GLuint i; + for (i=0;i<n;i++) { + r[i] = ctx->Pixel.MapItoR[index[i] & rmask]; + g[i] = ctx->Pixel.MapItoG[index[i] & gmask]; + b[i] = ctx->Pixel.MapItoB[index[i] & bmask]; + a[i] = ctx->Pixel.MapItoA[index[i] & amask]; + } +} + + + +void gl_shift_and_offset_stencil( const GLcontext *ctx, GLuint n, + GLstencil stencil[] ) +{ + GLuint i; + GLint shift = ctx->Pixel.IndexShift; + GLint offset = ctx->Pixel.IndexOffset; + if (shift > 0) { + for (i=0;i<n;i++) { + stencil[i] = (stencil[i] << shift) + offset; + } + } + else if (shift < 0) { + shift = -shift; + for (i=0;i<n;i++) { + stencil[i] = (stencil[i] >> shift) + offset; + } + } + else { + for (i=0;i<n;i++) { + stencil[i] = stencil[i] + offset; + } + } + +} + + + +void gl_map_stencil( const GLcontext *ctx, GLuint n, GLstencil stencil[] ) +{ + GLuint mask = ctx->Pixel.MapStoSsize - 1; + GLuint i; + for (i=0;i<n;i++) { + stencil[i] = ctx->Pixel.MapStoS[ stencil[i] & mask ]; + } +} + diff --git a/src/mesa/main/pixel.h b/src/mesa/main/pixel.h new file mode 100644 index 00000000000..c592d068539 --- /dev/null +++ b/src/mesa/main/pixel.h @@ -0,0 +1,111 @@ +/* $Id: pixel.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 PIXEL_H +#define PIXEL_H + + +#include "types.h" + + +/* + * API functions + */ + + +extern void gl_GetPixelMapfv( GLcontext *ctx, GLenum map, GLfloat *values ); + +extern void gl_GetPixelMapuiv( GLcontext *ctx, GLenum map, GLuint *values ); + +extern void gl_GetPixelMapusv( GLcontext *ctx, GLenum map, GLushort *values ); + + +extern void gl_PixelMapfv( GLcontext *ctx, + GLenum map, GLint mapsize, const GLfloat *values ); + +extern void gl_PixelStorei( GLcontext *ctx, GLenum pname, GLint param ); + +extern void gl_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param ); + +extern void gl_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor ); + + +/* + * Pixel processing functions + */ + +extern void gl_scale_and_bias_color( const GLcontext *ctx, GLuint n, + GLfloat red[], GLfloat green[], + GLfloat blue[], GLfloat alpha[] ); + + +extern void gl_scale_and_bias_rgba( const GLcontext *ctx, GLuint n, + GLubyte rgba[][4] ); + + +extern void gl_map_rgba( const GLcontext *ctx, GLuint n, GLubyte rgba[][4] ); + + +extern void gl_map_color( const GLcontext *ctx, GLuint n, + GLfloat red[], GLfloat green[], + GLfloat blue[], GLfloat alpha[] ); + + +extern void gl_shift_and_offset_ci( const GLcontext *ctx, GLuint n, + GLuint indexes[] ); + + +extern void gl_map_ci( const GLcontext *ctx, GLuint n, GLuint index[] ); + + +extern void gl_map_ci_to_rgba( const GLcontext *ctx, + GLuint n, const GLuint index[], + GLubyte rgba[][4] ); + + +extern void gl_map_ci8_to_rgba( const GLcontext *ctx, + GLuint n, const GLubyte index[], + GLubyte rgba[][4] ); + + +extern void gl_map_ci_to_color( const GLcontext *ctx, + GLuint n, const GLuint index[], + GLfloat r[], GLfloat g[], + GLfloat b[], GLfloat a[] ); + + +extern void gl_shift_and_offset_stencil( const GLcontext *ctx, GLuint n, + GLstencil indexes[] ); + + +extern void gl_map_stencil( const GLcontext *ctx, GLuint n, GLstencil index[] ); + + +#endif diff --git a/src/mesa/main/points.c b/src/mesa/main/points.c new file mode 100644 index 00000000000..928acc88913 --- /dev/null +++ b/src/mesa/main/points.c @@ -0,0 +1,1344 @@ +/* $Id: points.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include "context.h" +#include "feedback.h" +#include "macros.h" +#include "pb.h" +#include "span.h" +#include "texstate.h" +#include "types.h" +#include "vb.h" +#include "mmath.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +void gl_PointSize( GLcontext *ctx, GLfloat size ) +{ + if (size<=0.0) { + gl_error( ctx, GL_INVALID_VALUE, "glPointSize" ); + return; + } + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPointSize"); + + if (ctx->Point.Size != size) { + ctx->Point.Size = size; + ctx->TriangleCaps &= DD_POINT_SIZE; + if (size != 1.0) ctx->TriangleCaps |= DD_POINT_SIZE; + ctx->NewState |= NEW_RASTER_OPS; + } +} + + + +void gl_PointParameterfvEXT( GLcontext *ctx, GLenum pname, + const GLfloat *params) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPointParameterfvEXT"); + if(pname==GL_DISTANCE_ATTENUATION_EXT) { + GLboolean tmp = ctx->Point.Attenuated; + COPY_3V(ctx->Point.Params,params); + ctx->Point.Attenuated = (params[0] != 1.0 || + params[1] != 0.0 || + params[2] != 0.0); + + if (tmp != ctx->Point.Attenuated) { + ctx->Enabled ^= ENABLE_POINT_ATTEN; + ctx->TriangleCaps ^= DD_POINT_ATTEN; + ctx->NewState |= NEW_RASTER_OPS; + } + } else { + if (*params<0.0 ) { + gl_error( ctx, GL_INVALID_VALUE, "glPointParameterfvEXT" ); + return; + } + switch (pname) { + case GL_POINT_SIZE_MIN_EXT: + ctx->Point.MinSize=*params; + break; + case GL_POINT_SIZE_MAX_EXT: + ctx->Point.MaxSize=*params; + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + ctx->Point.Threshold=*params; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glPointParameterfvEXT" ); + return; + } + } + ctx->NewState |= NEW_RASTER_OPS; +} + + +/**********************************************************************/ +/***** Rasterization *****/ +/**********************************************************************/ + + +/* + * There are 3 pairs (RGBA, CI) of point rendering functions: + * 1. simple: size=1 and no special rasterization functions (fastest) + * 2. size1: size=1 and any rasterization functions + * 3. general: any size and rasterization functions (slowest) + * + * All point rendering functions take the same two arguments: first and + * last which specify that the points specified by VB[first] through + * VB[last] are to be rendered. + */ + + + +/* + * Put points in feedback buffer. + */ +static void feedback_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + GLuint texUnit = ctx->Texture.CurrentTransformUnit; + GLuint tsize = VB->TexCoordPtr[texUnit]->size; + GLuint i; + GLfloat texcoord[4]; + + ASSIGN_4V(texcoord, 0,0,0,1); + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLfloat x, y, z, w, invq; + GLfloat color[4]; + x = VB->Win.data[i][0]; + y = VB->Win.data[i][1]; + z = VB->Win.data[i][2] / DEPTH_SCALE; + w = VB->ClipPtr->data[i][3]; + + if (tsize == 4) { + invq = 1.0F / VB->TexCoordPtr[texUnit]->data[i][3]; + texcoord[0] = VB->TexCoordPtr[texUnit]->data[i][0] * invq; + texcoord[1] = VB->TexCoordPtr[texUnit]->data[i][1] * invq; + texcoord[2] = VB->TexCoordPtr[texUnit]->data[i][2] * invq; + texcoord[3] = VB->TexCoordPtr[texUnit]->data[i][3]; + } else { + COPY_SZ_4V(texcoord, tsize, VB->TexCoordPtr[texUnit]->data[i]); + } + + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POINT_TOKEN ); + + UBYTE_RGBA_TO_FLOAT_RGBA( color, VB->ColorPtr->data[i] ); + + gl_feedback_vertex( ctx, x, y, z, w, color, + (GLfloat) VB->IndexPtr->data[i], texcoord +); + } + } +} + + + +/* + * Put points in selection buffer. + */ +static void select_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + GLuint i; + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + gl_update_hitflag( ctx, VB->Win.data[i][2] / DEPTH_SCALE ); + } + } +} + + +/* + * CI points with size == 1.0 + */ +void size1_ci_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLfloat *win; + GLint *pbx = PB->x, *pby = PB->y; + GLdepth *pbz = PB->z; + GLuint *pbi = PB->i; + GLuint pbcount = PB->count; + GLuint i; + + win = &VB->Win.data[first][0]; + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + pbx[pbcount] = (GLint) win[0]; + pby[pbcount] = (GLint) win[1]; + pbz[pbcount] = (GLint) (win[2] + ctx->PointZoffset); + pbi[pbcount] = VB->IndexPtr->data[i]; + pbcount++; + } + win += 3; + } + PB->count = pbcount; + PB_CHECK_FLUSH(ctx, PB); +} + + + +/* + * RGBA points with size == 1.0 + */ +static void size1_rgba_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint red, green, blue, alpha; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + alpha = VB->ColorPtr->data[i][3]; + + PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue, alpha ); + } + } + PB_CHECK_FLUSH(ctx,PB); +} + + + +/* + * General CI points. + */ +static void general_ci_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + GLint isize = (GLint) (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F); + GLint radius = isize >> 1; + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint x0, x1, y0, y1; + GLint ix, iy; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + if (isize & 1) { + /* odd size */ + x0 = x - radius; + x1 = x + radius; + y0 = y - radius; + y1 = y + radius; + } + else { + /* even size */ + x0 = (GLint) (x + 1.5F) - radius; + x1 = x0 + isize - 1; + y0 = (GLint) (y + 1.5F) - radius; + y1 = y0 + isize - 1; + } + + PB_SET_INDEX( ctx, PB, VB->IndexPtr->data[i] ); + + for (iy=y0;iy<=y1;iy++) { + for (ix=x0;ix<=x1;ix++) { + PB_WRITE_PIXEL( PB, ix, iy, z ); + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } +} + + +/* + * General RGBA points. + */ +static void general_rgba_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + GLint isize = (GLint) (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F); + GLint radius = isize >> 1; + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint x0, x1, y0, y1; + GLint ix, iy; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + if (isize & 1) { + /* odd size */ + x0 = x - radius; + x1 = x + radius; + y0 = y - radius; + y1 = y + radius; + } + else { + /* even size */ + x0 = (GLint) (x + 1.5F) - radius; + x1 = x0 + isize - 1; + y0 = (GLint) (y + 1.5F) - radius; + y1 = y0 + isize - 1; + } + + PB_SET_COLOR( ctx, PB, + VB->ColorPtr->data[i][0], + VB->ColorPtr->data[i][1], + VB->ColorPtr->data[i][2], + VB->ColorPtr->data[i][3] ); + + for (iy=y0;iy<=y1;iy++) { + for (ix=x0;ix<=x1;ix++) { + PB_WRITE_PIXEL( PB, ix, iy, z ); + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } +} + + + + +/* + * Textured RGBA points. + */ +static void textured_rgba_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint x0, x1, y0, y1; + GLint ix, iy; + GLint isize, radius; + GLint red, green, blue, alpha; + GLfloat s, t, u; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + isize = (GLint) + (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F); + if (isize<1) { + isize = 1; + } + radius = isize >> 1; + + if (isize & 1) { + /* odd size */ + x0 = x - radius; + x1 = x + radius; + y0 = y - radius; + y1 = y + radius; + } + else { + /* even size */ + x0 = (GLint) (x + 1.5F) - radius; + x1 = x0 + isize - 1; + y0 = (GLint) (y + 1.5F) - radius; + y1 = y0 + isize - 1; + } + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + alpha = VB->ColorPtr->data[i][3]; + + switch (VB->TexCoordPtr[0]->size) { + case 4: + s = VB->TexCoordPtr[0]->data[i][0]/VB->TexCoordPtr[0]->data[i][3]; + t = VB->TexCoordPtr[0]->data[i][1]/VB->TexCoordPtr[0]->data[i][3]; + u = VB->TexCoordPtr[0]->data[i][2]/VB->TexCoordPtr[0]->data[i][3]; + break; + case 3: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = VB->TexCoordPtr[0]->data[i][2]; + break; + case 2: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = 0.0; + break; + case 1: + s = VB->TexCoordPtr[0]->data[i][0]; + t = 0.0; + u = 0.0; + break; + } + + + + +/* don't think this is needed + PB_SET_COLOR( red, green, blue, alpha ); +*/ + + for (iy=y0;iy<=y1;iy++) { + for (ix=x0;ix<=x1;ix++) { + PB_WRITE_TEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u ); + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } +} + + +/* + * Multitextured RGBA points. + */ +static void multitextured_rgba_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint x0, x1, y0, y1; + GLint ix, iy; + GLint isize, radius; + GLint red, green, blue, alpha; + GLfloat s, t, u; + GLfloat s1, t1, u1; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + isize = (GLint) + (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F); + if (isize<1) { + isize = 1; + } + radius = isize >> 1; + + if (isize & 1) { + /* odd size */ + x0 = x - radius; + x1 = x + radius; + y0 = y - radius; + y1 = y + radius; + } + else { + /* even size */ + x0 = (GLint) (x + 1.5F) - radius; + x1 = x0 + isize - 1; + y0 = (GLint) (y + 1.5F) - radius; + y1 = y0 + isize - 1; + } + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + alpha = VB->ColorPtr->data[i][3]; + + switch (VB->TexCoordPtr[0]->size) { + case 4: + s = VB->TexCoordPtr[0]->data[i][0]/VB->TexCoordPtr[0]->data[i][3]; + t = VB->TexCoordPtr[0]->data[i][1]/VB->TexCoordPtr[0]->data[i][3]; + u = VB->TexCoordPtr[0]->data[i][2]/VB->TexCoordPtr[0]->data[i][3]; + break; + case 3: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = VB->TexCoordPtr[0]->data[i][2]; + break; + case 2: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = 0.0; + break; + case 1: + s = VB->TexCoordPtr[0]->data[i][0]; + t = 0.0; + u = 0.0; + break; + } + + switch (VB->TexCoordPtr[1]->size) { + case 4: + s1 = VB->TexCoordPtr[1]->data[i][0]/VB->TexCoordPtr[1]->data[i][3]; + t1 = VB->TexCoordPtr[1]->data[i][1]/VB->TexCoordPtr[1]->data[i][3]; + u1 = VB->TexCoordPtr[1]->data[i][2]/VB->TexCoordPtr[1]->data[i][3]; + break; + case 3: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = VB->TexCoordPtr[1]->data[i][2]; + break; + case 2: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = 0.0; + break; + case 1: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = 0.0; + u1 = 0.0; + break; + } + + for (iy=y0;iy<=y1;iy++) { + for (ix=x0;ix<=x1;ix++) { + PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u, s1, t1, u1 ); + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } +} + + + + +/* + * Antialiased points with or without texture mapping. + */ +static void antialiased_rgba_points( GLcontext *ctx, + GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + GLfloat radius, rmin, rmax, rmin2, rmax2, cscale; + + radius = CLAMP( ctx->Point.Size, MIN_POINT_SIZE, MAX_POINT_SIZE ) * 0.5F; + rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ + rmax = radius + 0.7071F; + rmin2 = rmin*rmin; + rmax2 = rmax*rmax; + cscale = 256.0F / (rmax2-rmin2); + + if (ctx->Texture.ReallyEnabled) { + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint xmin, ymin, xmax, ymax; + GLint x, y, z; + GLint red, green, blue, alpha; + GLfloat s, t, u; + GLfloat s1, t1, u1; + + xmin = (GLint) (VB->Win.data[i][0] - radius); + xmax = (GLint) (VB->Win.data[i][0] + radius); + ymin = (GLint) (VB->Win.data[i][1] - radius); + ymax = (GLint) (VB->Win.data[i][1] + radius); + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + + switch (VB->TexCoordPtr[0]->size) { + case 4: + s = (VB->TexCoordPtr[0]->data[i][0]/ + VB->TexCoordPtr[0]->data[i][3]); + t = (VB->TexCoordPtr[0]->data[i][1]/ + VB->TexCoordPtr[0]->data[i][3]); + u = (VB->TexCoordPtr[0]->data[i][2]/ + VB->TexCoordPtr[0]->data[i][3]); + break; + case 3: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = VB->TexCoordPtr[0]->data[i][2]; + break; + case 2: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = 0.0; + break; + case 1: + s = VB->TexCoordPtr[0]->data[i][0]; + t = 0.0; + u = 0.0; + break; + } + + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) { + /* Multitextured! This is probably a slow enough path that + there's no reason to specialize the multitexture case. */ + switch (VB->TexCoordPtr[1]->size) { + case 4: + s1 = ( VB->TexCoordPtr[1]->data[i][0] / + VB->TexCoordPtr[1]->data[i][3]); + t1 = ( VB->TexCoordPtr[1]->data[i][1] / + VB->TexCoordPtr[1]->data[i][3]); + u1 = ( VB->TexCoordPtr[1]->data[i][2] / + VB->TexCoordPtr[1]->data[i][3]); + break; + case 3: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = VB->TexCoordPtr[1]->data[i][2]; + break; + case 2: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = 0.0; + break; + case 1: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = 0.0; + u1 = 0.0; + break; + } + } + + for (y=ymin;y<=ymax;y++) { + for (x=xmin;x<=xmax;x++) { + GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0]; + GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1]; + GLfloat dist2 = dx*dx + dy*dy; + if (dist2<rmax2) { + alpha = VB->ColorPtr->data[i][3]; + if (dist2>=rmin2) { + GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale); + /* coverage is in [0,256] */ + alpha = (alpha * coverage) >> 8; + } + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) { + PB_WRITE_MULTITEX_PIXEL( PB, x,y,z, red, green, blue, + alpha, s, t, u, s1, t1, u1 ); + } else { + PB_WRITE_TEX_PIXEL( PB, x,y,z, red, green, blue, + alpha, s, t, u ); + } + } + } + } + + PB_CHECK_FLUSH(ctx,PB); + } + } + } + else { + /* Not texture mapped */ + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint xmin, ymin, xmax, ymax; + GLint x, y, z; + GLint red, green, blue, alpha; + + xmin = (GLint) (VB->Win.data[i][0] - radius); + xmax = (GLint) (VB->Win.data[i][0] + radius); + ymin = (GLint) (VB->Win.data[i][1] - radius); + ymax = (GLint) (VB->Win.data[i][1] + radius); + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + + for (y=ymin;y<=ymax;y++) { + for (x=xmin;x<=xmax;x++) { + GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0]; + GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1]; + GLfloat dist2 = dx*dx + dy*dy; + if (dist2<rmax2) { + alpha = VB->ColorPtr->data[i][3]; + if (dist2>=rmin2) { + GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale); + /* coverage is in [0,256] */ + alpha = (alpha * coverage) >> 8; + } + PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue, + alpha ); + } + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } + } +} + + + +/* + * Null rasterizer for measuring transformation speed. + */ +static void null_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + (void) ctx; + (void) first; + (void) last; +} + + + +/* Definition of the functions for GL_EXT_point_parameters */ + +/* Calculates the distance attenuation formula of a vector of points in + * eye space coordinates + */ +static void dist3(GLfloat *out, GLuint first, GLuint last, + const GLcontext *ctx, const GLvector4f *v) +{ + GLuint stride = v->stride; + GLfloat *p = VEC_ELT(v, GLfloat, first); + GLuint i; + + for (i = first ; i <= last ; i++, STRIDE_F(p, stride) ) + { + GLfloat dist = GL_SQRT(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]); + out[i] = 1/(ctx->Point.Params[0]+ + dist * (ctx->Point.Params[1] + + dist * ctx->Point.Params[2])); + } +} + +static void dist2(GLfloat *out, GLuint first, GLuint last, + const GLcontext *ctx, const GLvector4f *v) +{ + GLuint stride = v->stride; + GLfloat *p = VEC_ELT(v, GLfloat, first); + GLuint i; + + for (i = first ; i <= last ; i++, STRIDE_F(p, stride) ) + { + GLfloat dist = GL_SQRT(p[0]*p[0]+p[1]*p[1]); + out[i] = 1/(ctx->Point.Params[0]+ + dist * (ctx->Point.Params[1] + + dist * ctx->Point.Params[2])); + } +} + + +typedef void (*dist_func)(GLfloat *out, GLuint first, GLuint last, + const GLcontext *ctx, const GLvector4f *v); + + +static dist_func eye_dist_tab[5] = { + 0, + 0, + dist2, + dist3, + dist3 +}; + + +static void clip_dist(GLfloat *out, GLuint first, GLuint last, + const GLcontext *ctx, GLvector4f *clip) +{ + /* this is never called */ + gl_problem(NULL, "clip_dist() called - dead code!\n"); + + (void) out; + (void) first; + (void) last; + (void) ctx; + (void) clip; + +#if 0 + GLuint i; + const GLfloat *from = (GLfloat *)clip_vec->start; + const GLuint stride = clip_vec->stride; + + for (i = first ; i <= last ; i++ ) + { + GLfloat dist = win[i][2]; + out[i] = 1/(ctx->Point.Params[0]+ + dist * (ctx->Point.Params[1] + + dist * ctx->Point.Params[2])); + } +#endif +} + + + +/* + * Distance Attenuated General CI points. + */ +static void dist_atten_general_ci_points( GLcontext *ctx, GLuint first, + GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + GLfloat psize,dsize; + GLfloat dist[VB_SIZE]; + psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE); + + if (ctx->NeedEyeCoords) + (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr ); + else + clip_dist( dist, first, last, ctx, VB->ClipPtr ); + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint x0, x1, y0, y1; + GLint ix, iy; + GLint isize, radius; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + dsize=psize*dist[i]; + if(dsize>=ctx->Point.Threshold) { + isize=(GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F); + } else { + isize=(GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F); + } + radius = isize >> 1; + + if (isize & 1) { + /* odd size */ + x0 = x - radius; + x1 = x + radius; + y0 = y - radius; + y1 = y + radius; + } + else { + /* even size */ + x0 = (GLint) (x + 1.5F) - radius; + x1 = x0 + isize - 1; + y0 = (GLint) (y + 1.5F) - radius; + y1 = y0 + isize - 1; + } + + PB_SET_INDEX( ctx, PB, VB->IndexPtr->data[i] ); + + for (iy=y0;iy<=y1;iy++) { + for (ix=x0;ix<=x1;ix++) { + PB_WRITE_PIXEL( PB, ix, iy, z ); + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } +} + +/* + * Distance Attenuated General RGBA points. + */ +static void dist_atten_general_rgba_points( GLcontext *ctx, GLuint first, + GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + GLubyte alpha; + GLfloat psize,dsize; + GLfloat dist[VB_SIZE]; + psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE); + + if (ctx->NeedEyeCoords) + (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr ); + else + clip_dist( dist, first, last, ctx, VB->ClipPtr ); + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint x0, x1, y0, y1; + GLint ix, iy; + GLint isize, radius; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + dsize=psize*dist[i]; + if (dsize >= ctx->Point.Threshold) { + isize = (GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F); + alpha = VB->ColorPtr->data[i][3]; + } + else { + isize = (GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F); + dsize /= ctx->Point.Threshold; + alpha = (GLint) (VB->ColorPtr->data[i][3]* (dsize*dsize)); + } + radius = isize >> 1; + + if (isize & 1) { + /* odd size */ + x0 = x - radius; + x1 = x + radius; + y0 = y - radius; + y1 = y + radius; + } + else { + /* even size */ + x0 = (GLint) (x + 1.5F) - radius; + x1 = x0 + isize - 1; + y0 = (GLint) (y + 1.5F) - radius; + y1 = y0 + isize - 1; + } + + PB_SET_COLOR( ctx, PB, + VB->ColorPtr->data[i][0], + VB->ColorPtr->data[i][1], + VB->ColorPtr->data[i][2], + alpha ); + + for (iy=y0;iy<=y1;iy++) { + for (ix=x0;ix<=x1;ix++) { + PB_WRITE_PIXEL( PB, ix, iy, z ); + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } +} + +/* + * Distance Attenuated Textured RGBA points. + */ +static void dist_atten_textured_rgba_points( GLcontext *ctx, GLuint first, + GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + GLfloat psize,dsize; + GLfloat dist[VB_SIZE]; + psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE); + + if (ctx->NeedEyeCoords) + (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr ); + else + clip_dist( dist, first, last, ctx, VB->ClipPtr ); + + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint x, y, z; + GLint x0, x1, y0, y1; + GLint ix, iy; + GLint isize, radius; + GLint red, green, blue, alpha; + GLfloat s, t, u; + GLfloat s1, t1, u1; + + x = (GLint) VB->Win.data[i][0]; + y = (GLint) VB->Win.data[i][1]; + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + dsize=psize*dist[i]; + if(dsize>=ctx->Point.Threshold) { + isize=(GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F); + alpha=VB->ColorPtr->data[i][3]; + } else { + isize=(GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F); + dsize/=ctx->Point.Threshold; + alpha = (GLint) (VB->ColorPtr->data[i][3]* (dsize*dsize)); + } + + if (isize<1) { + isize = 1; + } + radius = isize >> 1; + + if (isize & 1) { + /* odd size */ + x0 = x - radius; + x1 = x + radius; + y0 = y - radius; + y1 = y + radius; + } + else { + /* even size */ + x0 = (GLint) (x + 1.5F) - radius; + x1 = x0 + isize - 1; + y0 = (GLint) (y + 1.5F) - radius; + y1 = y0 + isize - 1; + } + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + + switch (VB->TexCoordPtr[0]->size) { + case 4: + s = (VB->TexCoordPtr[0]->data[i][0]/ + VB->TexCoordPtr[0]->data[i][3]); + t = (VB->TexCoordPtr[0]->data[i][1]/ + VB->TexCoordPtr[0]->data[i][3]); + u = (VB->TexCoordPtr[0]->data[i][2]/ + VB->TexCoordPtr[0]->data[i][3]); + break; + case 3: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = VB->TexCoordPtr[0]->data[i][2]; + break; + case 2: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = 0.0; + break; + case 1: + s = VB->TexCoordPtr[0]->data[i][0]; + t = 0.0; + u = 0.0; + break; + } + + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) { + /* Multitextured! This is probably a slow enough path that + there's no reason to specialize the multitexture case. */ + switch (VB->TexCoordPtr[1]->size) { + case 4: + s1 = ( VB->TexCoordPtr[1]->data[i][0] / + VB->TexCoordPtr[1]->data[i][3] ); + t1 = ( VB->TexCoordPtr[1]->data[i][1] / + VB->TexCoordPtr[1]->data[i][3] ); + u1 = ( VB->TexCoordPtr[1]->data[i][2] / + VB->TexCoordPtr[1]->data[i][3] ); + break; + case 3: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = VB->TexCoordPtr[1]->data[i][2]; + break; + case 2: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = 0.0; + break; + case 1: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = 0.0; + u1 = 0.0; + break; + } + } + +/* don't think this is needed + PB_SET_COLOR( red, green, blue, alpha ); +*/ + + for (iy=y0;iy<=y1;iy++) { + for (ix=x0;ix<=x1;ix++) { + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) { + PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u, s1, t1, u1 ); + } else { + PB_WRITE_TEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u ); + } + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } +} + +/* + * Distance Attenuated Antialiased points with or without texture mapping. + */ +static void dist_atten_antialiased_rgba_points( GLcontext *ctx, + GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint i; + GLfloat radius, rmin, rmax, rmin2, rmax2, cscale; + GLfloat psize,dsize,alphaf; + GLfloat dist[VB_SIZE]; + psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE); + + if (ctx->NeedEyeCoords) + (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr ); + else + clip_dist( dist, first, last, ctx, VB->ClipPtr ); + + if (ctx->Texture.ReallyEnabled) { + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint xmin, ymin, xmax, ymax; + GLint x, y, z; + GLint red, green, blue, alpha; + GLfloat s, t, u; + GLfloat s1, t1, u1; + + dsize=psize*dist[i]; + if(dsize>=ctx->Point.Threshold) { + radius=(MIN2(dsize,ctx->Point.MaxSize)*0.5F); + alphaf=1.0; + } else { + radius=(MAX2(ctx->Point.Threshold,ctx->Point.MinSize)*0.5F); + dsize/=ctx->Point.Threshold; + alphaf=(dsize*dsize); + } + rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ + rmax = radius + 0.7071F; + rmin2 = rmin*rmin; + rmax2 = rmax*rmax; + cscale = 256.0F / (rmax2-rmin2); + + xmin = (GLint) (VB->Win.data[i][0] - radius); + xmax = (GLint) (VB->Win.data[i][0] + radius); + ymin = (GLint) (VB->Win.data[i][1] - radius); + ymax = (GLint) (VB->Win.data[i][1] + radius); + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + + switch (VB->TexCoordPtr[0]->size) { + case 4: + s = (VB->TexCoordPtr[0]->data[i][0]/ + VB->TexCoordPtr[0]->data[i][3]); + t = (VB->TexCoordPtr[0]->data[i][1]/ + VB->TexCoordPtr[0]->data[i][3]); + u = (VB->TexCoordPtr[0]->data[i][2]/ + VB->TexCoordPtr[0]->data[i][3]); + break; + case 3: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = VB->TexCoordPtr[0]->data[i][2]; + break; + case 2: + s = VB->TexCoordPtr[0]->data[i][0]; + t = VB->TexCoordPtr[0]->data[i][1]; + u = 0.0; + break; + case 1: + s = VB->TexCoordPtr[0]->data[i][0]; + t = 0.0; + u = 0.0; + break; + } + + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) { + /* Multitextured! This is probably a slow enough path that + there's no reason to specialize the multitexture case. */ + switch (VB->TexCoordPtr[1]->size) { + case 4: + s1 = ( VB->TexCoordPtr[1]->data[i][0] / + VB->TexCoordPtr[1]->data[i][3] ); + t1 = ( VB->TexCoordPtr[1]->data[i][1] / + VB->TexCoordPtr[1]->data[i][3] ); + u1 = ( VB->TexCoordPtr[1]->data[i][2] / + VB->TexCoordPtr[1]->data[i][3] ); + break; + case 3: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = VB->TexCoordPtr[1]->data[i][2]; + break; + case 2: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = VB->TexCoordPtr[1]->data[i][1]; + u1 = 0.0; + break; + case 1: + s1 = VB->TexCoordPtr[1]->data[i][0]; + t1 = 0.0; + u1 = 0.0; + break; + } + } + + for (y=ymin;y<=ymax;y++) { + for (x=xmin;x<=xmax;x++) { + GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0]; + GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1]; + GLfloat dist2 = dx*dx + dy*dy; + if (dist2<rmax2) { + alpha = VB->ColorPtr->data[i][3]; + if (dist2>=rmin2) { + GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale); + /* coverage is in [0,256] */ + alpha = (alpha * coverage) >> 8; + } + alpha = (GLint) (alpha * alphaf); + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) { + PB_WRITE_MULTITEX_PIXEL( PB, x,y,z, red, green, blue, alpha, s, t, u, s1, t1, u1 ); + } else { + PB_WRITE_TEX_PIXEL( PB, x,y,z, red, green, blue, alpha, s, t, u ); + } + } + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } + } + else { + /* Not texture mapped */ + for (i=first;i<=last;i++) { + if (VB->ClipMask[i]==0) { + GLint xmin, ymin, xmax, ymax; + GLint x, y, z; + GLint red, green, blue, alpha; + + dsize=psize*dist[i]; + if(dsize>=ctx->Point.Threshold) { + radius=(MIN2(dsize,ctx->Point.MaxSize)*0.5F); + alphaf=1.0; + } else { + radius=(MAX2(ctx->Point.Threshold,ctx->Point.MinSize)*0.5F); + dsize/=ctx->Point.Threshold; + alphaf=(dsize*dsize); + } + rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ + rmax = radius + 0.7071F; + rmin2 = rmin*rmin; + rmax2 = rmax*rmax; + cscale = 256.0F / (rmax2-rmin2); + + xmin = (GLint) (VB->Win.data[i][0] - radius); + xmax = (GLint) (VB->Win.data[i][0] + radius); + ymin = (GLint) (VB->Win.data[i][1] - radius); + ymax = (GLint) (VB->Win.data[i][1] + radius); + z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset); + + red = VB->ColorPtr->data[i][0]; + green = VB->ColorPtr->data[i][1]; + blue = VB->ColorPtr->data[i][2]; + + for (y=ymin;y<=ymax;y++) { + for (x=xmin;x<=xmax;x++) { + GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0]; + GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1]; + GLfloat dist2 = dx*dx + dy*dy; + if (dist2<rmax2) { + alpha = VB->ColorPtr->data[i][3]; + if (dist2>=rmin2) { + GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale); + /* coverage is in [0,256] */ + alpha = (alpha * coverage) >> 8; + } + alpha = (GLint) (alpha * alphaf); + PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue, alpha ) + ; + } + } + } + PB_CHECK_FLUSH(ctx,PB); + } + } + } +} + + +/* + * Examine the current context to determine which point drawing function + * should be used. + */ +void gl_set_point_function( GLcontext *ctx ) +{ + GLboolean rgbmode = ctx->Visual->RGBAflag; + + if (ctx->RenderMode==GL_RENDER) { + if (ctx->NoRaster) { + ctx->Driver.PointsFunc = null_points; + return; + } + if (ctx->Driver.PointsFunc) { + /* Device driver will draw points. */ + ctx->IndirectTriangles &= ~DD_POINT_SW_RASTERIZE; + return; + } + + if (!ctx->Point.Attenuated) { + if (ctx->Point.SmoothFlag && rgbmode) { + ctx->Driver.PointsFunc = antialiased_rgba_points; + } + else if (ctx->Texture.ReallyEnabled) { + if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) { + ctx->Driver.PointsFunc = multitextured_rgba_points; + } + else { + ctx->Driver.PointsFunc = textured_rgba_points; + } + } + else if (ctx->Point.Size==1.0) { + /* size=1, any raster ops */ + if (rgbmode) + ctx->Driver.PointsFunc = size1_rgba_points; + else + ctx->Driver.PointsFunc = size1_ci_points; + } + else { + /* every other kind of point rendering */ + if (rgbmode) + ctx->Driver.PointsFunc = general_rgba_points; + else + ctx->Driver.PointsFunc = general_ci_points; + } + } + else if(ctx->Point.SmoothFlag && rgbmode) { + ctx->Driver.PointsFunc = dist_atten_antialiased_rgba_points; + } + else if (ctx->Texture.ReallyEnabled) { + ctx->Driver.PointsFunc = dist_atten_textured_rgba_points; + } + else { + /* every other kind of point rendering */ + if (rgbmode) + ctx->Driver.PointsFunc = dist_atten_general_rgba_points; + else + ctx->Driver.PointsFunc = dist_atten_general_ci_points; + } + } + else if (ctx->RenderMode==GL_FEEDBACK) { + ctx->Driver.PointsFunc = feedback_points; + } + else { + /* GL_SELECT mode */ + ctx->Driver.PointsFunc = select_points; + } + +} + diff --git a/src/mesa/main/points.h b/src/mesa/main/points.h new file mode 100644 index 00000000000..a53ce9b2d22 --- /dev/null +++ b/src/mesa/main/points.h @@ -0,0 +1,45 @@ +/* $Id: points.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 POINTS_H +#define POINTS_H + + +#include "types.h" + + +extern void gl_PointSize( GLcontext *ctx, GLfloat size ); + +extern void gl_set_point_function( GLcontext *ctx ); + +extern void gl_PointParameterfvEXT( GLcontext *ctx, GLenum pname, + const GLfloat *params ); + +#endif diff --git a/src/mesa/main/polygon.c b/src/mesa/main/polygon.c new file mode 100644 index 00000000000..83690035ffa --- /dev/null +++ b/src/mesa/main/polygon.c @@ -0,0 +1,177 @@ +/* $Id: polygon.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "context.h" +#include "image.h" +#include "enums.h" +#include "macros.h" +#include "polygon.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +void gl_CullFace( GLcontext *ctx, GLenum mode ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCullFace"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glCullFace %s\n", gl_lookup_enum_by_nr(mode)); + + if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) { + gl_error( ctx, GL_INVALID_ENUM, "glCullFace" ); + return; + } + + ctx->Polygon.CullFaceMode = mode; + ctx->NewState |= NEW_POLYGON; + + if (ctx->Driver.CullFace) + ctx->Driver.CullFace( ctx, mode ); +} + + + +void gl_FrontFace( GLcontext *ctx, GLenum mode ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glFrontFace"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glFrontFace %s\n", gl_lookup_enum_by_nr(mode)); + + if (mode!=GL_CW && mode!=GL_CCW) { + gl_error( ctx, GL_INVALID_ENUM, "glFrontFace" ); + return; + } + ctx->Polygon.FrontFace = mode; + ctx->Polygon.FrontBit = (mode == GL_CW); + + if (ctx->Driver.FrontFace) + ctx->Driver.FrontFace( ctx, mode ); +} + + + +void gl_PolygonMode( GLcontext *ctx, GLenum face, GLenum mode ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonMode"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glPolygonMode %s %s\n", + gl_lookup_enum_by_nr(face), + gl_lookup_enum_by_nr(mode)); + + if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) { + gl_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); + return; + } + else if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) { + gl_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" ); + return; + } + + if (face==GL_FRONT || face==GL_FRONT_AND_BACK) { + ctx->Polygon.FrontMode = mode; + } + if (face==GL_BACK || face==GL_FRONT_AND_BACK) { + ctx->Polygon.BackMode = mode; + } + + /* Compute a handy "shortcut" value: */ + ctx->TriangleCaps &= ~DD_TRI_UNFILLED; + ctx->Polygon.Unfilled = GL_FALSE; + + if (ctx->Polygon.FrontMode!=GL_FILL || ctx->Polygon.BackMode!=GL_FILL) { + ctx->Polygon.Unfilled = GL_TRUE; + ctx->TriangleCaps |= DD_TRI_UNFILLED; + } + else { + ctx->Polygon.Unfilled = GL_FALSE; + } + + ctx->NewState |= (NEW_POLYGON | NEW_RASTER_OPS); + + if (ctx->Driver.PolygonMode) { + (*ctx->Driver.PolygonMode)( ctx, face, mode ); + } +} + + + +/* + * NOTE: stipple pattern has already been unpacked. + */ +void gl_PolygonStipple( GLcontext *ctx, const GLuint pattern[32] ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonStipple"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glPolygonStipple\n"); + + MEMCPY( ctx->PolygonStipple, pattern, 32 * 4 ); + + if (ctx->Polygon.StippleFlag) { + ctx->NewState |= NEW_RASTER_OPS; + } +} + + + +void gl_GetPolygonStipple( GLcontext *ctx, GLubyte *dest ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonOffset"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glGetPolygonStipple\n"); + + gl_pack_polygon_stipple( ctx, ctx->PolygonStipple, dest ); +} + + + +void gl_PolygonOffset( GLcontext *ctx, + GLfloat factor, GLfloat units ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonOffset"); + + if (MESA_VERBOSE&VERBOSE_API) + fprintf(stderr, "glPolygonOffset %f %f\n", factor, units); + + ctx->Polygon.OffsetFactor = factor; + ctx->Polygon.OffsetUnits = units; +} + diff --git a/src/mesa/main/polygon.h b/src/mesa/main/polygon.h new file mode 100644 index 00000000000..ac591bbda4b --- /dev/null +++ b/src/mesa/main/polygon.h @@ -0,0 +1,53 @@ +/* $Id: polygon.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 POLYGON_H +#define POLYGON_H + + +#include "types.h" + + +extern void gl_CullFace( GLcontext *ctx, GLenum mode ); + +extern void gl_FrontFace( GLcontext *ctx, GLenum mode ); + +extern void gl_PolygonMode( GLcontext *ctx, GLenum face, GLenum mode ); + +extern void gl_PolygonOffset( GLcontext *ctx, + GLfloat factor, GLfloat units ); + +extern void gl_PolygonStipple( GLcontext *ctx, const GLuint pattern[32] ); + +extern void gl_GetPolygonStipple( GLcontext *ctx, GLubyte *mask ); + + +#endif + diff --git a/src/mesa/main/rastpos.c b/src/mesa/main/rastpos.c new file mode 100644 index 00000000000..000af375ba2 --- /dev/null +++ b/src/mesa/main/rastpos.c @@ -0,0 +1,227 @@ +/* $Id: rastpos.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include "clip.h" +#include "feedback.h" +#include "light.h" +#include "macros.h" +#include "matrix.h" +#include "mmath.h" +#include "shade.h" +#include "types.h" +#include "xform.h" +#include "context.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/* + * Caller: context->API.RasterPos4f + */ +void gl_RasterPos4f( GLcontext *ctx, + GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GLfloat v[4], eye[4], clip[4], ndc[3], d; + + /* KW: Added this test, which is in the spec. We can't do this + * outside begin/end any more because the ctx->Current values + * aren't uptodate during that period. + */ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glRasterPos" ); + + if (ctx->NewState) + gl_update_state( ctx ); + + ASSIGN_4V( v, x, y, z, w ); + TRANSFORM_POINT( eye, ctx->ModelView.m, v ); + + /* raster color */ + if (ctx->Light.Enabled) + { + /*GLfloat *vert;*/ + GLfloat *norm, eyenorm[3]; + GLfloat *objnorm = ctx->Current.Normal; + + /* Not needed??? + vert = (ctx->NeedEyeCoords ? eye : v); + */ + + if (ctx->NeedEyeNormals) { + GLfloat *inv = ctx->ModelView.inv; + TRANSFORM_NORMAL( eyenorm, objnorm, inv ); + norm = eyenorm; + } else { + norm = objnorm; + } + + gl_shade_rastpos( ctx, v, norm, + ctx->Current.RasterColor, + &ctx->Current.RasterIndex ); + + } + else { + /* use current color or index */ + if (ctx->Visual->RGBAflag) { + UBYTE_RGBA_TO_FLOAT_RGBA(ctx->Current.RasterColor, + ctx->Current.ByteColor); + } + else { + ctx->Current.RasterIndex = ctx->Current.Index; + } + } + + /* compute raster distance */ + ctx->Current.RasterDistance = + GL_SQRT( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] ); + + /* apply projection matrix: clip = Proj * eye */ + TRANSFORM_POINT( clip, ctx->ProjectionMatrix.m, eye ); + + /* clip to view volume */ + if (gl_viewclip_point( clip )==0) { + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + + /* clip to user clipping planes */ + if ( ctx->Transform.AnyClip && + gl_userclip_point(ctx, clip) == 0) + { + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + + /* ndc = clip / W */ + ASSERT( clip[3]!=0.0 ); + d = 1.0F / clip[3]; + ndc[0] = clip[0] * d; + ndc[1] = clip[1] * d; + ndc[2] = clip[2] * d; + + ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport.WindowMap.m[MAT_SX] + + ctx->Viewport.WindowMap.m[MAT_TX]); + ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport.WindowMap.m[MAT_SY] + + ctx->Viewport.WindowMap.m[MAT_TY]); + ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport.WindowMap.m[MAT_SZ] + + ctx->Viewport.WindowMap.m[MAT_TZ]) / DEPTH_SCALE; + ctx->Current.RasterPos[3] = clip[3]; + ctx->Current.RasterPosValid = GL_TRUE; + + /* FOG??? */ + + { + GLuint texSet; + for (texSet=0; texSet<MAX_TEXTURE_UNITS; texSet++) { + COPY_4FV( ctx->Current.RasterMultiTexCoord[texSet], + ctx->Current.Texcoord[texSet] ); + } + } + + if (ctx->RenderMode==GL_SELECT) { + gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); + } + +} + + + +/* + * This is a MESA extension function. Pretty much just like glRasterPos + * except we don't apply the modelview or projection matrices; specify a + * window coordinate directly. + * Caller: context->API.WindowPos4fMESA pointer. + */ +void gl_windowpos( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + /* KW: Assume that like rasterpos, this must be outside begin/end. + */ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glWindowPosMESA" ); + + /* set raster position */ + ctx->Current.RasterPos[0] = x; + ctx->Current.RasterPos[1] = y; + ctx->Current.RasterPos[2] = CLAMP( z, 0.0F, 1.0F ); + ctx->Current.RasterPos[3] = w; + + ctx->Current.RasterPosValid = GL_TRUE; + + /* raster color */ + if (0 && ctx->Light.Enabled) { + + /* KW: I don't see how this can work - would have to take the + * inverse of the projection matrix or the combined + * modelProjection matrix, transform point and normal, and + * do the lighting. Those inverses are not used for + * anything else. This is not an object-space lighting + * issue - what this is trying to do is something like + * clip-space or window-space lighting... + * + * Anyway, since the implementation was never correct, I'm + * not fixing it now - just use the unlit color. + */ + + /* KW: As a reprise, we now *do* keep the inverse of the projection + * matrix, so it is not infeasible to try to swim up stream + * in this manner. I still don't want to implement it, + * however. + */ + } + else { + /* use current color or index */ + if (ctx->Visual->RGBAflag) { + UBYTE_RGBA_TO_FLOAT_RGBA(ctx->Current.RasterColor, + ctx->Current.ByteColor); + } + else { + ctx->Current.RasterIndex = ctx->Current.Index; + } + } + + ctx->Current.RasterDistance = 0.0; + + { + GLuint texSet; + for (texSet=0; texSet<MAX_TEXTURE_UNITS; texSet++) { + COPY_4FV( ctx->Current.RasterMultiTexCoord[texSet], + ctx->Current.Texcoord[texSet] ); + } + } + + if (ctx->RenderMode==GL_SELECT) { + gl_update_hitflag( ctx, ctx->Current.RasterPos[2] ); + } +} diff --git a/src/mesa/main/rastpos.h b/src/mesa/main/rastpos.h new file mode 100644 index 00000000000..44dfbab0d62 --- /dev/null +++ b/src/mesa/main/rastpos.h @@ -0,0 +1,48 @@ +/* $Id: rastpos.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 RASTPOS_H +#define RASTPOS_H + + +#include "types.h" + + +extern void gl_RasterPos4f( GLcontext *ctx, + GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + + +extern void gl_windowpos( GLcontext *ctx, + GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + + + +#endif + diff --git a/src/mesa/main/simple_list.h b/src/mesa/main/simple_list.h new file mode 100644 index 00000000000..994d955b7fb --- /dev/null +++ b/src/mesa/main/simple_list.h @@ -0,0 +1,99 @@ +/* $Id: simple_list.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + +/* Simple macros for typesafe, intrusive lists. + * (C) 1997, Keith Whitwell + * + * Intended to work with a list sentinal which is created as an empty + * list. Insert & delete are O(1). + */ + + +#ifndef _SIMPLE_LIST_H +#define _SIMPLE_LIST_H + +#define remove_from_list(elem) \ +do { \ + (elem)->next->prev = (elem)->prev; \ + (elem)->prev->next = (elem)->next; \ +} while (0) + +#define insert_at_head(list, elem) \ +do { \ + (elem)->prev = list; \ + (elem)->next = (list)->next; \ + (list)->next->prev = elem; \ + (list)->next = elem; \ +} while(0) + +#define insert_at_tail(list, elem) \ +do { \ + (elem)->next = list; \ + (elem)->prev = (list)->prev; \ + (list)->prev->next = elem; \ + (list)->prev = elem; \ +} while(0) + +#define move_to_head(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_head(list, elem); \ +} while (0) + +#define move_to_tail(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_tail(list, elem); \ +} while (0) + + +#define make_empty_list(sentinal) \ +do { \ + (sentinal)->next = sentinal; \ + (sentinal)->prev = sentinal; \ +} while (0) + + +#define first_elem(list) ((list)->next) +#define last_elem(list) ((list)->prev) +#define next_elem(elem) ((elem)->next) +#define prev_elem(elem) ((elem)->prev) +#define at_end(list, elem) ((elem) == (list)) +#define is_empty_list(list) ((list)->next == (list)) + +#define foreach(ptr, list) \ + for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next ) + +/* Kludgey - Lets you unlink the current value during a list + * traversal. Useful for free()-ing a list, element + * by element. + */ +#define foreach_s(ptr, t, list) \ + for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next) + + +#endif + diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c new file mode 100644 index 00000000000..69bd70188b1 --- /dev/null +++ b/src/mesa/main/stencil.c @@ -0,0 +1,1107 @@ +/* $Id: stencil.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <stdlib.h> +#include <string.h> +#include "context.h" +#include "macros.h" +#include "pb.h" +#include "stencil.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +#if STENCIL_BITS==8 +# define STENCIL_MAX 0xff +#elif STENCIL_BITS==16 +# define STENCIL_MAX 0xffff +#else + illegal number of stencil bits +#endif + + + +/* + * Return the address of a stencil buffer value given the window coords: + */ +#define STENCIL_ADDRESS(X,Y) (ctx->Buffer->Stencil + ctx->Buffer->Width * (Y) + (X)) + + +void gl_ClearStencil( GLcontext *ctx, GLint s ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearStencil"); + ctx->Stencil.Clear = (GLstencil) s; + + if (ctx->Driver.ClearStencil) { + (*ctx->Driver.ClearStencil)( ctx, s ); + } +} + + + +void gl_StencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask ) +{ + GLint maxref; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilFunc"); + + switch (func) { + case GL_NEVER: + case GL_LESS: + case GL_LEQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_EQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + ctx->Stencil.Function = func; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glStencilFunc" ); + return; + } + + maxref = (1 << STENCIL_BITS) - 1; + ctx->Stencil.Ref = CLAMP( ref, 0, maxref ); + ctx->Stencil.ValueMask = mask; + + if (ctx->Driver.StencilFunc) { + (*ctx->Driver.StencilFunc)( ctx, func, ctx->Stencil.Ref, mask ); + } +} + + + +void gl_StencilMask( GLcontext *ctx, GLuint mask ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilMask"); + ctx->Stencil.WriteMask = (GLstencil) mask; + + if (ctx->Driver.StencilMask) { + (*ctx->Driver.StencilMask)( ctx, mask ); + } +} + + + +void gl_StencilOp( GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilOp"); + switch (fail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + ctx->Stencil.FailFunc = fail; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" ); + return; + } + switch (zfail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + ctx->Stencil.ZFailFunc = zfail; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" ); + return; + } + switch (zpass) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + ctx->Stencil.ZPassFunc = zpass; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" ); + return; + } + + if (ctx->Driver.StencilOp) { + (*ctx->Driver.StencilOp)( ctx, fail, zfail, zpass ); + } +} + + + +/* Stencil Logic: + +IF stencil test fails THEN + Don't write the pixel (RGBA,Z) + Execute FailOp +ELSE + Write the pixel +ENDIF + +Perform Depth Test + +IF depth test passes OR no depth buffer THEN + Execute ZPass + Write the pixel +ELSE + Execute ZFail +ENDIF + +*/ + + + + +/* + * Apply the given stencil operator for each pixel in the span whose + * mask flag is set. + * Input: n - number of pixels in the span + * x, y - location of leftmost pixel in the span + * oper - the stencil buffer operator + * mask - array [n] of flag: 1=apply operator, 0=don't apply operator + */ +static void apply_stencil_op_to_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, + GLenum oper, GLubyte mask[] ) +{ + const GLstencil ref = ctx->Stencil.Ref; + const GLstencil wrtmask = ctx->Stencil.WriteMask; + const GLstencil invmask = ~ctx->Stencil.WriteMask; + GLstencil *stencil = STENCIL_ADDRESS( x, y ); + 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] = 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] = (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] = 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] = (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] = 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] = (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] = (invmask & s) | (wrtmask & (stencil[i]+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] = (invmask & s) | (wrtmask & (stencil[i]-1)); + } + } + } + break; + case GL_INVERT: + if (invmask==0) { + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil s = stencil[i]; + stencil[i] = ~s; + } + } + } + else { + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil s = stencil[i]; + stencil[i] = (invmask & s) | (wrtmask & ~s); + } + } + } + break; + default: + gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_span"); + } +} + + + + +/* + * Apply stencil test to a span of pixels before depth buffering. + * Input: n - number of pixels in the span + * x, y - coordinate of left-most pixel in the span + * 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: 0 = all pixels failed, 1 = zero or more pixels passed. + */ +GLint gl_stencil_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLubyte mask[] ) +{ + GLubyte fail[MAX_WIDTH]; + GLint allfail = 0; + GLuint i; + GLstencil r, s; + GLstencil *stencil; + + stencil = STENCIL_ADDRESS( x, y ); + + /* + * 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) { + 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 = 1; + break; + case GL_LESS: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + s = stencil[i] & ctx->Stencil.ValueMask; + if (r < s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_LEQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + s = stencil[i] & ctx->Stencil.ValueMask; + if (r <= s) { + /* pass */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_GREATER: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + s = stencil[i] & ctx->Stencil.ValueMask; + if (r > s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_GEQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + s = stencil[i] & ctx->Stencil.ValueMask; + if (r >= s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_EQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + s = stencil[i] & ctx->Stencil.ValueMask; + if (r == s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_NOTEQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + s = stencil[i] & ctx->Stencil.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: + gl_problem(ctx, "Bad stencil func in gl_stencil_span"); + return 0; + } + + apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.FailFunc, fail ); + + return (allfail) ? 0 : 1; +} + + + + +/* + * Apply the combination depth-buffer/stencil operator to a span of pixels. + * Input: n - number of pixels in the span + * x, y - location of leftmost pixel in span + * z - array [n] of z values + * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel) + * Output: mask - array [n] of flags (1=depth test passed, 0=failed) + */ +void gl_depth_stencil_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, const GLdepth z[], + GLubyte mask[] ) +{ + if (ctx->Depth.Test==GL_FALSE) { + /* + * No depth buffer, just apply zpass stencil function to active pixels. + */ + apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask ); + } + else { + /* + * Perform depth buffering, then apply zpass or zfail stencil function. + */ + GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH]; + GLuint i; + + /* init pass and fail masks to zero, copy mask[] to oldmask[] */ + for (i=0;i<n;i++) { + passmask[i] = failmask[i] = 0; + oldmask[i] = mask[i]; + } + + /* apply the depth test */ + if (ctx->Driver.DepthTestSpan) + (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask ); + + /* set the stencil pass/fail flags according to result of depth test */ + for (i=0;i<n;i++) { + if (oldmask[i]) { + if (mask[i]) { + passmask[i] = 1; + } + else { + failmask[i] = 1; + } + } + } + + /* apply the pass and fail operations */ + apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZFailFunc, failmask ); + apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, passmask ); + } +} + + + + +/* + * Apply the given stencil operator for each pixel in the array whose + * mask flag is set. + * 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( GLcontext *ctx, + GLuint n, const GLint x[], + const GLint y[], + GLenum oper, GLubyte mask[] ) +{ + GLuint i; + GLstencil ref; + GLstencil wrtmask, invmask; + + wrtmask = ctx->Stencil.WriteMask; + invmask = ~ctx->Stencil.WriteMask; + + ref = ctx->Stencil.Ref; + + 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 = 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 = (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 = *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 = (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 = *sptr - 1; + } + } + } + } + else { + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); + if (*sptr>0) { + *sptr = (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 = *sptr + 1; + } + } + } + else { + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); + *sptr = (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 = *sptr - 1; + } + } + } + else { + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); + *sptr = (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 = ~*sptr; + } + } + } + else { + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); + *sptr = (invmask & *sptr) | (wrtmask & ~*sptr); + } + } + } + break; + default: + gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels"); + } +} + + + +/* + * Apply stencil test to an array of pixels before depth buffering. + * 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: 0 = all pixels failed, 1 = zero or more pixels passed. + */ +GLint gl_stencil_pixels( GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLubyte mask[] ) +{ + GLubyte fail[PB_SIZE]; + GLstencil r, s; + GLuint i; + GLint allfail = 0; + + /* + * 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) { + 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 = 1; + break; + case GL_LESS: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); + s = *sptr & ctx->Stencil.ValueMask; + if (r < s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_LEQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); + s = *sptr & ctx->Stencil.ValueMask; + if (r <= s) { + /* pass */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_GREATER: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); + s = *sptr & ctx->Stencil.ValueMask; + if (r > s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_GEQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); + s = *sptr & ctx->Stencil.ValueMask; + if (r >= s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_EQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); + s = *sptr & ctx->Stencil.ValueMask; + if (r == s) { + /* passed */ + fail[i] = 0; + } + else { + fail[i] = 1; + mask[i] = 0; + } + } + else { + fail[i] = 0; + } + } + break; + case GL_NOTEQUAL: + r = ctx->Stencil.Ref & ctx->Stencil.ValueMask; + for (i=0;i<n;i++) { + if (mask[i]) { + GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); + s = *sptr & ctx->Stencil.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: + gl_problem(ctx, "Bad stencil func in gl_stencil_pixels"); + return 0; + } + + apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail ); + + return (allfail) ? 0 : 1; +} + + + + +/* + * Apply the combination depth-buffer/stencil operator to a span of pixels. + * Input: n - number of pixels in the span + * x, y - array of [n] pixels to stencil + * z - array [n] of z values + * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel) + * Output: mask - array [n] of flags (1=depth test passed, 0=failed) + */ +void gl_depth_stencil_pixels( GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ) +{ + if (ctx->Depth.Test==GL_FALSE) { + /* + * No depth buffer, just apply zpass stencil function to active pixels. + */ + apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask ); + } + else { + /* + * Perform depth buffering, then apply zpass or zfail stencil function. + */ + GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE]; + GLuint i; + + /* init pass and fail masks to zero */ + for (i=0;i<n;i++) { + passmask[i] = failmask[i] = 0; + oldmask[i] = mask[i]; + } + + /* apply the depth test */ + if (ctx->Driver.DepthTestPixels) + (*ctx->Driver.DepthTestPixels)( ctx, n, x, y, z, mask ); + + /* set the stencil pass/fail flags according to result of depth test */ + for (i=0;i<n;i++) { + if (oldmask[i]) { + if (mask[i]) { + passmask[i] = 1; + } + else { + failmask[i] = 1; + } + } + } + + /* apply the pass and fail operations */ + apply_stencil_op_to_pixels( ctx, n, x, y, + ctx->Stencil.ZFailFunc, failmask ); + apply_stencil_op_to_pixels( ctx, n, x, y, + ctx->Stencil.ZPassFunc, passmask ); + } + +} + + + +/* + * Return a span of stencil values from the stencil buffer. + * Input: n - how many pixels + * x,y - location of first pixel + * Output: stencil - the array of stencil values + */ +void gl_read_stencil_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLstencil stencil[] ) +{ + if (ctx->Buffer->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. + * Input: n - how many pixels + * x,y - location of first pixel + * stencil - the array of stencil values + */ +void gl_write_stencil_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, + const GLstencil stencil[] ) +{ + if (ctx->Buffer->Stencil) { + GLstencil *s = STENCIL_ADDRESS( x, y ); +#if STENCIL_BITS == 8 + MEMCPY( s, stencil, n * sizeof(GLstencil) ); +#else + GLuint i; + for (i=0;i<n;i++) + s[i] = stencil[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 gl_alloc_stencil_buffer( GLcontext *ctx ) +{ + GLuint buffersize = ctx->Buffer->Width * ctx->Buffer->Height; + + /* deallocate current stencil buffer if present */ + if (ctx->Buffer->Stencil) { + free(ctx->Buffer->Stencil); + ctx->Buffer->Stencil = NULL; + } + + /* allocate new stencil buffer */ + ctx->Buffer->Stencil = (GLstencil *) malloc(buffersize * sizeof(GLstencil)); + if (!ctx->Buffer->Stencil) { + /* out of memory */ + ctx->Stencil.Enabled = GL_FALSE; + gl_error( ctx, GL_OUT_OF_MEMORY, "gl_alloc_stencil_buffer" ); + } +} + + + + +/* + * Clear the stencil buffer. If the stencil buffer doesn't exist yet we'll + * allocate it now. + */ +void gl_clear_stencil_buffer( GLcontext *ctx ) +{ + if (ctx->Visual->StencilBits==0 || !ctx->Buffer->Stencil) { + /* no stencil buffer */ + return; + } + + if (ctx->Scissor.Enabled) { + /* clear scissor region only */ + GLint y; + GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1; + for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) { + GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y ); +#if STENCIL_BITS==8 + MEMSET( ptr, ctx->Stencil.Clear, width * sizeof(GLstencil) ); +#else + GLint x; + for (x = 0; x < width; x++) + ptr[x] = ctx->Stencil.Clear; +#endif + } + } + else { + /* clear whole stencil buffer */ +#if STENCIL_BITS==8 + MEMSET( ctx->Buffer->Stencil, ctx->Stencil.Clear, + ctx->Buffer->Width * ctx->Buffer->Height * sizeof(GLstencil) ); +#else + GLuint i; + GLuint pixels = ctx->Buffer->Width * ctx->Buffer->Height; + GLstencil *buffer = ctx->Buffer->Stencil; + for (i = 0; i < pixels; i++) + ptr[i] = ctx->Stencil.Clear; +#endif + } +} diff --git a/src/mesa/main/stencil.h b/src/mesa/main/stencil.h new file mode 100644 index 00000000000..989cd988fe8 --- /dev/null +++ b/src/mesa/main/stencil.h @@ -0,0 +1,88 @@ +/* $Id: stencil.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 STENCIL_H +#define STENCIL_H + + +#include "types.h" + + +extern void gl_ClearStencil( GLcontext *ctx, GLint s ); + + +extern void gl_StencilFunc( GLcontext *ctx, GLenum func, + GLint ref, GLuint mask ); + + +extern void gl_StencilMask( GLcontext *ctx, GLuint mask ); + + +extern void gl_StencilOp( GLcontext *ctx, GLenum fail, + GLenum zfail, GLenum zpass ); + + + +extern GLint gl_stencil_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLubyte mask[] ); + + +extern void gl_depth_stencil_span( GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLdepth z[], GLubyte mask[] ); + + +extern GLint gl_stencil_pixels( GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLubyte mask[] ); + + +extern void gl_depth_stencil_pixels( GLcontext *ctx, + GLuint n, const GLint x[], + const GLint y[], const GLdepth z[], + GLubyte mask[] ); + + +extern void gl_read_stencil_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, + GLstencil stencil[] ); + + +extern void gl_write_stencil_span( GLcontext *ctx, + GLuint n, GLint x, GLint y, + const GLstencil stencil[] ); + + +extern void gl_alloc_stencil_buffer( GLcontext *ctx ); + + +extern void gl_clear_stencil_buffer( GLcontext *ctx ); + + +#endif diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c new file mode 100644 index 00000000000..f2f301e398b --- /dev/null +++ b/src/mesa/main/teximage.c @@ -0,0 +1,2344 @@ +/* $Id: teximage.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "context.h" +#include "image.h" +#include "macros.h" +#include "mmath.h" +#include "span.h" +#include "teximage.h" +#include "texstate.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +/* + * NOTES: + * + * The internal texture storage convension is an array of N GLubytes + * where N = width * height * components. There is no padding. + */ + + + + +/* + * Compute log base 2 of n. + * If n isn't an exact power of two return -1. + * If n<0 return -1. + */ +static int logbase2( int n ) +{ + GLint i = 1; + GLint log2 = 0; + + if (n<0) { + return -1; + } + + while ( n > i ) { + i *= 2; + log2++; + } + if (i != n) { + return -1; + } + else { + return log2; + } +} + + + +/* + * Given an internal texture format enum or 1, 2, 3, 4 return the + * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, + * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return -1 if + * invalid enum. + */ +static GLint decode_internal_format( GLint format ) +{ + switch (format) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return GL_ALPHA; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return GL_LUMINANCE; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return GL_LUMINANCE_ALPHA; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return GL_INTENSITY; + case 3: + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return GL_RGB; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_RGBA; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return GL_COLOR_INDEX; + default: + return -1; /* error */ + } +} + + + +/* + * Given an internal texture format enum or 1, 2, 3, 4 return the + * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, + * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the + * number of components for the format. Return -1 if invalid enum. + */ +static GLint components_in_intformat( GLint format ) +{ + switch (format) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return 1; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return 1; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return 2; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return 1; + case 3: + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return 3; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return 4; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return 1; + default: + return -1; /* error */ + } +} + + + +struct gl_texture_image *gl_alloc_texture_image( void ) +{ + return (struct gl_texture_image *) calloc( 1, sizeof(struct gl_texture_image) ); +} + + + +void gl_free_texture_image( struct gl_texture_image *teximage ) +{ + if (teximage->Data) { + free( teximage->Data ); + } + free( teximage ); +} + + + +/* + * Examine the texImage->Format field and set the Red, Green, Blue, etc + * texel component sizes to default values. + * These fields are set only here by core Mesa but device drivers may + * overwritting these fields to indicate true texel resolution. + */ +static void set_teximage_component_sizes( struct gl_texture_image *texImage ) +{ + switch (texImage->Format) { + case GL_ALPHA: + texImage->RedBits = 0; + texImage->GreenBits = 0; + texImage->BlueBits = 0; + texImage->AlphaBits = 8; + texImage->IntensityBits = 0; + texImage->LuminanceBits = 0; + texImage->IndexBits = 0; + break; + case GL_LUMINANCE: + texImage->RedBits = 0; + texImage->GreenBits = 0; + texImage->BlueBits = 0; + texImage->AlphaBits = 0; + texImage->IntensityBits = 0; + texImage->LuminanceBits = 8; + texImage->IndexBits = 0; + break; + case GL_LUMINANCE_ALPHA: + texImage->RedBits = 0; + texImage->GreenBits = 0; + texImage->BlueBits = 0; + texImage->AlphaBits = 8; + texImage->IntensityBits = 0; + texImage->LuminanceBits = 8; + texImage->IndexBits = 0; + break; + case GL_INTENSITY: + texImage->RedBits = 0; + texImage->GreenBits = 0; + texImage->BlueBits = 0; + texImage->AlphaBits = 0; + texImage->IntensityBits = 8; + texImage->LuminanceBits = 0; + texImage->IndexBits = 0; + break; + case GL_RGB: + texImage->RedBits = 8; + texImage->GreenBits = 8; + texImage->BlueBits = 8; + texImage->AlphaBits = 0; + texImage->IntensityBits = 0; + texImage->LuminanceBits = 0; + texImage->IndexBits = 0; + break; + case GL_RGBA: + texImage->RedBits = 8; + texImage->GreenBits = 8; + texImage->BlueBits = 8; + texImage->AlphaBits = 8; + texImage->IntensityBits = 0; + texImage->LuminanceBits = 0; + texImage->IndexBits = 0; + break; + case GL_COLOR_INDEX: + texImage->RedBits = 0; + texImage->GreenBits = 0; + texImage->BlueBits = 0; + texImage->AlphaBits = 0; + texImage->IntensityBits = 0; + texImage->LuminanceBits = 0; + texImage->IndexBits = 8; + break; + default: + gl_problem(NULL, "unexpected format in set_teximage_component_sizes"); + } +} + + +/* Need this to prevent an out-of-bounds memory access when using + * X86 optimized code. + */ +#ifdef USE_X86_ASM +# define EXTRA_BYTE 1 +#else +# define EXTRA_BYTE 0 +#endif + + +/* + * Given a gl_image, apply the pixel transfer scale, bias, and mapping + * to produce a gl_texture_image. Convert image data to GLubytes. + * Input: image - the incoming gl_image + * internalFormat - desired format of resultant texture + * border - texture border width (0 or 1) + * Return: pointer to a gl_texture_image or NULL if an error occurs. + */ +static struct gl_texture_image * +image_to_texture( GLcontext *ctx, const struct gl_image *image, + GLint internalFormat, GLint border ) +{ + GLint components; + struct gl_texture_image *texImage; + GLint numPixels, pixel; + GLboolean scaleOrBias; + + assert(image); + assert(image->Width>0); + assert(image->Height>0); + assert(image->Depth>0); + + /* internalFormat = decode_internal_format(internalFormat);*/ + components = components_in_intformat(internalFormat); + numPixels = image->Width * image->Height * image->Depth; + + texImage = gl_alloc_texture_image(); + if (!texImage) + return NULL; + + texImage->Format = (GLenum) decode_internal_format(internalFormat); + set_teximage_component_sizes( texImage ); + texImage->IntFormat = (GLenum) internalFormat; + texImage->Border = border; + texImage->Width = image->Width; + texImage->Height = image->Height; + texImage->Depth = image->Depth; + texImage->WidthLog2 = logbase2(image->Width - 2*border); + if (image->Height==1) /* 1-D texture */ + texImage->HeightLog2 = 0; + else + texImage->HeightLog2 = logbase2(image->Height - 2*border); + if (image->Depth==1) /* 2-D texture */ + texImage->DepthLog2 = 0; + else + texImage->DepthLog2 = logbase2(image->Depth - 2*border); + texImage->Width2 = 1 << texImage->WidthLog2; + texImage->Height2 = 1 << texImage->HeightLog2; + texImage->Depth2 = 1 << texImage->DepthLog2; + texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 ); + texImage->Data = (GLubyte *) malloc( numPixels * components + EXTRA_BYTE ); + + if (!texImage->Data) { + /* out of memory */ + gl_free_texture_image( texImage ); + return NULL; + } + + /* Determine if scaling and/or biasing is needed */ + if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F || + ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F || + ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F || + ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) { + scaleOrBias = GL_TRUE; + } + else { + scaleOrBias = GL_FALSE; + } + + switch (image->Type) { + case GL_BITMAP: + { + GLint shift = ctx->Pixel.IndexShift; + GLint offset = ctx->Pixel.IndexOffset; + /* MapIto[RGBA]Size must be powers of two */ + GLint rMask = ctx->Pixel.MapItoRsize-1; + GLint gMask = ctx->Pixel.MapItoGsize-1; + GLint bMask = ctx->Pixel.MapItoBsize-1; + GLint aMask = ctx->Pixel.MapItoAsize-1; + GLint i, j; + GLubyte *srcPtr = (GLubyte *) image->Data; + + assert( image->Format==GL_COLOR_INDEX ); + + for (j=0; j<image->Height; j++) { + GLubyte bitMask = 128; + for (i=0; i<image->Width; i++) { + GLint index; + GLubyte red, green, blue, alpha; + + /* Fetch image color index */ + index = (*srcPtr & bitMask) ? 1 : 0; + bitMask = bitMask >> 1; + if (bitMask==0) { + bitMask = 128; + srcPtr++; + } + /* apply index shift and offset */ + if (shift>=0) { + index = (index << shift) + offset; + } + else { + index = (index >> -shift) + offset; + } + /* convert index to RGBA */ + red = (GLint) (ctx->Pixel.MapItoR[index & rMask] * 255.0F); + green = (GLint) (ctx->Pixel.MapItoG[index & gMask] * 255.0F); + blue = (GLint) (ctx->Pixel.MapItoB[index & bMask] * 255.0F); + alpha = (GLint) (ctx->Pixel.MapItoA[index & aMask] * 255.0F); + + /* store texel (components are GLubytes in [0,255]) */ + pixel = j * image->Width + i; + switch (texImage->Format) { + case GL_ALPHA: + texImage->Data[pixel] = alpha; + break; + case GL_LUMINANCE: + texImage->Data[pixel] = red; + break; + case GL_LUMINANCE_ALPHA: + texImage->Data[pixel*2+0] = red; + texImage->Data[pixel*2+1] = alpha; + break; + case GL_INTENSITY: + texImage->Data[pixel] = red; + break; + case GL_RGB: + texImage->Data[pixel*3+0] = red; + texImage->Data[pixel*3+1] = green; + texImage->Data[pixel*3+2] = blue; + break; + case GL_RGBA: + texImage->Data[pixel*4+0] = red; + texImage->Data[pixel*4+1] = green; + texImage->Data[pixel*4+2] = blue; + texImage->Data[pixel*4+3] = alpha; + break; + default: + gl_problem(ctx,"Bad format in image_to_texture"); + return NULL; + } + } + if (bitMask!=128) { + srcPtr++; + } + } + } + break; + + case GL_UNSIGNED_BYTE: + if (image->Format == texImage->Format && !scaleOrBias && !ctx->Pixel.MapColorFlag) { + switch (image->Format) { + case GL_COLOR_INDEX: + if (decode_internal_format(internalFormat)!=GL_COLOR_INDEX) { + /* convert color index to RGBA */ + for (pixel=0; pixel<numPixels; pixel++) { + GLint index = ((GLubyte*)image->Data)[pixel]; + index = (GLint) (255.0F * ctx->Pixel.MapItoR[index]); + texImage->Data[pixel] = index; + } + numPixels = 0; + break; + } + case GL_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + MEMCPY(texImage->Data, image->Data, numPixels * 1); + numPixels = 0; + break; + case GL_LUMINANCE_ALPHA: + MEMCPY(texImage->Data, image->Data, numPixels * 2); + numPixels = 0; + break; + case GL_RGB: + MEMCPY(texImage->Data, image->Data, numPixels * 3); + numPixels = 0; + break; + case GL_RGBA: + MEMCPY(texImage->Data, image->Data, numPixels * 4); + numPixels = 0; + break; + default: + break; + } + } + for (pixel=0; pixel<numPixels; pixel++) { + GLubyte red, green, blue, alpha; + switch (image->Format) { + case GL_COLOR_INDEX: + if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) { + /* a paletted texture */ + GLint index = ((GLubyte*)image->Data)[pixel]; + red = index; + } + else { + /* convert color index to RGBA */ + GLint index = ((GLubyte*)image->Data)[pixel]; + red = (GLint) (255.0F * ctx->Pixel.MapItoR[index]); + green = (GLint) (255.0F * ctx->Pixel.MapItoG[index]); + blue = (GLint) (255.0F * ctx->Pixel.MapItoB[index]); + alpha = (GLint) (255.0F * ctx->Pixel.MapItoA[index]); + } + break; + case GL_RGB: + /* Fetch image RGBA values */ + red = ((GLubyte*) image->Data)[pixel*3+0]; + green = ((GLubyte*) image->Data)[pixel*3+1]; + blue = ((GLubyte*) image->Data)[pixel*3+2]; + alpha = 255; + break; + case GL_RGBA: + red = ((GLubyte*) image->Data)[pixel*4+0]; + green = ((GLubyte*) image->Data)[pixel*4+1]; + blue = ((GLubyte*) image->Data)[pixel*4+2]; + alpha = ((GLubyte*) image->Data)[pixel*4+3]; + break; + case GL_RED: + red = ((GLubyte*) image->Data)[pixel]; + green = 0; + blue = 0; + alpha = 255; + break; + case GL_GREEN: + red = 0; + green = ((GLubyte*) image->Data)[pixel]; + blue = 0; + alpha = 255; + break; + case GL_BLUE: + red = 0; + green = 0; + blue = ((GLubyte*) image->Data)[pixel]; + alpha = 255; + break; + case GL_ALPHA: + red = 0; + green = 0; + blue = 0; + alpha = ((GLubyte*) image->Data)[pixel]; + break; + case GL_LUMINANCE: + red = ((GLubyte*) image->Data)[pixel]; + green = red; + blue = red; + alpha = 255; + break; + case GL_LUMINANCE_ALPHA: + red = ((GLubyte*) image->Data)[pixel*2+0]; + green = red; + blue = red; + alpha = ((GLubyte*) image->Data)[pixel*2+1]; + break; + default: + gl_problem(ctx,"Bad format (2) in image_to_texture"); + return NULL; + } + + if (scaleOrBias || ctx->Pixel.MapColorFlag) { + /* Apply RGBA scale and bias */ + GLfloat r = UBYTE_COLOR_TO_FLOAT_COLOR(red); + GLfloat g = UBYTE_COLOR_TO_FLOAT_COLOR(green); + GLfloat b = UBYTE_COLOR_TO_FLOAT_COLOR(blue); + GLfloat a = UBYTE_COLOR_TO_FLOAT_COLOR(alpha); + if (scaleOrBias) { + /* r,g,b,a now in [0,1] */ + r = r * ctx->Pixel.RedScale + ctx->Pixel.RedBias; + g = g * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; + b = b * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; + a = a * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; + r = CLAMP( r, 0.0F, 1.0F ); + g = CLAMP( g, 0.0F, 1.0F ); + b = CLAMP( b, 0.0F, 1.0F ); + a = CLAMP( a, 0.0F, 1.0F ); + } + /* Apply pixel maps */ + if (ctx->Pixel.MapColorFlag) { + GLint ir = (GLint) (r*ctx->Pixel.MapRtoRsize); + GLint ig = (GLint) (g*ctx->Pixel.MapGtoGsize); + GLint ib = (GLint) (b*ctx->Pixel.MapBtoBsize); + GLint ia = (GLint) (a*ctx->Pixel.MapAtoAsize); + r = ctx->Pixel.MapRtoR[ir]; + g = ctx->Pixel.MapGtoG[ig]; + b = ctx->Pixel.MapBtoB[ib]; + a = ctx->Pixel.MapAtoA[ia]; + } + red = (GLint) (r * 255.0F); + green = (GLint) (g * 255.0F); + blue = (GLint) (b * 255.0F); + alpha = (GLint) (a * 255.0F); + } + + /* store texel (components are GLubytes in [0,255]) */ + switch (texImage->Format) { + case GL_COLOR_INDEX: + texImage->Data[pixel] = red; /* really an index */ + break; + case GL_ALPHA: + texImage->Data[pixel] = alpha; + break; + case GL_LUMINANCE: + texImage->Data[pixel] = red; + break; + case GL_LUMINANCE_ALPHA: + texImage->Data[pixel*2+0] = red; + texImage->Data[pixel*2+1] = alpha; + break; + case GL_INTENSITY: + texImage->Data[pixel] = red; + break; + case GL_RGB: + texImage->Data[pixel*3+0] = red; + texImage->Data[pixel*3+1] = green; + texImage->Data[pixel*3+2] = blue; + break; + case GL_RGBA: + texImage->Data[pixel*4+0] = red; + texImage->Data[pixel*4+1] = green; + texImage->Data[pixel*4+2] = blue; + texImage->Data[pixel*4+3] = alpha; + break; + default: + gl_problem(ctx,"Bad format (3) in image_to_texture"); + return NULL; + } + } + break; + + case GL_FLOAT: + for (pixel=0; pixel<numPixels; pixel++) { + GLfloat red, green, blue, alpha; + switch (image->Format) { + case GL_COLOR_INDEX: + if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) { + /* a paletted texture */ + GLint index = (GLint) ((GLfloat*) image->Data)[pixel]; + red = index; + } + else { + GLint shift = ctx->Pixel.IndexShift; + GLint offset = ctx->Pixel.IndexOffset; + /* MapIto[RGBA]Size must be powers of two */ + GLint rMask = ctx->Pixel.MapItoRsize-1; + GLint gMask = ctx->Pixel.MapItoGsize-1; + GLint bMask = ctx->Pixel.MapItoBsize-1; + GLint aMask = ctx->Pixel.MapItoAsize-1; + /* Fetch image color index */ + GLint index = (GLint) ((GLfloat*) image->Data)[pixel]; + /* apply index shift and offset */ + if (shift>=0) { + index = (index << shift) + offset; + } + else { + index = (index >> -shift) + offset; + } + /* convert index to RGBA */ + red = ctx->Pixel.MapItoR[index & rMask]; + green = ctx->Pixel.MapItoG[index & gMask]; + blue = ctx->Pixel.MapItoB[index & bMask]; + alpha = ctx->Pixel.MapItoA[index & aMask]; + } + break; + case GL_RGB: + /* Fetch image RGBA values */ + red = ((GLfloat*) image->Data)[pixel*3+0]; + green = ((GLfloat*) image->Data)[pixel*3+1]; + blue = ((GLfloat*) image->Data)[pixel*3+2]; + alpha = 1.0; + break; + case GL_RGBA: + red = ((GLfloat*) image->Data)[pixel*4+0]; + green = ((GLfloat*) image->Data)[pixel*4+1]; + blue = ((GLfloat*) image->Data)[pixel*4+2]; + alpha = ((GLfloat*) image->Data)[pixel*4+3]; + break; + case GL_RED: + red = ((GLfloat*) image->Data)[pixel]; + green = 0.0; + blue = 0.0; + alpha = 1.0; + break; + case GL_GREEN: + red = 0.0; + green = ((GLfloat*) image->Data)[pixel]; + blue = 0.0; + alpha = 1.0; + break; + case GL_BLUE: + red = 0.0; + green = 0.0; + blue = ((GLfloat*) image->Data)[pixel]; + alpha = 1.0; + break; + case GL_ALPHA: + red = 0.0; + green = 0.0; + blue = 0.0; + alpha = ((GLfloat*) image->Data)[pixel]; + break; + case GL_LUMINANCE: + red = ((GLfloat*) image->Data)[pixel]; + green = red; + blue = red; + alpha = 1.0; + break; + case GL_LUMINANCE_ALPHA: + red = ((GLfloat*) image->Data)[pixel*2+0]; + green = red; + blue = red; + alpha = ((GLfloat*) image->Data)[pixel*2+1]; + break; + default: + gl_problem(ctx,"Bad format (4) in image_to_texture"); + return NULL; + } + + if (image->Format!=GL_COLOR_INDEX) { + /* Apply RGBA scale and bias */ + if (scaleOrBias) { + red = red * ctx->Pixel.RedScale + ctx->Pixel.RedBias; + green = green * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; + blue = blue * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; + alpha = alpha * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; + red = CLAMP( red, 0.0F, 1.0F ); + green = CLAMP( green, 0.0F, 1.0F ); + blue = CLAMP( blue, 0.0F, 1.0F ); + alpha = CLAMP( alpha, 0.0F, 1.0F ); + } + /* Apply pixel maps */ + if (ctx->Pixel.MapColorFlag) { + GLint ir = (GLint) (red *ctx->Pixel.MapRtoRsize); + GLint ig = (GLint) (green*ctx->Pixel.MapGtoGsize); + GLint ib = (GLint) (blue *ctx->Pixel.MapBtoBsize); + GLint ia = (GLint) (alpha*ctx->Pixel.MapAtoAsize); + red = ctx->Pixel.MapRtoR[ir]; + green = ctx->Pixel.MapGtoG[ig]; + blue = ctx->Pixel.MapBtoB[ib]; + alpha = ctx->Pixel.MapAtoA[ia]; + } + } + + /* store texel (components are GLubytes in [0,255]) */ + switch (texImage->Format) { + case GL_COLOR_INDEX: + /* a paletted texture */ + texImage->Data[pixel] = (GLint) (red * 255.0F); + break; + case GL_ALPHA: + texImage->Data[pixel] = (GLint) (alpha * 255.0F); + break; + case GL_LUMINANCE: + texImage->Data[pixel] = (GLint) (red * 255.0F); + break; + case GL_LUMINANCE_ALPHA: + texImage->Data[pixel*2+0] = (GLint) (red * 255.0F); + texImage->Data[pixel*2+1] = (GLint) (alpha * 255.0F); + break; + case GL_INTENSITY: + texImage->Data[pixel] = (GLint) (red * 255.0F); + break; + case GL_RGB: + texImage->Data[pixel*3+0] = (GLint) (red * 255.0F); + texImage->Data[pixel*3+1] = (GLint) (green * 255.0F); + texImage->Data[pixel*3+2] = (GLint) (blue * 255.0F); + break; + case GL_RGBA: + texImage->Data[pixel*4+0] = (GLint) (red * 255.0F); + texImage->Data[pixel*4+1] = (GLint) (green * 255.0F); + texImage->Data[pixel*4+2] = (GLint) (blue * 255.0F); + texImage->Data[pixel*4+3] = (GLint) (alpha * 255.0F); + break; + default: + gl_problem(ctx,"Bad format (5) in image_to_texture"); + return NULL; + } + } + break; + + default: + gl_problem(ctx, "Bad image type in image_to_texture"); + return NULL; + } + + return texImage; +} + + + +/* + * glTexImage[123]D can accept a NULL image pointer. In this case we + * create a texture image with unspecified image contents per the OpenGL + * spec. + */ +static struct gl_texture_image * +make_null_texture( GLcontext *ctx, GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei depth, GLint border ) +{ + GLint components; + struct gl_texture_image *texImage; + GLint numPixels; + (void) ctx; + + /*internalFormat = decode_internal_format(internalFormat);*/ + components = components_in_intformat(internalFormat); + numPixels = width * height * depth; + + texImage = gl_alloc_texture_image(); + if (!texImage) + return NULL; + + texImage->Format = (GLenum) decode_internal_format(internalFormat); + set_teximage_component_sizes( texImage ); + texImage->IntFormat = internalFormat; + texImage->Border = border; + texImage->Width = width; + texImage->Height = height; + texImage->Depth = depth; + texImage->WidthLog2 = logbase2(width - 2*border); + if (height==1) /* 1-D texture */ + texImage->HeightLog2 = 0; + else + texImage->HeightLog2 = logbase2(height - 2*border); + if (depth==1) /* 2-D texture */ + texImage->DepthLog2 = 0; + else + texImage->DepthLog2 = logbase2(depth - 2*border); + texImage->Width2 = 1 << texImage->WidthLog2; + texImage->Height2 = 1 << texImage->HeightLog2; + texImage->Depth2 = 1 << texImage->DepthLog2; + texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 ); + + /* XXX should we really allocate memory for the image or let it be NULL? */ + /*texImage->Data = NULL;*/ + + texImage->Data = (GLubyte *) malloc( numPixels * components + EXTRA_BYTE ); + + /* + * Let's see if anyone finds this. If glTexImage2D() is called with + * a NULL image pointer then load the texture image with something + * interesting instead of leaving it indeterminate. + */ + if (texImage->Data) { + char message[8][32] = { + " X X XXXXX XXX X ", + " XX XX X X X X X ", + " X X X X X X X ", + " X X XXXX XXX XXXXX ", + " X X X X X X ", + " X X X X X X X ", + " X X XXXXX XXX X X ", + " " + }; + + GLubyte *imgPtr = texImage->Data; + GLint i, j, k; + for (i=0;i<height;i++) { + GLint srcRow = 7 - i % 8; + for (j=0;j<width;j++) { + GLint srcCol = j % 32; + GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; + for (k=0;k<components;k++) { + *imgPtr++ = texel; + } + } + } + } + + return texImage; +} + + + +/* + * Test glTexImage() parameters for errors. + * Input: + * dimensions - must be 1 or 2 or 3 + * Return: GL_TRUE = an error was detected, GL_FALSE = no errors + */ +static GLboolean texture_error_check( GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLenum format, GLenum type, + GLint dimensions, + GLint width, GLint height, + GLint depth, GLint border ) +{ + GLboolean isProxy; + GLint iformat; + + if (dimensions == 1) { + isProxy = (target == GL_PROXY_TEXTURE_1D); + if (target != GL_TEXTURE_1D && !isProxy) { + gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 2) { + isProxy = (target == GL_PROXY_TEXTURE_2D); + if (target != GL_TEXTURE_2D && !isProxy) { + gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 3) { + isProxy = (target == GL_PROXY_TEXTURE_3D); + if (target != GL_TEXTURE_3D && !isProxy) { + gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); + return GL_TRUE; + } + } + else { + gl_problem( ctx, "bad dims in texture_error_check" ); + return GL_TRUE; + } + + /* Border */ + if (border!=0 && border!=1) { + if (!isProxy) { + if (dimensions == 1) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(border)" ); + else if (dimensions == 2) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(border)" ); + else if (dimensions == 3) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(border)" ); + } + return GL_TRUE; + } + + /* Width */ + if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize + || logbase2( width - 2 * border ) < 0) { + if (!isProxy) { + if (dimensions == 1) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(width)" ); + else if (dimensions == 2) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(width)" ); + else if (dimensions == 3) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(width)" ); + } + return GL_TRUE; + } + + /* Height */ + if (dimensions >= 2) { + if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize + || logbase2( height - 2 * border ) < 0) { + if (!isProxy) { + if (dimensions == 2) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(height)" ); + else if (dimensions == 3) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(height)" ); + return GL_TRUE; + } + } + } + + /* Depth */ + if (dimensions >= 3) { + if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize + || logbase2( depth - 2 * border ) < 0) { + if (!isProxy) { + gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" ); + } + return GL_TRUE; + } + } + + /* Level */ + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + if (dimensions == 1) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(level)" ); + else if (dimensions == 2) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(level)" ); + else if (dimensions == 3) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(level)" ); + return GL_TRUE; + } + + iformat = decode_internal_format( internalFormat ); + if (iformat < 0) { + if (dimensions == 1) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(internalFormat)" ); + else if (dimensions == 2) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(internalFormat)" ); + else if (dimensions == 3) + gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(internalFormat)" ); + return GL_TRUE; + } + + if (!gl_is_legal_format_and_type( format, type )) { + if (dimensions == 1) + gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(format or type)"); + else if (dimensions == 2) + gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(format or type)"); + else if (dimensions == 3) + gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(format or type)"); + return GL_TRUE; + } + + /* if we get here, the parameters are OK */ + return GL_FALSE; +} + + + +/* + * Called from the API. Note that width includes the border. + */ +void gl_TexImage1D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLint border, GLenum format, + GLenum type, struct gl_image *image ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D"); + + if (target==GL_TEXTURE_1D) { + struct gl_texture_image *teximage; + if (texture_error_check( ctx, target, level, internalformat, + format, type, 1, width, 1, 1, border )) { + /* error in texture image was detected */ + return; + } + + /* free current texture image, if any */ + if (texUnit->CurrentD[1]->Image[level]) { + gl_free_texture_image( texUnit->CurrentD[1]->Image[level] ); + } + + /* make new texture from source image */ + if (image) { + teximage = image_to_texture(ctx, image, internalformat, border); + } + else { + teximage = make_null_texture(ctx, (GLenum) internalformat, + width, 1, 1, border); + } + + /* install new texture image */ + + texUnit->CurrentD[1]->Image[level] = teximage; + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); + ctx->NewState |= NEW_TEXTURING; + + /* free the source image */ + if (image && image->RefCount==0) { + /* if RefCount>0 then image must be in a display list */ + gl_free_image(image); + } + + /* tell driver about change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, + texUnit->CurrentD[1], + level, internalformat, teximage ); + } + } + else if (target==GL_PROXY_TEXTURE_1D) { + /* Proxy texture: check for errors and update proxy state */ + if (texture_error_check( ctx, target, level, internalformat, + format, type, 1, width, 1, 1, border )) { + if (level>=0 && level<ctx->Const.MaxTextureLevels) { + MEMSET( ctx->Texture.Proxy1D->Image[level], 0, + sizeof(struct gl_texture_image) ); + } + } + else { + ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format; + set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] ); + ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalformat; + ctx->Texture.Proxy1D->Image[level]->Border = border; + ctx->Texture.Proxy1D->Image[level]->Width = width; + ctx->Texture.Proxy1D->Image[level]->Height = 1; + ctx->Texture.Proxy1D->Image[level]->Depth = 1; + } + if (image && image->RefCount==0) { + /* if RefCount>0 then image must be in a display list */ + gl_free_image(image); + } + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); + return; + } +} + + + + +/* + * Called by the API or display list executor. + * Note that width and height include the border. + */ +void gl_TexImage2D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + struct gl_image *image ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); + + if (target==GL_TEXTURE_2D) { + struct gl_texture_image *teximage; + if (texture_error_check( ctx, target, level, internalformat, + format, type, 2, width, height, 1, border )) { + /* error in texture image was detected */ + return; + } + + /* free current texture image, if any */ + if (texUnit->CurrentD[2]->Image[level]) { + gl_free_texture_image( texUnit->CurrentD[2]->Image[level] ); + } + + /* make new texture from source image */ + if (image) { + teximage = image_to_texture(ctx, image, internalformat, border); + } + else { + teximage = make_null_texture(ctx, (GLenum) internalformat, + width, height, 1, border); + } + + /* install new texture image */ + texUnit->CurrentD[2]->Image[level] = teximage; + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); + ctx->NewState |= NEW_TEXTURING; + + /* free the source image */ + if (image && image->RefCount==0) { + /* if RefCount>0 then image must be in a display list */ + gl_free_image(image); + } + + /* tell driver about change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, + texUnit->CurrentD[2], + level, internalformat, teximage ); + } + } + else if (target==GL_PROXY_TEXTURE_2D) { + /* Proxy texture: check for errors and update proxy state */ + if (texture_error_check( ctx, target, level, internalformat, + format, type, 2, width, height, 1, border )) { + if (level>=0 && level<ctx->Const.MaxTextureLevels) { + MEMSET( ctx->Texture.Proxy2D->Image[level], 0, + sizeof(struct gl_texture_image) ); + } + } + else { + ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format; + set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] ); + ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalformat; + ctx->Texture.Proxy2D->Image[level]->Border = border; + ctx->Texture.Proxy2D->Image[level]->Width = width; + ctx->Texture.Proxy2D->Image[level]->Height = height; + ctx->Texture.Proxy2D->Image[level]->Depth = 1; + } + if (image && image->RefCount==0) { + /* if RefCount>0 then image must be in a display list */ + gl_free_image(image); + } + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); + return; + } +} + + + +/* + * Called by the API or display list executor. + * Note that width and height include the border. + */ +void gl_TexImage3DEXT( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + struct gl_image *image ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3DEXT"); + + if (target==GL_TEXTURE_3D_EXT) { + struct gl_texture_image *teximage; + if (texture_error_check( ctx, target, level, internalformat, + format, type, 3, width, height, depth, + border )) { + /* error in texture image was detected */ + return; + } + + /* free current texture image, if any */ + if (texUnit->CurrentD[3]->Image[level]) { + gl_free_texture_image( texUnit->CurrentD[3]->Image[level] ); + } + + /* make new texture from source image */ + if (image) { + teximage = image_to_texture(ctx, image, internalformat, border); + } + else { + teximage = make_null_texture(ctx, (GLenum) internalformat, + width, height, depth, border); + } + + /* install new texture image */ + texUnit->CurrentD[3]->Image[level] = teximage; + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] ); + ctx->NewState |= NEW_TEXTURING; + + /* free the source image */ + if (image && image->RefCount==0) { + /* if RefCount>0 then image must be in a display list */ + gl_free_image(image); + } + + /* tell driver about change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, + texUnit->CurrentD[3], + level, internalformat, teximage ); + } + } + else if (target==GL_PROXY_TEXTURE_3D_EXT) { + /* Proxy texture: check for errors and update proxy state */ + if (texture_error_check( ctx, target, level, internalformat, + format, type, 3, width, height, depth, + border )) { + if (level>=0 && level<ctx->Const.MaxTextureLevels) { + MEMSET( ctx->Texture.Proxy3D->Image[level], 0, + sizeof(struct gl_texture_image) ); + } + } + else { + ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format; + set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] ); + ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalformat; + ctx->Texture.Proxy3D->Image[level]->Border = border; + ctx->Texture.Proxy3D->Image[level]->Width = width; + ctx->Texture.Proxy3D->Image[level]->Height = height; + ctx->Texture.Proxy3D->Image[level]->Depth = depth; + } + if (image && image->RefCount==0) { + /* if RefCount>0 then image must be in a display list */ + gl_free_image(image); + } + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexImage3DEXT(target)" ); + return; + } +} + + + +void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, GLenum format, + GLenum type, GLvoid *pixels ) +{ + const struct gl_texture_object *texObj; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage"); + + if (level < 0 || level >= ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); + return; + } + + if (gl_sizeof_type(type) <= 0) { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); + return; + } + + if (gl_components_in_format(format) <= 0) { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); + return; + } + + if (!pixels) + return; /* XXX generate an error??? */ + + switch (target) { + case GL_TEXTURE_1D: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1]; + break; + case GL_TEXTURE_2D: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2]; + break; + case GL_TEXTURE_3D: + texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3]; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" ); + return; + } + + if (texObj->Image[level] && texObj->Image[level]->Data) { + const struct gl_texture_image *texImage = texObj->Image[level]; + GLint width = texImage->Width; + GLint height = texImage->Height; + GLint row; + + for (row = 0; row < height; row++) { + /* compute destination address in client memory */ + GLvoid *dest = gl_pixel_addr_in_image( &ctx->Unpack, pixels, + width, height, + format, type, 0, row, 0); + + assert(dest); + if (texImage->Format == GL_RGBA) { + const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte); + gl_pack_rgba_span( ctx, width, (void *) src, format, type, dest, + &ctx->Pack, GL_TRUE ); + } + else { + /* fetch RGBA row from texture image then pack it in client mem */ + GLubyte rgba[MAX_WIDTH][4]; + GLint i; + const GLubyte *src; + switch (texImage->Format) { + case GL_ALPHA: + src = texImage->Data + row * width * sizeof(GLubyte); + for (i = 0; i < width; i++) { + rgba[i][RCOMP] = 255; + rgba[i][GCOMP] = 255; + rgba[i][BCOMP] = 255; + rgba[i][ACOMP] = src[i]; + } + break; + case GL_LUMINANCE: + src = texImage->Data + row * width * sizeof(GLubyte); + for (i = 0; i < width; i++) { + rgba[i][RCOMP] = src[i]; + rgba[i][GCOMP] = src[i]; + rgba[i][BCOMP] = src[i]; + rgba[i][ACOMP] = 255; + } + break; + case GL_LUMINANCE_ALPHA: + src = texImage->Data + row * 2 * width * sizeof(GLubyte); + for (i = 0; i < width; i++) { + rgba[i][RCOMP] = src[i*2+0]; + rgba[i][GCOMP] = src[i*2+0]; + rgba[i][BCOMP] = src[i*2+0]; + rgba[i][ACOMP] = src[i*2+1]; + } + break; + case GL_INTENSITY: + src = texImage->Data + row * width * sizeof(GLubyte); + for (i = 0; i < width; i++) { + rgba[i][RCOMP] = src[i]; + rgba[i][GCOMP] = src[i]; + rgba[i][BCOMP] = src[i]; + rgba[i][ACOMP] = 255; + } + break; + case GL_RGB: + src = texImage->Data + row * 3 * width * sizeof(GLubyte); + for (i = 0; i < width; i++) { + rgba[i][RCOMP] = src[i*3+0]; + rgba[i][GCOMP] = src[i*3+1]; + rgba[i][BCOMP] = src[i*3+2]; + rgba[i][ACOMP] = 255; + } + break; + case GL_RGBA: + /* this special case should have been handled above! */ + gl_problem( ctx, "error 1 in gl_GetTexImage" ); + break; + case GL_COLOR_INDEX: + gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" ); + break; + default: + gl_problem( ctx, "bad format in gl_GetTexImage" ); + } + gl_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba, + format, type, dest, &ctx->Pack, GL_TRUE ); + } + } + } +} + + + +/* + * Unpack the image data given to glTexSubImage[12]D. + * This function is just a wrapper for gl_unpack_image() but it does + * some extra error checking. + */ +struct gl_image * +gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height, + GLenum format, GLenum type, const GLvoid *pixels ) +{ + if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { + return NULL; + } + + if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){ + return NULL; + } + + if (gl_sizeof_type(type)<=0) { + return NULL; + } + + return gl_unpack_image3D( ctx, width, height, 1, format, type, pixels, &ctx->Unpack ); +} + + +/* + * Unpack the image data given to glTexSubImage3D. + * This function is just a wrapper for gl_unpack_image() but it does + * some extra error checking. + */ +struct gl_image * +gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height, + GLint depth, GLenum format, GLenum type, + const GLvoid *pixels ) +{ + if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { + return NULL; + } + + if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){ + return NULL; + } + + if (gl_sizeof_type(type)<=0) { + return NULL; + } + + return gl_unpack_image3D( ctx, width, height, depth, format, type, pixels, + &ctx->Unpack ); +} + + + +void gl_TexSubImage1D( GLcontext *ctx, + GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, GLenum type, + struct gl_image *image ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *destTex; + + if (target!=GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(level)" ); + return; + } + + destTex = texUnit->CurrentD[1]->Image[level]; + if (!destTex) { + gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage1D" ); + return; + } + + if (xoffset < -((GLint)destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset)" ); + return; + } + if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset+width)" ); + return; + } + + if (image) { + /* unpacking must have been error-free */ + GLint texcomponents = components_in_intformat(destTex->Format); + + if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { + /* Simple case, just byte copy image data into texture image */ + /* row by row. */ + GLubyte *dst = destTex->Data + texcomponents * xoffset; + GLubyte *src = (GLubyte *) image->Data; + MEMCPY( dst, src, width * texcomponents ); + } + else { + /* General case, convert image pixels into texels, scale, bias, etc */ + struct gl_texture_image *subTexImg = image_to_texture(ctx, image, + destTex->IntFormat, destTex->Border); + GLubyte *dst = destTex->Data + texcomponents * xoffset; + GLubyte *src = subTexImg->Data; + MEMCPY( dst, src, width * texcomponents ); + gl_free_texture_image(subTexImg); + } + + /* if the image's reference count is zero, delete it now */ + if (image->RefCount==0) { + gl_free_image(image); + } + + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); + + /* tell driver about change */ + if (ctx->Driver.TexSubImage) { + (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D, + texUnit->CurrentD[1], level, + xoffset,0,width,1, + texUnit->CurrentD[1]->Image[level]->IntFormat, + destTex ); + } + else { + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level, + texUnit->CurrentD[1]->Image[level]->IntFormat, + destTex ); + } + } + } + else { + /* if no image, an error must have occured, do more testing now */ + GLint components, size; + + if (width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(width)" ); + return; + } + if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); + return; + } + components = components_in_intformat( format ); + if (components<0 || format==GL_STENCIL_INDEX + || format==GL_DEPTH_COMPONENT){ + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); + return; + } + size = gl_sizeof_type( type ); + if (size<=0) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(type)" ); + return; + } + /* if we get here, probably ran out of memory during unpacking */ + gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D" ); + } +} + + + +void gl_TexSubImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + struct gl_image *image ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *destTex; + + if (target!=GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)" ); + return; + } + + destTex = texUnit->CurrentD[2]->Image[level]; + if (!destTex) { + gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage2D" ); + return; + } + + if (xoffset < -((GLint)destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset)" ); + return; + } + if (yoffset < -((GLint)destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset)" ); + return; + } + if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset+width)" ); + return; + } + if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset+height)" ); + return; + } + + if (image) { + /* unpacking must have been error-free */ + GLint texcomponents = components_in_intformat(destTex->Format); + + if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { + /* Simple case, just byte copy image data into texture image */ + /* row by row. */ + GLubyte *dst = destTex->Data + + (yoffset * destTex->Width + xoffset) * texcomponents; + GLubyte *src = (GLubyte *) image->Data; + GLint j; + for (j=0;j<height;j++) { + MEMCPY( dst, src, width * texcomponents ); + dst += destTex->Width * texcomponents * sizeof(GLubyte); + src += width * texcomponents * sizeof(GLubyte); + } + } + else { + /* General case, convert image pixels into texels, scale, bias, etc */ + struct gl_texture_image *subTexImg = image_to_texture(ctx, image, + destTex->IntFormat, destTex->Border); + GLubyte *dst = destTex->Data + + (yoffset * destTex->Width + xoffset) * texcomponents; + GLubyte *src = subTexImg->Data; + GLint j; + for (j=0;j<height;j++) { + MEMCPY( dst, src, width * texcomponents ); + dst += destTex->Width * texcomponents * sizeof(GLubyte); + src += width * texcomponents * sizeof(GLubyte); + } + gl_free_texture_image(subTexImg); + } + + /* if the image's reference count is zero, delete it now */ + if (image->RefCount==0) { + gl_free_image(image); + } + + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); + + /* tell driver about change */ + if (ctx->Driver.TexSubImage) { + (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, + xoffset, yoffset, width, height, + texUnit->CurrentD[2]->Image[level]->IntFormat, + destTex ); + } + else { + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, + texUnit->CurrentD[2]->Image[level]->IntFormat, + destTex ); + } + } + } + else { + /* if no image, an error must have occured, do more testing now */ + GLint components, size; + + if (width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(width)" ); + return; + } + if (height<0) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(height)" ); + return; + } + if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); + return; + } + components = gl_components_in_format( format ); + if (components<0 || format==GL_STENCIL_INDEX + || format==GL_DEPTH_COMPONENT){ + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(format)" ); + return; + } + size = gl_sizeof_packed_type( type ); + if (size<=0) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(type)" ); + return; + } + /* if we get here, probably ran out of memory during unpacking */ + gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D" ); + } +} + + + +void gl_TexSubImage3DEXT( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + struct gl_image *image ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *destTex; + + if (target!=GL_TEXTURE_3D_EXT) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(level)" ); + return; + } + + destTex = texUnit->CurrentD[3]->Image[level]; + if (!destTex) { + gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage3DEXT" ); + return; + } + + if (xoffset < -((GLint)destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset)" ); + return; + } + if (yoffset < -((GLint)destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset)" ); + return; + } + if (zoffset < -((GLint)destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset)" ); + return; + } + if (xoffset + width > (GLint) (destTex->Width+destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset+width)" ); + return; + } + if (yoffset + height > (GLint) (destTex->Height+destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset+height)" ); + return; + } + if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset+depth)" ); + return; + } + + if (image) { + /* unpacking must have been error-free */ + GLint texcomponents = components_in_intformat(destTex->Format); + GLint dstRectArea = destTex->Width * destTex->Height; + GLint srcRectArea = width * height; + + if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { + /* Simple case, just byte copy image data into texture image */ + /* row by row. */ + GLubyte *dst = destTex->Data + + (zoffset * dstRectArea + yoffset * destTex->Width + xoffset) + * texcomponents; + GLubyte *src = (GLubyte *) image->Data; + GLint j, k; + for(k=0;k<depth; k++) { + for (j=0;j<height;j++) { + MEMCPY( dst, src, width * texcomponents ); + dst += destTex->Width * texcomponents; + src += width * texcomponents; + } + dst += dstRectArea * texcomponents * sizeof(GLubyte); + src += srcRectArea * texcomponents * sizeof(GLubyte); + } + } + else { + /* General case, convert image pixels into texels, scale, bias, etc */ + struct gl_texture_image *subTexImg = image_to_texture(ctx, image, + destTex->IntFormat, destTex->Border); + GLubyte *dst = destTex->Data + + (zoffset * dstRectArea + yoffset * destTex->Width + xoffset) + * texcomponents; + GLubyte *src = subTexImg->Data; + GLint j, k; + for(k=0;k<depth; k++) { + for (j=0;j<height;j++) { + MEMCPY( dst, src, width * texcomponents ); + dst += destTex->Width * texcomponents; + src += width * texcomponents; + } + dst += dstRectArea * texcomponents * sizeof(GLubyte); + src += srcRectArea * texcomponents * sizeof(GLubyte); + } + gl_free_texture_image(subTexImg); + } + /* if the image's reference count is zero, delete it now */ + if (image->RefCount==0) { + gl_free_image(image); + } + + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] ); + + /* tell driver about change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3], + level, texUnit->CurrentD[3]->Image[level]->IntFormat, + destTex ); + } + } + else { + /* if no image, an error must have occured, do more testing now */ + GLint components, size; + + if (width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(width)" ); + return; + } + if (height<0) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(height)" ); + return; + } + if (depth<0) { + gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(depth)" ); + return; + } + if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" ); + return; + } + components = components_in_intformat( format ); + if (components<0 || format==GL_STENCIL_INDEX + || format==GL_DEPTH_COMPONENT){ + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" ); + return; + } + size = gl_sizeof_type( type ); + if (size<=0) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(type)" ); + return; + } + /* if we get here, probably ran out of memory during unpacking */ + gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage3DEXT" ); + } +} + + + +/* + * Read an RGBA image from the frame buffer. + * Input: ctx - the context + * x, y - lower left corner + * width, height - size of region to read + * format - one of GL_RED, GL_RGB, GL_LUMINANCE, etc. + * Return: gl_image pointer or NULL if out of memory + */ +static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format ) +{ + struct gl_image *image; + GLubyte *imgptr; + GLint components; + GLint i, j; + + components = components_in_intformat( format ); + + /* + * Allocate image struct and image data buffer + */ + image = (struct gl_image *) malloc( sizeof(struct gl_image) ); + if (image) { + image->Width = width; + image->Height = height; + image->Depth = 1; + image->Components = components; + image->Format = format; + image->Type = GL_UNSIGNED_BYTE; + image->RefCount = 0; + image->Data = (GLubyte *) malloc( width * height * components ); + if (!image->Data) { + free(image); + return NULL; + } + } + else { + return NULL; + } + + imgptr = (GLubyte *) image->Data; + + /* Select buffer to read from */ + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); + + for (j=0;j<height;j++) { + GLubyte rgba[MAX_WIDTH][4]; + gl_read_rgba_span( ctx, width, x, y+j, rgba ); + + switch (format) { + case GL_ALPHA: + for (i=0;i<width;i++) { + *imgptr++ = rgba[i][ACOMP]; + } + break; + case GL_LUMINANCE: + for (i=0;i<width;i++) { + *imgptr++ = rgba[i][RCOMP]; + } + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<width;i++) { + *imgptr++ = rgba[i][RCOMP]; + *imgptr++ = rgba[i][ACOMP]; + } + break; + case GL_INTENSITY: + for (i=0;i<width;i++) { + *imgptr++ = rgba[i][RCOMP]; + } + break; + case GL_RGB: + for (i=0;i<width;i++) { + *imgptr++ = rgba[i][RCOMP]; + *imgptr++ = rgba[i][GCOMP]; + *imgptr++ = rgba[i][BCOMP]; + } + break; + case GL_RGBA: + for (i=0;i<width;i++) { + *imgptr++ = rgba[i][RCOMP]; + *imgptr++ = rgba[i][GCOMP]; + *imgptr++ = rgba[i][BCOMP]; + *imgptr++ = rgba[i][ACOMP]; + } + break; + default: + gl_problem(ctx, "Bad format in read_color_image"); + break; + } /*switch*/ + + } /*for*/ + + /* Restore drawing buffer */ + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); + + return image; +} + + + + +void gl_CopyTexImage1D( GLcontext *ctx, + GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, + GLsizei width, GLint border ) +{ + GLint format; + struct gl_image *teximage; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D"); + if (target!=GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(level)" ); + return; + } + if (border!=0 && border!=1) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(border)" ); + return; + } + if (width < 2*border || width > 2 + ctx->Const.MaxTextureSize || width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(width)" ); + return; + } + format = decode_internal_format( internalformat ); + if (format<0 || (internalformat>=1 && internalformat<=4)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(format)" ); + return; + } + + teximage = read_color_image( ctx, x, y, width, 1, (GLenum) format ); + if (!teximage) { + gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); + return; + } + + gl_TexImage1D( ctx, target, level, internalformat, width, + border, GL_RGBA, GL_UNSIGNED_BYTE, teximage ); + + /* teximage was freed in gl_TexImage1D */ +} + + + +void gl_CopyTexImage2D( GLcontext *ctx, + GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border ) +{ + GLint format; + struct gl_image *teximage; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D"); + if (target!=GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(level)" ); + return; + } + if (border!=0 && border!=1) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(border)" ); + return; + } + if (width<2*border || width>2+ctx->Const.MaxTextureSize || width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width)" ); + return; + } + if (height<2*border || height>2+ctx->Const.MaxTextureSize || height<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(height)" ); + return; + } + format = decode_internal_format( internalformat ); + if (format<0 || (internalformat>=1 && internalformat<=4)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(format)" ); + return; + } + + teximage = read_color_image( ctx, x, y, width, height, (GLenum) format ); + if (!teximage) { + gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); + return; + } + + gl_TexImage2D( ctx, target, level, internalformat, width, height, + border, GL_RGBA, GL_UNSIGNED_BYTE, teximage ); + + /* teximage was freed in gl_TexImage2D */ +} + + + + +/* + * Do the work of glCopyTexSubImage[123]D. + * TODO: apply pixel bias scale and mapping. + */ +static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, + GLint width, GLint height, + GLint srcx, GLint srcy, + GLint dstx, GLint dsty, GLint zoffset ) +{ + GLint i, j; + GLint format, components, rectarea; + GLint texwidth, texheight; + + texwidth = dest->Width; + texheight = dest->Height; + rectarea = texwidth * texheight; + zoffset *= rectarea; + format = dest->Format; + components = components_in_intformat( format ); + + /* Select buffer to read from */ + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); + + for (j=0;j<height;j++) { + GLubyte rgba[MAX_WIDTH][4]; + GLubyte *texptr; + + gl_read_rgba_span( ctx, width, srcx, srcy+j, rgba ); + + texptr = dest->Data + ( zoffset + (dsty+j) * texwidth + dstx) * components; + + switch (format) { + case GL_ALPHA: + for (i=0;i<width;i++) { + *texptr++ = rgba[i][ACOMP]; + } + break; + case GL_LUMINANCE: + for (i=0;i<width;i++) { + *texptr++ = rgba[i][RCOMP]; + } + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<width;i++) { + *texptr++ = rgba[i][RCOMP]; + *texptr++ = rgba[i][ACOMP]; + } + break; + case GL_INTENSITY: + for (i=0;i<width;i++) { + *texptr++ = rgba[i][RCOMP]; + } + break; + case GL_RGB: + for (i=0;i<width;i++) { + *texptr++ = rgba[i][RCOMP]; + *texptr++ = rgba[i][GCOMP]; + *texptr++ = rgba[i][BCOMP]; + } + break; + case GL_RGBA: + for (i=0;i<width;i++) { + *texptr++ = rgba[i][RCOMP]; + *texptr++ = rgba[i][GCOMP]; + *texptr++ = rgba[i][BCOMP]; + *texptr++ = rgba[i][ACOMP]; + } + break; + } /*switch*/ + } /*for*/ + + + /* Restore drawing buffer */ + (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); +} + + + + +void gl_CopyTexSubImage1D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *teximage; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D"); + if (target!=GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(level)" ); + return; + } + if (width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(width)" ); + return; + } + + teximage = texUnit->CurrentD[1]->Image[level]; + + if (teximage) { + if (xoffset < -((GLint)teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(xoffset)" ); + return; + } + /* NOTE: we're adding the border here, not subtracting! */ + if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, + "glCopyTexSubImage1D(xoffset+width)" ); + return; + } + if (teximage->Data) { + copy_tex_sub_image( ctx, teximage, width, 1, x, y, xoffset, 0, 0 ); + + /* tell driver about change */ + if (ctx->Driver.TexSubImage) { + (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D, + texUnit->CurrentD[1], level, + xoffset,0,width,1, + teximage->IntFormat, + teximage ); + } + else { + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level, + teximage->IntFormat, + teximage ); + } + } + } + } + else { + gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" ); + } +} + + + +void gl_CopyTexSubImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *teximage; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D"); + if (target!=GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(level)" ); + return; + } + if (width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(width)" ); + return; + } + if (height<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(height)" ); + return; + } + + teximage = texUnit->CurrentD[2]->Image[level]; + + if (teximage) { + if (xoffset < -((GLint)teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(xoffset)" ); + return; + } + if (yoffset < -((GLint)teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(yoffset)" ); + return; + } + /* NOTE: we're adding the border here, not subtracting! */ + if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, + "glCopyTexSubImage2D(xoffset+width)" ); + return; + } + if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, + "glCopyTexSubImage2D(yoffset+height)" ); + return; + } + + if (teximage->Data) { + copy_tex_sub_image( ctx, teximage, width, height, + x, y, xoffset, yoffset, 0 ); + /* tell driver about change */ + if (ctx->Driver.TexSubImage) { + (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, + xoffset, yoffset, width, height, + teximage->IntFormat, + teximage ); + } + else { + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, + teximage->IntFormat, + teximage ); + } + } + } + } + else { + gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" ); + } +} + + + +void gl_CopyTexSubImage3DEXT( 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 = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *teximage; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3DEXT"); + if (target!=GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3DEXT(target)" ); + return; + } + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(level)" ); + return; + } + if (width<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(width)" ); + return; + } + if (height<0) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(height)" ); + return; + } + + teximage = texUnit->CurrentD[3]->Image[level]; + if (teximage) { + if (xoffset < -((GLint)teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(xoffset)" ); + return; + } + if (yoffset < -((GLint)teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(yoffset)" ); + return; + } + if (zoffset < -((GLint)teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(zoffset)" ); + return; + } + /* NOTE: we're adding the border here, not subtracting! */ + if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, + "glCopyTexSubImage3DEXT(xoffset+width)" ); + return; + } + if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, + "glCopyTexSubImage3DEXT(yoffset+height)" ); + return; + } + if (zoffset > (GLint) (teximage->Depth+teximage->Border)) { + gl_error( ctx, GL_INVALID_VALUE, + "glCopyTexSubImage3DEXT(zoffset+depth)" ); + return; + } + + if (teximage->Data) { + copy_tex_sub_image( ctx, teximage, width, height, + x, y, xoffset, yoffset, zoffset); + + /* tell driver about change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3], + level, teximage->IntFormat, + teximage ); + } + } + } + else { + gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage3DEXT" ); + } +} + diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h new file mode 100644 index 00000000000..eb72f961e5a --- /dev/null +++ b/src/mesa/main/teximage.h @@ -0,0 +1,186 @@ +/* $Id: teximage.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 TEXIMAGE_H +#define TEXIMAGE_H + + +#include "types.h" + + +/*** Internal functions ***/ + + +extern struct gl_texture_image *gl_alloc_texture_image( void ); + + +extern void gl_free_texture_image( struct gl_texture_image *teximage ); + + +extern struct gl_image * +gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern struct gl_image * +gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height,GLint depth, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern struct gl_texture_image * +gl_unpack_texture( GLcontext *ctx, + GLint dimensions, + GLenum target, + GLint level, + GLint internalformat, + GLsizei width, GLsizei height, + GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ); + +extern struct gl_texture_image * +gl_unpack_texture3D( GLcontext *ctx, + GLint dimensions, + GLenum target, + GLint level, + GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void gl_tex_image_1D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLint border, GLenum format, + GLenum type, const GLvoid *pixels ); + + +extern void gl_tex_image_2D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLint height, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ); + +extern void gl_tex_image_3D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLint height, GLint depth, + GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +/*** API entry points ***/ + + +extern void gl_TexImage1D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLint border, GLenum format, + GLenum type, struct gl_image *teximage ); + + +extern void gl_TexImage2D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + struct gl_image *teximage ); + + +extern void gl_TexImage3DEXT( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, + GLenum format, GLenum type, + struct gl_image *teximage ); + + +extern void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels ); + + + +extern void gl_TexSubImage1D( GLcontext *ctx, + GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, GLenum type, + struct gl_image *image ); + + +extern void gl_TexSubImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + struct gl_image *image ); + + +extern void gl_TexSubImage3DEXT( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + struct gl_image *image ); + + +extern void gl_CopyTexImage1D( GLcontext *ctx, + GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, + GLsizei width, GLint border ); + + +extern void gl_CopyTexImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLenum internalformat, GLint x, GLint y, + GLsizei width, GLsizei height, + GLint border ); + + +extern void gl_CopyTexSubImage1D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, + GLsizei width ); + + +extern void gl_CopyTexSubImage2D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLsizei height ); + + +extern void gl_CopyTexSubImage3DEXT( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, + GLint x, GLint y, + GLsizei width, GLsizei height ); + +#endif + diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c new file mode 100644 index 00000000000..78691d24f2c --- /dev/null +++ b/src/mesa/main/texobj.c @@ -0,0 +1,571 @@ +/* $Id: texobj.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include "context.h" +#include "enums.h" +#include "hash.h" +#include "macros.h" +#include "teximage.h" +#include "texstate.h" +#include "texobj.h" +#include "types.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +/* + * Allocate a new texture object and add it to the linked list of texture + * objects. If name>0 then also insert the new texture object into the hash + * table. + * Input: shared - the shared GL state structure to contain the texture object + * name - integer name for the texture object + * dimensions - either 1, 2 or 3 + * Return: pointer to new texture object + */ +struct gl_texture_object * +gl_alloc_texture_object( struct gl_shared_state *shared, GLuint name, + GLuint dimensions) +{ + struct gl_texture_object *obj; + + assert(dimensions <= 3); + + obj = (struct gl_texture_object *) + calloc(1,sizeof(struct gl_texture_object)); + if (obj) { + /* init the non-zero fields */ + obj->Name = name; + obj->Dimensions = dimensions; + obj->WrapS = GL_REPEAT; + obj->WrapT = GL_REPEAT; + obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR; + obj->MagFilter = GL_LINEAR; + obj->MinLod = -1000.0; + obj->MaxLod = 1000.0; + obj->BaseLevel = 0; + obj->MaxLevel = 1000; + obj->MinMagThresh = 0.0F; + obj->Palette[0] = 255; + obj->Palette[1] = 255; + obj->Palette[2] = 255; + obj->Palette[3] = 255; + obj->PaletteSize = 1; + obj->PaletteIntFormat = GL_RGBA; + obj->PaletteFormat = GL_RGBA; + + /* insert into linked list */ + if (shared) { + obj->Next = shared->TexObjectList; + shared->TexObjectList = obj; + } + + if (name > 0) { + /* insert into hash table */ + HashInsert(shared->TexObjects, name, obj); + } + } + return obj; +} + + +/* + * Deallocate a texture object struct and remove it from the given + * shared GL state. + * Input: shared - the shared GL state to which the object belongs + * t - the texture object to delete + */ +void gl_free_texture_object( struct gl_shared_state *shared, + struct gl_texture_object *t ) +{ + struct gl_texture_object *tprev, *tcurr; + + assert(t); + + /* Remove t from dirty list so we don't touch free'd memory later. + * Test for shared since Proxy texture aren't in global linked list. + */ + if (shared) + gl_remove_texobj_from_dirty_list( shared, t ); + + /* unlink t from the linked list */ + if (shared) { + tprev = NULL; + tcurr = shared->TexObjectList; + while (tcurr) { + if (tcurr==t) { + if (tprev) { + tprev->Next = t->Next; + } + else { + shared->TexObjectList = t->Next; + } + break; + } + tprev = tcurr; + tcurr = tcurr->Next; + } + } + + if (t->Name) { + /* remove from hash table */ + HashRemove(shared->TexObjects, t->Name); + } + + /* free texture image */ + { + GLuint i; + for (i=0;i<MAX_TEXTURE_LEVELS;i++) { + if (t->Image[i]) { + gl_free_texture_image( t->Image[i] ); + } + } + } + /* free this object */ + free( t ); +} + + + +/* + * Examine a texture object to determine if it is complete or not. + * The t->Complete flag will be set to GL_TRUE or GL_FALSE accordingly. + */ +void gl_test_texture_object_completeness( const GLcontext *ctx, struct gl_texture_object *t ) +{ + t->Complete = GL_TRUE; /* be optimistic */ + + /* Always need level zero image */ + if (!t->Image[0] || !t->Image[0]->Data) { + t->Complete = GL_FALSE; + return; + } + + /* Compute number of mipmap levels */ + if (t->Dimensions==1) { + t->P = t->Image[0]->WidthLog2; + } + else if (t->Dimensions==2) { + t->P = MAX2(t->Image[0]->WidthLog2, t->Image[0]->HeightLog2); + } + else if (t->Dimensions==3) { + GLint max = MAX2(t->Image[0]->WidthLog2, t->Image[0]->HeightLog2); + max = MAX2(max, (GLint)(t->Image[0]->DepthLog2)); + t->P = max; + } + + /* Compute M (see the 1.2 spec) used during mipmapping */ + t->M = (GLfloat) (MIN2(t->MaxLevel, t->P) - t->BaseLevel); + + + if (t->MinFilter!=GL_NEAREST && t->MinFilter!=GL_LINEAR) { + /* + * Mipmapping: determine if we have a complete set of mipmaps + */ + GLint i; + GLint minLevel = t->BaseLevel; + GLint maxLevel = MIN2(t->P, ctx->Const.MaxTextureLevels-1); + maxLevel = MIN2(maxLevel, t->MaxLevel); + + if (minLevel > maxLevel) { + t->Complete = GL_FALSE; + return; + } + + /* Test dimension-independent attributes */ + for (i = minLevel; i <= maxLevel; i++) { + if (t->Image[i]) { + if (!t->Image[i]->Data) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Format != t->Image[0]->Format) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Border != t->Image[0]->Border) { + t->Complete = GL_FALSE; + return; + } + } + } + + /* Test things which depend on number of texture image dimensions */ + if (t->Dimensions==1) { + /* Test 1-D mipmaps */ + GLuint width = t->Image[0]->Width2; + for (i=1; i<ctx->Const.MaxTextureLevels; i++) { + if (width>1) { + width /= 2; + } + if (i >= minLevel && i <= maxLevel) { + if (!t->Image[i]) { + t->Complete = GL_FALSE; + return; + } + if (!t->Image[i]->Data) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Width2 != width ) { + t->Complete = GL_FALSE; + return; + } + } + if (width==1) { + return; /* found smallest needed mipmap, all done! */ + } + } + } + else if (t->Dimensions==2) { + /* Test 2-D mipmaps */ + GLuint width = t->Image[0]->Width2; + GLuint height = t->Image[0]->Height2; + for (i=1; i<ctx->Const.MaxTextureLevels; i++) { + if (width>1) { + width /= 2; + } + if (height>1) { + height /= 2; + } + if (i >= minLevel && i <= maxLevel) { + if (!t->Image[i]) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Width2 != width) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Height2 != height) { + t->Complete = GL_FALSE; + return; + } + if (width==1 && height==1) { + return; /* found smallest needed mipmap, all done! */ + } + } + } + } + else if (t->Dimensions==3) { + /* Test 3-D mipmaps */ + GLuint width = t->Image[0]->Width2; + GLuint height = t->Image[0]->Height2; + GLuint depth = t->Image[0]->Depth2; + for (i=1; i<ctx->Const.MaxTextureLevels; i++) { + if (width>1) { + width /= 2; + } + if (height>1) { + height /= 2; + } + if (depth>1) { + depth /= 2; + } + if (i >= minLevel && i <= maxLevel) { + if (!t->Image[i]) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Width2 != width) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Height2 != height) { + t->Complete = GL_FALSE; + return; + } + if (t->Image[i]->Depth2 != depth) { + t->Complete = GL_FALSE; + return; + } + } + if (width==1 && height==1 && depth==1) { + return; /* found smallest needed mipmap, all done! */ + } + } + } + else { + /* Dimensions = ??? */ + gl_problem(NULL, "Bug in gl_test_texture_object_completeness\n"); + } + } +} + + + +/* + * Execute glGenTextures + */ +void gl_GenTextures( GLcontext *ctx, GLsizei n, GLuint *texName ) +{ + GLuint first; + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGenTextures"); + if (n<0) { + gl_error( ctx, GL_INVALID_VALUE, "glGenTextures" ); + return; + } + + first = HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); + + /* Return the texture names */ + for (i=0;i<n;i++) { + texName[i] = first + i; + } + + /* Allocate new, empty texture objects */ + for (i=0;i<n;i++) { + GLuint name = first + i; + GLuint dims = 0; + (void) gl_alloc_texture_object(ctx->Shared, name, dims); + } +} + + + +/* + * Execute glDeleteTextures + */ +void gl_DeleteTextures( GLcontext *ctx, GLsizei n, const GLuint *texName) +{ + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDeleteTextures"); + + for (i=0;i<n;i++) { + struct gl_texture_object *t; + if (texName[i]>0) { + t = (struct gl_texture_object *) + HashLookup(ctx->Shared->TexObjects, texName[i]); + if (t) { + GLuint u; + for (u=0; u<MAX_TEXTURE_UNITS; u++) { + struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; + GLuint d; + for (d = 1 ; d <= 3 ; d++) { + if (unit->CurrentD[d]==t) { + unit->CurrentD[d] = ctx->Shared->DefaultD[d][u]; + ctx->Shared->DefaultD[d][u]->RefCount++; + t->RefCount--; + assert( t->RefCount >= 0 ); + } + } + } + + /* tell device driver to delete texture */ + if (ctx->Driver.DeleteTexture) { + (*ctx->Driver.DeleteTexture)( ctx, t ); + } + + if (t->RefCount==0) { + gl_free_texture_object(ctx->Shared, t); + } + } + } + } +} + + + +/* + * Execute glBindTexture + */ +void gl_BindTexture( GLcontext *ctx, GLenum target, GLuint texName ) +{ + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *oldTexObj; + struct gl_texture_object *newTexObj; + GLint dim; + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glBindTexture %s %d\n", + gl_lookup_enum_by_nr(target), (GLint) texName); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBindTexture"); + + dim = target - GL_TEXTURE_1D; + + if (dim < 0 || dim > 2) { + gl_error( ctx, GL_INVALID_ENUM, "glBindTexture" ); + return; + } + + dim++; + oldTexObj = texUnit->CurrentD[dim]; + + if (oldTexObj->Name == texName) + return; + + if (texName == 0) + newTexObj = ctx->Shared->DefaultD[unit][dim]; + else { + struct HashTable *hash = ctx->Shared->TexObjects; + newTexObj = (struct gl_texture_object *) HashLookup(hash, texName); + + if (!newTexObj) + newTexObj = gl_alloc_texture_object(ctx->Shared, texName, dim); + + if (newTexObj->Dimensions != dim) { + if (newTexObj->Dimensions) { + gl_error( ctx, GL_INVALID_OPERATION, "glBindTexture" ); + return; + } + newTexObj->Dimensions = dim; + } + } + + oldTexObj->RefCount--; + newTexObj->RefCount++; + texUnit->CurrentD[dim] = newTexObj; + + /* If we've changed the CurrentD[123] texture object then update the + * ctx->Texture.Current pointer to point to the new texture object. + */ + texUnit->Current = texUnit->CurrentD[texUnit->CurrentDimension]; + + /* Check if we may have to use a new triangle rasterizer */ + if ((ctx->IndirectTriangles & DD_SW_RASTERIZE) && + ( oldTexObj->WrapS != newTexObj->WrapS + || oldTexObj->WrapT != newTexObj->WrapT + || oldTexObj->WrapR != newTexObj->WrapR + || oldTexObj->MinFilter != newTexObj->MinFilter + || oldTexObj->MagFilter != newTexObj->MagFilter + || (oldTexObj->Image[0] && newTexObj->Image[0] && + (oldTexObj->Image[0]->Format!=newTexObj->Image[0]->Format)))) + { + ctx->NewState |= (NEW_RASTER_OPS | NEW_TEXTURING); + } + + if (oldTexObj->Complete != newTexObj->Complete) + ctx->NewState |= NEW_TEXTURING; + + /* Pass BindTexture call to device driver */ + if (ctx->Driver.BindTexture) { + (*ctx->Driver.BindTexture)( ctx, target, newTexObj ); + } +} + + + +/* + * Execute glPrioritizeTextures + */ +void gl_PrioritizeTextures( GLcontext *ctx, + GLsizei n, const GLuint *texName, + const GLclampf *priorities ) +{ + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPrioritizeTextures"); + if (n<0) { + gl_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" ); + return; + } + + for (i=0;i<n;i++) { + struct gl_texture_object *t; + if (texName[i]>0) { + t = (struct gl_texture_object *) + HashLookup(ctx->Shared->TexObjects, texName[i]); + if (t) { + t->Priority = CLAMP( priorities[i], 0.0F, 1.0F ); + } + } + } +} + + + +/* + * Execute glAreTexturesResident + */ +GLboolean gl_AreTexturesResident( GLcontext *ctx, GLsizei n, + const GLuint *texName, + GLboolean *residences ) +{ + GLboolean resident = GL_TRUE; + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, + "glAreTexturesResident", + GL_FALSE); + if (n<0) { + gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)" ); + return GL_FALSE; + } + + for (i=0;i<n;i++) { + struct gl_texture_object *t; + if (texName[i]==0) { + gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" ); + return GL_FALSE; + } + t = (struct gl_texture_object *) + HashLookup(ctx->Shared->TexObjects, texName[i]); + if (t) { + /* we consider all valid texture objects to be resident */ + residences[i] = GL_TRUE; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" ); + return GL_FALSE; + } + } + return resident; +} + + + +/* + * Execute glIsTexture + */ +GLboolean gl_IsTexture( GLcontext *ctx, GLuint texture ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glIsTextures", + GL_FALSE); + if (texture>0 && HashLookup(ctx->Shared->TexObjects, texture)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h new file mode 100644 index 00000000000..655c823753c --- /dev/null +++ b/src/mesa/main/texobj.h @@ -0,0 +1,85 @@ +/* $Id: texobj.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 TEXTOBJ_H +#define TEXTOBJ_H + + +#include "types.h" + + +#ifdef VMS +#define gl_test_texture_object_completeness gl_test_texture_object_complete +#endif + +/* + * Internal functions + */ + +extern struct gl_texture_object * +gl_alloc_texture_object( struct gl_shared_state *shared, GLuint name, + GLuint dimensions ); + + +extern void gl_free_texture_object( struct gl_shared_state *shared, + struct gl_texture_object *t ); + + +extern void gl_test_texture_object_completeness( const GLcontext *ctx, struct gl_texture_object *t ); + + +/* + * API functions + */ + +extern void gl_GenTextures( GLcontext *ctx, GLsizei n, GLuint *textures ); + + +extern void gl_DeleteTextures( GLcontext *ctx, + GLsizei n, const GLuint *textures); + + +extern void gl_BindTexture( GLcontext *ctx, GLenum target, GLuint texture ); + + +extern void gl_PrioritizeTextures( GLcontext *ctx, + GLsizei n, const GLuint *textures, + const GLclampf *priorities ); + + +extern GLboolean gl_AreTexturesResident( GLcontext *ctx, GLsizei n, + const GLuint *textures, + GLboolean *residences ); + + +extern GLboolean gl_IsTexture( GLcontext *ctx, GLuint texture ); + + +#endif diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c new file mode 100644 index 00000000000..eee5eaa0e44 --- /dev/null +++ b/src/mesa/main/texstate.c @@ -0,0 +1,1146 @@ +/* $Id: texstate.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <assert.h> +#include <stdio.h> +#include "context.h" +#include "enums.h" +#include "macros.h" +#include "matrix.h" +#include "texobj.h" +#include "texstate.h" +#include "texture.h" +#include "types.h" +#include "xform.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + + +#ifdef SPECIALCAST +/* Needed for an Amiga compiler */ +#define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X)) +#define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X)) +#else +/* all other compilers */ +#define ENUM_TO_FLOAT(X) ((GLfloat)(X)) +#define ENUM_TO_DOUBLE(X) ((GLdouble)(X)) +#endif + + + + +/**********************************************************************/ +/* Texture Environment */ +/**********************************************************************/ + + +void gl_TexEnvfv( GLcontext *ctx, + GLenum target, GLenum pname, const GLfloat *param ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexEnv"); + + if (target!=GL_TEXTURE_ENV) { + gl_error( ctx, GL_INVALID_ENUM, "glTexEnv(target)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glTexEnv %s %s %.1f(%s) ...\n", + gl_lookup_enum_by_nr(target), + gl_lookup_enum_by_nr(pname), + *param, + gl_lookup_enum_by_nr((GLenum) (GLint) *param)); + + + if (pname==GL_TEXTURE_ENV_MODE) { + GLenum mode = (GLenum) (GLint) *param; + switch (mode) { + case GL_MODULATE: + case GL_BLEND: + case GL_DECAL: + case GL_REPLACE: + /* A small optimization for drivers */ + if (texUnit->EnvMode == mode) + return; + + if (MESA_VERBOSE & (VERBOSE_STATE|VERBOSE_TEXTURE)) + fprintf(stderr, "glTexEnv: old mode %s, new mode %s\n", + gl_lookup_enum_by_nr(texUnit->EnvMode), + gl_lookup_enum_by_nr(mode)); + + texUnit->EnvMode = mode; + ctx->NewState |= NEW_TEXTURE_ENV; + break; + default: + gl_error( ctx, GL_INVALID_VALUE, "glTexEnv(param)" ); + return; + } + } + else if (pname==GL_TEXTURE_ENV_COLOR) { + texUnit->EnvColor[0] = CLAMP( param[0], 0.0, 1.0 ); + texUnit->EnvColor[1] = CLAMP( param[1], 0.0, 1.0 ); + texUnit->EnvColor[2] = CLAMP( param[2], 0.0, 1.0 ); + texUnit->EnvColor[3] = CLAMP( param[3], 0.0, 1.0 ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); + return; + } + + /* Tell device driver about the new texture environment */ + if (ctx->Driver.TexEnv) { + (*ctx->Driver.TexEnv)( ctx, pname, param ); + } +} + + + + + +void gl_GetTexEnvfv( GLcontext *ctx, + GLenum target, GLenum pname, GLfloat *params ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (target!=GL_TEXTURE_ENV) { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); + return; + } + switch (pname) { + case GL_TEXTURE_ENV_MODE: + *params = ENUM_TO_FLOAT(texUnit->EnvMode); + break; + case GL_TEXTURE_ENV_COLOR: + COPY_4FV( params, texUnit->EnvColor ); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); + } +} + + +void gl_GetTexEnviv( GLcontext *ctx, + GLenum target, GLenum pname, GLint *params ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + if (target!=GL_TEXTURE_ENV) { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); + return; + } + switch (pname) { + case GL_TEXTURE_ENV_MODE: + *params = (GLint) texUnit->EnvMode; + break; + case GL_TEXTURE_ENV_COLOR: + params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] ); + params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] ); + params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] ); + params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] ); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); + } +} + + + + +/**********************************************************************/ +/* Texture Parameters */ +/**********************************************************************/ + + +void gl_TexParameterfv( GLcontext *ctx, + GLenum target, GLenum pname, const GLfloat *params ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + GLenum eparam = (GLenum) (GLint) params[0]; + struct gl_texture_object *texObj; + + if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "texPARAM %s %s %d...\n", + gl_lookup_enum_by_nr(target), + gl_lookup_enum_by_nr(pname), + eparam); + + + switch (target) { + case GL_TEXTURE_1D: + texObj = texUnit->CurrentD[1]; + break; + case GL_TEXTURE_2D: + texObj = texUnit->CurrentD[2]; + break; + case GL_TEXTURE_3D_EXT: + texObj = texUnit->CurrentD[3]; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" ); + return; + } + + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + /* A small optimization */ + if (texObj->MinFilter == eparam) + return; + + if (eparam==GL_NEAREST || eparam==GL_LINEAR + || eparam==GL_NEAREST_MIPMAP_NEAREST + || eparam==GL_LINEAR_MIPMAP_NEAREST + || eparam==GL_NEAREST_MIPMAP_LINEAR + || eparam==GL_LINEAR_MIPMAP_LINEAR) { + texObj->MinFilter = eparam; + ctx->NewState |= NEW_TEXTURING; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + break; + case GL_TEXTURE_MAG_FILTER: + /* A small optimization */ + if (texObj->MagFilter == eparam) + return; + + if (eparam==GL_NEAREST || eparam==GL_LINEAR) { + texObj->MagFilter = eparam; + ctx->NewState |= NEW_TEXTURING; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + break; + case GL_TEXTURE_WRAP_S: + if (texObj->WrapS == eparam) + return; + + if (eparam==GL_CLAMP || eparam==GL_REPEAT || eparam==GL_CLAMP_TO_EDGE) { + texObj->WrapS = eparam; + ctx->NewState |= NEW_TEXTURING; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + break; + case GL_TEXTURE_WRAP_T: + if (texObj->WrapT == eparam) + return; + + if (eparam==GL_CLAMP || eparam==GL_REPEAT || eparam==GL_CLAMP_TO_EDGE) { + texObj->WrapT = eparam; + ctx->NewState |= NEW_TEXTURING; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + break; + case GL_TEXTURE_WRAP_R_EXT: + if (texObj->WrapR == eparam) + return; + + if (eparam==GL_CLAMP || eparam==GL_REPEAT || eparam==GL_CLAMP_TO_EDGE) { + texObj->WrapR = eparam; + ctx->NewState |= NEW_TEXTURING; + } + else { + gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + } + break; + case GL_TEXTURE_BORDER_COLOR: + texObj->BorderColor[0] = CLAMP((GLint)(params[0]*255.0), 0, 255); + texObj->BorderColor[1] = CLAMP((GLint)(params[1]*255.0), 0, 255); + texObj->BorderColor[2] = CLAMP((GLint)(params[2]*255.0), 0, 255); + texObj->BorderColor[3] = CLAMP((GLint)(params[3]*255.0), 0, 255); + break; + case GL_TEXTURE_MIN_LOD: + texObj->MinLod = params[0]; + ctx->NewState |= NEW_TEXTURING; + break; + case GL_TEXTURE_MAX_LOD: + texObj->MaxLod = params[0]; + ctx->NewState |= NEW_TEXTURING; + break; + case GL_TEXTURE_BASE_LEVEL: + if (params[0] < 0.0) { + gl_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + texObj->BaseLevel = (GLint) params[0]; + ctx->NewState |= NEW_TEXTURING; + break; + case GL_TEXTURE_MAX_LEVEL: + if (params[0] < 0.0) { + gl_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + texObj->MaxLevel = (GLint) params[0]; + ctx->NewState |= NEW_TEXTURING; + break; + case GL_TEXTURE_PRIORITY: + /* ([email protected]) */ + texObj->Priority = CLAMP( params[0], 0.0, 1.0 ); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(pname)" ); + return; + } + + gl_put_texobj_on_dirty_list( ctx, texObj ); + + if (ctx->Driver.TexParameter) { + (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params ); + } +} + + + +void gl_GetTexLevelParameterfv( GLcontext *ctx, GLenum target, GLint level, + GLenum pname, GLfloat *params ) +{ + GLint iparam; + gl_GetTexLevelParameteriv( ctx, target, level, pname, &iparam ); + *params = (GLfloat) iparam; +} + + + +void gl_GetTexLevelParameteriv( GLcontext *ctx, GLenum target, GLint level, + GLenum pname, GLint *params ) +{ + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + const struct gl_texture_image *img = NULL; + GLuint dimensions; + + if (level < 0 || level >= ctx->Const.MaxTextureLevels) { + gl_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" ); + return; + } + + switch (target) { + case GL_TEXTURE_1D: + img = texUnit->CurrentD[1]->Image[level]; + dimensions = 1; + break; + case GL_TEXTURE_2D: + img = texUnit->CurrentD[2]->Image[level]; + dimensions = 2; + break; + case GL_TEXTURE_3D: + img = texUnit->CurrentD[3]->Image[level]; + dimensions = 3; + break; + case GL_PROXY_TEXTURE_1D: + img = ctx->Texture.Proxy1D->Image[level]; + dimensions = 1; + break; + case GL_PROXY_TEXTURE_2D: + img = ctx->Texture.Proxy2D->Image[level]; + dimensions = 2; + break; + case GL_PROXY_TEXTURE_3D: + img = ctx->Texture.Proxy3D->Image[level]; + dimensions = 3; + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)"); + return; + } + + if (!img) { + if (pname == GL_TEXTURE_COMPONENTS) + *params = 1; + else + *params = 0; + return; + } + + switch (pname) { + case GL_TEXTURE_WIDTH: + *params = img->Width; + return; + case GL_TEXTURE_HEIGHT: + if (dimensions > 1) { + *params = img->Height; + } + else { + gl_error( ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname=GL_TEXTURE_HEIGHT)" ); + } + return; + case GL_TEXTURE_DEPTH: + if (dimensions > 2) { + *params = img->Depth; + } + else { + gl_error( ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname=GL_TEXTURE_DEPTH)" ); + } + return; + case GL_TEXTURE_COMPONENTS: + *params = img->IntFormat; + return; + case GL_TEXTURE_BORDER: + *params = img->Border; + return; + case GL_TEXTURE_RED_SIZE: + *params = img->RedBits; + return; + case GL_TEXTURE_GREEN_SIZE: + *params = img->GreenBits; + return; + case GL_TEXTURE_BLUE_SIZE: + *params = img->BlueBits; + return; + case GL_TEXTURE_ALPHA_SIZE: + *params = img->AlphaBits; + return; + case GL_TEXTURE_INTENSITY_SIZE: + *params = img->IntensityBits; + return; + case GL_TEXTURE_LUMINANCE_SIZE: + *params = img->LuminanceBits; + return; + case GL_TEXTURE_INDEX_SIZE_EXT: + *params = img->IndexBits; + return; + default: + gl_error( ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)" ); + } +} + + + + +void gl_GetTexParameterfv( GLcontext *ctx, + GLenum target, GLenum pname, GLfloat *params ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *obj; + + switch (target) { + case GL_TEXTURE_1D: + obj = texUnit->CurrentD[1]; + break; + case GL_TEXTURE_2D: + obj = texUnit->CurrentD[2]; + break; + case GL_TEXTURE_3D_EXT: + obj = texUnit->CurrentD[3]; + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)"); + return; + } + + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + *params = ENUM_TO_FLOAT(obj->MagFilter); + break; + case GL_TEXTURE_MIN_FILTER: + *params = ENUM_TO_FLOAT(obj->MinFilter); + break; + case GL_TEXTURE_WRAP_S: + *params = ENUM_TO_FLOAT(obj->WrapS); + break; + case GL_TEXTURE_WRAP_T: + *params = ENUM_TO_FLOAT(obj->WrapT); + break; + case GL_TEXTURE_WRAP_R_EXT: + *params = ENUM_TO_FLOAT(obj->WrapR); + break; + case GL_TEXTURE_BORDER_COLOR: + params[0] = obj->BorderColor[0] / 255.0F; + params[1] = obj->BorderColor[1] / 255.0F; + params[2] = obj->BorderColor[2] / 255.0F; + params[3] = obj->BorderColor[3] / 255.0F; + break; + case GL_TEXTURE_RESIDENT: + *params = ENUM_TO_FLOAT(GL_TRUE); + break; + case GL_TEXTURE_PRIORITY: + *params = obj->Priority; + break; + case GL_TEXTURE_MIN_LOD: + *params = obj->MinLod; + break; + case GL_TEXTURE_MAX_LOD: + *params = obj->MaxLod; + break; + case GL_TEXTURE_BASE_LEVEL: + *params = obj->BaseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + *params = obj->MaxLevel; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname)" ); + } +} + + +void gl_GetTexParameteriv( GLcontext *ctx, + GLenum target, GLenum pname, GLint *params ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *obj; + + switch (target) { + case GL_TEXTURE_1D: + obj = texUnit->CurrentD[1]; + break; + case GL_TEXTURE_2D: + obj = texUnit->CurrentD[2]; + break; + case GL_TEXTURE_3D_EXT: + obj = texUnit->CurrentD[3]; + break; + default: + gl_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)"); + return; + } + + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + *params = (GLint) obj->MagFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLint) obj->MinFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLint) obj->WrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLint) obj->WrapT; + break; + case GL_TEXTURE_WRAP_R_EXT: + *params = (GLint) obj->WrapR; + break; + case GL_TEXTURE_BORDER_COLOR: + { + GLfloat color[4]; + color[0] = obj->BorderColor[0]/255.0; + color[1] = obj->BorderColor[1]/255.0; + color[2] = obj->BorderColor[2]/255.0; + color[3] = obj->BorderColor[3]/255.0; + params[0] = FLOAT_TO_INT( color[0] ); + params[1] = FLOAT_TO_INT( color[1] ); + params[2] = FLOAT_TO_INT( color[2] ); + params[3] = FLOAT_TO_INT( color[3] ); + } + break; + case GL_TEXTURE_RESIDENT: + *params = (GLint) GL_TRUE; + break; + case GL_TEXTURE_PRIORITY: + *params = (GLint) obj->Priority; + break; + case GL_TEXTURE_MIN_LOD: + *params = (GLint) obj->MinLod; + break; + case GL_TEXTURE_MAX_LOD: + *params = (GLint) obj->MaxLod; + break; + case GL_TEXTURE_BASE_LEVEL: + *params = obj->BaseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + *params = obj->MaxLevel; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname)" ); + } +} + + + + +/**********************************************************************/ +/* Texture Coord Generation */ +/**********************************************************************/ + + +void gl_TexGenfv( GLcontext *ctx, + GLenum coord, GLenum pname, const GLfloat *params ) +{ + GLuint tUnit = ctx->Texture.CurrentTransformUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexGenfv"); + + if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "texGEN %s %s %x...\n", + gl_lookup_enum_by_nr(coord), + gl_lookup_enum_by_nr(pname), + *(int *)params); + + switch( coord ) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + switch (mode) { + case GL_OBJECT_LINEAR: + texUnit->GenModeS = mode; + texUnit->GenBitS = TEXGEN_OBJ_LINEAR; + break; + case GL_EYE_LINEAR: + texUnit->GenModeS = mode; + texUnit->GenBitS = TEXGEN_EYE_LINEAR; + break; + case GL_REFLECTION_MAP_NV: + texUnit->GenModeS = mode; + texUnit->GenBitS = TEXGEN_REFLECTION_MAP_NV; + break; + case GL_NORMAL_MAP_NV: + texUnit->GenModeS = mode; + texUnit->GenBitS = TEXGEN_NORMAL_MAP_NV; + break; + case GL_SPHERE_MAP: + texUnit->GenModeS = mode; + texUnit->GenBitS = TEXGEN_SPHERE_MAP; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + } + else if (pname==GL_OBJECT_PLANE) { + texUnit->ObjectPlaneS[0] = params[0]; + texUnit->ObjectPlaneS[1] = params[1]; + texUnit->ObjectPlaneS[2] = params[2]; + texUnit->ObjectPlaneS[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + /* Transform plane equation by the inverse modelview matrix */ + if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) { + gl_matrix_analyze( &ctx->ModelView ); + } + gl_transform_vector( texUnit->EyePlaneS, params, + ctx->ModelView.inv ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + switch(mode) { + case GL_OBJECT_LINEAR: + texUnit->GenModeT = GL_OBJECT_LINEAR; + texUnit->GenBitT = TEXGEN_OBJ_LINEAR; + break; + case GL_EYE_LINEAR: + texUnit->GenModeT = GL_EYE_LINEAR; + texUnit->GenBitT = TEXGEN_EYE_LINEAR; + break; + case GL_REFLECTION_MAP_NV: + texUnit->GenModeT = GL_REFLECTION_MAP_NV; + texUnit->GenBitT = TEXGEN_REFLECTION_MAP_NV; + break; + case GL_NORMAL_MAP_NV: + texUnit->GenModeT = GL_NORMAL_MAP_NV; + texUnit->GenBitT = TEXGEN_NORMAL_MAP_NV; + break; + case GL_SPHERE_MAP: + texUnit->GenModeT = GL_SPHERE_MAP; + texUnit->GenBitT = TEXGEN_SPHERE_MAP; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + } + else if (pname==GL_OBJECT_PLANE) { + texUnit->ObjectPlaneT[0] = params[0]; + texUnit->ObjectPlaneT[1] = params[1]; + texUnit->ObjectPlaneT[2] = params[2]; + texUnit->ObjectPlaneT[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + /* Transform plane equation by the inverse modelview matrix */ + if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) { + gl_matrix_analyze( &ctx->ModelView ); + } + gl_transform_vector( texUnit->EyePlaneT, params, + ctx->ModelView.inv ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + switch (mode) { + case GL_OBJECT_LINEAR: + texUnit->GenModeR = GL_OBJECT_LINEAR; + texUnit->GenBitR = TEXGEN_OBJ_LINEAR; + break; + case GL_REFLECTION_MAP_NV: + texUnit->GenModeR = GL_REFLECTION_MAP_NV; + texUnit->GenBitR = TEXGEN_REFLECTION_MAP_NV; + break; + case GL_NORMAL_MAP_NV: + texUnit->GenModeR = GL_NORMAL_MAP_NV; + texUnit->GenBitR = TEXGEN_NORMAL_MAP_NV; + break; + case GL_EYE_LINEAR: + texUnit->GenModeR = GL_EYE_LINEAR; + texUnit->GenBitR = TEXGEN_EYE_LINEAR; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + } + else if (pname==GL_OBJECT_PLANE) { + texUnit->ObjectPlaneR[0] = params[0]; + texUnit->ObjectPlaneR[1] = params[1]; + texUnit->ObjectPlaneR[2] = params[2]; + texUnit->ObjectPlaneR[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + /* Transform plane equation by the inverse modelview matrix */ + if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) { + gl_matrix_analyze( &ctx->ModelView ); + } + gl_transform_vector( texUnit->EyePlaneR, params, + ctx->ModelView.inv ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + switch (mode) { + case GL_OBJECT_LINEAR: + texUnit->GenModeQ = GL_OBJECT_LINEAR; + texUnit->GenBitQ = TEXGEN_OBJ_LINEAR; + break; + case GL_EYE_LINEAR: + texUnit->GenModeQ = GL_EYE_LINEAR; + texUnit->GenBitQ = TEXGEN_EYE_LINEAR; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + } + else if (pname==GL_OBJECT_PLANE) { + texUnit->ObjectPlaneQ[0] = params[0]; + texUnit->ObjectPlaneQ[1] = params[1]; + texUnit->ObjectPlaneQ[2] = params[2]; + texUnit->ObjectPlaneQ[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + /* Transform plane equation by the inverse modelview matrix */ + if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) { + gl_matrix_analyze( &ctx->ModelView ); + } + gl_transform_vector( texUnit->EyePlaneQ, params, + ctx->ModelView.inv ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(coord)" ); + return; + } + + ctx->NewState |= NEW_TEXTURING; +} + + + +void gl_GetTexGendv( GLcontext *ctx, + GLenum coord, GLenum pname, GLdouble *params ) +{ + GLuint tUnit = ctx->Texture.CurrentTransformUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexGendv"); + + switch( coord ) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeS); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneS ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneS ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeT); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneT ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneT ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeR); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneR ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneR ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeQ); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneQ ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneQ ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)" ); + return; + } +} + + + +void gl_GetTexGenfv( GLcontext *ctx, + GLenum coord, GLenum pname, GLfloat *params ) +{ + GLuint tUnit = ctx->Texture.CurrentTransformUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexGenfv"); + + switch( coord ) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeS); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneS ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneS ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeT); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneT ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneT ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeR); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneR ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneR ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeQ); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneQ ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneQ ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)" ); + return; + } +} + + + +void gl_GetTexGeniv( GLcontext *ctx, + GLenum coord, GLenum pname, GLint *params ) +{ + GLuint tUnit = ctx->Texture.CurrentTransformUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexGeniv"); + + switch( coord ) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeS; + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneS ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneS ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeT; + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneT ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneT ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeR; + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneR ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneR ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeQ; + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneQ ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneQ ); + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)" ); + return; + } +} + + +/* GL_ARB_multitexture */ +void gl_ActiveTexture( GLcontext *ctx, GLenum target ) +{ + GLint maxUnits = ctx->Const.MaxTextureUnits; + + ASSERT_OUTSIDE_BEGIN_END( ctx, "glActiveTextureARB" ); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + fprintf(stderr, "glActiveTexture %s\n", + gl_lookup_enum_by_nr(target)); + + if (target >= GL_TEXTURE0_ARB && target < GL_TEXTURE0_ARB + maxUnits) { + GLint texUnit = target - GL_TEXTURE0_ARB; + ctx->TexCoordUnit = texUnit; + ctx->Texture.CurrentUnit = texUnit; + ctx->Texture.CurrentTransformUnit = texUnit; + if (ctx->Driver.ActiveTexture) { + (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit ); + } + } + else { + gl_error(ctx, GL_INVALID_OPERATION, "glActiveTextureARB(target)"); + } +} + + +/* GL_ARB_multitexture */ +void gl_ClientActiveTexture( GLcontext *ctx, GLenum target ) +{ + GLint maxUnits = ctx->Const.MaxTextureUnits; + + ASSERT_OUTSIDE_BEGIN_END( ctx, "glClientActiveTextureARB" ); + + if (target >= GL_TEXTURE0_ARB && target < GL_TEXTURE0_ARB + maxUnits) { + GLint texUnit = target - GL_TEXTURE0_ARB; + ctx->Array.ActiveTexture = texUnit; + } + else { + gl_error(ctx, GL_INVALID_OPERATION, "glActiveTextureARB(target)"); + } +} + + + +/* + * Put the given texture object into the list of dirty texture objects. + * When a texture object is dirty we have to reexamine it for completeness + * and perhaps choose a different texture sampling function. + */ +void gl_put_texobj_on_dirty_list( GLcontext *ctx, struct gl_texture_object *t ) +{ + ASSERT(ctx); + ASSERT(t); + /* Only insert if not already in the dirty list. + * The Dirty flag is only set iff the texture object is in the dirty list. + */ + if (!t->Dirty) { + ASSERT(t->NextDirty == NULL); + t->Dirty = GL_TRUE; + t->NextDirty = ctx->Shared->DirtyTexObjList; + ctx->Shared->DirtyTexObjList = t; + } +#ifdef DEBUG + else { + /* make sure t is in the list */ + struct gl_texture_object *obj = ctx->Shared->DirtyTexObjList; + while (obj) { + if (obj == t) { + return; + } + obj = obj->NextDirty; + } + gl_problem(ctx, "Error in gl_put_texobj_on_dirty_list"); + } +#endif +} + + +/* + * Remove a texture object from the dirty texture list. + */ +void gl_remove_texobj_from_dirty_list( struct gl_shared_state *shared, + struct gl_texture_object *tObj ) +{ + struct gl_texture_object *t, *prev = NULL; + ASSERT(shared); + ASSERT(tObj); + for (t = shared->DirtyTexObjList; t; t = t->NextDirty) { + if (t == tObj) { + if (prev) { + prev->NextDirty = t->NextDirty; + } + else { + shared->DirtyTexObjList = t->NextDirty; + } + return; + } + prev = t; + } +} + + +/* + * This is called by gl_update_state() if the NEW_TEXTURING bit in + * ctx->NewState is unit. + */ +void gl_update_dirty_texobjs( GLcontext *ctx ) +{ + struct gl_texture_object *t, *next; + for (t = ctx->Shared->DirtyTexObjList; t; t = next) { + next = t->NextDirty; + gl_test_texture_object_completeness(ctx, t); + gl_set_texture_sampler(t); + t->NextDirty = NULL; + t->Dirty = GL_FALSE; + } + ctx->Shared->DirtyTexObjList = NULL; +} diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h new file mode 100644 index 00000000000..870693bfa70 --- /dev/null +++ b/src/mesa/main/texstate.h @@ -0,0 +1,112 @@ +/* $Id: texstate.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 TEXSTATE_H +#define TEXSTATE_H + + +#include "types.h" + + +/*** Called from API ***/ + +extern void gl_GetTexEnvfv( GLcontext *ctx, + GLenum target, GLenum pname, GLfloat *params ); + +extern void gl_GetTexEnviv( GLcontext *ctx, + GLenum target, GLenum pname, GLint *params ); + +extern void gl_GetTexGendv( GLcontext *ctx, + GLenum coord, GLenum pname, GLdouble *params ); + +extern void gl_GetTexGenfv( GLcontext *ctx, + GLenum coord, GLenum pname, GLfloat *params ); + +extern void gl_GetTexGeniv( GLcontext *ctx, + GLenum coord, GLenum pname, GLint *params ); + +extern void gl_GetTexLevelParameterfv( GLcontext *ctx, + GLenum target, GLint level, + GLenum pname, GLfloat *params ); + +extern void gl_GetTexLevelParameteriv( GLcontext *ctx, + GLenum target, GLint level, + GLenum pname, GLint *params ); + +extern void gl_GetTexParameterfv( GLcontext *ctx, GLenum target, + GLenum pname, GLfloat *params ); + +extern void gl_GetTexParameteriv( GLcontext *ctx, + GLenum target, GLenum pname, GLint *params ); + + +extern void gl_TexEnvfv( GLcontext *ctx, + GLenum target, GLenum pname, const GLfloat *param ); + + +extern void gl_TexParameterfv( GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *params ); + + +extern void gl_TexGenfv( GLcontext *ctx, + GLenum coord, GLenum pname, const GLfloat *params ); + + + +extern void gl_SelectTextureTransform( GLcontext *ctx, GLenum target ); + + +/* + * GL_ARB_multitexture + */ +extern void gl_ActiveTexture( GLcontext *ctx, GLenum target ); + +extern void gl_ClientActiveTexture( GLcontext *ctx, GLenum target ); + + + +/*** Internal functions ***/ + +extern void +gl_put_texobj_on_dirty_list( GLcontext *ctx, struct gl_texture_object *t ); + +#ifdef VMS +#define gl_remove_texobj_from_dirty_list gl_remove_texobj_from_dirty_lis +#endif +extern void +gl_remove_texobj_from_dirty_list( struct gl_shared_state *shared, + struct gl_texture_object *tObj ); + +extern void +gl_update_dirty_texobjs( GLcontext *ctx ); + + +#endif + diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c new file mode 100644 index 00000000000..b63d6a7cceb --- /dev/null +++ b/src/mesa/main/varray.c @@ -0,0 +1,1259 @@ +/* $Id: varray.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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. + */ + +#ifdef PC_HEADER +#include "all.h" +#else +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "context.h" +#include "api.h" +#include "cva.h" +#include "enable.h" +#include "enums.h" +#include "dlist.h" +#include "light.h" +#include "macros.h" +#include "mmath.h" +#include "pipeline.h" +#include "texstate.h" +#include "translate.h" +#include "types.h" +#include "varray.h" +#include "vb.h" +#include "vbfill.h" +#include "vbrender.h" +#include "vbindirect.h" +#include "vbxform.h" +#include "xform.h" +#ifdef XFree86Server +#include "GL/xf86glx.h" +#endif +#endif + + +void GLAPIENTRY glVertexPointer(CTX_ARG GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr ) +{ + GLcontext *ctx; + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + if (size<2 || size>4) { + gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" ); + return; + } + if (stride<0) { + gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + fprintf(stderr, "glVertexPointer( sz %d type %s stride %d )\n", size, + gl_lookup_enum_by_nr( type ), + stride); + + ctx->Array.Vertex.StrideB = stride; + if (!stride) { + switch (type) { + case GL_SHORT: + ctx->Array.Vertex.StrideB = size*sizeof(GLshort); + break; + case GL_INT: + ctx->Array.Vertex.StrideB = size*sizeof(GLint); + break; + case GL_FLOAT: + ctx->Array.Vertex.StrideB = size*sizeof(GLfloat); + break; + case GL_DOUBLE: + ctx->Array.Vertex.StrideB = size*sizeof(GLdouble); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" ); + return; + } + } + ctx->Array.Vertex.Size = size; + ctx->Array.Vertex.Type = type; + ctx->Array.Vertex.Stride = stride; + ctx->Array.Vertex.Ptr = (void *) ptr; + ctx->Array.VertexFunc = gl_trans_4f_tab[size][TYPE_IDX(type)]; + ctx->Array.VertexEltFunc = gl_trans_elt_4f_tab[size][TYPE_IDX(type)]; + ctx->Array.NewArrayState |= VERT_OBJ_ANY; + ctx->NewState |= NEW_CLIENT_STATE; +} + + + + +void GLAPIENTRY glNormalPointer(CTX_ARG GLenum type, GLsizei stride, + const GLvoid *ptr ) +{ + GLcontext *ctx; + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + if (stride<0) { + gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + fprintf(stderr, "glNormalPointer( type %s stride %d )\n", + gl_lookup_enum_by_nr( type ), + stride); + + ctx->Array.Normal.StrideB = stride; + if (!stride) { + switch (type) { + case GL_BYTE: + ctx->Array.Normal.StrideB = 3*sizeof(GLbyte); + break; + case GL_SHORT: + ctx->Array.Normal.StrideB = 3*sizeof(GLshort); + break; + case GL_INT: + ctx->Array.Normal.StrideB = 3*sizeof(GLint); + break; + case GL_FLOAT: + ctx->Array.Normal.StrideB = 3*sizeof(GLfloat); + break; + case GL_DOUBLE: + ctx->Array.Normal.StrideB = 3*sizeof(GLdouble); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" ); + return; + } + } + ctx->Array.Normal.Type = type; + ctx->Array.Normal.Stride = stride; + ctx->Array.Normal.Ptr = (void *) ptr; + ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(type)]; + ctx->Array.NormalEltFunc = gl_trans_elt_3f_tab[TYPE_IDX(type)]; + ctx->Array.NewArrayState |= VERT_NORM; + ctx->NewState |= NEW_CLIENT_STATE; +} + + + +void GLAPIENTRY glColorPointer(CTX_ARG GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr ) +{ + GLcontext *ctx; + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + if (size<3 || size>4) { + gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" ); + return; + } + if (stride<0) { + gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size, + gl_lookup_enum_by_nr( type ), + stride); + + ctx->Array.Color.StrideB = stride; + if (!stride) { + switch (type) { + case GL_BYTE: + ctx->Array.Color.StrideB = size*sizeof(GLbyte); + break; + case GL_UNSIGNED_BYTE: + ctx->Array.Color.StrideB = size*sizeof(GLubyte); + break; + case GL_SHORT: + ctx->Array.Color.StrideB = size*sizeof(GLshort); + break; + case GL_UNSIGNED_SHORT: + ctx->Array.Color.StrideB = size*sizeof(GLushort); + break; + case GL_INT: + ctx->Array.Color.StrideB = size*sizeof(GLint); + break; + case GL_UNSIGNED_INT: + ctx->Array.Color.StrideB = size*sizeof(GLuint); + break; + case GL_FLOAT: + ctx->Array.Color.StrideB = size*sizeof(GLfloat); + break; + case GL_DOUBLE: + ctx->Array.Color.StrideB = size*sizeof(GLdouble); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" ); + return; + } + } + ctx->Array.Color.Size = size; + ctx->Array.Color.Type = type; + ctx->Array.Color.Stride = stride; + ctx->Array.Color.Ptr = (void *) ptr; + ctx->Array.ColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)]; + ctx->Array.ColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)]; + ctx->Array.NewArrayState |= VERT_RGBA; + ctx->NewState |= NEW_CLIENT_STATE; +} + + + +void GLAPIENTRY glIndexPointer(CTX_ARG GLenum type, GLsizei stride, + const GLvoid *ptr ) +{ + GLcontext *ctx; + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + if (stride<0) { + gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" ); + return; + } + + ctx->Array.Index.StrideB = stride; + if (!stride) { + switch (type) { + case GL_UNSIGNED_BYTE: + ctx->Array.Index.StrideB = sizeof(GLubyte); + break; + case GL_SHORT: + ctx->Array.Index.StrideB = sizeof(GLshort); + break; + case GL_INT: + ctx->Array.Index.StrideB = sizeof(GLint); + break; + case GL_FLOAT: + ctx->Array.Index.StrideB = sizeof(GLfloat); + break; + case GL_DOUBLE: + ctx->Array.Index.StrideB = sizeof(GLdouble); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" ); + return; + } + } + ctx->Array.Index.Type = type; + ctx->Array.Index.Stride = stride; + ctx->Array.Index.Ptr = (void *) ptr; + ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(type)]; + ctx->Array.IndexEltFunc = gl_trans_elt_1ui_tab[TYPE_IDX(type)]; + ctx->Array.NewArrayState |= VERT_INDEX; + ctx->NewState |= NEW_CLIENT_STATE; +} + + + +void GLAPIENTRY glTexCoordPointer(CTX_ARG GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ) +{ + GLuint texUnit; + + GLcontext *ctx; + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + texUnit = ctx->TexCoordUnit; + + if (size<1 || size>4) { + gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" ); + return; + } + if (stride<0) { + gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + fprintf(stderr, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n", + texUnit, + size, + gl_lookup_enum_by_nr( type ), + stride); + + ctx->Array.TexCoord[texUnit].StrideB = stride; + if (!stride) { + switch (type) { + case GL_SHORT: + ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLshort); + break; + case GL_INT: + ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLint); + break; + case GL_FLOAT: + ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLfloat); + break; + case GL_DOUBLE: + ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLdouble); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" ); + return; + } + } + ctx->Array.TexCoord[texUnit].Size = size; + ctx->Array.TexCoord[texUnit].Type = type; + ctx->Array.TexCoord[texUnit].Stride = stride; + ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr; + + ctx->Array.TexCoordFunc[texUnit] = gl_trans_4f_tab[size][TYPE_IDX(type)]; + ctx->Array.TexCoordEltFunc[texUnit] = gl_trans_elt_4f_tab[size][TYPE_IDX(type)]; + ctx->Array.NewArrayState |= PIPE_TEX(texUnit); + ctx->NewState |= NEW_CLIENT_STATE; +} + + + + +void GLAPIENTRY glEdgeFlagPointer(CTX_ARG GLsizei stride, const void *vptr ) +{ + const GLboolean *ptr = (GLboolean *)vptr; + + GLcontext *ctx; + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + if (stride<0) { + gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" ); + return; + } + ctx->Array.EdgeFlag.Stride = stride; + ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean); + ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr; + if (stride != sizeof(GLboolean)) { + ctx->Array.EdgeFlagFunc = gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)]; + } else { + ctx->Array.EdgeFlagFunc = 0; + } + ctx->Array.EdgeFlagEltFunc = gl_trans_elt_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)]; + ctx->Array.NewArrayState |= VERT_EDGE; + ctx->NewState |= NEW_CLIENT_STATE; +} + + +/* Called only from gl_DrawElements + */ +void gl_CVAEltPointer( GLcontext *ctx, GLenum type, const GLvoid *ptr ) +{ + switch (type) { + case GL_UNSIGNED_BYTE: + ctx->CVA.Elt.StrideB = sizeof(GLubyte); + break; + case GL_UNSIGNED_SHORT: + ctx->CVA.Elt.StrideB = sizeof(GLushort); + break; + case GL_UNSIGNED_INT: + ctx->CVA.Elt.StrideB = sizeof(GLuint); + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glEltPointer(type)" ); + return; + } + ctx->CVA.Elt.Type = type; + ctx->CVA.Elt.Stride = 0; + ctx->CVA.Elt.Ptr = (void *) ptr; + ctx->CVA.EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)]; + ctx->Array.NewArrayState |= VERT_ELT; /* ??? */ +} + + + +/* KW: Batch function to exec all the array elements in the input + * buffer prior to transform. Done only the first time a vertex + * buffer is executed or compiled. + */ +void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM ) +{ + GLuint *flags = IM->Flag; + GLuint *elts = IM->Elt; + GLuint count = IM->Count; + GLuint start = IM->Start; + GLuint translate = ctx->Array.Flags; + GLuint i; + + if (translate & VERT_OBJ_ANY) + (ctx->Array.VertexEltFunc)( IM->Obj, + &ctx->Array.Vertex, + flags, elts, VERT_ELT, + start, count); + + if (translate & VERT_NORM) + (ctx->Array.NormalEltFunc)( IM->Normal, + &ctx->Array.Normal, + flags, elts, (VERT_ELT|VERT_NORM), + start, count); + + if (translate & VERT_EDGE) + (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag, + &ctx->Array.EdgeFlag, + flags, elts, (VERT_ELT|VERT_EDGE), + start, count); + + if (translate & VERT_RGBA) + (ctx->Array.ColorEltFunc)( IM->Color, + &ctx->Array.Color, + flags, elts, (VERT_ELT|VERT_RGBA), + start, count); + + if (translate & VERT_INDEX) + (ctx->Array.IndexEltFunc)( IM->Index, + &ctx->Array.Index, + flags, elts, (VERT_ELT|VERT_INDEX), + start, count); + + if (translate & VERT_TEX0_ANY) + (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0], + &ctx->Array.TexCoord[0], + flags, elts, (VERT_ELT|VERT_TEX0_ANY), + start, count); + + if (translate & VERT_TEX1_ANY) + (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1], + &ctx->Array.TexCoord[1], + flags, elts, (VERT_ELT|VERT_TEX1_ANY), + start, count); + + IM->OrFlag |= translate; + + /* Lighting ignores the and-flag, so still need to do this. + */ + if (IM->AndFlag & VERT_ELT) { + for (i = 0 ; i < count ; i++) + flags[i] |= translate; + IM->AndFlag |= translate; + } else { + GLuint andflag = ~0; + for (i = 0 ; i < count ; i++) { + if (flags[i] & VERT_ELT) flags[i] |= translate; + andflag &= flags[i]; + } + IM->AndFlag = andflag; + } +} + + + +/* KW: I think this is moving in the right direction, but it still feels + * like we are doing way too much work. + */ +void gl_DrawArrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count ) +{ + struct vertex_buffer *VB = ctx->VB; + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays"); + + if (count<0) { + gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" ); + return; + } + + if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled) + { + GLint remaining = count; + GLint i; + GLvector4f obj; + GLvector3f norm; + GLvector4f tc[MAX_TEXTURE_UNITS]; + GLvector4ub col; + GLvector1ub edge; + GLvector1ui index; + GLuint update = 0, translate = 0; + struct vertex_array_pointers VSrc; + struct immediate *IM = VB->IM; + struct gl_client_array *client_data; + struct gl_pipeline *elt = &ctx->CVA.elt; + GLuint relock; + GLuint fallback, required; + + if (ctx->NewState) + gl_update_state( ctx ); + + /* This will die miserably with CVA... Need more work to support this. + */ + relock = ctx->CompileCVAFlag; + ctx->CompileCVAFlag = 0; + + if (!elt->pipeline_valid || relock) + gl_build_immediate_pipeline( ctx ); + + required = elt->inputs; + fallback = (elt->inputs & ~ctx->Array.Summary); + + VSrc.Color = &IM->v.Color; + VSrc.Index = &IM->v.Index; + VSrc.EdgeFlag = &IM->v.EdgeFlag; + VSrc.TexCoord[0] = &IM->v.TexCoord[0]; + VSrc.TexCoord[1] = &IM->v.TexCoord[1]; + VSrc.Obj = &IM->v.Obj; + VSrc.Normal = &IM->v.Normal; + + if (required & VERT_RGBA) + { + client_data = &ctx->Array.Color; + if (fallback & VERT_RGBA) + client_data = &ctx->Fallback.Color; + + if (client_data->Type == GL_UNSIGNED_BYTE && + client_data->Size == 4) + { + VSrc.Color = &col; + col.data = (GLubyte (*)[4]) client_data->Ptr; + col.stride = client_data->StrideB; + col.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE; + if (client_data->StrideB != 4 * sizeof(GLubyte)) + col.flags ^= VEC_STRIDE_FLAGS; + + update |= VERT_RGBA; + } else { + translate |= VERT_RGBA; + } + } + + if (required & VERT_INDEX) + { + client_data = &ctx->Array.Index; + if (fallback & VERT_INDEX) + client_data = &ctx->Fallback.Index; + + if (client_data->Type == GL_UNSIGNED_INT) + { + VSrc.Index = &index; + index.data = (GLuint *) client_data->Ptr; + index.stride = client_data->StrideB; + index.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE; + if (client_data->StrideB != sizeof(GLuint)) + index.flags ^= VEC_STRIDE_FLAGS; + + update |= VERT_INDEX; + } else { + translate |= VERT_INDEX; + } + } + + for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) + { + GLuint flag = VERT_TEX_ANY(i); + + if (required & flag) { + + client_data = &ctx->Array.TexCoord[i]; + + if (fallback & flag) + { + client_data = &ctx->Fallback.TexCoord[i]; + client_data->Size = gl_texcoord_size( ctx->Current.Flag, i ); + } + + if (client_data->Type == GL_FLOAT) + { + VSrc.TexCoord[i] = &tc[i]; + tc[i].data = (GLfloat (*)[4]) client_data->Ptr; + tc[i].stride = client_data->StrideB; + tc[i].size = client_data->Size; + tc[i].flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE; + if (tc[i].stride |= 4 * sizeof(GLfloat)) + tc[i].flags ^= VEC_STRIDE_FLAGS; + update |= flag; + } else { + translate |= flag; + } + } + } + + if (ctx->Array.Flags != ctx->Array.Flag[0]) + for (i = 0 ; i < VB_MAX ; i++) + ctx->Array.Flag[i] = ctx->Array.Flags; + + + if (ctx->Array.Vertex.Type == GL_FLOAT) + { + VSrc.Obj = &obj; + obj.data = (GLfloat (*)[4]) ctx->Array.Vertex.Ptr; + obj.stride = ctx->Array.Vertex.StrideB; + obj.size = ctx->Array.Vertex.Size; + obj.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE; + if (obj.stride != 4 * sizeof(GLfloat)) + obj.flags ^= VEC_STRIDE_FLAGS; + + update |= VERT_OBJ_ANY; + } + else + { + translate |= VERT_OBJ_ANY; + } + + if (required & VERT_NORM) + { + client_data = &ctx->Array.Normal; + if (fallback & VERT_NORM) + client_data = &ctx->Fallback.Normal; + + if (client_data->Type == GL_FLOAT) + { + VSrc.Normal = &norm; + norm.flags = 0; + norm.data = (GLfloat (*)[3]) client_data->Ptr; + norm.stride = client_data->StrideB; + update |= VERT_NORM; + } else { + translate |= VERT_NORM; + } + } + + if ( (required & VERT_EDGE) && + (mode == GL_TRIANGLES || + mode == GL_QUADS || + mode == GL_POLYGON)) + { + client_data = &ctx->Array.EdgeFlag; + + if (fallback & VERT_EDGE) + client_data = &ctx->Fallback.EdgeFlag; + + VSrc.EdgeFlag = &edge; + edge.data = (GLboolean *) client_data->Ptr; + edge.stride = client_data->StrideB; + edge.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE; + if (edge.stride != sizeof(GLubyte)) + edge.flags ^= VEC_STRIDE_FLAGS; + + update |= VERT_EDGE; + } + + VB->Primitive = IM->Primitive; + VB->NextPrimitive = IM->NextPrimitive; + VB->MaterialMask = IM->MaterialMask; + VB->Material = IM->Material; + VB->BoundsPtr = 0; + + while (remaining > 0) { + GLint vbspace = VB_MAX - VB_START; + GLuint count, n; + + + if (vbspace >= remaining) { + n = remaining; + VB->LastPrimitive = VB_START + n; + } else { + n = vbspace; + VB->LastPrimitive = VB_START; + } + + VB->CullMode = 0; + + + /* Update pointers. + */ + if (update) { + if (update & VERT_OBJ_ANY) + obj.start = VEC_ELT(&obj, GLfloat, start); + + if (update & VERT_NORM) + norm.start = VEC_ELT(&norm, GLfloat, start); + + if (update & VERT_EDGE) + edge.start = VEC_ELT(&edge, GLubyte, start); + + if (update & VERT_RGBA) + col.start = VEC_ELT(&col, GLubyte, start); + + if (update & VERT_INDEX) + index.start = VEC_ELT(&index, GLuint, start); + + if (update & VERT_TEX0_ANY) + tc[0].start = VEC_ELT(&tc[0], GLfloat, start); + + if (update & VERT_TEX1_ANY) + tc[1].start = VEC_ELT(&tc[1], GLfloat, start); + } + + + /* Translate data to fix up type and stride. + */ + if (translate) { + if (translate & VERT_OBJ_ANY) { + ctx->Array.VertexFunc( IM->Obj + VB_START, + &ctx->Array.Vertex, start, n ); + } + + if (translate & VERT_NORM) { + ctx->Array.NormalFunc( IM->Normal + VB_START, + &ctx->Array.Normal, start, n ); + } + + if (translate & VERT_EDGE) { + ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START, + &ctx->Array.EdgeFlag, start, n ); + } + + if (translate & VERT_RGBA) { + ctx->Array.ColorFunc( IM->Color + VB_START, + &ctx->Array.Color, start, n ); + } + + if (translate & VERT_INDEX) { + ctx->Array.IndexFunc( IM->Index + VB_START, + &ctx->Array.Index, start, n ); + } + + if (translate & VERT_TEX0_ANY) { + IM->v.TexCoord[0].size = tc[0].size; + ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START, + &ctx->Array.TexCoord[0], start, n ); + } + + if (translate & VERT_TEX1_ANY) { + IM->v.TexCoord[1].size = tc[1].size; + ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START, + &ctx->Array.TexCoord[1], start, n ); + } + } + + + VB->ObjPtr = VSrc.Obj; + VB->NormalPtr = VSrc.Normal; + VB->Color[0] = VB->Color[1] = VB->ColorPtr = VSrc.Color; + VB->IndexPtr = VSrc.Index; + VB->EdgeFlagPtr = VSrc.EdgeFlag; + VB->TexCoordPtr[0] = VSrc.TexCoord[0]; + VB->TexCoordPtr[1] = VSrc.TexCoord[1]; + + VB->Flag = ctx->Array.Flag; + VB->AndFlag = ctx->Array.Flags; + VB->OrFlag = ctx->Array.Flags; + + count = VB->Count = VB_START + n; + + VB->ObjPtr->count = count; + VB->NormalPtr->count = count; + VB->ColorPtr->count = count; + VB->IndexPtr->count = count; + VB->EdgeFlagPtr->count = count; + VB->TexCoordPtr[0]->count = count; + VB->TexCoordPtr[1]->count = count; + + VB->Flag[count] |= VERT_END_VB; + VB->Flag[VB_START] |= VERT_NORM; +/* VB->Flag[VB_START] |= (IM->Flag[vb_start] & VERT_MATERIAL); */ + + VB->NextPrimitive[VB->CopyStart] = VB->Count; + VB->Primitive[VB->CopyStart] = mode; + + /* Transform and render. + */ + gl_run_pipeline( VB ); + gl_reset_vb( VB ); + + ctx->Array.Flag[count] = ctx->Array.Flags; + ctx->Array.Flag[VB_START] = ctx->Array.Flags; + IM->Flag[VB_START] = 0; + + start += n; + remaining -= n; + } + + ctx->CompileCVAFlag = relock; + } + else if (ctx->Array.Vertex.Enabled) + { + /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These + * could be handled by the above code, but it gets a little + * complex. + */ + /* No need to reset - never called from inside a display list */ + gl_Begin( ctx, mode ); + for (i=0;i<count;i++) { + gl_ArrayElement( ctx, start+i ); + } + gl_End( ctx ); + } + else + { + /* The degenerate case where vertices are not enabled - only + * need to process the very final array element, as all of the + * preceding ones would be overwritten anyway. + */ + gl_Begin( ctx, mode ); + gl_ArrayElement( ctx, start+count ); + gl_End( ctx ); + } +} + + + +/* KW: Exactly fakes the effects of calling glArrayElement multiple times. + * Compilation is handled via. the IM->maybe_transform_vb() callback. + */ +#define DRAW_ELT(FUNC, TYPE) \ +static void FUNC( GLcontext *ctx, GLenum mode, \ + TYPE *indices, GLuint count ) \ +{ \ + GLuint i,j; \ + \ + if (count) gl_Begin( ctx, mode ); \ + \ + for (j = 0 ; j < count ; ) { \ + GLuint nr = MIN2( VB_MAX, count - j + VB_START ); \ + struct immediate *IM = ctx->input; \ + GLuint sf = IM->Flag[VB_START]; \ + GLuint flags = IM->ArrayOrFlags; \ + \ + for (i = VB_START ; i < nr ; i++) { \ + IM->Elt[i] = (GLuint) *indices++; \ + IM->Flag[i] = flags; \ + } \ + \ + if (j == 0) IM->Flag[VB_START] |= sf; \ + \ + IM->Count = nr; \ + j += nr - VB_START; \ + \ + if (j == count) gl_End( ctx ); \ + \ + IM->maybe_transform_vb( IM ); \ + } \ +} + +DRAW_ELT( draw_elt_ubyte, GLubyte ) +DRAW_ELT( draw_elt_ushort, GLushort ) +DRAW_ELT( draw_elt_uint, GLuint ) + + +static GLuint natural_stride[0x10] = +{ + sizeof(GLbyte), /* 0 */ + sizeof(GLubyte), /* 1 */ + sizeof(GLshort), /* 2 */ + sizeof(GLushort), /* 3 */ + sizeof(GLint), /* 4 */ + sizeof(GLuint), /* 5 */ + sizeof(GLfloat), /* 6 */ + 2 * sizeof(GLbyte), /* 7 */ + 3 * sizeof(GLbyte), /* 8 */ + 4 * sizeof(GLbyte), /* 9 */ + sizeof(GLdouble), /* a */ + 0, /* b */ + 0, /* c */ + 0, /* d */ + 0, /* e */ + 0 /* f */ +}; + +void GLAPIENTRY glDrawElements(CTX_ARG GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices ) +{ + GLcontext *ctx; + struct gl_cva *cva; + + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + cva = &ctx->CVA; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements"); + + if (count<0) { + gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" ); + return; + } + + if (mode < 0 || mode > GL_POLYGON) { + gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); + return; + } + + if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT) + { + gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + return; + } + + if (ctx->NewState) + gl_update_state(ctx); + + if (ctx->CompileCVAFlag) + { +#if defined(MESA_CVA_PROF) + force_init_prof(); +#endif + + /* Treat VERT_ELT like a special client array. + */ + ctx->Array.NewArrayState |= VERT_ELT; + ctx->Array.Summary |= VERT_ELT; + ctx->Array.Flags |= VERT_ELT; + + cva->elt_mode = mode; + cva->elt_count = count; + cva->Elt.Type = type; + cva->Elt.Ptr = (void *) indices; + cva->Elt.StrideB = natural_stride[TYPE_IDX(type)]; + cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)]; + + if (!cva->pre.pipeline_valid) + gl_build_precalc_pipeline( ctx ); + else if (MESA_VERBOSE & VERBOSE_PIPELINE) + fprintf(stderr, ": dont rebuild\n"); + + gl_cva_force_precalc( ctx ); + + /* Did we 'precalculate' the render op? + */ + if (ctx->CVA.pre.ops & PIPE_OP_RENDER) { + ctx->Array.NewArrayState |= VERT_ELT; + ctx->Array.Summary &= ~VERT_ELT; + ctx->Array.Flags &= ~VERT_ELT; + return; + } + + if ( (MESA_VERBOSE&VERBOSE_VARRAY) ) + printf("using immediate\n"); + } + + + /* Otherwise, have to use the immediate path to render. + */ + switch (type) { + case GL_UNSIGNED_BYTE: + { + GLubyte *ub_indices = (GLubyte *) indices; + if (ctx->Array.Summary & VERT_OBJ_ANY) { + draw_elt_ubyte( ctx, mode, ub_indices, count ); + } else { + gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] ); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLushort *us_indices = (GLushort *) indices; + if (ctx->Array.Summary & VERT_OBJ_ANY) { + draw_elt_ushort( ctx, mode, us_indices, count ); + } else { + gl_ArrayElement( ctx, (GLuint) us_indices[count-1] ); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *ui_indices = (GLuint *) indices; + if (ctx->Array.Summary & VERT_OBJ_ANY) { + draw_elt_uint( ctx, mode, ui_indices, count ); + } else { + gl_ArrayElement( ctx, ui_indices[count-1] ); + } + } + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + break; + } + + if (ctx->CompileCVAFlag) { + ctx->Array.NewArrayState |= VERT_ELT; + ctx->Array.Summary &= ~VERT_ELT; + } +} + + + +void GLAPIENTRY glInterleavedArrays(CTX_ARG GLenum format, GLsizei stride, + const GLvoid *pointer ) +{ + GLcontext *ctx; + GLboolean tflag, cflag, nflag; /* enable/disable flags */ + GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */ + + GLenum ctype; /* color type */ + GLint coffset, noffset, voffset;/* color, normal, vertex offsets */ + GLint defstride; /* default stride */ + GLint c, f; + GLint coordUnitSave; + + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + + f = sizeof(GLfloat); + c = f * ((4*sizeof(GLubyte) + (f-1)) / f); + + if (stride<0) { + gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" ); + return; + } + + switch (format) { + case GL_V2F: + tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 0; ccomps = 0; vcomps = 2; + voffset = 0; + defstride = 2*f; + break; + case GL_V3F: + tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 0; ccomps = 0; vcomps = 3; + voffset = 0; + defstride = 3*f; + break; + case GL_C4UB_V2F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 0; ccomps = 4; vcomps = 2; + ctype = GL_UNSIGNED_BYTE; + coffset = 0; + voffset = c; + defstride = c + 2*f; + break; + case GL_C4UB_V3F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 0; ccomps = 4; vcomps = 3; + ctype = GL_UNSIGNED_BYTE; + coffset = 0; + voffset = c; + defstride = c + 3*f; + break; + case GL_C3F_V3F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 0; ccomps = 3; vcomps = 3; + ctype = GL_FLOAT; + coffset = 0; + voffset = 3*f; + defstride = 6*f; + break; + case GL_N3F_V3F: + tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE; + tcomps = 0; ccomps = 0; vcomps = 3; + noffset = 0; + voffset = 3*f; + defstride = 6*f; + break; + case GL_C4F_N3F_V3F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE; + tcomps = 0; ccomps = 4; vcomps = 3; + ctype = GL_FLOAT; + coffset = 0; + noffset = 4*f; + voffset = 7*f; + defstride = 10*f; + break; + case GL_T2F_V3F: + tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 2; ccomps = 0; vcomps = 3; + voffset = 2*f; + defstride = 5*f; + break; + case GL_T4F_V4F: + tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 4; ccomps = 0; vcomps = 4; + voffset = 4*f; + defstride = 8*f; + break; + case GL_T2F_C4UB_V3F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 2; ccomps = 4; vcomps = 3; + ctype = GL_UNSIGNED_BYTE; + coffset = 2*f; + voffset = c+2*f; + defstride = c+5*f; + break; + case GL_T2F_C3F_V3F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 2; ccomps = 3; vcomps = 3; + ctype = GL_FLOAT; + coffset = 2*f; + voffset = 5*f; + defstride = 8*f; + break; + case GL_T2F_N3F_V3F: + tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE; + tcomps = 2; ccomps = 0; vcomps = 3; + noffset = 2*f; + voffset = 5*f; + defstride = 8*f; + break; + case GL_T2F_C4F_N3F_V3F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; + tcomps = 2; ccomps = 4; vcomps = 3; + ctype = GL_FLOAT; + coffset = 2*f; + noffset = 6*f; + voffset = 9*f; + defstride = 12*f; + break; + case GL_T4F_C4F_N3F_V4F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; + tcomps = 4; ccomps = 4; vcomps = 4; + ctype = GL_FLOAT; + coffset = 4*f; + noffset = 8*f; + voffset = 11*f; + defstride = 15*f; + break; + default: + gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" ); + return; + } + + if (stride==0) { + stride = defstride; + } + + gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY ); + gl_DisableClientState( ctx, GL_INDEX_ARRAY ); + + /* Texcoords */ + coordUnitSave = ctx->TexCoordUnit; + if (tflag) { + GLint i; + GLint factor = ctx->Array.TexCoordInterleaveFactor; + for (i = 0; i < factor; i++) { + gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) ); + gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY ); + glTexCoordPointer(CTX_PRM tcomps, GL_FLOAT, stride, + (GLubyte *) pointer + i * coffset ); + } + for (i = factor; i < ctx->Const.MaxTextureUnits; i++) { + gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) ); + gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY ); + } + } + else { + GLint i; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) ); + gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY ); + } + } + /* Restore texture coordinate unit index */ + gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) ); + + + /* Color */ + if (cflag) { + gl_EnableClientState( ctx, GL_COLOR_ARRAY ); + glColorPointer(CTX_PRM ccomps, ctype, stride, + (GLubyte*) pointer + coffset ); + } + else { + gl_DisableClientState( ctx, GL_COLOR_ARRAY ); + } + + + /* Normals */ + if (nflag) { + gl_EnableClientState( ctx, GL_NORMAL_ARRAY ); + glNormalPointer(CTX_PRM GL_FLOAT, stride, + (GLubyte*) pointer + noffset ); + } + else { + gl_DisableClientState( ctx, GL_NORMAL_ARRAY ); + } + + gl_EnableClientState( ctx, GL_VERTEX_ARRAY ); + glVertexPointer(CTX_PRM vcomps, GL_FLOAT, stride, + (GLubyte *) pointer + voffset ); +} + + + +void GLAPIENTRY glDrawRangeElements(CTX_ARG GLenum mode, GLuint start, + GLuint end, GLsizei count, + GLenum type, const GLvoid *indices ) +{ + GLcontext *ctx; + GET_CONTEXT; + CHECK_CONTEXT; + ctx = CC; + + if (end < start) { + gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )"); + return; + } + + if (!ctx->Array.LockCount && 2*count > 3*(end-start)) { + glLockArraysEXT(CTX_PRM start, end ); + glDrawElements(CTX_PRM mode, count, type, indices ); + glUnlockArraysEXT(CTX_VPRM ); + } else { + glDrawElements(CTX_PRM mode, count, type, indices ); + } +} + + + +void gl_update_client_state( GLcontext *ctx ) +{ + static GLuint sz_flags[5] = { 0, + 0, + VERT_OBJ_2, + VERT_OBJ_23, + VERT_OBJ_234 }; + + static GLuint tc_flags[5] = { 0, + VERT_TEX0_1, + VERT_TEX0_12, + VERT_TEX0_123, + VERT_TEX0_1234 }; + + ctx->Array.Flags = 0; + ctx->Array.Summary = 0; + ctx->input->ArrayIncr = 0; + + if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM; + if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA; + if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX; + if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE; + if (ctx->Array.Vertex.Enabled) { + ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size]; + ctx->input->ArrayIncr = 1; + } + if (ctx->Array.TexCoord[0].Enabled) { + ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size]; + } + if (ctx->Array.TexCoord[1].Enabled) { + ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS); + } + + /* Not really important any more: + */ + ctx->Array.Summary = ctx->Array.Flags & VERT_DATA; + + ctx->input->ArrayOrFlags = (ctx->Array.Flags & VERT_OBJ_234) | VERT_ELT; + ctx->input->ArrayAndFlags = ~ctx->Array.Flags; + ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag); +} + diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h new file mode 100644 index 00000000000..fc81a61c720 --- /dev/null +++ b/src/mesa/main/varray.h @@ -0,0 +1,113 @@ +/* $Id: varray.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 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 VARRAY_H +#define VARRAY_H + + +#include "types.h" + + +extern void gl_VertexPointer( GLcontext *ctx, + GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr ); + + +extern void gl_NormalPointer( GLcontext *ctx, + GLenum type, GLsizei stride, const GLvoid *ptr ); + + +extern void gl_ColorPointer( GLcontext *ctx, + GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr ); + + +extern void gl_IndexPointer( GLcontext *ctx, + GLenum type, GLsizei stride, + const GLvoid *ptr ); + + +extern void gl_TexCoordPointer( GLcontext *ctx, + GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr ); + + +extern void gl_EdgeFlagPointer( GLcontext *ctx, + GLsizei stride, const GLboolean *ptr ); + + +extern void gl_GetPointerv( GLcontext *ctx, GLenum pname, GLvoid **params ); + + + +extern void gl_DrawArrays( GLcontext *ctx, + GLenum mode, GLint first, GLsizei count ); + +extern void gl_save_DrawArrays( GLcontext *ctx, + GLenum mode, GLint first, GLsizei count ); + + +extern void gl_DrawElements( GLcontext *ctx, + GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices ); + +extern void gl_save_DrawElements( GLcontext *ctx, + GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices ); + + +extern void gl_InterleavedArrays( GLcontext *ctx, + GLenum format, GLsizei stride, + const GLvoid *pointer ); + +extern void gl_save_InterleavedArrays( GLcontext *ctx, + GLenum format, GLsizei stride, + const GLvoid *pointer ); + + +extern void gl_DrawRangeElements( GLcontext *ctx, GLenum mode, GLuint start, + GLuint end, GLsizei count, GLenum type, + const GLvoid *indices ); + +extern void gl_save_DrawRangeElements( GLcontext *ctx, GLenum mode, + GLuint start, GLuint end, GLsizei count, + GLenum type, const GLvoid *indices ); + + + +extern void gl_exec_array_elements( GLcontext *ctx, + struct immediate *IM ); + +extern void gl_update_client_state( GLcontext *ctx ); + +#endif + + + |