summaryrefslogtreecommitdiff
path: root/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main')
-rw-r--r--src/mesa/main/Imakefile127
-rw-r--r--src/mesa/main/KNOWN_BUGS20
-rw-r--r--src/mesa/main/Makefile.DJ95
-rw-r--r--src/mesa/main/Makefile.X11243
-rw-r--r--src/mesa/main/accum.c495
-rw-r--r--src/mesa/main/accum.h51
-rw-r--r--src/mesa/main/attrib.c863
-rw-r--r--src/mesa/main/attrib.h47
-rw-r--r--src/mesa/main/blend.c812
-rw-r--r--src/mesa/main/blend.h68
-rw-r--r--src/mesa/main/clip.c460
-rw-r--r--src/mesa/main/clip.h105
-rw-r--r--src/mesa/main/colortab.c312
-rw-r--r--src/mesa/main/colortab.h55
-rw-r--r--src/mesa/main/config.h222
-rw-r--r--src/mesa/main/context.c2388
-rw-r--r--src/mesa/main/context.h167
-rw-r--r--src/mesa/main/dd.h635
-rw-r--r--src/mesa/main/depth.c879
-rw-r--r--src/mesa/main/depth.h98
-rw-r--r--src/mesa/main/descrip.mms156
-rw-r--r--src/mesa/main/dlist.c3501
-rw-r--r--src/mesa/main/dlist.h79
-rw-r--r--src/mesa/main/drawpix.c946
-rw-r--r--src/mesa/main/drawpix.h54
-rw-r--r--src/mesa/main/enable.c699
-rw-r--r--src/mesa/main/enable.h51
-rw-r--r--src/mesa/main/enums.c893
-rw-r--r--src/mesa/main/enums.h34
-rw-r--r--src/mesa/main/eval.c2725
-rw-r--r--src/mesa/main/eval.h95
-rw-r--r--src/mesa/main/extensions.c196
-rw-r--r--src/mesa/main/extensions.h56
-rw-r--r--src/mesa/main/feedback.c395
-rw-r--r--src/mesa/main/feedback.h74
-rw-r--r--src/mesa/main/fog.c327
-rw-r--r--src/mesa/main/fog.h51
-rw-r--r--src/mesa/main/get.c3692
-rw-r--r--src/mesa/main/get.h48
-rw-r--r--src/mesa/main/hash.c295
-rw-r--r--src/mesa/main/hash.h59
-rw-r--r--src/mesa/main/image.c2417
-rw-r--r--src/mesa/main/image.h109
-rw-r--r--src/mesa/main/light.c1183
-rw-r--r--src/mesa/main/light.h103
-rw-r--r--src/mesa/main/lines.c1146
-rw-r--r--src/mesa/main/lines.h45
-rw-r--r--src/mesa/main/macros.h546
-rw-r--r--src/mesa/main/matrix.c1438
-rw-r--r--src/mesa/main/matrix.h115
-rw-r--r--src/mesa/main/mesa.conf74
-rw-r--r--src/mesa/main/pixel.c774
-rw-r--r--src/mesa/main/pixel.h111
-rw-r--r--src/mesa/main/points.c1344
-rw-r--r--src/mesa/main/points.h45
-rw-r--r--src/mesa/main/polygon.c177
-rw-r--r--src/mesa/main/polygon.h53
-rw-r--r--src/mesa/main/rastpos.c227
-rw-r--r--src/mesa/main/rastpos.h48
-rw-r--r--src/mesa/main/simple_list.h99
-rw-r--r--src/mesa/main/stencil.c1107
-rw-r--r--src/mesa/main/stencil.h88
-rw-r--r--src/mesa/main/teximage.c2344
-rw-r--r--src/mesa/main/teximage.h186
-rw-r--r--src/mesa/main/texobj.c571
-rw-r--r--src/mesa/main/texobj.h85
-rw-r--r--src/mesa/main/texstate.c1146
-rw-r--r--src/mesa/main/texstate.h112
-rw-r--r--src/mesa/main/varray.c1259
-rw-r--r--src/mesa/main/varray.h113
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 mesa-bugs@mesa3d.org\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 joukj@crys.chem.uva.nl
+# 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 (bdbarsuh@cip.informatik.uni-erlangen.de) and
+ * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
+ *
+ * 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 jle@star.be
+ * 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 (erich@uruk.org) */
+ 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:
+ /* (keithh@netcomuk.co.uk) */
+ 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
+
+
+