diff options
| author | jtg <jtg> | 1999-08-19 00:55:39 +0000 | 
|---|---|---|
| committer | jtg <jtg> | 1999-08-19 00:55:39 +0000 | 
| commit | afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1c (patch) | |
| tree | 59d65b4da12fb5379224cf5f6b808fde91523c7f /src/mesa | |
| parent | f2544d4920ce168bec9cd94d774b7ea5103a3d74 (diff) | |
Initial revision
Diffstat (limited to 'src/mesa')
137 files changed, 80903 insertions, 0 deletions
diff --git a/src/mesa/Makefile.X11 b/src/mesa/Makefile.X11 new file mode 100644 index 0000000000..e6419b555a --- /dev/null +++ b/src/mesa/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/drivers/allegro/amesa.c b/src/mesa/drivers/allegro/amesa.c new file mode 100644 index 0000000000..6e0f21d804 --- /dev/null +++ b/src/mesa/drivers/allegro/amesa.c @@ -0,0 +1,395 @@ +/*
 + * Mesa 3-D graphics library
 + * Version:  3.0
 + * 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.
 + */
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <allegro.h>
 +#include "context.h"
 +#include "matrix.h"
 +#include "types.h"
 +#include "GL/amesa.h"
 +
 +
 +struct amesa_visual
 +    {
 +    GLvisual   *GLVisual;       /* inherit from GLvisual      */
 +    GLboolean   DBFlag;         /* double buffered?           */
 +    GLuint      Depth;          /* bits per pixel ( >= 15 )   */
 +    };
 +
 +
 +struct amesa_buffer
 +    {
 +    GLframebuffer *GLBuffer;    /* inherit from GLframebuffer */
 +    GLuint         Width, Height;
 +    BITMAP        *Screen;
 +	BITMAP        *Background;
 +	BITMAP        *Active;
 +    };
 +
 +
 +struct amesa_context
 +    {
 +    GLcontext   *GLContext;     /* inherit from GLcontext     */
 +    AMesaVisual  Visual;
 +	AMesaBuffer  Buffer;
 +    GLuint       ClearColor;
 +    GLuint       CurrentColor;
 +    };
 +
 +
 +static void setup_dd_pointers(GLcontext *ctx);
 +
 +
 +/**********************************************************************/
 +/*****                   drawing functions                        *****/
 +/**********************************************************************/
 +
 +#define FLIP(context, y)  (context->Buffer->Height - (y) - 1)
 +
 +#include "allegro/generic.h"
 +#include "allegro/direct.h"
 +
 +
 +/**********************************************************************/
 +/*****            15-bit accelerated drawing funcs                *****/
 +/**********************************************************************/
 +
 +IMPLEMENT_WRITE_RGBA_SPAN(15, unsigned short)
 +IMPLEMENT_WRITE_RGB_SPAN(15, unsigned short)
 +IMPLEMENT_WRITE_MONO_RGBA_SPAN(15, unsigned short)
 +IMPLEMENT_READ_RGBA_SPAN(15, unsigned short)
 +IMPLEMENT_WRITE_RGBA_PIXELS(15, unsigned short)
 +IMPLEMENT_WRITE_MONO_RGBA_PIXELS(15, unsigned short)
 +IMPLEMENT_READ_RGBA_PIXELS(15, unsigned short)
 +
 +
 +/**********************************************************************/
 +/*****            16-bit accelerated drawing funcs                *****/
 +/**********************************************************************/
 +
 +IMPLEMENT_WRITE_RGBA_SPAN(16, unsigned short)
 +IMPLEMENT_WRITE_RGB_SPAN(16, unsigned short)
 +IMPLEMENT_WRITE_MONO_RGBA_SPAN(16, unsigned short)
 +IMPLEMENT_READ_RGBA_SPAN(16, unsigned short)
 +IMPLEMENT_WRITE_RGBA_PIXELS(16, unsigned short)
 +IMPLEMENT_WRITE_MONO_RGBA_PIXELS(16, unsigned short)
 +IMPLEMENT_READ_RGBA_PIXELS(16, unsigned short)
 +
 +
 +/**********************************************************************/
 +/*****            32-bit accelerated drawing funcs                *****/
 +/**********************************************************************/
 +
 +IMPLEMENT_WRITE_RGBA_SPAN(32, unsigned long)
 +IMPLEMENT_WRITE_RGB_SPAN(32, unsigned long)
 +IMPLEMENT_WRITE_MONO_RGBA_SPAN(32, unsigned long)
 +IMPLEMENT_READ_RGBA_SPAN(32, unsigned long)
 +IMPLEMENT_WRITE_RGBA_PIXELS(32, unsigned long)
 +IMPLEMENT_WRITE_MONO_RGBA_PIXELS(32, unsigned long)
 +IMPLEMENT_READ_RGBA_PIXELS(32, unsigned long)
 +
 +
 +/**********************************************************************/
 +/*****              Miscellaneous device driver funcs             *****/
 +/**********************************************************************/
 +
 +static GLboolean set_buffer(GLcontext *ctx, GLenum mode)
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    GLboolean    ok      = GL_TRUE;
 +
 +    if (mode == GL_FRONT_LEFT)
 +        context->Buffer->Active = context->Buffer->Screen;
 +
 +    else if (mode == GL_BACK_LEFT)
 +        {
 +        if (context->Buffer->Background)
 +            context->Buffer->Active = context->Buffer->Background;
 +        else
 +            ok = GL_FALSE;
 +        }
 +
 +    else
 +        ok = GL_FALSE;
 +
 +    return ok;
 +    }
 +
 +
 +static void get_buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
 +    {
 +	AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +
 +    *width  = context->Buffer->Width;
 +    *height = context->Buffer->Height;
 +    }
 +
 +
 +/**********************************************************************/
 +/**********************************************************************/
 +
 +static void setup_dd_pointers(GLcontext *ctx)
 +	{
 +	AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +
 +   	/* Initialize all the pointers in the driver struct. Do this whenever */
 +   	/* a new context is made current or we change buffers via set_buffer! */
 +
 +    ctx->Driver.UpdateState   = setup_dd_pointers;
 +   	ctx->Driver.SetBuffer     = set_buffer;
 +   	ctx->Driver.GetBufferSize = get_buffer_size;
 +
 +    ctx->Driver.Color               = set_color_generic;
 +    ctx->Driver.ClearColor          = clear_color_generic;
 +    ctx->Driver.Clear               = clear_generic;
 +    ctx->Driver.WriteRGBASpan       = write_rgba_span_generic;
 +    ctx->Driver.WriteRGBSpan        = write_rgb_span_generic;
 +    ctx->Driver.WriteMonoRGBASpan   = write_mono_rgba_span_generic;
 +    ctx->Driver.WriteRGBAPixels     = write_rgba_pixels_generic;
 +    ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_generic;
 +    ctx->Driver.ReadRGBASpan        = read_rgba_span_generic;
 +    ctx->Driver.ReadRGBAPixels      = read_rgba_pixels_generic;
 +
 +    if (context->Buffer->Active != screen)
 +        {
 +        switch (context->Visual->Depth)
 +            {
 +            case 15:
 +                ctx->Driver.WriteRGBASpan       = write_rgba_span_15;
 +                ctx->Driver.WriteRGBSpan        = write_rgb_span_15;
 +                ctx->Driver.WriteMonoRGBASpan   = write_mono_rgba_span_15;
 +                ctx->Driver.WriteRGBAPixels     = write_rgba_pixels_15;
 +                ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_15;
 +                ctx->Driver.ReadRGBASpan        = read_rgba_span_15;
 +                ctx->Driver.ReadRGBAPixels      = read_rgba_pixels_15;
 +                break;
 +
 +            case 16:
 +                ctx->Driver.WriteRGBASpan       = write_rgba_span_16;
 +                ctx->Driver.WriteRGBSpan        = write_rgb_span_16;
 +                ctx->Driver.WriteMonoRGBASpan   = write_mono_rgba_span_16;
 +                ctx->Driver.WriteRGBAPixels     = write_rgba_pixels_16;
 +                ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_16;
 +                ctx->Driver.ReadRGBASpan        = read_rgba_span_16;
 +                ctx->Driver.ReadRGBAPixels      = read_rgba_pixels_16;
 +                break;
 +
 +            case 32:
 +                ctx->Driver.WriteRGBASpan       = write_rgba_span_32;
 +                ctx->Driver.WriteRGBSpan        = write_rgb_span_32;
 +                ctx->Driver.WriteMonoRGBASpan   = write_mono_rgba_span_32;
 +                ctx->Driver.WriteRGBAPixels     = write_rgba_pixels_32;
 +                ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_32;
 +                ctx->Driver.ReadRGBASpan        = read_rgba_span_32;
 +                ctx->Driver.ReadRGBAPixels      = read_rgba_pixels_32;
 +                break;
 +            }
 +        }
 +	}
 +
 +
 +/**********************************************************************/
 +/*****                AMesa Public API Functions                  *****/
 +/**********************************************************************/
 +
 +
 +AMesaVisual AMesaCreateVisual(GLboolean dbFlag, GLint depth,
 +                              GLint depthSize, GLint stencilSize, GLint accumSize)
 +	{
 +   	AMesaVisual visual;
 +    GLbyte      redBits, greenBits, blueBits;
 +
 +    visual = (AMesaVisual)calloc(1, sizeof(struct amesa_visual));
 +   	if (!visual)
 +    	return NULL;
 +
 +    switch (depth)
 +        {
 +        case 15:
 +            redBits   = 5;
 +            greenBits = 5;
 +            blueBits  = 5;
 +            break;
 +
 +        case 16:
 +            redBits   = 5;
 +            greenBits = 6;
 +            blueBits  = 5;
 +            break;
 +
 +        case 24: case 32:
 +            redBits   = 8;
 +            greenBits = 8;
 +            blueBits  = 8;
 +            break;
 +
 +        default:
 +            free(visual);
 +            return NULL;
 +        }
 +
 +    visual->DBFlag   = dbFlag;
 +    visual->Depth    = depth;
 +    visual->GLVisual = gl_create_visual(GL_TRUE,    /* rgb mode       */
 +                                        GL_TRUE,    /* software alpha */
 +                                        dbFlag,     /* db_flag        */
 +                                        GL_FALSE,   /* stereo         */
 +                                        depthSize,  /* depth bits     */
 +                                        stencilSize,/* stencil bits   */
 +                                        accumSize,  /* accum bits     */
 +                                        0,          /* index bits     */
 +                                        redBits, greenBits, blueBits, 0);
 +    if (!visual->GLVisual)
 +        {
 +        free(visual);
 +        return NULL;
 +        }
 +
 +  	return visual;
 +	}
 +
 +
 +void AMesaDestroyVisual(AMesaVisual visual)
 +	{
 +    gl_destroy_visual(visual->GLVisual);
 +   	free(visual);
 +	}
 +
 +
 +AMesaBuffer AMesaCreateBuffer(AMesaVisual visual,
 +							  GLint width, GLint height)
 +	{
 +   	AMesaBuffer buffer;
 +
 +    buffer = (AMesaBuffer)calloc(1, sizeof(struct amesa_buffer));
 +   	if (!buffer)
 +     	return NULL;
 +
 +	buffer->Screen     = NULL;
 +	buffer->Background = NULL;
 +	buffer->Active     = NULL;
 +	buffer->Width      = width;
 +	buffer->Height     = height;
 +
 +	if (visual->DBFlag)
 +		{
 +		buffer->Background = create_bitmap_ex(visual->Depth, width, height);
 +		if (!buffer->Background)
 +			{
 +			free(buffer);
 +			return NULL;
 +			}
 +		}
 +
 +    buffer->GLBuffer = gl_create_framebuffer(visual->GLVisual);
 +    if (!buffer->GLBuffer)
 +        {
 +        if (buffer->Background) destroy_bitmap(buffer->Background);
 +        free(buffer);
 +        return NULL;
 +        }
 +
 +   	return buffer;
 +	}
 +
 +
 +void AMesaDestroyBuffer(AMesaBuffer buffer)
 +	{
 +    if (buffer->Screen)     destroy_bitmap(buffer->Screen);
 +	if (buffer->Background) destroy_bitmap(buffer->Background);
 +    gl_destroy_framebuffer(buffer->GLBuffer);
 +   	free(buffer);
 +	}
 +
 +
 +AMesaContext AMesaCreateContext(AMesaVisual visual,
 +                                AMesaContext share)
 +	{
 +   	AMesaContext context;
 +   	GLboolean    direct = GL_FALSE;
 +
 +    context = (AMesaContext)calloc(1, sizeof(struct amesa_context));
 +	if (!context)
 +		return NULL;
 +
 +	context->Visual       = visual;
 +	context->Buffer		  = NULL;
 +	context->ClearColor   = 0;
 +	context->CurrentColor = 0;
 +    context->GLContext    = gl_create_context(visual->GLVisual,
 +                                              share ? share->GLContext : NULL,
 +                                  		      (void*)context,
 +                                              direct);
 +    if (!context->GLContext)
 +        {
 +        free(context);
 +        return NULL;
 +        }
 +
 +   	return context;
 +	}
 +
 +
 +void AMesaDestroyContext(AMesaContext context)
 +	{
 +    gl_destroy_context(context->GLContext);
 +   	free(context);
 +	}
 +
 +
 +GLboolean AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer)
 +	{
 +   	if (context && buffer)
 +   		{
 +      	set_color_depth(context->Visual->Depth);
 +        if (set_gfx_mode(GFX_AUTODETECT, buffer->Width, buffer->Height, 0, 0) != 0)
 +            return GL_FALSE;
 +
 +		context->Buffer = buffer;
 +        buffer->Screen  = screen;
 +        buffer->Active  = buffer->Background ? buffer->Background : screen;
 +        
 +        setup_dd_pointers(context->GLContext);
 +        gl_make_current(context->GLContext, buffer->GLBuffer);
 +        gl_Viewport(context->GLContext, 0, 0, buffer->Width, buffer->Height);
 +     	}
 +  	else
 +  		{
 +        destroy_bitmap(context->Buffer->Screen);
 +        context->Buffer->Screen = NULL;
 +        context->Buffer->Active = NULL;
 +        context->Buffer         = NULL;
 +     	gl_make_current(NULL, NULL);
 +   		}
 +
 +    return GL_TRUE;
 +	}
 +
 +
 +void AMesaSwapBuffers(AMesaBuffer buffer)
 +	{
 +	if (buffer->Background)
 +		{
 +		blit(buffer->Background, buffer->Screen,
 +             0, 0, 0, 0,
 +             buffer->Width, buffer->Height);
 +		}
 +	}
 diff --git a/src/mesa/drivers/allegro/direct.h b/src/mesa/drivers/allegro/direct.h new file mode 100644 index 0000000000..3998fc19d7 --- /dev/null +++ b/src/mesa/drivers/allegro/direct.h @@ -0,0 +1,189 @@ +/*
 + * Mesa 3-D graphics library
 + * Version:  3.0
 + * 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.
 + */
 +
 +
 +#define DESTINATION(BMP, X, Y, TYPE)                                \
 +    ({                                                              \
 +    BITMAP *_bmp = BMP;                                             \
 +                                                                    \
 +    (TYPE*)(_bmp->line[_bmp->h - (Y) - 1]) + (X);                   \
 +    })
 +
 +
 +#define IMPLEMENT_WRITE_RGBA_SPAN(DEPTH, TYPE)                                                   \
 +static void write_rgba_span_##DEPTH (const GLcontext *ctx,                                       \
 +                                     GLuint n, GLint x, GLint y,                                 \
 +                                     const GLubyte rgba[][4],                                    \
 +                                     const GLubyte mask[])                                       \
 +    {                                                                                            \
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);                                       \
 +    TYPE              *d = DESTINATION(context->Buffer->Active, x, y, TYPE);                     \
 +                                                                                                 \
 +    if (mask)                                                                                    \
 +        {                                                                                        \
 +        while (n--)                                                                              \
 +            {                                                                                    \
 +            if (mask[0]) d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]);  \
 +            d++; rgba++; mask++;                                                                 \
 +            }                                                                                    \
 +        }                                                                                        \
 +    else                                                                                         \
 +        {                                                                                        \
 +        while (n--)                                                                              \
 +            {                                                                                    \
 +            d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]);               \
 +            d++; rgba++;                                                                         \
 +            }                                                                                    \
 +        }                                                                                        \
 +    }
 +
 +
 +#define IMPLEMENT_WRITE_RGB_SPAN(DEPTH, TYPE)                                                    \
 +static void write_rgb_span_##DEPTH (const GLcontext *ctx,                                        \
 +                                    GLuint n, GLint x, GLint y,                                  \
 +                                    const GLubyte rgb[][3],                                      \
 +                                    const GLubyte mask[])                                        \
 +    {                                                                                            \
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);                                       \
 +    TYPE              *d = DESTINATION(context->Buffer->Active, x, y, TYPE);                     \
 +                                                                                                 \
 +    if (mask)                                                                                    \
 +        {                                                                                        \
 +        while (n--)                                                                              \
 +            {                                                                                    \
 +            if (mask[0]) d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]);     \
 +            d++; rgb++; mask++;                                                                  \
 +            }                                                                                    \
 +        }                                                                                        \
 +    else                                                                                         \
 +        {                                                                                        \
 +        while (n--)                                                                              \
 +            {                                                                                    \
 +            d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]);                  \
 +            d++; rgb++;                                                                          \
 +            }                                                                                    \
 +        }                                                                                        \
 +    }
 +
 +
 +#define IMPLEMENT_WRITE_MONO_RGBA_SPAN(DEPTH, TYPE)                                              \
 +static void write_mono_rgba_span_##DEPTH (const GLcontext *ctx,                                  \
 +                                          GLuint n, GLint x, GLint y,                            \
 +                                          const GLubyte mask[])                                  \
 +    {                                                                                            \
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);                                       \
 +    TYPE           color = context->CurrentColor;                                                \
 +    TYPE              *d = DESTINATION(context->Buffer->Active, x, y, TYPE);                     \
 +                                                                                                 \
 +    while (n--)                                                                                  \
 +        {                                                                                        \
 +        if (mask[0]) d[0] = color;                                                               \
 +        d++; mask++;                                                                             \
 +        }                                                                                        \
 +    }
 +
 +
 +#define IMPLEMENT_READ_RGBA_SPAN(DEPTH, TYPE)                           \
 +static void read_rgba_span_##DEPTH (const GLcontext *ctx,				\
 +                                    GLuint n, GLint x, GLint y,			\
 +                                    GLubyte rgba[][4])					\
 +    {																	\
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);				\
 +    BITMAP          *bmp = context->Buffer->Active;                     \
 +    TYPE              *d = DESTINATION(bmp, x, y, TYPE);                \
 +                                                                        \
 +    while (n--)                                                         \
 +        {                                                               \
 +        rgba[0][RCOMP] = getr##DEPTH(d[0]);                             \
 +        rgba[0][GCOMP] = getg##DEPTH(d[0]);                             \
 +        rgba[0][BCOMP] = getb##DEPTH(d[0]);                             \
 +        rgba[0][ACOMP] = 255;                                           \
 +                                                                        \
 +        d++; rgba++;                                                    \
 +        }                                                               \
 +    }
 +
 +
 +#define IMPLEMENT_WRITE_RGBA_PIXELS(DEPTH, TYPE)                                                                                 \
 +static void write_rgba_pixels_##DEPTH (const GLcontext *ctx,                                                                     \
 +                                       GLuint n,                                                                                 \
 +                                       const GLint x[],                                                                          \
 +                                       const GLint y[],                                                                          \
 +                                       const GLubyte rgba[][4],                                                                  \
 +                                       const GLubyte mask[])                                                                     \
 +    {                                                                                                                            \
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);                                                                       \
 +    BITMAP          *bmp = context->Buffer->Active;                                                                              \
 +                                                                                                                                 \
 +    while (n--)                                                                                                                  \
 +        {                                                                                                                        \
 +        if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]);       \
 +        rgba++; x++; y++; mask++;                                                                                                \
 +        }                                                                                                                        \
 +    }
 +
 +
 +
 +#define IMPLEMENT_WRITE_MONO_RGBA_PIXELS(DEPTH, TYPE)                                                                            \
 +static void write_mono_rgba_pixels_##DEPTH (const GLcontext *ctx,                                                                \
 +                                            GLuint n,                                                                            \
 +                                            const GLint x[],                                                                     \
 +                                            const GLint y[],                                                                     \
 +                                            const GLubyte mask[])                                                                \
 +    {                                                                                                                            \
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);                                                                       \
 +    TYPE          color  = context->CurrentColor;                                                                                \
 +    BITMAP          *bmp = context->Buffer->Active;                                                                              \
 +                                                                                                                                 \
 +    while (n--)                                                                                                                  \
 +        {                                                                                                                        \
 +        if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = color;                                                                \
 +        x++; y++; mask++;                                                                                                        \
 +        }                                                                                                                        \
 +    }
 +
 +
 +#define IMPLEMENT_READ_RGBA_PIXELS(DEPTH, TYPE)                         \
 +static void read_rgba_pixels_##DEPTH (const GLcontext *ctx,				\
 +                              		  GLuint n,							\
 +                              		  const GLint x[],					\
 +                              		  const GLint y[],					\
 +                              		  GLubyte rgba[][4],				\
 +                              		  const GLubyte mask[])				\
 +    {																	\
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);				\
 +    BITMAP          *bmp = context->Buffer->Active;                     \
 +                                                                        \
 +    while (n--)                                                         \
 +        {                                                               \
 +        if (mask[0])                                                    \
 +            {                                                           \
 +            int color = *DESTINATION(bmp, x[0], y[0], TYPE);            \
 +                                                                        \
 +            rgba[0][RCOMP] = getr##DEPTH(color);                        \
 +            rgba[0][GCOMP] = getg##DEPTH(color);                        \
 +            rgba[0][BCOMP] = getb##DEPTH(color);                        \
 +            rgba[0][ACOMP] = 255;                                       \
 +            }                                                           \
 +                                                                        \
 +        x++; y++; rgba++; mask++;                                       \
 +        }                                                               \
 +    }
 +
 diff --git a/src/mesa/drivers/allegro/generic.h b/src/mesa/drivers/allegro/generic.h new file mode 100644 index 0000000000..898a055d62 --- /dev/null +++ b/src/mesa/drivers/allegro/generic.h @@ -0,0 +1,233 @@ +/*
 + * Mesa 3-D graphics library
 + * Version:  3.0
 + * 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.
 + */
 +
 +static void clear_color_generic(GLcontext *ctx,
 +                                GLubyte red,  GLubyte green,
 +                                GLubyte blue, GLubyte alpha)
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +
 +    context->ClearColor = makecol(red, green, blue);
 +    }
 +
 +
 +static void set_color_generic(GLcontext *ctx,
 +                              GLubyte red,  GLubyte green,
 +                              GLubyte blue, GLubyte alpha)
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +
 +    context->CurrentColor = makecol(red, green, blue);
 +    }
 +
 +
 +static GLbitfield clear_generic(GLcontext *ctx,
 +                                GLbitfield mask, GLboolean all,
 +                                GLint x, GLint y,
 +                                GLint width, GLint height)
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +
 +    if (mask & GL_COLOR_BUFFER_BIT)
 +        {
 +        if (all)
 +            clear_to_color(context->Buffer->Active, context->ClearColor);
 +        else
 +            rect(context->Buffer->Active,
 +                 x, y, x+width-1, y+height-1,
 +                 context->ClearColor);
 +        }
 +
 +    return mask & (~GL_COLOR_BUFFER_BIT);
 +    }
 +
 +
 +static void write_rgba_span_generic(const GLcontext *ctx,
 +                                    GLuint n, GLint x, GLint y,
 +                                    const GLubyte rgba[][4],
 +                                    const GLubyte mask[])
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    BITMAP          *bmp = context->Buffer->Active;
 +
 +    y = FLIP(context, y);
 +
 +    if (mask)
 +        {
 +        while (n--)
 +            {
 +            if (mask[0]) putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
 +            x++; mask++; rgba++;
 +            }
 +        }
 +    else
 +        {
 +        while (n--)
 +            {
 +            putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
 +            x++; rgba++;
 +            }
 +        }
 +    }
 +
 +
 +static void write_rgb_span_generic(const GLcontext *ctx,
 +                                   GLuint n, GLint x, GLint y,
 +                                   const GLubyte rgb[][3],
 +                                   const GLubyte mask[])
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    BITMAP          *bmp = context->Buffer->Active;
 +
 +    y = FLIP(context, y);
 +
 +    if (mask)
 +        {
 +        while(n--)
 +            {
 +            if (mask[0]) putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]));
 +            x++; mask++; rgb++;
 +            }
 +        }
 +    else
 +        {
 +        while (n--)
 +            {
 +            putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]));
 +            x++; rgb++;
 +            }
 +        }
 +    }
 +
 +
 +static void write_mono_rgba_span_generic(const GLcontext *ctx,
 +                                         GLuint n, GLint x, GLint y,
 +                                         const GLubyte mask[])
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    BITMAP          *bmp = context->Buffer->Active;
 +    int            color = context->CurrentColor;
 +
 +    y = FLIP(context, y);
 +
 +    if (mask)
 +        {
 +        while(n--)
 +            {
 +            if (mask[0]) putpixel(bmp, x, y, color);
 +            x++; mask++;
 +            }
 +        }
 +    else
 +        {
 +        while(n--)
 +            {
 +            putpixel(bmp, x, y, color);
 +            x++;
 +            }
 +        }
 +    }
 +
 +
 +static void read_rgba_span_generic(const GLcontext *ctx,
 +                                   GLuint n, GLint x, GLint y,
 +                                   GLubyte rgba[][4])
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    BITMAP          *bmp = context->Buffer->Active;
 +
 +    y = FLIP(context, y);
 +
 +    while (n--)
 +        {
 +        int color = getpixel(bmp, x, y);
 +
 +        rgba[0][RCOMP] = getr(color);
 +        rgba[0][GCOMP] = getg(color);
 +        rgba[0][BCOMP] = getb(color);
 +        rgba[0][ACOMP] = 255;
 +
 +        x++; rgba++;
 +        }
 +    }
 +
 +
 +static void write_rgba_pixels_generic(const GLcontext *ctx,
 +                                      GLuint n,
 +                                      const GLint x[],
 +                                      const GLint y[],
 +                                      const GLubyte rgba[][4],
 +                                      const GLubyte mask[])
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    BITMAP          *bmp = context->Buffer->Active;
 +
 +    while (n--)
 +        {
 +        if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
 +        x++; y++; mask++;
 +        }
 +    }
 +
 +
 +static void write_mono_rgba_pixels_generic(const GLcontext *ctx,
 +                                           GLuint n,
 +                                           const GLint x[],
 +                                           const GLint y[],
 +                                           const GLubyte mask[])
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    BITMAP          *bmp = context->Buffer->Active;
 +    int            color = context->CurrentColor;
 +
 +    while (n--)
 +        {
 +        if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), color);
 +        x++; y++; mask++;
 +        }
 +    }
 +
 +
 +static void read_rgba_pixels_generic(const GLcontext *ctx,
 +                                     GLuint n,
 +                                     const GLint x[],
 +                                     const GLint y[],
 +                                     GLubyte rgba[][4],
 +                                     const GLubyte mask[])
 +    {
 +    AMesaContext context = (AMesaContext)(ctx->DriverCtx);
 +    BITMAP          *bmp = context->Buffer->Active;
 +
 +    while (n--)
 +        {
 +        if (mask[0])
 +            {
 +            int color = getpixel(bmp, x[0], FLIP(context, y[0]));
 +
 +            rgba[0][RCOMP] = getr(color);
 +            rgba[0][GCOMP] = getg(color);
 +            rgba[0][BCOMP] = getb(color);
 +            rgba[0][ACOMP] = 255;
 +            }
 +
 +        x++; y++; mask++; rgba++;
 +        }
 +    }
 +
 diff --git a/src/mesa/drivers/beos/GLView.cpp b/src/mesa/drivers/beos/GLView.cpp new file mode 100644 index 0000000000..4332f97b20 --- /dev/null +++ b/src/mesa/drivers/beos/GLView.cpp @@ -0,0 +1,1233 @@ +/* $Id: GLView.cpp,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. + */ + + +/* + * $Log: GLView.cpp,v $ + * Revision 1.1  1999/08/19 00:55:41  jtg + * Initial revision + * + * Revision 1.7  1999/03/28 21:08:17  brianp + * updated SetBuffer driver function + * + * Revision 1.6  1999/02/14 03:44:37  brianp + * new copyright + * + * Revision 1.5  1999/02/11 03:50:57  brianp + * added CopySubBufferMESA() + * + * Revision 1.4  1999/02/06 17:44:59  brianp + * code clean-up and bug fixes + * + * Revision 1.3  1999/02/04 04:13:15  brianp + * implemented double buffering + * + * Revision 1.2  1999/02/03 04:23:28  brianp + * basic device driver functions now work (yeah!) + * + * Revision 1.1  1999/02/02 04:40:46  brianp + * Initial revision + */ + + + +#include <assert.h> +#include <stdio.h> +#include <GLView.h> +#include "../src/context.h" + + +// BeOS component ordering for B_RGBA32 bitmap format +#define BE_RCOMP 2 +#define BE_GCOMP 1 +#define BE_BCOMP 0 +#define BE_ACOMP 3 + + +// +// This object hangs off of the BGLView object.  We have to use +// Be's BGLView class as-is to maintain binary compatibility (we +// can't add new members to it).  Instead we just put all our data +// in this class and use BGLVIew::m_gc to point to it. +// +class AuxInfo +{ +public: +   AuxInfo(); +   ~AuxInfo(); +   void Init(BGLView *bglView, GLcontext *c, GLvisual *v, GLframebuffer *b); + +   void MakeCurrent(); +   void SwapBuffers() const; +   void CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const; + +private: +   AuxInfo(const AuxInfo &rhs);  // copy constructor illegal +   AuxInfo &operator=(const AuxInfo &rhs);  // assignment oper. illegal + +   GLcontext *mContext; +   GLvisual *mVisual; +   GLframebuffer *mBuffer; + +   BGLView *mBGLView; +   BBitmap *mBitmap; + +   GLubyte mColor[4];       // current color +   GLuint mIndex;           // current color index +   GLubyte mClearColor[4];  // buffer clear color +   GLuint mClearIndex;      // buffer clear color index +   GLint mBottom;           // used for flipping Y coords +   GLint mWidth, mHeight;   // size of buffer + +   // Mesa device driver functions +   static void UpdateState(GLcontext *ctx); +   static void ClearIndex(GLcontext *ctx, GLuint index); +   static void ClearColor(GLcontext *ctx, GLubyte r, GLubyte g, +                          GLubyte b, GLubyte a); +   static GLbitfield ClearFront(GLcontext *ctx, GLbitfield mask, +                                GLboolean all, GLint x, GLint y, +                                GLint width, GLint height); +   static GLbitfield ClearBack(GLcontext *ctx, GLbitfield mask, +                               GLboolean all, GLint x, GLint y, +                               GLint width, GLint height); +   static void Index(GLcontext *ctx, GLuint index); +   static void Color(GLcontext *ctx, GLubyte r, GLubyte g, +                     GLubyte b, GLubyte a); +   static GLboolean SetBuffer(GLcontext *ctx, GLenum mode); +   static void GetBufferSize(GLcontext *ctgx, GLuint *width, +                             GLuint *height); +   static const GLubyte *GetString(GLcontext *ctx, GLenum name); + +   // Front-buffer functions +   static void WriteRGBASpanFront(const GLcontext *ctx, GLuint n, +                                  GLint x, GLint y, +                                  CONST GLubyte rgba[][4], +                                  const GLubyte mask[]); +   static void WriteRGBSpanFront(const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 CONST GLubyte rgba[][3], +                                 const GLubyte mask[]); +   static void WriteMonoRGBASpanFront(const GLcontext *ctx, GLuint n, +                                      GLint x, GLint y, const GLubyte mask[]); +   static void WriteRGBAPixelsFront(const GLcontext *ctx, GLuint n, +                                    const GLint x[], const GLint y[], +                                    CONST GLubyte rgba[][4], +                                    const GLubyte mask[]); +   static void WriteMonoRGBAPixelsFront(const GLcontext *ctx, GLuint n, +                                        const GLint x[], const GLint y[], +                                        const GLubyte mask[]); +   static void WriteCI32SpanFront(const GLcontext *ctx, GLuint n, +                                  GLint x, GLint y, +                                  const GLuint index[], const GLubyte mask[]); +   static void WriteCI8SpanFront(const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 const GLubyte index[], const GLubyte mask[]); +   static void WriteMonoCISpanFront(const GLcontext *ctx, GLuint n, +                                    GLint x, GLint y, const GLubyte mask[]); +   static void WriteCI32PixelsFront(const GLcontext *ctx, +                                    GLuint n, const GLint x[], const GLint y[], +                                    const GLuint index[], const GLubyte mask[]); +   static void WriteMonoCIPixelsFront(const GLcontext *ctx, GLuint n, +                                      const GLint x[], const GLint y[], +                                      const GLubyte mask[]); +   static void ReadCI32SpanFront(const GLcontext *ctx, +                                 GLuint n, GLint x, GLint y, GLuint index[]); +   static void ReadRGBASpanFront(const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 GLubyte rgba[][4]); +   static void ReadCI32PixelsFront(const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   GLuint indx[], const GLubyte mask[]); +   static void ReadRGBAPixelsFront(const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   GLubyte rgba[][4], const GLubyte mask[]); + +   // Back buffer functions +   static void WriteRGBASpanBack(const GLcontext *ctx, GLuint n, +                                  GLint x, GLint y, +                                  CONST GLubyte rgba[][4], +                                  const GLubyte mask[]); +   static void WriteRGBSpanBack(const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 CONST GLubyte rgba[][3], +                                 const GLubyte mask[]); +   static void WriteMonoRGBASpanBack(const GLcontext *ctx, GLuint n, +                                      GLint x, GLint y, const GLubyte mask[]); +   static void WriteRGBAPixelsBack(const GLcontext *ctx, GLuint n, +                                    const GLint x[], const GLint y[], +                                    CONST GLubyte rgba[][4], +                                    const GLubyte mask[]); +   static void WriteMonoRGBAPixelsBack(const GLcontext *ctx, GLuint n, +                                        const GLint x[], const GLint y[], +                                        const GLubyte mask[]); +   static void WriteCI32SpanBack(const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 const GLuint index[], const GLubyte mask[]); +   static void WriteCI8SpanBack(const GLcontext *ctx, GLuint n, GLint x, GLint y, +                                const GLubyte index[], const GLubyte mask[]); +   static void WriteMonoCISpanBack(const GLcontext *ctx, GLuint n, +                                   GLint x, GLint y, +                                   const GLubyte mask[]); +   static void WriteCI32PixelsBack(const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   const GLuint index[], const GLubyte mask[]); +   static void WriteMonoCIPixelsBack(const GLcontext *ctx, +                                     GLuint n, const GLint x[], const GLint y[], +                                     const GLubyte mask[]); +   static void ReadCI32SpanBack(const GLcontext *ctx, +                                GLuint n, GLint x, GLint y, GLuint index[]); +   static void ReadRGBASpanBack(const GLcontext *ctx, GLuint n, +                                GLint x, GLint y, +                                GLubyte rgba[][4]); +   static void ReadCI32PixelsBack(const GLcontext *ctx, +                                  GLuint n, const GLint x[], const GLint y[], +                                  GLuint indx[], const GLubyte mask[]); +   static void ReadRGBAPixelsBack(const GLcontext *ctx, +                                  GLuint n, const GLint x[], const GLint y[], +                                  GLubyte rgba[][4], const GLubyte mask[]); + +}; + + + +AuxInfo::AuxInfo() +{ +   mContext = NULL; +   mVisual = NULL; +   mBuffer = NULL; +   mBGLView = NULL; +   mBitmap = NULL; +   mClearColor[BE_RCOMP] = 0; +   mClearColor[BE_GCOMP] = 0; +   mClearColor[BE_BCOMP] = 0; +   mClearColor[BE_ACOMP] = 0; +   mClearIndex = 0; +   mColor[BE_RCOMP] = 255; +   mColor[BE_GCOMP] = 255; +   mColor[BE_BCOMP] = 255; +   mColor[BE_ACOMP] = 255; +   mIndex = 1; +} + + +AuxInfo::~AuxInfo() +{ + +   gl_destroy_visual(mVisual); +   gl_destroy_framebuffer(mBuffer); +   gl_destroy_context(mContext); +} + + +void AuxInfo::Init(BGLView *bglView, GLcontext *c, GLvisual *v, GLframebuffer *b) +{ +   mBGLView = bglView; +   mContext = c; +   mVisual = v; +   mBuffer = b; +} + + +void AuxInfo::MakeCurrent() +{ +   UpdateState(mContext); +   gl_make_current(mContext, mBuffer); +} + + +void AuxInfo::SwapBuffers() const +{ +   if (mBitmap) { +      mBGLView->DrawBitmap(mBitmap, BPoint(0, 0)); +   } +} + + +void AuxInfo::CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const +{ +   if (mBitmap) { +      // Source bitmap and view's bitmap are same size. +      // Source and dest rectangle are the same. +      // Note (x,y) = (0,0) is the lower-left corner, have to flip Y +      BRect srcAndDest; +      srcAndDest.left = x; +      srcAndDest.right = x + width - 1; +      srcAndDest.bottom = mBottom - y; +      srcAndDest.top = srcAndDest.bottom - height + 1; +      mBGLView->DrawBitmap(mBitmap, srcAndDest, srcAndDest); +   } +} + + +void AuxInfo::UpdateState( GLcontext *ctx ) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; + +   assert(aux->mContext == ctx ); + +   ctx->Driver.UpdateState = AuxInfo::UpdateState; +   ctx->Driver.SetBuffer = AuxInfo::SetBuffer; +   ctx->Driver.Color = AuxInfo::Color; +   ctx->Driver.Index = AuxInfo::Index; +   ctx->Driver.ClearIndex = AuxInfo::ClearIndex; +   ctx->Driver.ClearColor = AuxInfo::ClearColor; +   ctx->Driver.GetBufferSize = AuxInfo::GetBufferSize; +   ctx->Driver.GetString = AuxInfo::GetString; + +   if (ctx->Color.DrawBuffer == GL_FRONT) { +      /* read/write front buffer */ +      ctx->Driver.Clear = AuxInfo::ClearFront; +      ctx->Driver.WriteRGBASpan = AuxInfo::WriteRGBASpanFront; +      ctx->Driver.WriteRGBSpan = AuxInfo::WriteRGBSpanFront; +      ctx->Driver.WriteRGBAPixels = AuxInfo::WriteRGBAPixelsFront; +      ctx->Driver.WriteMonoRGBASpan = AuxInfo::WriteMonoRGBASpanFront; +      ctx->Driver.WriteMonoRGBAPixels = AuxInfo::WriteMonoRGBAPixelsFront; +      ctx->Driver.WriteCI32Span = AuxInfo::WriteCI32SpanFront; +      ctx->Driver.WriteCI8Span = AuxInfo::WriteCI8SpanFront; +      ctx->Driver.WriteMonoCISpan = AuxInfo::WriteMonoCISpanFront; +      ctx->Driver.WriteCI32Pixels = AuxInfo::WriteCI32PixelsFront; +      ctx->Driver.WriteMonoCIPixels = AuxInfo::WriteMonoCIPixelsFront; +      ctx->Driver.ReadRGBASpan = AuxInfo::ReadRGBASpanFront; +      ctx->Driver.ReadRGBAPixels = AuxInfo::ReadRGBAPixelsFront; +      ctx->Driver.ReadCI32Span = AuxInfo::ReadCI32SpanFront; +      ctx->Driver.ReadCI32Pixels = AuxInfo::ReadCI32PixelsFront; +   } +   else { +      /* read/write back buffer */ +      ctx->Driver.Clear = AuxInfo::ClearBack; +      ctx->Driver.WriteRGBASpan = AuxInfo::WriteRGBASpanBack; +      ctx->Driver.WriteRGBSpan = AuxInfo::WriteRGBSpanBack; +      ctx->Driver.WriteRGBAPixels = AuxInfo::WriteRGBAPixelsBack; +      ctx->Driver.WriteMonoRGBASpan = AuxInfo::WriteMonoRGBASpanBack; +      ctx->Driver.WriteMonoRGBAPixels = AuxInfo::WriteMonoRGBAPixelsBack; +      ctx->Driver.WriteCI32Span = AuxInfo::WriteCI32SpanBack; +      ctx->Driver.WriteCI8Span = AuxInfo::WriteCI8SpanBack; +      ctx->Driver.WriteMonoCISpan = AuxInfo::WriteMonoCISpanBack; +      ctx->Driver.WriteCI32Pixels = AuxInfo::WriteCI32PixelsBack; +      ctx->Driver.WriteMonoCIPixels = AuxInfo::WriteMonoCIPixelsBack; +      ctx->Driver.ReadRGBASpan = AuxInfo::ReadRGBASpanBack; +      ctx->Driver.ReadRGBAPixels = AuxInfo::ReadRGBAPixelsBack; +      ctx->Driver.ReadCI32Span = AuxInfo::ReadCI32SpanBack; +      ctx->Driver.ReadCI32Pixels = AuxInfo::ReadCI32PixelsBack; +    } +} + + +void AuxInfo::ClearIndex(GLcontext *ctx, GLuint index) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   aux->mClearIndex = index; +} + + +void AuxInfo::ClearColor(GLcontext *ctx, GLubyte r, GLubyte g, +                         GLubyte b, GLubyte a) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   aux->mClearColor[BE_RCOMP] = r; +   aux->mClearColor[BE_GCOMP] = g; +   aux->mClearColor[BE_BCOMP] = b; +   aux->mClearColor[BE_ACOMP] = a; +   assert(aux->mBGLView); +} + + +GLbitfield AuxInfo::ClearFront(GLcontext *ctx, GLbitfield mask, +                               GLboolean all, GLint x, GLint y, +                               GLint width, GLint height) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); + +   bglview->SetHighColor(aux->mClearColor[BE_RCOMP], +                         aux->mClearColor[BE_GCOMP], +                         aux->mClearColor[BE_BCOMP], +                         aux->mClearColor[BE_ACOMP]); +   bglview->SetLowColor(aux->mClearColor[BE_RCOMP], +                        aux->mClearColor[BE_GCOMP], +                        aux->mClearColor[BE_BCOMP], +                        aux->mClearColor[BE_ACOMP]); +   if (all) { +      BRect b = bglview->Bounds(); +      bglview->FillRect(b); +   } +   else { +      // XXX untested +      BRect b; +      b.left = x; +      b.right = x + width; +      b.bottom = aux->mHeight - y - 1; +      b.top = b.bottom - height; +      bglview->FillRect(b); +   } + +   // restore drawing color +   bglview->SetHighColor(aux->mColor[BE_RCOMP], +                         aux->mColor[BE_GCOMP], +                         aux->mColor[BE_BCOMP], +                         aux->mColor[BE_ACOMP]); +   bglview->SetLowColor(aux->mColor[BE_RCOMP], +                        aux->mColor[BE_GCOMP], +                        aux->mColor[BE_BCOMP], +                        aux->mColor[BE_ACOMP]); +    +   return mask & (~GL_COLOR_BUFFER_BIT); +} + + +GLbitfield AuxInfo::ClearBack(GLcontext *ctx, GLbitfield mask, +                               GLboolean all, GLint x, GLint y, +                               GLint width, GLint height) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   GLuint *start = (GLuint *) bitmap->Bits(); +   const GLuint *clearPixelPtr = (const GLuint *) aux->mClearColor; +   const GLuint clearPixel = *clearPixelPtr; + +   if (all) { +      const int numPixels = aux->mWidth * aux->mHeight; +      if (clearPixel == 0) { +         memset(start, 0, numPixels * 4); +      } +      else { +         for (int i = 0; i < numPixels; i++) { +             start[i] = clearPixel; +         } +      } +   } +   else { +      // XXX untested +      start += y * aux->mWidth + x; +      for (int i = 0; i < height; i++) { +         for (int j = 0; j < width; j++) { +            start[j] = clearPixel; +         } +         start += aux->mWidth; +      } +   } + +   return mask & (~GL_COLOR_BUFFER_BIT); +} + + +void AuxInfo::Index(GLcontext *ctx, GLuint index) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   aux->mIndex = index; +} + + +void AuxInfo::Color(GLcontext *ctx, GLubyte r, GLubyte g, +						GLubyte b, GLubyte a) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   aux->mColor[BE_RCOMP] = r; +   aux->mColor[BE_GCOMP] = g; +   aux->mColor[BE_BCOMP] = b; +   aux->mColor[BE_ACOMP] = a; +   bglview->SetHighColor(r, g, b, a); +   bglview->SetLowColor(r, g, b, a); +} + +GLboolean AuxInfo::SetBuffer(GLcontext *ctx, GLenum buffer) +{ +   if (buffer == GL_FRONT_LEFT) +      return GL_TRUE; +   else if (buffer == GL_BACK_LEFT) +      return GL_TRUE; +   else +      return GL_FALSE; +} + +void AuxInfo::GetBufferSize(GLcontext *ctx, GLuint *width, +                            GLuint *height) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   BRect b = bglview->Bounds(); +   *width = (GLuint) (b.right - b.left + 1); +   *height = (GLuint) (b.bottom - b.top + 1); +   aux->mBottom = (GLint) b.bottom; + +   if (ctx->Visual->DBflag) { +      if (*width != aux->mWidth || *height != aux->mHeight) { +         // allocate new size of back buffer bitmap +         if (aux->mBitmap) +            delete aux->mBitmap; +         BRect rect(0.0, 0.0, *width - 1, *height - 1); +         aux->mBitmap = new BBitmap(rect, B_RGBA32); +      } +   } +   else +   { +      aux->mBitmap = NULL; +   } + +   aux->mWidth = *width; +   aux->mHeight = *height; +} + + +const GLubyte *AuxInfo::GetString(GLcontext *ctx, GLenum name) +{ +   switch (name) { +      case GL_RENDERER: +         return (const GLubyte *) "Mesa BeOS"; +      default: +         // Let core library handle all other cases +         return NULL; +   } +} + + +// Plot a pixel.  (0,0) is upper-left corner +// This is only used when drawing to the front buffer. +static void Plot(BGLView *bglview, int x, int y) +{ +   // XXX There's got to be a better way! +   BPoint p(x, y), q(x+1, y); +   bglview->StrokeLine(p, q); +} + + +void AuxInfo::WriteRGBASpanFront(const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 CONST GLubyte rgba[][4], +                                 const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   int flippedY = aux->mBottom - y; +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]); +            Plot(bglview, x++, flippedY); +         } +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]); +         Plot(bglview, x++, flippedY); +      } +   } +} + +void AuxInfo::WriteRGBSpanFront(const GLcontext *ctx, GLuint n, +                                GLint x, GLint y, +                                CONST GLubyte rgba[][3], +                                const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   int flippedY = aux->mBottom - y; +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); +            Plot(bglview, x++, flippedY); +         } +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); +         Plot(bglview, x++, flippedY); +      } +   } +} + +void AuxInfo::WriteMonoRGBASpanFront(const GLcontext *ctx, GLuint n, +                                     GLint x, GLint y, const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   int flippedY = aux->mBottom - y; +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            Plot(bglview, x++, flippedY); +         } +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         Plot(bglview, x++, flippedY); +      } +   } +} + +void AuxInfo::WriteRGBAPixelsFront(const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   CONST GLubyte rgba[][4], +                                   const GLubyte mask[] ) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); +            Plot(bglview, x[i], aux->mBottom - y[i]); +         } +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); +         Plot(bglview, x[i], aux->mBottom - y[i]); +      } +   } +} + + +void AuxInfo::WriteMonoRGBAPixelsFront(const GLcontext *ctx, GLuint n, +                                       const GLint x[], const GLint y[], +                                       const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BGLView *bglview = aux->mBGLView; +   assert(bglview); +   // plot points using current color +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            Plot(bglview, x[i], aux->mBottom - y[i]); +         } +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         Plot(bglview, x[i], aux->mBottom - y[i]); +      } +   } +} + + +void AuxInfo::WriteCI32SpanFront( const GLcontext *ctx, GLuint n, GLint x, GLint y, +                             const GLuint index[], const GLubyte mask[] ) +{ +   // XXX to do +} + +void AuxInfo::WriteCI8SpanFront( const GLcontext *ctx, GLuint n, GLint x, GLint y, +                            const GLubyte index[], const GLubyte mask[] ) +{ +   // XXX to do +} + +void AuxInfo::WriteMonoCISpanFront( const GLcontext *ctx, GLuint n, +                               GLint x, GLint y, const GLubyte mask[] ) +{ +   // XXX to do +} + + +void AuxInfo::WriteCI32PixelsFront( const GLcontext *ctx, GLuint n, +                                    const GLint x[], const GLint y[], +                                    const GLuint index[], const GLubyte mask[] ) +{ +   // XXX to do +} + +void AuxInfo::WriteMonoCIPixelsFront( const GLcontext *ctx, GLuint n, +                                      const GLint x[], const GLint y[], +                                      const GLubyte mask[] ) +{ +   // XXX to do +} + + +void AuxInfo::ReadCI32SpanFront( const GLcontext *ctx, +                                 GLuint n, GLint x, GLint y, GLuint index[] ) +{ +   // XXX to do +} + + +void AuxInfo::ReadRGBASpanFront( const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, GLubyte rgba[][4] ) +{ +   // XXX to do +} + + +void AuxInfo::ReadCI32PixelsFront( const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   GLuint indx[], const GLubyte mask[] ) +{ +   // XXX to do +} + + +void AuxInfo::ReadRGBAPixelsFront( const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   GLubyte rgba[][4], const GLubyte mask[] ) +{ +   // XXX to do +} + + + + +void AuxInfo::WriteRGBASpanBack(const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 CONST GLubyte rgba[][4], +                                 const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   int row = aux->mBottom - y; +   GLubyte *pixel = (GLubyte *) bitmap->Bits() + (row * aux->mWidth + x) * 4; +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            pixel[BE_RCOMP] = rgba[i][RCOMP]; +            pixel[BE_GCOMP] = rgba[i][GCOMP]; +            pixel[BE_BCOMP] = rgba[i][BCOMP]; +            pixel[BE_ACOMP] = rgba[i][ACOMP]; +         } +         pixel += 4; +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         pixel[BE_RCOMP] = rgba[i][RCOMP]; +         pixel[BE_GCOMP] = rgba[i][GCOMP]; +         pixel[BE_BCOMP] = rgba[i][BCOMP]; +         pixel[BE_ACOMP] = rgba[i][ACOMP]; +         pixel += 4; +      } +   } +} + + +void AuxInfo::WriteRGBSpanBack(const GLcontext *ctx, GLuint n, +                                GLint x, GLint y, +                                CONST GLubyte rgb[][3], +                                const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   int row = aux->mBottom - y; +   GLubyte *pixel = (GLubyte *) bitmap->Bits() + (row * aux->mWidth + x) * 4; +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            pixel[BE_RCOMP] = rgb[i][RCOMP]; +            pixel[BE_GCOMP] = rgb[i][GCOMP]; +            pixel[BE_BCOMP] = rgb[i][BCOMP]; +            pixel[BE_ACOMP] = 255; +         } +         pixel += 4; +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         pixel[BE_RCOMP] = rgb[i][RCOMP]; +         pixel[BE_GCOMP] = rgb[i][GCOMP]; +         pixel[BE_BCOMP] = rgb[i][BCOMP]; +         pixel[BE_ACOMP] = 255; +         pixel += 4; +      } +   } +} + + +void AuxInfo::WriteMonoRGBASpanBack(const GLcontext *ctx, GLuint n, +                                     GLint x, GLint y, const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   int row = aux->mBottom - y; +   GLuint *pixelPtr = (GLuint *) bitmap->Bits() + row * aux->mWidth + x; +   const GLuint pixel = *((GLuint *) aux->mColor); +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) +            *pixelPtr = pixel; +         pixelPtr++; +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         *pixelPtr++ = pixel; +      } +   } +} + + +void AuxInfo::WriteRGBAPixelsBack(const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   CONST GLubyte rgba[][4], +                                   const GLubyte mask[] ) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            GLubyte *pixel = (GLubyte *) bitmap->Bits() +            + (aux->mBottom - y[i]) * bitmap->BytesPerRow() + x[i] * 4; +            pixel[BE_RCOMP] = rgba[i][RCOMP]; +            pixel[BE_GCOMP] = rgba[i][GCOMP]; +            pixel[BE_BCOMP] = rgba[i][BCOMP]; +            pixel[BE_ACOMP] = rgba[i][ACOMP]; +         } +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         GLubyte *pixel = (GLubyte *) bitmap->Bits() +            + (aux->mBottom - y[i]) * bitmap->BytesPerRow() + x[i] * 4; +         pixel[BE_RCOMP] = rgba[i][RCOMP]; +         pixel[BE_GCOMP] = rgba[i][GCOMP]; +         pixel[BE_BCOMP] = rgba[i][BCOMP]; +         pixel[BE_ACOMP] = rgba[i][ACOMP]; +      } +   } +} + + +void AuxInfo::WriteMonoRGBAPixelsBack(const GLcontext *ctx, GLuint n, +                                       const GLint x[], const GLint y[], +                                       const GLubyte mask[]) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   const GLuint pixel = *((GLuint *) aux->mColor); +   if (mask) { +      for (GLuint i = 0; i < n; i++) { +         if (mask[i]) { +            GLuint *pixelPtr = (GLuint *) bitmap->Bits() +                    + (aux->mBottom - y[i]) * aux->mWidth + x[i]; +            *pixelPtr = pixel; +         } +      } +   } +   else { +      for (GLuint i = 0; i < n; i++) { +         GLuint *pixelPtr = (GLuint *) bitmap->Bits() +                 + (aux->mBottom - y[i]) * aux->mWidth + x[i]; +         *pixelPtr = pixel; +      } +   } +} + + +void AuxInfo::WriteCI32SpanBack( const GLcontext *ctx, GLuint n, +                                 GLint x, GLint y, +                                 const GLuint index[], const GLubyte mask[] ) +{ +   // XXX to do +} + +void AuxInfo::WriteCI8SpanBack( const GLcontext *ctx, GLuint n, +                                GLint x, GLint y, +                                const GLubyte index[], const GLubyte mask[] ) +{ +   // XXX to do +} + +void AuxInfo::WriteMonoCISpanBack( const GLcontext *ctx, GLuint n, +                                   GLint x, GLint y, const GLubyte mask[] ) +{ +   // XXX to do +} + + +void AuxInfo::WriteCI32PixelsBack( const GLcontext *ctx, GLuint n, +                                   const GLint x[], const GLint y[], +                                   const GLuint index[], const GLubyte mask[] ) +{ +   // XXX to do +} + +void AuxInfo::WriteMonoCIPixelsBack( const GLcontext *ctx, GLuint n, +                                     const GLint x[], const GLint y[], +                                     const GLubyte mask[] ) +{ +   // XXX to do +} + + +void AuxInfo::ReadCI32SpanBack( const GLcontext *ctx, +                                GLuint n, GLint x, GLint y, GLuint index[] ) +{ +   // XXX to do +} + + +void AuxInfo::ReadRGBASpanBack( const GLcontext *ctx, GLuint n, +                                GLint x, GLint y, GLubyte rgba[][4] ) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   const BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   int row = aux->mBottom - y; +   const GLubyte *pixel = (GLubyte *) bitmap->Bits() +                        + row * bitmap->BytesPerRow() + x * 4; +   for (GLuint i = 0; i < n; i++) { +      rgba[i][RCOMP] = pixel[BE_RCOMP]; +      rgba[i][GCOMP] = pixel[BE_GCOMP]; +      rgba[i][BCOMP] = pixel[BE_BCOMP]; +      rgba[i][ACOMP] = pixel[BE_ACOMP]; +      pixel += 4; +   } +} + + +void AuxInfo::ReadCI32PixelsBack( const GLcontext *ctx, +                                   GLuint n, const GLint x[], const GLint y[], +                                   GLuint indx[], const GLubyte mask[] ) +{ +   // XXX to do +} + + +void AuxInfo::ReadRGBAPixelsBack( const GLcontext *ctx, +                                  GLuint n, const GLint x[], const GLint y[], +                                  GLubyte rgba[][4], const GLubyte mask[] ) +{ +   AuxInfo *aux = (AuxInfo *) ctx->DriverCtx; +   const BBitmap *bitmap = aux->mBitmap; +   assert(bitmap); +   for (GLuint i = 0; i < n; i++) { +      if (y[i] < aux->mHeight) { +         const GLubyte *pixel = (const GLubyte *) bitmap->Bits() +            + ((aux->mBottom - y[i]) * aux->mWidth + x[i]) * 4; +         rgba[i][RCOMP] = pixel[BE_RCOMP]; +         rgba[i][GCOMP] = pixel[BE_GCOMP]; +         rgba[i][BCOMP] = pixel[BE_BCOMP]; +         rgba[i][ACOMP] = pixel[BE_ACOMP]; +      } +   } +} + + + + +//------------------------------------------------------------------ +// Public interface methods +//------------------------------------------------------------------ + + +// +// Input:  rect - initial rectangle +//         name - window name +//         resizingMode - example: B_FOLLOW_NONE +//         mode - usually 0 ? +//         options - Bitwise-OR of BGL_* tokens +// +BGLView::BGLView(BRect rect, char *name, +                 ulong resizingMode, ulong mode, +                 ulong options) +   :BView(rect, name, resizingMode, mode) +{ +   const GLboolean rgbFlag = (options & BGL_RGB) == BGL_RGB; +   const GLboolean alphaFlag = (options & BGL_ALPHA) == BGL_ALPHA; +   const GLboolean dblFlag = (options & BGL_DOUBLE) == BGL_DOUBLE; +   const GLboolean stereoFlag = false; +   const GLint depth = (options & BGL_DEPTH) ? 16 : 0; +   const GLint stencil = (options & BGL_STENCIL) ? 8 : 0; +   const GLint accum = (options & BGL_ACCUM) ? 16 : 0; +   const GLint index = (options & BGL_INDEX) ? 32 : 0; +   const GLint red = (options & BGL_RGB) ? 8 : 0; +   const GLint green = (options & BGL_RGB) ? 8 : 0; +   const GLint blue = (options & BGL_RGB) ? 8 : 0; +   const GLint alpha = (options & BGL_RGB) ? 8 : 0; + +   if (!rgbFlag) { +      fprintf(stderr, "Mesa Warning: color index mode not supported\n"); +   } + +   // Allocate auxiliary data object +   AuxInfo *aux = new AuxInfo; + +   // examine option flags and create gl_context struct +   GLvisual *visual = gl_create_visual( rgbFlag, alphaFlag, +                                        dblFlag, stereoFlag, +                                        depth, stencil, accum, index, +                                        red, green, blue, alpha); + +   // create core framebuffer +   GLframebuffer *buffer = gl_create_framebuffer(visual); + +   // create core context +   const GLboolean direct = GL_TRUE; +   GLcontext *ctx = gl_create_context( visual, NULL, aux, direct ); + +   aux->Init(this, ctx, visual, buffer ); + +   // Hook aux data into BGLView object +   m_gc = aux; +} + + +BGLView::~BGLView() +{ +   printf("BGLView destructor\n"); +   AuxInfo *aux = (AuxInfo *) m_gc; +   assert(aux); +   delete aux; +} + +void BGLView::LockGL() +{ +   AuxInfo *aux = (AuxInfo *) m_gc; +   assert(aux); +   aux->MakeCurrent(); +} + +void BGLView::UnlockGL() +{ +   AuxInfo *aux = (AuxInfo *) m_gc; +   assert(aux); +   // Could call gl_make_current(NULL, NULL) but it would just +   // hinder performance +} + +void BGLView::SwapBuffers() +{ +   AuxInfo *aux = (AuxInfo *) m_gc; +   assert(aux); +   aux->SwapBuffers(); +} + + +void BGLView::CopySubBufferMESA(GLint x, GLint y, GLuint width, GLuint height) +{ +   AuxInfo *aux = (AuxInfo *) m_gc; +   assert(aux); +   aux->CopySubBuffer(x, y, width, height); +} + + +BView *BGLView::EmbeddedView() +{ +   // XXX to do + +} + +status_t BGLView::CopyPixelsOut(BPoint source, BBitmap *dest) +{ +   // XXX to do +} + + +status_t BGLView::CopyPixelsIn(BBitmap *source, BPoint dest) +{ +   // XXX to do +} + +void BGLView::ErrorCallback(GLenum errorCode) +{ +   // XXX to do +} + +void BGLView::Draw(BRect updateRect) +{ +//   printf("BGLView draw\n"); +   // XXX to do +} + +void BGLView::AttachedToWindow() +{ +   BView::AttachedToWindow(); + +   // don't paint window background white when resized +   SetViewColor(B_TRANSPARENT_32_BIT); +} + +void BGLView::AllAttached() +{ +   BView::AllAttached(); +//   printf("BGLView AllAttached\n"); +} + +void BGLView::DetachedFromWindow() +{ +   BView::DetachedFromWindow(); +} + +void BGLView::AllDetached() +{ +   BView::AllDetached(); +//   printf("BGLView AllDetached"); +} + +void BGLView::FrameResized(float width, float height) +{ +   return BView::FrameResized(width, height); +} + +status_t BGLView::Perform(perform_code d, void *arg) +{ +   return BView::Perform(d, arg); +} + + +status_t BGLView::Archive(BMessage *data, bool deep) const +{ +   return BView::Archive(data, deep); +} + +void BGLView::MessageReceived(BMessage *msg) +{ +   BView::MessageReceived(msg); +} + +void BGLView::SetResizingMode(uint32 mode) +{ +   BView::SetResizingMode(mode); +} + +void BGLView::Show() +{ +//   printf("BGLView Show\n"); +   BView::Show(); +} + +void BGLView::Hide() +{ +//   printf("BGLView Hide\n"); +   BView::Hide(); +} + +BHandler *BGLView::ResolveSpecifier(BMessage *msg, int32 index, +                                    BMessage *specifier, int32 form, +                                    const char *property) +{ +   return BView::ResolveSpecifier(msg, index, specifier, form, property); +} + +status_t BGLView::GetSupportedSuites(BMessage *data) +{ +   return BView::GetSupportedSuites(data); +} + +void BGLView::DirectConnected( direct_buffer_info *info ) +{ +   // XXX to do +} + +void BGLView::EnableDirectMode( bool enabled ) +{ +   // XXX to do +} + + + +//---- private methods ---------- + +void BGLView::_ReservedGLView1() {} +void BGLView::_ReservedGLView2() {} +void BGLView::_ReservedGLView3() {} +void BGLView::_ReservedGLView4() {} +void BGLView::_ReservedGLView5() {} +void BGLView::_ReservedGLView6() {} +void BGLView::_ReservedGLView7() {} +void BGLView::_ReservedGLView8() {} + +#if 0 +BGLView::BGLView(const BGLView &v) +	: BView(v) +{ +   // XXX not sure how this should work +   printf("Warning BGLView::copy constructor not implemented\n"); +} +#endif + + +BGLView &BGLView::operator=(const BGLView &v) +{ +   printf("Warning BGLView::operator= not implemented\n"); +} + +void BGLView::dither_front() +{ +   // no-op +} + +bool BGLView::confirm_dither() +{ +   // no-op +   return false; +} + +void BGLView::draw(BRect r) +{ +   // XXX no-op ??? +} + +/* Direct Window stuff */ +void BGLView::drawScanline( int x1, int x2, int y, void *data ) +{ +   // no-op +} + +void BGLView::scanlineHandler(struct rasStateRec *state, +                              GLint x1, GLint x2) +{ +   // no-op +} + +void BGLView::lock_draw() +{ +   // no-op +} + +void BGLView::unlock_draw() +{ +   // no-op +} + +bool BGLView::validateView() +{ +   // no-op +   return true; +} + diff --git a/src/mesa/drivers/d3d/D3DCAPS.CPP b/src/mesa/drivers/d3d/D3DCAPS.CPP new file mode 100644 index 0000000000..53595f0c34 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DCAPS.CPP @@ -0,0 +1,251 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                       Build 5   */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "D3DHAL.h"
 +/*===========================================================================*/
 +/* Macros.                                                                   */
 +/*===========================================================================*/
 +#define SRCBLEND_MAP(gl,d3d,fall)	if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwSrcBlendCaps & d3d ) \
 +                                   { \
 +					            sprintf( buffer, "SRC Blend: %s -> %s", # gl, # d3d ); \
 +                                     DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
 +                                     pShared->dwSrcBlendCaps[index] = d3d; \
 +						     } \
 +							else \
 +                                   { \
 +					            sprintf( buffer, "SRC Blend: %s -> %s", # gl, # fall ); \
 +                                     DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
 +                                     pShared->dwSrcBlendCaps[index] = fall; \
 +							}
 +#define DSTBLEND_MAP(gl,d3d,fall)	if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwDestBlendCaps & d3d ) \
 +                                   { \
 +					            sprintf( buffer, "DST Blend: %s -> %s", # gl, # d3d ); \
 +                                     DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
 +                                     pShared->dwDestBlendCaps[index] = d3d; \
 +						     } \
 +							else \
 +                                   { \
 +					            sprintf( buffer, "DST Blend: %s -> %s", # gl, # fall ); \
 +                                     DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
 +                                     pShared->dwDestBlendCaps[index] = fall; \
 +							}
 +
 +/*===========================================================================*/
 +/*  I use this function to handle the fact that the D3D texture blending and */
 +/* OpenGL texture blending functions don't map one to one.  Also there is the*/
 +/* problem with cards not supporting all the D3D functions. So I use the CAPS*/
 +/* of the card to make a table of functions that will have defaults for the  */
 +/* unsupported functions.                                                    */
 +/*  So first I fill the table with the fallback function then I check to see */
 +/* if the card supports the requested function.  If it does I replace the    */
 +/* default thats already in the array.  Now order does matter as I used an   */
 +/* enum type in D3DShared.h so that the mapping would be a little easier.    */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void AlphaBlendTableHAL( PMESAD3DHAL pHAL )
 +{
 +  PMESAD3DSHARED	pShared = &pHAL->shared;
 +  int			index;
 +  char			buffer[128];
 +
 +  DPF(( DBG_FUNC, "AlphaBlendTableHAL();" ));
 +
 +  /* Make the fallback for the Source blend. */
 +  for( index = 0; index < 14; index++ )
 +  {
 +    switch( index )
 +    {
 +      case s_zero:
 +        SRCBLEND_MAP( GL_ZERO, D3DBLEND_ZERO, D3DBLEND_ONE );
 +	   break;
 +      case s_one:
 +        SRCBLEND_MAP( GL_ONE, D3DBLEND_ONE, D3DBLEND_ONE );
 +	   break;
 +      case s_dst_color:
 +        SRCBLEND_MAP( GL_DST_COLOR, D3DBLEND_DESTCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case s_one_minus_dst_color:
 +        SRCBLEND_MAP( GL_ONE_MINUS_DST_COLOR, D3DBLEND_INVDESTCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case s_src_alpha:
 +        SRCBLEND_MAP( GL_SRC_ALPHA, D3DBLEND_SRCALPHA, D3DBLEND_ONE );
 +	   break;
 +      case s_one_minus_src_alpha:
 +        SRCBLEND_MAP( GL_ONE_MINUS_SRC_ALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_ONE );
 +	   break;
 +      case s_dst_alpha:
 +        SRCBLEND_MAP( GL_DST_ALPHA, D3DBLEND_DESTALPHA, D3DBLEND_ONE );
 +	   break;
 +      case s_one_minus_dst_alpha:
 +        SRCBLEND_MAP( GL_ONE_MINUS_DST_ALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_ONE );
 +	   break;
 +      case s_src_alpha_saturate:
 +        SRCBLEND_MAP( GL_SRC_ALPHA_SATURATE, D3DBLEND_SRCALPHASAT, D3DBLEND_ONE );
 +	   break;
 +      case s_constant_color:
 +        SRCBLEND_MAP( GL_CONSTANT_COLOR, D3DBLEND_SRCCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case s_one_minus_constant_color:
 +        SRCBLEND_MAP( GL_ONE_MINUS_CONSTANT_COLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case s_constant_alpha:
 +        SRCBLEND_MAP( GL_CONSTANT_ALPHA, D3DBLEND_BOTHSRCALPHA, D3DBLEND_ONE );
 +	   break;
 +      case s_one_minus_constant_alpha:
 +        SRCBLEND_MAP( GL_ONE_MINUS_CONSTANT_ALPHA, D3DBLEND_BOTHINVSRCALPHA, D3DBLEND_ONE );
 +	   break;
 +    }
 +  }
 +
 +  /* Make the fallback for the Destination blend. */
 +  for( index = 0; index < 14; index++ )
 +  {
 +    switch( index )
 +    {
 +      case d_zero:
 +        DSTBLEND_MAP( GL_ZERO, D3DBLEND_ZERO, D3DBLEND_ONE );
 +	   break;
 +      case d_one:
 +        DSTBLEND_MAP( GL_ONE, D3DBLEND_ONE, D3DBLEND_ONE );
 +	   break;
 +      case d_src_color:
 +        DSTBLEND_MAP( GL_SRC_COLOR, D3DBLEND_SRCCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case d_one_minus_src_color:
 +        DSTBLEND_MAP( GL_ONE_MINUS_SRC_COLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case d_src_alpha:
 +        DSTBLEND_MAP( GL_SRC_ALPHA, D3DBLEND_SRCALPHA, D3DBLEND_ONE );
 +	   break;
 +      case d_one_minus_src_alpha:
 +        DSTBLEND_MAP( GL_ONE_MINUS_SRC_ALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_ONE );
 +	   break;
 +      case d_dst_alpha:
 +        DSTBLEND_MAP( GL_DST_ALPHA, D3DBLEND_DESTALPHA, D3DBLEND_ONE );
 +	   break;
 +      case d_one_minus_dst_alpha:
 +        DSTBLEND_MAP( GL_ONE_MINUS_DST_ALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_ONE );
 +	   break;
 +      case d_constant_color:
 +        DSTBLEND_MAP( GL_CONSTANT_COLOR, D3DBLEND_DESTCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case d_one_minus_constant_color:
 +        DSTBLEND_MAP( GL_ONE_MINUS_CONSTANT_COLOR, D3DBLEND_INVDESTCOLOR, D3DBLEND_ONE );
 +	   break;
 +      case d_constant_alpha:
 +        DSTBLEND_MAP( GL_CONSTANT_ALPHAR, D3DBLEND_BOTHSRCALPHA, D3DBLEND_ONE );
 +	   break;
 +      case d_one_minus_constant_alpha:
 +        DSTBLEND_MAP( GL_ONE_MINUS_CONSTANT_ALPHA, D3DBLEND_BOTHINVSRCALPHA, D3DBLEND_ONE );
 +	   break;
 +    }
 +  }
 +
 +  /* Make the fallbacks for the texture functions. */
 +  for( index = 0; index < 4; index++ )
 +  {
 +    switch( index )
 +    {
 +      case d3dtblend_decal:
 +	   if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
 +	   {
 +		DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_DECAL" )); 
 +		pShared->dwTexFunc[index] = D3DTBLEND_DECAL; 
 +	   }
 +        else
 +	   {
 +		if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_MODULATE" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_MODULATE; 
 +		}
 +		else
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_ADD" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_ADD; 
 +		}
 +	   }
 +	   break;
 +      case d3dtblend_decalalpha:
 +	   if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECALALPHA )
 +	   {
 +		DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPHA -> D3DTBLEND_DECALALPHA" )); 
 +		pShared->dwTexFunc[index] = D3DTBLEND_DECALALPHA; 
 +	   }
 +        else
 +	   {
 +		if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPA -> D3DTBLEND_DECAL" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_DECAL; 
 +		}
 +		else
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPHA -> D3DTBLEND_ADD" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_ADD; 
 +		}
 +	   }
 +	   break;
 +    case d3dtblend_modulate:
 +	   if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
 +	   {
 +		DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_MODULATE" )); 
 +		pShared->dwTexFunc[index] = D3DTBLEND_MODULATE; 
 +	   }
 +        else
 +	   {
 +		if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATEALPHA )
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_MODULATEALPHA" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_MODULATEALPHA; 
 +		}
 +		else	if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_DECAL" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_DECAL; 
 +		}
 +		else
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_ADD" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_ADD; 
 +		}
 +	   }
 +	   break;
 +    case d3dtblend_modulatealpha:
 +	   if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATEALPHA )
 +	   {
 +		DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_MODULATEALPHA" )); 
 +		pShared->dwTexFunc[index] = D3DTBLEND_MODULATEALPHA; 
 +	   }
 +        else
 +	   {
 +		if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_MODULATE" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_MODULATE;
 +		}
 +		else	if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_DECALE" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_DECAL; 
 +		}
 +		else
 +		{
 +		  DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_ADD" )); 
 +		  pShared->dwTexFunc[index] = D3DTBLEND_ADD; 
 +		}
 +	   }
 +	   break;
 +    }
 +  }
 +}
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3DHAL.H b/src/mesa/drivers/d3d/D3DHAL.H new file mode 100644 index 0000000000..12f4b4e728 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DHAL.H @@ -0,0 +1,69 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#ifndef _D3D_HAL_INC
 +#define _D3D_HAL_INC
 +   
 +/*===========================================================================*/
 +/* Includes.                                                                 */
 +/*===========================================================================*/
 +#include <windows.h>
 +#include <ddraw.h>
 +#include <d3d.h>
 +#include <stdlib.h>
 +#include <time.h>
 +#include "D3DShared.h"
 +#include "D3DTextureMgr.h"
 +#include "Debug.h"
 +/*===========================================================================*/
 +/* Defines.                                                                  */
 +/*===========================================================================*/
 +#define	DX_RESTORE(ps)			if ( (ps) && (ps)->IsLost() ) (ps)->Restore();
 +/*===========================================================================*/
 +/* Type defines.                                                             */
 +/*===========================================================================*/
 +typedef struct _d3d_hal_struct
 +{
 +  MESAD3DSHARED		shared;
 +
 +  GUID				guid;
 +  LPDIRECTDRAW  		lpDD;
 +  LPDIRECTDRAW4        	lpDD4;
 +  LPDIRECT3D3          	lpD3D3;
 +  LPDIRECT3DDEVICE3    	lpD3DDevice;
 +  D3DDEVICEDESC 	 	D3DHWDevDesc;
 +  LPDIRECTDRAWSURFACE4 	lpDDSPrimary,
 +                         lpDDSRender,
 +                         lpDDSZbuffer;
 +  LPDIRECT3DVIEWPORT3  	lpViewport;
 +  LPDIRECTDRAWCLIPPER	lpClipper;
 +  DDPIXELFORMAT        	ddpf,
 +                         ddpfZBuffer;
 +  PTM_OBJECT           	pTMList;
 +
 +} MESAD3DHAL, *PMESAD3DHAL;
 +/*===========================================================================*/
 +/* External function prototypes.                                             */
 +/*===========================================================================*/
 +extern BOOL InitTMgrHAL( PMESAD3DHAL pHAL );
 +extern void TermTMgrHAL( PMESAD3DHAL pHAL );
 +extern void AlphaBlendTableHAL( PMESAD3DHAL pHAL );
 +
 +extern void Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel );
 +extern char *ErrorStringD3D( HRESULT hr );
 +extern void  FatalShutDown( PMESAD3DHAL pHAL );
 +/*===========================================================================*/
 +/* Global variables.                                                         */
 +/*===========================================================================*/
 +extern char	*errorMsg;
 +
 +#endif
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3DInit.cpp b/src/mesa/drivers/d3d/D3DInit.cpp new file mode 100644 index 0000000000..ba7891612e --- /dev/null +++ b/src/mesa/drivers/d3d/D3DInit.cpp @@ -0,0 +1,891 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                       Build 5   */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "D3DHAL.h"
 +/*===========================================================================*/
 +/* Local function prototypes.                                                */
 +/*===========================================================================*/
 +static void	DestroyAllSurfaces( PMESAD3DHAL pHAL );
 +static void	DestroyDevice( PMESAD3DHAL pHAL );
 +static void	DestroyInterfaces( PMESAD3DHAL pHAL );
 +
 +HRESULT WINAPI   EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid );
 +HRESULT CALLBACK EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid );
 +HRESULT CALLBACK EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc,  void *pVoid );
 +/*===========================================================================*/
 +/* Globals.                                                                  */
 +/*===========================================================================*/
 +//char		*errorMsg;
 +/*===========================================================================*/
 +/*  This function is responable for allocating the actual MESAD3DHAL struct. */
 +/* Each Mesa context will have its own MESAD3DHAL struct so its like a mini  */
 +/* context to some extent. All one time allocations/operations get done here.*/
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +extern "C" PMESAD3DSHARED InitHAL( HWND hwnd )
 +{
 +  PMESAD3DHAL	pHAL;
 +  ULONG     	rc;
 +
 +  DPF(( DBG_FUNC, "InitHAL();" ));
 +  DPF(( DBG_CNTX_INFO, "hwnd: %d", hwnd ));
 +
 +  /* Allocate the structure and zero it out. */   
 +  pHAL = (PMESAD3DHAL)ALLOC( sizeof(MESAD3DHAL) );
 +  if ( pHAL == NULL )
 +  {   
 +    RIP( pHAL, "InitHAL->", "Memory Allocation" );
 +    return (PMESAD3DSHARED)NULL;
 +  }
 +  memset( pHAL, 0, sizeof(MESAD3DHAL) );
 +
 +  /* Get the texture manager going. */
 +  rc = InitTMgrHAL( pHAL );
 +  if ( rc == FALSE )
 +  {   
 +    RIP( pHAL, "InitTMgrHAL->", "Failed" );
 +    return (PMESAD3DSHARED)NULL;
 +  }
 +
 +  /* Fill in the window parameters if we can. */
 +  pHAL->shared.hwnd = hwnd;
 +
 +  /* Parse the user's enviroment variables to generate a debug mask. */
 +  ReadDBGEnv();
 +  
 +  return (PMESAD3DSHARED)pHAL;
 +}
 +/*===========================================================================*/
 +/*  This function will unload all the resources that the MESAD3DHAL struct   */
 +/* has bound to it.  The actual structure itself will be freed.              */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void TermHAL( PMESAD3DSHARED pShared )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +
 +  DPF(( DBG_FUNC, "TermHAL();" ));
 +
 +  /* Check for an empty wrapper structure. */
 +  if ( pHAL == NULL )
 +    return;
 +
 +  /* Kill this texture manager. */
 +  TermTMgrHAL( pHAL );
 +
 +  /* Kill any DDraw stuff if exists. */
 +  DestroyDevice( pHAL );
 +  DestroyAllSurfaces( pHAL );
 +  DestroyInterfaces( pHAL );
 +
 +  FREE( pHAL );
 +}
 +/*===========================================================================*/
 +/*  This function is used to init and resize the rendering surface as the two*/
 +/* are almost the same.  First the device and all the surfaces are destoryed */
 +/* if they already exist.  Next we create a OffScreen rendering surface and  */
 +/* save some pixelformat info to do color convertions. Next we start to take */
 +/* care of getting the most out of the hardware. I use bHardware to determine*/
 +/* the state of the device we found in the device enumeration.  The enum proc*/
 +/* will try for hardware first.  I next use a bForceSW to make the enum proc */
 +/* choose a software device.  So I will try some combinations with HW first  */
 +/* until I feel I have to set the bForceSW and call this function again.  If */
 +/* this function is called with no width or height then use the internals.   */
 +/*   NOTE:  The worst case is that all will be in SW (RGBDevice) and really  */
 +/*         I should forget the whole thing and fall back to a DDraw span type*/
 +/*         rendering but what is the point.  This way I always know I have a */
 +/*         D3DDevice and that makes things easier.  I do impliment the span  */
 +/*         rendering function for stuff that I haven't done support for such */
 +/*         as points and lines.                                              */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE                                                       */
 +/*===========================================================================*/
 +extern "C" BOOL	CreateHAL( PMESAD3DSHARED pShared )
 +{
 +  PMESAD3DHAL 		pHAL = (PMESAD3DHAL)pShared;
 +  DDSURFACEDESC2	ddsd2;
 +  D3DDEVICEDESC  	D3DSWDevDesc;
 +  DDSCAPS2 	  	ddscaps;
 +  DWORD          	dwCoopFlags,
 +                    dwWidth,
 +                    dwHeight;
 +  ULONG          	rc;
 +
 +  DPF(( DBG_FUNC, "CreateHAL();" ));
 +
 +#define InitDDSD2(f)      memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); \
 +                          ddsd2.dwSize  = sizeof( DDSURFACEDESC2 ); \
 +                          ddsd2.dwFlags = f;
 +
 +  if ( pHAL == NULL )
 +    return FALSE;
 +
 +  /* Use the internal rectangle struct. */
 +  dwWidth  = pShared->rectW.right - pShared->rectW.left;
 +  dwHeight = pShared->rectW.bottom - pShared->rectW.top;
 +
 +  DPF(( DBG_CNTX_INFO, "Width: %d Height: %d", dwWidth, dwHeight ));
 +
 +  /* The dimensions might still be the same so just leave. */
 +  if ( (dwWidth == pShared->dwWidth) && (dwHeight == pShared->dwHeight) )
 +  {
 +    DPF(( DBG_CNTX_WARN, "Context size hasn't changed" ));
 +    return TRUE;
 +  }
 +
 +  /* If one of the dimensions are zero then leave. WM_SIZE should get us back here. */
 +  if ( (dwWidth == 0) || (dwHeight == 0) )
 +    return TRUE;
 +
 +  /* Save the renders dimensions. */
 +  pShared->dwWidth  = dwWidth;
 +  pShared->dwHeight = dwHeight;
 +
 +  DPF(( DBG_CNTX_INFO, "Creating Context:\n cx:%d cy:%d", pShared->dwWidth, pShared->dwHeight ));
 +
 +  /*=================================*/
 +  /* Create all required interfaces. */
 +  /*=================================*/
 +
 +  /* Kill any DDraw stuff if exists. */
 +  DestroyDevice( pHAL );
 +  DestroyAllSurfaces( pHAL );
 +  DestroyInterfaces( pHAL );
 +
 +  /* Create a instance of DDraw using the Primary display driver. */
 +  rc = DirectDrawCreate( NULL, &pHAL->lpDD, NULL );
 +  if( FAILED(rc) )
 +  {
 +    RIP( pHAL, "DirectDrawCreate->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Get the DDraw4 interface. */
 +  rc = pHAL->lpDD->QueryInterface( IID_IDirectDraw4, (void **)&pHAL->lpDD4 );
 +  if( FAILED(rc) )
 +  {
 +    RIP( pHAL, "QueryInterface (IID_IDirectDraw4) ->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Get the Direct3D3 interface. */
 +  rc = pHAL->lpDD4->QueryInterface( IID_IDirect3D3, (void **)&pHAL->lpD3D3 );
 +  if( FAILED(rc) )
 +  {
 +    RIP( pHAL, "QueryInterface (IID_IDirect3D3) ->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Set the Cooperative level. NOTE: we need to know if we are FS at this point.*/
 +  dwCoopFlags = (pShared->bWindow == TRUE) ? DDSCL_NORMAL : (DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
 +  rc = pHAL->lpDD4->SetCooperativeLevel( pShared->hwnd, dwCoopFlags );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "SetCooperativeLevel->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /*==================================================================*/
 +  /* Get the best device we can and note whether its hardware or not. */
 +  /*==================================================================*/
 +  pShared->bForceSW = FALSE;
 +  pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
 +  pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
 +  DPF(( DBG_CNTX_INFO, "bHardware: %s", (pShared->bHardware) ? "TRUE" : "FALSE" ));
 +  DPF(( DBG_CNTX_INFO, "bWindowed: %s", (pShared->bWindow) ? "TRUE" : "FALSE" ));
 +
 +  /*========================================================================*/
 +  /* HARDWARE was found.                                                    */
 +  /*========================================================================*/
 +  if ( pShared->bHardware == TRUE )
 +  {
 +    /*===================================*/
 +    /* HARDWARE -> Z-BUFFER.             */
 +    /*===================================*/
 +
 +    /* Get a Z-Buffer pixelformat. */
 +    memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
 +    ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
 +    rc = pHAL->lpD3D3->EnumZBufferFormats( pHAL->guid, EnumZBufferHook, (VOID*)&ddsd2.ddpfPixelFormat );
 +    if ( FAILED(rc) )
 +    {
 +	 RIP( pHAL, "EnumZBufferFormatsl->", ErrorStringD3D(rc) );
 +	 return FALSE;
 +    }
 +        
 +    /* Setup our request structure for the Z-buffer surface. */
 +    ddsd2.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
 +    ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
 +    ddsd2.dwWidth        = dwWidth;
 +    ddsd2.dwHeight       = dwHeight;
 +    rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSZbuffer, NULL );
 +    if ( !FAILED(rc) )
 +    {
 +	 DPF(( DBG_CNTX_INFO, "HW ZBuffer" ));
 +
 +	 /*===================================*/
 +	 /* HARDWARE -> Z-BUFFER -> FLIPABLE  */
 +	 /*===================================*/
 +	 if ( pShared->bWindow == FALSE )
 +	 {
 +	   InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
 +	   ddsd2.dwBackBufferCount = 1;
 +	   ddsd2.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
 +	   rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
 +	   if ( FAILED(rc) )
 +	   {	
 +		/* Make sure we try the next fall back. */
 +		DPF(( DBG_CNTX_WARN, "HW Flip/Complex not available" ));
 +		pHAL->lpDDSPrimary = NULL;
 +	   }
 +	   else
 +	   {
 +		/* Get the back buffer that was created. */
 +		ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
 +		rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
 +		if ( FAILED(rc) )
 +		{	
 +		  DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> HW Flip/Complex" ));
 +		  
 +		  /* Make sure we try the next fall back. */
 + 		  pHAL->lpDDSPrimary->Release();
 +		  pHAL->lpDDSPrimary = NULL;
 +		}	
 +		else
 +		{
 +		  /*  I have had problems when a complex surface comes back  */
 +		  /* with the back buffer being created in SW.  Not sure why */
 +		  /* or how this is possable but I'm checking for it here.   */
 +		  memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); 
 +		  ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
 +		  DX_RESTORE( pHAL->lpDDSRender );
 +		  rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
 +		  if ( FAILED(rc) )
 +		  {
 +		    RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
 +		    return FALSE;
 +		  }
 +
 +		  /* If the surface is in VID then we are happy with are Flipable. */
 +		  if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
 +		  {
 +		    pShared->bFlipable = TRUE;
 +		    DPF(( DBG_CNTX_INFO, "HW Flip/Complex!" ));
 +		  }
 +		  else
 +		  {
 +		    /* Kill this setup. */
 +		    pHAL->lpDDSPrimary->Release();
 +		    pHAL->lpDDSPrimary = NULL;
 +		  }
 +		}
 +	   }
 +	 }
 +
 +	 /*===================================*/
 +	 /* HARDWARE -> Z-BUFFER -> BLT       */
 +	 /*===================================*/
 +	 if ( pHAL->lpDDSPrimary == NULL )
 +	 {
 +	   pShared->bFlipable = FALSE;
 +
 +	   /* Create the Primary (front buffer). */
 +	   InitDDSD2( DDSD_CAPS );
 +	   ddsd2.ddsCaps.dwCaps  = DDSCAPS_PRIMARYSURFACE;
 +	   rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
 +	   if ( FAILED(rc) )
 +	   {
 +		/* This is an error as we should be able to do this at minimum. */
 +		RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
 +		return FALSE;
 +	   }
 +
 +	   /* Create the Render (back buffer). */
 +	   InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
 +	   ddsd2.dwWidth	    = dwWidth;
 +	   ddsd2.dwHeight	    = dwHeight;
 +	   ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
 +	   rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
 +	   if ( FAILED(rc) )
 +	   {
 +		DPF(( DBG_CNTX_WARN, "Failed HW Offscreen surface" ));
 +
 +		/* Make sure we try the next fall back. */
 +		pHAL->lpDDSPrimary->Release();
 +		pHAL->lpDDSPrimary = NULL;
 +	   }
 +	   else
 +	   {
 +		/*  Might as well check here too see if this surface is in */
 +		/* hardware.  If nothing else just to be consistant.       */
 +		memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); 
 +		ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
 +		DX_RESTORE( pHAL->lpDDSRender );
 +		rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
 +		if ( FAILED(rc) )
 +		{
 +		  RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
 +		  return FALSE;
 +		}
 +
 +		/* If the surface is in VID then we are happy. */
 +		if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
 +		{
 +		  /*  Create a clipper object so that DDraw will be able to blt windows that */
 +		  /* have been clipped by the screen or other windows.                       */
 +		  pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
 +		  pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
 +		  pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
 +		  pHAL->lpClipper->Release();
 +		  DPF(( DBG_CNTX_INFO, "HW RENDER surface" ));
 +		}
 +		else
 +		{
 +		  /* Kill this setup. */
 +		  pHAL->lpDDSRender->Release();
 +		  pHAL->lpDDSRender = NULL;
 +		  pHAL->lpDDSPrimary->Release();
 +		  pHAL->lpDDSPrimary = NULL;
 +		}
 +	   }
 +	 }	
 +
 +	 /*===================================*/
 +	 /* Create D3DDEVICE -> HARDWARE.     */
 +	 /*===================================*/
 +	 if ( pHAL->lpDDSZbuffer && pHAL->lpDDSPrimary && pHAL->lpDDSRender )
 +	 {
 +	   DX_RESTORE( pHAL->lpDDSRender );
 +	   DX_RESTORE( pHAL->lpDDSZbuffer );
 +
 +	   rc = pHAL->lpDDSRender->AddAttachedSurface( pHAL->lpDDSZbuffer );
 +	   if ( FAILED(rc) )
 +	   {
 +		RIP( pHAL, "AddAttachedSurface (ZBUFFER) ->", ErrorStringD3D(rc) );
 +		return FALSE;
 +	   }
 +
 +	   rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DHALDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
 +	   if ( rc != D3D_OK )
 +	   {
 +		DPF(( DBG_CNTX_WARN, "Failed HW Device" ));
 +		pHAL->lpD3DDevice = NULL;
 +	   }
 +	   else
 +	   {
 +		DPF(( DBG_CNTX_INFO, "HW Device" ));
 +	   }
 +	 }
 +    }	
 +  }
 +      
 +  /*========================================================================*/
 +  /* SOFTWARE fallback.                                                     */
 +  /*========================================================================*/
 +  if ( pHAL->lpD3DDevice == NULL )
 +  {
 +    DPF(( DBG_CNTX_INFO, "SW fallback :(" ));
 +
 +    /* Make sure we have no surfaces allocated.  Just incase. */
 +    DestroyAllSurfaces( pHAL );
 +
 +    /* Get a software device. */
 +    pShared->bFlipable = FALSE;
 +    pShared->bForceSW = TRUE;
 +    pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
 +    pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
 +
 +     /*===================================*/
 +    /* SOFTWARE -> Z-BUFFER.             */
 +    /*===================================*/
 +
 +    /*===================================*/
 +    /* SOFTWARE -> Z-BUFFER -> FLIPABLE  */
 +    /*===================================*/
 +    if ( pShared->bWindow == FALSE )
 +    {
 +	 InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
 +	 ddsd2.dwBackBufferCount = 1;
 +	 ddsd2.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
 +	 ddsd2.ddpfPixelFormat.dwSize  = sizeof( DDPIXELFORMAT );
 +	 ddsd2.ddpfPixelFormat.dwFlags = (DDPF_RGB | DDPF_ALPHAPIXELS);
 +	 rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
 +	 if ( FAILED(rc) )
 +	 {	
 +	   DPF(( DBG_CNTX_WARN, "Failed SW Flip/Complex" ));
 +
 +	   /* Make sure we try the next fall back. */
 +	   pHAL->lpDDSPrimary = NULL;
 +	 }
 +	 else
 +	 {
 +	   ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
 +	   rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
 +	   if ( FAILED(rc) )
 +	   {	
 +		/* Make sure we try the next fall back. */
 +		DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> SW Flip/Complex" ));
 +		pHAL->lpDDSPrimary->Release();
 +		pHAL->lpDDSPrimary = NULL;
 +	   }	
 +	   else
 +	   {
 +		DPF(( DBG_CNTX_INFO, "SW Flip/Complex" ));
 +		pShared->bFlipable = TRUE;
 +	   }
 +	 }
 +    }		
 +
 +    /*===================================*/
 +    /* SOFTWARE -> Z-BUFFER -> BLT       */
 +    /*===================================*/
 +    if ( pHAL->lpDDSPrimary == NULL )
 +    {
 +	 /* Create the Primary (front buffer). */
 +	 InitDDSD2( DDSD_CAPS );
 +	 ddsd2.ddsCaps.dwCaps  = DDSCAPS_PRIMARYSURFACE;
 +	 rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
 +	 if ( FAILED(rc) )
 +	 {
 +	   /* This is an error as we should be able to do this at minimum. */
 +	   RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
 +	   return FALSE;
 +	 }
 +
 +	 /* Create the Render (back buffer). */
 +	 InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
 +	 ddsd2.dwWidth					= dwWidth;
 +	 ddsd2.dwHeight				= dwHeight;
 +	 ddsd2.ddsCaps.dwCaps 			= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
 +	 ddsd2.ddpfPixelFormat.dwSize 	= sizeof( DDPIXELFORMAT );
 +	 ddsd2.ddpfPixelFormat.dwFlags	= (DDPF_RGB | DDPF_ALPHAPIXELS);
 +	 rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
 +	 if ( FAILED(rc) )
 +	 {
 +	   /* That was our last hope. */
 +	   RIP( pHAL, "CreateSurface (RENDER) ->", ErrorStringD3D(rc) );
 +	   return FALSE;
 +	 }
 +	 else
 +	 {
 +	   DPF(( DBG_CNTX_INFO, "SW RENDER surface" ));
 +
 +	   /*  Create a clipper object so that DDraw will be able to blt windows that */
 +	   /* have been clipped by the screen or other windows.                       */
 +	   pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
 +	   pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
 +	   pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
 +	   pHAL->lpClipper->Release();
 +	 }
 +    }		
 +	
 +    /*===================================*/
 +    /* Create D3DDEVICE -> SOFTWARE.     */
 +    /*===================================*/
 +    if ( pHAL->lpDDSPrimary && pHAL->lpDDSRender )
 +    {
 +	 DX_RESTORE( pHAL->lpDDSRender );
 +	 rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DRGBDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
 +	 if ( rc != D3D_OK )
 +	 {
 +	   /* That was our last hope. */
 +	   RIP( pHAL, "CreateDevice (IID_IDirect3DRGBDevice) ->", ErrorStringD3D(rc) );
 +	   return FALSE;
 +	 }
 +	 
 +	 DPF(( DBG_CNTX_INFO, "SW Device" ));
 +    }	
 +  }
 +
 +  /*==============================================================================*/
 +  /* Get a copy of the render pixelformat so that wgl.c can call GetPixelInfoD3D. */
 +  /*==============================================================================*/
 +  memset( &pHAL->ddpf, 0, sizeof(DDPIXELFORMAT) );
 +  pHAL->ddpf.dwSize = sizeof( DDPIXELFORMAT );
 +  rc = pHAL->lpDDSRender->GetPixelFormat( &pHAL->ddpf );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "GetPixelFormat ->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +  DebugPixelFormat( "Using OFFSCREEN", &pHAL->ddpf );
 +  DebugPixelFormat( "Using ZBUFFER", &ddsd2.ddpfPixelFormat );
 +
 +  /* Get a copy of what the D3DDevice supports for later use. */
 +  memset( &D3DSWDevDesc, 0, sizeof(D3DDEVICEDESC) );
 +  memset( &pHAL->D3DHWDevDesc, 0, sizeof(D3DDEVICEDESC) );
 +  D3DSWDevDesc.dwSize       = sizeof( D3DDEVICEDESC );
 +  pHAL->D3DHWDevDesc.dwSize = sizeof( D3DDEVICEDESC );
 +  rc = pHAL->lpD3DDevice->GetCaps( &pHAL->D3DHWDevDesc, &D3DSWDevDesc );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "GetCaps ->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Get a copy of the pixel convertion stuff for direct buffer access. */
 +  Solve8BitChannelPixelFormat( &pHAL->ddpf, &pShared->pixel );
 +  AlphaBlendTableHAL( pHAL );
 +
 +  /* We must prime the Begin/End scene for SwapBuffers to work. */
 +  rc = pHAL->lpD3DDevice->BeginScene();   
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "BeginScene ->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +#undef InitDDSD2
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function will make sure a viewport is created and set for the device*/
 +/* in the supplied structure.  If a rect is supplied then it will be used for*/
 +/* the viewport otherwise the current setting in the strucute will be used.  */
 +/* Note that the rect is relative to the window.  So left/top must be 0,0 to */
 +/* use the whole window else there is scissoring going down.                 */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +extern "C" BOOL SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ  )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +  D3DVIEWPORT2 vdData;
 +  ULONG		rc;
 +  POINT		pt;
 +
 +  DPF(( DBG_FUNC, "SetViewportHAL();" ));
 +
 +  /* Make sure we have enough info. */
 +  if ( !pHAL || !pHAL->lpDDSPrimary || !pHAL->lpD3DDevice )
 +  {
 +    DPF(( DBG_CNTX_WARN, "SetViewport() -> NULL Pointer" ));
 +    return FALSE;
 +  }
 +
 +  /* TODO: this is just a temp fix to stop redundant changes. */
 +  if ( pRect &&
 +	  (pShared->rectV.left   == pRect->left)    &&
 +	  (pShared->rectV.right  == pRect->right)   &&
 +	  (pShared->rectV.top    == pRect->top)     &&
 +	  (pShared->rectV.bottom == pRect->bottom) )
 +  {
 +    DPF(( DBG_CNTX_WARN, "Redundant viewport" ));
 +    return TRUE;
 +  }
 +
 +  DPF(( DBG_CNTX_INFO, "Current Viewport:" ));
 +  DPF(( DBG_CNTX_INFO, "x: %d y: %d", pShared->rectV.left, pShared->rectV.top ));
 +  DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pShared->rectV.right-pShared->rectV.left), (pShared->rectV.bottom-pShared->rectV.top) ));
 +  DPF(( DBG_CNTX_INFO, "New Viewport:" ));
 +  DPF(( DBG_CNTX_INFO, "x: %d y: %d", pRect->left, pRect->top ));
 +  DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pRect->right-pRect->left), (pRect->bottom-pRect->top) ));
 +
 +  /* Update the current viewport rect if one is supplied. */
 +  if ( pRect )      
 +    memcpy( &pShared->rectV, pRect, sizeof(RECT) );
 +	 
 +  /* Build the request structure. */
 +  memset( &vdData, 0, sizeof(D3DVIEWPORT2) );
 +  vdData.dwSize   = sizeof(D3DVIEWPORT2);  
 +  vdData.dwX      = pShared->rectV.left;
 +  vdData.dwY      = pShared->rectV.top;
 +  vdData.dwWidth  = (pShared->rectV.right - pShared->rectV.left);
 +  vdData.dwHeight = (pShared->rectV.bottom - pShared->rectV.top);
 +
 +  if ( !vdData.dwWidth || !vdData.dwHeight )
 +  {
 +    GetClientRect( pShared->hwnd, &pShared->rectW );
 +    pt.x = pt.y = 0;
 +    ClientToScreen( pShared->hwnd, &pt );
 +    OffsetRect( &pShared->rectW, pt.x, pt.y);
 +    vdData.dwX      = pShared->rectW.left;
 +    vdData.dwY      = pShared->rectW.top;
 +    vdData.dwWidth  = (pShared->rectW.right - pShared->rectW.left);
 +    vdData.dwHeight = (pShared->rectW.bottom - pShared->rectW.top);
 +    memcpy( &pShared->rectV, &pShared->rectW, sizeof(RECT) );
 +  }
 +
 +  // The dvClipX, dvClipY, dvClipWidth, dvClipHeight, dvMinZ, 
 +  // and dvMaxZ members define the non-normalized post-perspective 
 +  // 3-D view volume which is visible to the viewer. In most cases, 
 +  // dvClipX is set to -1.0 and dvClipY is set to the inverse of 
 +  // the viewport's aspect ratio on the target surface, which can be 
 +  // calculated by dividing the dwHeight member by dwWidth. Similarly, 
 +  // the dvClipWidth member is typically 2.0 and dvClipHeight is set 
 +  // to twice the aspect ratio set in dwClipY. The dvMinZ and dvMaxZ 
 +  // are usually set to 0.0 and 1.0.
 +  vdData.dvClipX      = -1.0f;
 +  vdData.dvClipWidth  = 2.0f;
 +  vdData.dvClipY      = 1.0f;
 +  vdData.dvClipHeight = 2.0f;
 +  vdData.dvMaxZ       = maxZ;
 +  vdData.dvMinZ       = minZ;
 +
 +  DPF(( DBG_CNTX_INFO, "zMin: %f zMax: %f", minZ, maxZ ));
 +
 +  /*  I'm going to destroy the viewport everytime as when we size we will */
 +  /* have a new D3DDevice.  As this area doesn't need to be fast...       */
 +  if ( pHAL->lpViewport )
 +  {
 +    DPF(( DBG_CNTX_INFO, "DeleteViewport" ));
 +
 +    pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
 +    rc = pHAL->lpViewport->Release();
 +    pHAL->lpViewport = NULL;
 +  }
 +
 +  rc = pHAL->lpD3D3->CreateViewport( &pHAL->lpViewport, NULL );
 +  if ( rc != D3D_OK )
 +  {
 +    DPF(( DBG_CNTX_ERROR, "CreateViewport Failed" ));
 +    return FALSE;
 +  }
 +
 +  /* Update the device with the new viewport. */
 +  pHAL->lpD3DDevice->AddViewport( pHAL->lpViewport );
 +  pHAL->lpViewport->SetViewport2( &vdData );
 +  pHAL->lpD3DDevice->SetCurrentViewport( pHAL->lpViewport );
 +
 +  return TRUE; 
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +HRESULT WINAPI EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid )
 +{
 +  DDSURFACEDESC2 *pddsd2 = (DDSURFACEDESC2 *)pVoid;
 +
 +  DPF(( DBG_FUNC, "EnumSurfacesHook();" ));
 +
 +  if ( (lpDDSDesc->ddpfPixelFormat.dwFlags == pddsd2->ddpfPixelFormat.dwFlags) && (lpDDSDesc->ddsCaps.dwCaps == pddsd2->ddsCaps.dwCaps) )
 +  {
 +    /* Save the pixelformat now so that we know we have one. */
 +    memcpy( pddsd2, lpDDSDesc, sizeof(DDSURFACEDESC2) );
 +
 +    return D3DENUMRET_CANCEL;
 +  }
 +
 +  return D3DENUMRET_OK;
 +}
 +/*===========================================================================*/
 +/*  This is the callback proc to get a Z-Buffer.  Thats it.                  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +HRESULT CALLBACK  EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid )
 +{
 +  DDPIXELFORMAT  *pddpfChoice = (DDPIXELFORMAT *)pVoid;
 +
 +  DPF(( DBG_FUNC, "EnumZBufferHook();" ));
 +
 +  /* If this is ANY type of depth-buffer, stop. */
 +  if( pddpf->dwFlags == DDPF_ZBUFFER )
 +  {
 +    /* Save the pixelformat now so that we know we have one. */
 +    memcpy( pddpfChoice, pddpf, sizeof(DDPIXELFORMAT) );
 +
 +    /* I feel if the hardware supports this low then lets use it.  Could get ugly. */
 +    if( pddpf->dwZBufferBitDepth >= 8 )
 +    {
 +	 return D3DENUMRET_CANCEL;
 +    }
 +  }
 + 
 +   return D3DENUMRET_OK;
 +}
 +/*===========================================================================*/
 +/*  This function handles the callback for the D3DDevice enumeration.  Good  */
 +/* god who's idea was this?  The D3D wrapper has two variable related to what*/
 +/* kind of device we want and have.  First we have a Bool that is set if we  */
 +/* have allocated a HW device.  We always look for the HW device first.  The */
 +/* other variable is used to force SW.  If we have run into a case that we   */
 +/* want to fallback to SW then we set this.  We will fallback if we cannot   */
 +/* texture in video memory (among others).                                   */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +HRESULT CALLBACK  EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc,  void *pVoid )
 +{
 +  PMESAD3DHAL		pHAL = (PMESAD3DHAL)pVoid;
 +  LPD3DDEVICEDESC   pChoice = lpD3DHWDesc;
 +
 +  DPF(( DBG_FUNC, "EnumDeviceHook();" ));
 +
 +  /* Determine if which device description is valid. */
 +  if ( pChoice->dcmColorModel == 0 )
 +    pChoice = lpD3DHELDesc;
 +
 +  /* Make sure we always have a GUID. */
 +  memcpy( &pHAL->guid, lpGuid, sizeof(GUID) );
 +
 +  /* This controls whether we will except HW or not. */
 +  if ( pHAL->shared.bForceSW == TRUE )
 +  {
 +    return (pChoice == lpD3DHELDesc) ? D3DENUMRET_CANCEL : D3DENUMRET_OK;
 +  }
 +
 +  /* Always try for hardware. */
 +  if ( pChoice == lpD3DHWDesc )
 +  {
 +    return D3DENUMRET_CANCEL;
 +  }
 +
 +  return D3DENUMRET_OK;
 +}
 +/*===========================================================================*/
 +/*  This function will destroy any and all surfaces that this context has    */
 +/* allocated.  If there is a clipper object then it will also be destoryed as*/
 +/* it is part of the Primary Surface.                                        */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void DestroyAllSurfaces( PMESAD3DHAL pHAL )
 +{
 +  LONG	refCount;
 +
 +  DPF(( DBG_FUNC, "DestroyAllSurfaces();" ));
 +
 +  DX_RESTORE( pHAL->lpDDSPrimary );
 +  DX_RESTORE( pHAL->lpDDSRender );
 +  DX_RESTORE( pHAL->lpDDSZbuffer);
 +
 +  if ( pHAL->lpDDSRender )
 +  {
 +    pHAL->lpDDSRender->Unlock( NULL );
 +
 +    /* If this isn't a Flipable surface then we must clean up the render. */
 +    if ( pHAL->shared.bFlipable == FALSE)
 +    {
 +	 if ( pHAL->lpDDSZbuffer )
 +	 {
 +	   DPF(( DBG_CNTX_INFO, "Remove attached surfaces from RENDER" ));
 +	   pHAL->lpDDSRender->DeleteAttachedSurface( 0, NULL );
 +	 }
 +
 +	 DPF(( DBG_CNTX_INFO, "Release RENDER" ));
 +	 refCount = pHAL->lpDDSRender->Release();
 +	 pHAL->lpDDSRender = NULL;
 +    }
 +  }
 +
 +  if ( pHAL->lpDDSZbuffer )
 +  {
 +    DPF(( DBG_CNTX_INFO, "Release ZBuffer" ));
 +    pHAL->lpDDSZbuffer->Unlock( NULL );
 +    refCount = pHAL->lpDDSZbuffer->Release();
 +    pHAL->lpDDSZbuffer = NULL;
 +  }
 +
 +  if ( pHAL->lpClipper )
 +  {
 +    DPF(( DBG_CNTX_INFO, "Release Clipper" ));
 +    refCount = pHAL->lpClipper->Release();
 +    pHAL->lpClipper = NULL;
 +  }
 +
 +  if ( pHAL->lpDDSPrimary )
 +  {
 +    pHAL->lpDDSPrimary->Unlock( NULL );
 +
 +    DPF(( DBG_CNTX_INFO, "Release PRIMARY" ));
 +    refCount = pHAL->lpDDSPrimary->Release();
 +    pHAL->lpDDSPrimary = NULL;
 +  }
 +}
 +/*===========================================================================*/
 +/*  This function will destroy the current D3DDevice and any resources that  */
 +/* belong to it.                                                             */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void DestroyDevice( PMESAD3DHAL pHAL )
 +{
 +  LONG	refCount;
 +
 +  DPF(( DBG_FUNC, "DestroyDevice();" ));
 +
 +  /* Kill the D3D stuff if exists. */
 +  if ( pHAL->lpViewport )
 +  {
 +    DPF(( DBG_CNTX_INFO, "Delete Viewport" ));
 +    pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
 +
 +    DPF(( DBG_CNTX_INFO, "Release Viewport" ));
 +    refCount = pHAL->lpViewport->Release();
 +    pHAL->lpViewport = NULL;
 +  }
 +
 +  if ( pHAL->lpD3DDevice != NULL )
 +  {
 +    DPF(( DBG_CNTX_INFO, "Release D3DDevice" ));
 +    refCount = pHAL->lpD3DDevice->EndScene();  
 +    refCount = pHAL->lpD3DDevice->Release();
 +    pHAL->lpD3DDevice = NULL;
 +  }
 +}
 +/*===========================================================================*/
 +/*  This function will destroy the current D3DDevice and any resources that  */
 +/* belong to it.                                                             */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void DestroyInterfaces( PMESAD3DHAL pHAL )
 +{
 +  LONG	refCount;
 +
 +  DPF(( DBG_FUNC, "DestroyInterfaces();" ));
 +
 +  if ( pHAL->lpD3D3 != NULL )
 +  {
 +    DPF(( DBG_CNTX_INFO, "Release Direct3D3" ));
 +    refCount = pHAL->lpD3D3->Release();
 +    pHAL->lpD3D3 = NULL;
 +  }
 +
 +  if ( pHAL->lpDD4 != NULL )
 +  {
 +    DPF(( DBG_CNTX_INFO, "Release DDraw4" ));
 +    refCount = pHAL->lpDD4->Release();
 +    pHAL->lpDD4 = NULL;
 +  }
 +
 +  if ( pHAL->lpDD != NULL )
 +  {
 +    DPF(( DBG_CNTX_INFO, "Release DDraw" ));
 +    refCount = pHAL->lpDD->Release();
 +    pHAL->lpDD = NULL;
 +  }
 +}
 +/*===========================================================================*/
 +/*  This function will first send (not post) a message to the client window  */
 +/* that this context is using.  The client will respond by unbinding itself  */
 +/* and binding the 'default' context.  This allows the API to be supported   */
 +/* until the window can be destroyed.  Finally we post the quit message to   */
 +/* the client in hopes to end the application.                               */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void  FatalShutDown( PMESAD3DHAL pHAL )
 +{
 +  /* Whip this baby in too try and support the API until we die... */
 +  if ( pHAL )
 +    SendMessage( pHAL->shared.hwnd, UM_FATALSHUTDOWN, 0L, 0L );
 +
 +  /* Close the client application down. */
 +  PostQuitMessage( 0 );
 +}
 +
 diff --git a/src/mesa/drivers/d3d/D3DMESA.H b/src/mesa/drivers/d3d/D3DMESA.H new file mode 100644 index 0000000000..907f69ffb1 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DMESA.H @@ -0,0 +1,85 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#ifndef D3D_MESA_H
 +#define D3D_MESA_H
 +/*===========================================================================*/
 +/* Includes.                                                                 */
 +/*===========================================================================*/
 +#include <windows.h>
 +#include <ddraw.h>
 +#include <d3d.h>
 +#include "matrix.h"
 +#include "context.h"
 +#include "types.h"
 +#include "vb.h"
 +#include "D3DShared.h"
 +#include "Debug.h"
 +#include "NULLProcs.h"
 +/*===========================================================================*/
 +/* Macros.                                                                   */
 +/*===========================================================================*/
 +#define FLIP(h,y)                       (h-y)
 +/*===========================================================================*/
 +/* Magic numbers.                                                            */
 +/*===========================================================================*/
 +/*===========================================================================*/
 +/* Type defines.                                                             */
 +/*===========================================================================*/
 +struct __extensions__
 +{
 +   PROC  proc;
 +   char  *name;
 +};
 +
 +typedef GLbitfield   (*ClearPROC)( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
 +typedef void         (*WSpanRGBPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] );
 +typedef void         (*WSpanRGBAPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
 +typedef void         (*WSpanRGBAMonoPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] );
 +typedef void         (*WPixelsRGBAPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
 +typedef void         (*WPixelsRGBAMonoPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] );
 +typedef void         (*RSpanRGBAPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
 +typedef void         (*RPixelsRGBAPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
 +
 +typedef struct D3D_mesa_context 
 +{
 +  PMESAD3DSHARED        pShared;
 +
 +  GLcontext             *gl_ctx;       /* The core GL/Mesa context */
 +  GLvisual              *gl_visual;    /* Describes the buffers */
 +  GLframebuffer *gl_buffer;    /* Depth, stencil, accum, etc buffers */
 +
 +  HDC                   hdc;
 +  WNDPROC               hOldProc;
 +
 +  UCHAR                 rClear,         /* Current clear colors. */
 +		    gClear,
 +		    bClear,
 +		    aClear,
 +		    rCurrent,           /* Current rendering colors. */
 +		    gCurrent,
 +		    bCurrent,
 +		    aCurrent;
 +
 +   struct D3D_mesa_context *next;
 +
 +} D3DMESACONTEXT, *PD3DMESACONTEXT;
 +/*===========================================================================*/
 +/* Extern function prototypes.                                               */
 +/*===========================================================================*/
 +extern void gl_Viewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height );
 +/*===========================================================================*/
 +/* Global variables.                                                         */
 +/*===========================================================================*/
 +extern D3DTLVERTEX   D3DTLVertices[(VB_MAX*6)];
 +
 +#endif
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3DRaster.cpp b/src/mesa/drivers/d3d/D3DRaster.cpp new file mode 100644 index 0000000000..b87b3abd6d --- /dev/null +++ b/src/mesa/drivers/d3d/D3DRaster.cpp @@ -0,0 +1,214 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "D3DHAL.h"
 +/*===========================================================================*/
 +/*  This function clears the context bound to the supplied shared context.   */
 +/* The function takes the D3D flags D3DCLEAR_TARGET, D3DCLEAR_STENCIL and    */
 +/* D3DCLEAR_ZBUFFER.  Set bAll to TRUE for a full clear else supply the coord*/
 +/* of the rect to be cleared relative to the window.  The color is always a  */
 +/* 32bit value (RGBA).  Fill in the z-value and stencil if needed.           */
 +/*                                                                           */
 +/*  TODO: this can be redone to be called by Mesa directly.                  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void ClearHAL( PMESAD3DSHARED pShared, DWORD dwFlags, BOOL bAll, int x, int y, int cx, int cy, DWORD dwColor, float zv, DWORD dwStencil )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +  D3DRECT		d3dRect;
 +
 +#ifdef D3D_DEBUG
 +  HRESULT		rc;
 +
 +  DPF(( DBG_FUNC, "CleaHAL();" ));
 +
 +  /* Make sure we have enough info. */
 +  if ( (pHAL == NULL) || (pHAL->lpViewport == NULL) )
 +    return;
 +#endif
 +
 +  if ( bAll )
 +  {
 +    /* I assume my viewport is valid. */
 +    d3dRect.lX1 = pShared->rectV.left;
 +    d3dRect.lY1 = pShared->rectV.top;
 +    d3dRect.lX2 = pShared->rectV.right;
 +    d3dRect.lY2 = pShared->rectV.bottom;
 +  }
 +  else
 +  {
 +    d3dRect.lX1 = pShared->rectV.left + x;
 +    d3dRect.lY1 = pShared->rectV.top  + y;
 +    d3dRect.lX2 = d3dRect.lX1 + cx;
 +    d3dRect.lY2 = d3dRect.lY1 + cy;
 +  }
 +
 +#ifdef D3D_DEBUG
 +  rc = pHAL->lpViewport->Clear2( 1, &d3dRect, dwFlags, dwColor, zv, dwStencil );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "Clear2 ->", ErrorStringD3D(rc) );
 +  }
 +#else
 +  pHAL->lpViewport->Clear2( 1, &d3dRect, dwFlags, dwColor, zv, dwStencil );
 +#endif
 +}
 +/*===========================================================================*/
 +/*  Well this is the guts of it all.  Here we rasterize the primitives that  */
 +/* are in their final form.  OpenGL has done all the lighting, transfomations*/
 +/* and clipping at this point.                                               */
 +/*                                                                           */
 +/* TODO:  I'm not sure if I want to bother to check for errors on this call. */
 +/*       The overhead kills me...                                            */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void DrawPrimitiveHAL( PMESAD3DSHARED pShared, D3DPRIMITIVETYPE dptPrimitiveType, D3DTLVERTEX *pVertices, DWORD dwCount )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +
 +#ifdef D3D_DEBUG
 +  HRESULT		rc;      
 +
 +  DPF(( DBG_FUNC, "DrawPrimitveHAL();" ));
 +
 +  /* Make sure we have enough info. */
 +  if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
 +    return;
 +
 +  DPF(( DBG_PRIM_INFO, "DP( %d )", dwCount ));
 +
 +  rc = pHAL->lpD3DDevice->DrawPrimitive( dptPrimitiveType,
 +								 D3DFVF_TLVERTEX,
 +								 (LPVOID)pVertices,
 +								 dwCount, 
 +								 (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "DrawPrimitive ->", ErrorStringD3D(rc) );
 +  }
 +#else
 +  pHAL->lpD3DDevice->DrawPrimitive( dptPrimitiveType,
 +							 D3DFVF_TLVERTEX,
 +							 (LPVOID)pVertices,
 +							 dwCount, 
 +							 (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
 +#endif
 +}
 +/*===========================================================================*/
 +/*  This call will handle the swapping of the buffers.  Now I didn't bother  */
 +/* to support single buffered so this will be used for glFlush() as its all  */
 +/* the same.  So first we do an EndScene as we are always considered to be in*/
 +/* a BeginScene because when we leave we do a BeginScene.  Now note that when*/
 +/* the context is created in the first place we do a BeginScene also just to */
 +/* get things going.  The call will use either Flip/blt based on the type of */
 +/* surface was created for rendering.                                        */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void SwapBuffersHAL( PMESAD3DSHARED pShared )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +
 +#ifdef D3D_DEBUG
 +  HRESULT		rc;      
 +
 +  DPF(( DBG_FUNC, "SwapBuffersHAL();" ));
 +  DPF(( DBG_ALL_PROFILE, "=================SWAP===================" ));
 +
 +  /* Make sure we have enough info. */
 +  if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
 +    return;
 +
 +  /* Make sure we have enough info. */
 +  if ( pHAL->lpDDSPrimary != NULL )
 +  {
 +    rc = pHAL->lpD3DDevice->EndScene();   
 +    if ( FAILED(rc) )
 +    {
 +	 RIP( pHAL, "EndScene ->", ErrorStringD3D(rc) );
 +    }
 + 
 +    if ( pShared->bFlipable )
 +    {
 +	 DPF(( DBG_CNTX_PROFILE, "Swap->FLIP" ));
 +	 rc = pHAL->lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
 +    }
 +    else
 +    {
 +	 DPF(( DBG_CNTX_PROFILE, "Swap->Blt" ));
 +	 rc = pHAL->lpDDSPrimary->Blt( &pShared->rectW, pHAL->lpDDSRender, NULL, DDBLT_WAIT, NULL );
 +    }
 +    if ( FAILED(rc) )
 +    {
 +	 RIP( pHAL, "Blt (RENDER/PRIMARY) ->", ErrorStringD3D(rc) );
 +    }
 +
 +    rc = pHAL->lpD3DDevice->BeginScene(); 
 +    if ( FAILED(rc) )
 +    {
 +	 RIP( pHAL, "BeginScene ->", ErrorStringD3D(rc) );
 +    }
 +  }
 +#else
 +  pHAL->lpD3DDevice->EndScene();   
 +
 +  if ( pShared->bFlipable )
 +    pHAL->lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
 +  else
 +    pHAL->lpDDSPrimary->Blt( &pShared->rectW, pHAL->lpDDSRender, NULL, DDBLT_WAIT, NULL );
 +
 +  pHAL->lpD3DDevice->BeginScene(); 
 +
 +#endif
 +}
 +/*===========================================================================*/
 +/*  This function is a very thin wrapper for the D3D call 'SetRenderState'.  */
 +/* Using this function requires all the types to be defined by including the */
 +/* D3D header file.                                                          */
 +/*                                                                           */
 +/*  TODO:  would be much better to get ride of all these calls per VBRender. */
 +/*        I feel I should get this call into SetRenderStates() the RenderVB. */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void SetStateHAL( PMESAD3DSHARED pShared, DWORD dwType, DWORD dwState )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +
 +#ifdef D3D_DEBUG   
 +  HRESULT		rc;
 +
 +  DPF(( DBG_FUNC, "SetStateHAL();" ));
 +
 +  /* Make sure we have enough info. */
 +  if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
 +    return;
 +
 +  rc = pHAL->lpD3DDevice->SetRenderState( (D3DRENDERSTATETYPE)dwType, dwState );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "SetRenderState ->", ErrorStringD3D(rc) );
 +  }
 +
 +#else
 +  pHAL->lpD3DDevice->SetRenderState( (D3DRENDERSTATETYPE)dwType, dwState );
 +#endif
 +}
 +
 +
 +
 +
 +
 +
 +
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3DShared.h b/src/mesa/drivers/d3d/D3DShared.h new file mode 100644 index 0000000000..cc629e2111 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DShared.h @@ -0,0 +1,154 @@ +/*===========================================================================*/ +/*                                                                           */ +/* Mesa-3.0 DirectX 6 Driver                                                 */ +/*                                                                           */ +/* By Leigh McRae                                                            */ +/*                                                                           */ +/* http://www.altsoftware.com/                                               */ +/*                                                                           */ +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */ +/*===========================================================================*/ +#ifndef D3D_MESA_ALL_H +#define D3D_MESA_ALL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ +/* Includes.                                                                 */ +/*===========================================================================*/ +#include <stdio.h> +#include <string.h> +/*===========================================================================*/ +/* Magic numbers.                                                            */ +/*===========================================================================*/ +#define	TM_ACTION_LOAD      0x01 +#define 	TM_ACTION_BIND      0x02 +#define 	TM_ACTION_UPDATE  	0x04 + +#define	UM_FATALSHUTDOWN	(WM_USER+42) +/*===========================================================================*/ +/* Macros defines.                                                           */ +/*===========================================================================*/ +#define  ALLOC(cb)            malloc( (cb) ) +#define  FREE(p)              { free( (p) ); (p) = NULL; } +/*===========================================================================*/ +/* Type defines.                                                             */ +/*===========================================================================*/ +typedef struct _pixel_convert +{ +  int	cb,			/* Count in bytes of one pixel. */ +          rShift,		/* Shift count that postions each componet. */ +	     gShift,		 +	     bShift,		 +          aShift;		 +  float   rScale,		/* Value that scales a color that ranges 0.0 -> 1.0 */ +          gScale,		/* to this pixel format.                            */ +          bScale, +          aScale; +  DWORD   dwRMask,		/* Color mask per component. */ +	     dwGMask, +          dwBMask, +          dwAMask; + +} PIXELINFO, *PPIXELINFO; + + +typedef struct _d3d_shared_info +{ +  HWND		hwnd; +  BOOL    	bWindow, +               bFlipable, +               bForceSW, +               bHardware; +  RECT    	rectW,			/* Window size and postion in screen space. */ +               rectV;			/* Viewport size and postion. */ +  DWORD		dwWidth,			/* Current render size for quick checks. */ +               dwHeight; + +  PIXELINFO	pixel;			 +  DWORD		dwSrcBlendCaps[14],	/* See D3DCAPS.CPP */ +               dwDestBlendCaps[14], +               dwTexFunc[4]; + +} MESAD3DSHARED, *PMESAD3DSHARED; + +typedef struct _render_options +{ +  BOOL	bForceSoftware,		/* TODO: Add user switches. */ +	     bStretchtoPrimary; + +} USER_CTRL, *PUSER_CRTL; + +enum { s_zero = 0,				 +	  s_one,  +	  s_dst_color,  +	  s_one_minus_dst_color,  +	  s_src_alpha,  +	  s_one_minus_src_alpha,  +	  s_dst_alpha, +	  s_one_minus_dst_alpha, +	  s_src_alpha_saturate,  +	  s_constant_color,  +	  s_one_minus_constant_color,  +	  s_constant_alpha,  +	  s_one_minus_constant_alpha }; + +enum { d_zero = 0,  +	  d_one,  +	  d_src_color,  +	  d_one_minus_src_color,  +	  d_src_alpha,  +	  d_one_minus_src_alpha,  +	  d_dst_alpha, +	  d_one_minus_dst_alpha, +	  d_constant_color, +	  d_one_minus_constant_color, +	  d_constant_alpha, +	  d_one_minus_constant_alpha }; + +enum { d3dtblend_decal = 0, +	  d3dtblend_decalalpha, +	  d3dtblend_modulate, +	  d3dtblend_modulatealpha }; + +/*===========================================================================*/ +/* Function prototypes.                                                      */ +/*===========================================================================*/ +PMESAD3DSHARED	InitHAL( HWND hwnd ); +void 	   	TermHAL( PMESAD3DSHARED pShared ); +BOOL 	   	CreateHAL( PMESAD3DSHARED pShared ); +BOOL 	   	SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ  ); + +void ClearHAL( PMESAD3DSHARED pShared, DWORD dwFlags, BOOL bAll, int x, int y, int cx, int cy, DWORD dwColor, float zv, DWORD dwStencil ); +void SetStateHAL( PMESAD3DSHARED pShared, DWORD dwType, DWORD dwState ); +void DrawPrimitiveHAL( PMESAD3DSHARED pShared, D3DPRIMITIVETYPE dptPrimitiveType, D3DTLVERTEX *pVertices, DWORD dwCount ); + +void 		SwapBuffersHAL( PMESAD3DSHARED pShared ); +DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack ); +void 		UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack ); +void 		UpdateScreenPosHAL( PMESAD3DSHARED pShared ); +void			GetPixelInfoHAL( PMESAD3DSHARED pShared, PPIXELINFO pPixel ); +BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags, RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels ); +void DisableTMgrHAL( PMESAD3DSHARED pShared ); + + +int  SaveDIBitmap( char *filename, BITMAPINFO *info, void *bits ); +int	ARGB_SaveBitmap( char *filename, int width, int height, unsigned char *pARGB ); +int  BGRA_SaveBitmap( char *filename, int width, int height, unsigned char *pBGRA ); +int  BGR_SaveBitmap( char *filename, int width, int height, unsigned char *pBGR ); +/*===========================================================================*/ +/* Global variables.                                                         */ +/*===========================================================================*/ +extern float	g_DepthScale,	/* Mesa needs to scale Z in SW.  The HAL */ +               g_MaxDepth;    /* doesn't but I wanted SW still to work.*/ + +#ifdef __cplusplus +} +#endif + +#endif + + + diff --git a/src/mesa/drivers/d3d/D3DTEXT.CPP b/src/mesa/drivers/d3d/D3DTEXT.CPP new file mode 100644 index 0000000000..7321eeb7c4 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DTEXT.CPP @@ -0,0 +1,577 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "d3dText.h"
 +
 +/*=============================================================================
 +
 +       1     
 +     ------
 +    |      | 
 +  6 |      | 2
 +    |  7   |
 +     ------  
 +    |      |
 +  5 |      | 3
 +    |      |
 +     ------ 
 +       4 
 +
 +	    TL_0		TR_0
 +TLL		TL_1		TR_1	TRR
 +
 +MLL_0   ML_0		MR_0	MRR_0
 +MLL_1   ML_1		MR_1	MRR_1
 +
 +BLL		BL_0		BR_0	BRR
 +        BL_1		BR_1
 +
 +=============================================================================*/
 +
 +#define TLL		0
 +#define TRR		1
 +#define TL_0	2
 +#define TL_1	3
 +#define TR_0	4
 +#define TR_1	5
 +
 +#define	MLL_0	6
 +#define	MLL_1	7
 +#define	MRR_0	8
 +#define	MRR_1	9
 +
 +#define	ML_0	10
 +#define	ML_1	11
 +#define	MR_0	12
 +#define	MR_1	13
 +
 +#define	BL_0	14
 +#define	BL_1	15
 +#define	BR_0	16
 +#define	BR_1	17
 +#define	BLL		18
 +#define	BRR		19
 +
 +#define	BIT1	0x00000001
 +#define	BIT2	0x00000002
 +#define	BIT3	0x00000004
 +#define	BIT4	0x00000008
 +#define	BIT5	0x00000010
 +#define	BIT6	0x00000020
 +#define	BIT7	0x00000040
 +
 +#define TOP		BIT4
 +#define MIDDLE		BIT7
 +#define BOTTOM		BIT1
 +#define TLEFT 		BIT5
 +#define BLEFT   	BIT6
 +#define LEFT		(TLEFT|BLEFT)
 +#define TRIGHT		BIT3
 +#define BRIGHT		BIT2
 +#define RIGHT		(TRIGHT|BRIGHT)
 +#define ALL		0xFFFFFFFF
 +
 +/*===========================================================================*/
 +/*  This is the static array that will map the ASCII value of the character  */
 +/* being draw to the bit mask that will be scan converted to the LED display.*/
 +/*===========================================================================*/
 +DWORD	textBitMasks[] = 
 +{
 +  0xFFFFFFFF, // 000
 +  0xFFFFFFFF, // 001
 +  0xFFFFFFFF, // 002
 +  0xFFFFFFFF, // 003  
 +  0xFFFFFFFF, // 004
 +  0xFFFFFFFF, // 005
 +  0xFFFFFFFF, // 006
 +  0xFFFFFFFF, // 007  
 +  0xFFFFFFFF, // 008
 +  0xFFFFFFFF, // 009
 +  0xFFFFFFFF, // 010
 +  0xFFFFFFFF, // 011
 +  0xFFFFFFFF, // 012
 +  0xFFFFFFFF, // 013
 +  0xFFFFFFFF, // 014
 +  0xFFFFFFFF, // 015
 +  0xFFFFFFFF, // 016
 +  0xFFFFFFFF, // 017
 +  0xFFFFFFFF, // 018
 +  0xFFFFFFFF, // 019
 +  0xFFFFFFFF, // 020
 +  0xFFFFFFFF, // 021
 +  0xFFFFFFFF, // 022
 +  0xFFFFFFFF, // 023 
 +  0xFFFFFFFF, // 024
 +  0xFFFFFFFF, // 025
 +  0xFFFFFFFF, // 026
 +  0xFFFFFFFF, // 027
 +  0xFFFFFFFF, // 028
 +  0xFFFFFFFF, // 029
 +  0xFFFFFFFF, // 030
 +  0XFFFFFFFF, // 031 
 +  0x00000000, // 032 'SPC'
 +  0xFFFFFFFF, // 033
 +  0xFFFFFFFF, // 034
 +  0xFFFFFFFF, // 035
 +  0xFFFFFFFF, // 036
 +  0xFFFFFFFF, // 037
 +  0xFFFFFFFF, // 038
 +  0xFFFFFFFF, // 039
 +  0xFFFFFFFF, // 040
 +  0xFFFFFFFF, // 041
 +  0xFFFFFFFF, // 042
 +  0xFFFFFFFF, // 043
 +  0xFFFFFFFF, // 044
 +  0xFFFFFFFF, // 045
 +  0xFFFFFFFF, // 046
 +  0xFFFFFFFF, // 047 
 +  (ALL &~ MIDDLE), 			// 048	'0'
 +  (RIGHT),     				// 049	'1'
 +  (ALL &~ TLEFT &~ BRIGHT), // 050	'2'
 +  (ALL &~ LEFT), 			// 051	'3'
 +  (TLEFT | MIDDLE | RIGHT), // 052	'4'
 +  (ALL &~ TRIGHT &~ BLEFT), // 053	'5'
 +  (ALL &~ TRIGHT), 			// 054	'6'
 +  (TOP | RIGHT), 			// 055	'7'
 +  (ALL), 					// 056	'8'
 +  (ALL &~ BOTTOM &~ BLEFT), // 057	'9'
 +  0xFFFFFFFF, // 058
 +  0xFFFFFFFF, // 059
 +  0xFFFFFFFF, // 060
 +  0XFFFFFFFF, // 061
 +  0xFFFFFFFF, // 062
 +  0xFFFFFFFF, // 063
 +  0xFFFFFFFF, // 064
 +  (ALL &~ BOTTOM),			// 065	'A'
 +  (ALL), 					// 066	'B'
 +  (TOP | LEFT | BOTTOM), 	// 067	'C'
 +  (ALL &~ MIDDLE), 			// 068	'D'
 +  (ALL &~ RIGHT), 			// 069	'E'
 +  (LEFT | TOP | MIDDLE), 	// 070	'F'
 +  0x00000000,  				// 071	'G'
 +  (ALL &~ TOP &~ BOTTOM), 	// 072	'H'
 +  (RIGHT), 					// 073	'I'
 +  (RIGHT | BOTTOM),			// 074	'J'
 +  0x00000000,  				// 075	'K'
 +  (LEFT | BOTTOM),			// 076	'L'
 +  0x00000000, 				// 088	'M'
 +  0x00000000, 				// 089	'N'
 +  (ALL &~ MIDDLE),  		// 090	'O'
 +  (ALL &~ BRIGHT &~ BOTTOM),// 091	'P'
 +  0x00000000, 				// 092	'Q'
 +  0x00000000,				// 093	'R'
 +  (ALL &~ TRIGHT &~ BLEFT),	// 094	'S'
 +  0X00000000, 				// 095	'T'
 +  (LEFT | RIGHT | BOTTOM),  // 096	'U'
 +  0x00000000, 				// 097	'V'
 +  0x00000000, 				// 098	'W'
 +  0x00000000, 				// 099	'X'
 +  0x00000000,  				// 1000	'Z'
 +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,  // 100 
 +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,  // 104 
 +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,  // 108 
 +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,  // 112 
 +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,  // 116 
 +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,  // 120 
 +  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF   // 124 
 +};
 +
 +#define	CT	1.0f
 +#define	CX	7.0f
 +#define	CY	13.0f
 +#define CM	((CY-(CT*3.0f))/2.0f)
 +
 +float lCoords[][2] = 
 +{
 +  /* Top outsides. */
 +  { 0,  		(CY-CT) },		
 +  { CX, 		(CY-CT) },
 +
 +  /* Top Line. */
 +  { CT, 		CY },
 +  { CT, 		(CY-CT) },
 +  { (CX-CT), 	CY },
 +  { (CX-CT), 	(CY-CT) },
 +
 +  /* Middle outsides. */
 +  { 0.0f,		(CT+CM+CT) },
 +  { 0.0f,		(CT+CM) },
 +  { CX,			(CT+CM+CT) },
 +  { CX,			(CT+CM) },
 +
 +  /* Middle Line. */
 +  { CT,			(CT+CM+CT) },	
 +  { CT,			(CT+CM)	},	
 +  { (CX-CT),	(CT+CM+CT) },
 +  { (CX-CT),	(CT+CM) },
 +
 +  /* Bottom line. */
 +  { CT,			CT },
 +  { CT,			0.0f },
 +  { (CX-CT),	CT },
 +  { (CX-CT),	0.0f },
 +
 +  /* Bottom outsides. */
 +  { 0.0f,		CT},
 +  { CX,			CT }
 +};
 +
 +static int	ConvertCharacter( char *c, int cIndex,  PD3DFONTMETRICS pfntMetrics );
 +
 +D3DTLVERTEX TextVertices[MAX_VERTICES];
 +/*===========================================================================*/
 +/*  When we attach I will zero out the whole D3D vertex buffer I'm using for */
 +/* the text.  This way I don't need to set all the redundant values.  I also */
 +/* set all the oow values to 1 as I will be doing direct rendering.          */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +extern "C" BOOL InitD3DText( void )
 +{
 +  int	index;
 +
 +  /* Set the D3D Vertex Buffer up once so we don't do redundant changes. */
 +  memset( &TextVertices[0], 0, sizeof(TextVertices) );
 +  for( index = 0; index < MAX_VERTICES; index++ )
 +	TextVertices[index].rhw	= D3DVAL( 1.0 );
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function takes a single character and draw it using the supplied    */
 +/* fontmetrics structure.                                                    */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void d3dTextDrawString( char *pszString, int x, int y, PD3DFONTMETRICS pfntMetrics )
 +{
 +  int	cIndex,
 +	     nIndex,
 +	     index;
 +  float	cWidth = CX,
 +	     cHeight = CY;
 +
 +  /*  Find the max width/height of a character and add the spacing so */
 +  /* that we can use this value to calculate the x,y of the character.*/
 +  cWidth  = (cWidth  * pfntMetrics->fntXScale)  + pfntMetrics->fntXSpacing;
 +  cHeight = (cHeight * pfntMetrics->fntYScale) + pfntMetrics->fntYSpacing;
 +
 +  /* Walk the string.  This must be NULL terminated. */
 +  for( cIndex = 0, nIndex = 0; *pszString; pszString++, cIndex = nIndex, x++ )
 +  {
 +	/* Convert the character and get the index into the text vertex buffer. */
 +	nIndex = ConvertCharacter( &pszString[0], cIndex, pfntMetrics );
 +	if ( (nIndex - cIndex) > 2 )
 +    {
 +	  /* Modify the text vertex buffer based on the fntMetrics structure. */
 +	  for( index = cIndex; index < nIndex; index++ )
 +	  {
 +		/* Scale the character. */
 +		TextVertices[index].sx	*= pfntMetrics->fntXScale;
 +		TextVertices[index].sy   *= pfntMetrics->fntYScale;
 +		
 +		/* Move the character. */
 +		TextVertices[index].sx	+= (cWidth*x);
 +		TextVertices[index].sy   += (cHeight*y);
 +
 +		/* Set the color. */
 +		TextVertices[index].color = pfntMetrics->dwColor;
 +	  }
 +	}
 +  }
 +
 +  if ( nIndex < 3 )
 +	return;
 +
 +  /* Set the states that slim things down. */
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, 			D3DCULL_NONE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, 			D3DFILL_SOLID );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, 			FALSE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE , 		FALSE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, 	FALSE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, 	FALSE );
 +
 +  /* Blast them baby... */
 +  pfntMetrics->lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
 +										   D3DFVF_TLVERTEX,
 +										   (LPVOID)&TextVertices[0],
 +										   nIndex, 
 +										   (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
 +}
 +/*===========================================================================*/
 +/*  This function takes a single character and draw it directly to the screen*/
 +/* unsing the supplied fntMetrics structure.  The character will be drawn at */
 +/* the supplied x,y.  The x,y position is relative to the top left and uses  */
 +/* the spacing in the fntMetrics structure.                                  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void d3dTextDrawCharacter( char *c, int x, int y, PD3DFONTMETRICS pfntMetrics )
 +{
 +  int	cIndex = 0,
 +	    index;
 +  float	cWidth = CX,
 +	    cHeight = CY;
 +
 +  /* Convert the character and get the index into the text vertex buffer. */
 +  cIndex = ConvertCharacter( c, 0, pfntMetrics );
 +  if ( cIndex < 3 )
 +	return;
 +
 +  /*  Find the max width/height of a character and add the spacing so */
 +  /* that we can use this value to calculate the x,y of the character.*/
 +  cWidth  = (cWidth  * pfntMetrics->fntXScale)  + pfntMetrics->fntXSpacing;
 +  cHeight = (cHeight * pfntMetrics->fntYScale) + pfntMetrics->fntYSpacing;
 +
 +  /* Modify the text vertex buffer based on the fntMetrics structure. */
 +  for( index = 0; index < cIndex; index++ )
 +  {
 +	/* Scale the character. */
 +	TextVertices[index].sx	*= pfntMetrics->fntXScale;
 +	TextVertices[index].sy   *= pfntMetrics->fntYScale;
 +
 +	/* Move the character. */
 +	TextVertices[index].sx	+= (cWidth*x);
 +	TextVertices[index].sy   += (cHeight*y);
 +
 +	/* Set the color. */
 +	TextVertices[index].color = pfntMetrics->dwColor;
 +  }
 + 
 +
 +  /* Set the states that slim things down. */
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, 			D3DCULL_NONE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, 			D3DFILL_SOLID );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, 			FALSE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE , 		FALSE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, 	FALSE );
 +  pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, 	FALSE );
 +
 +  /* Blast them baby... */
 +  pfntMetrics->lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
 +										   D3DFVF_TLVERTEX,
 +										   (LPVOID)&TextVertices[0],
 +										   cIndex, 
 +										   (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
 +}
 +/*===========================================================================*/
 +/*  This function takes a single character and draw it using the supplied    */
 +/* fontmetrics structure.                                                    */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static int	ConvertCharacter( char *c, int cIndex,  PD3DFONTMETRICS pfntMetrics )
 +{
 +  DWORD	asciiChar = (int)(*c);
 +
 +  /* Handle the TOP line. */
 +  if ( textBitMasks[asciiChar] & BIT1 )
 +  { 
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TL_0][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_0][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TR_0][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_0][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TR_1][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TR_1][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TL_1][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_1][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TL_0][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_0][1] );
 +  }
 +
 +  /* Handle the TOP/BOTTOM RIGHT lines. */
 +  //  if ( textBitMasks[index] & (BIT2|BIT3) )
 +  if ( 1 == 0 )
 +  {
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TR_1][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TRR][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TRR][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[BRR][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[BRR][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[BRR][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[BRR][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[BR_0][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_0][1] );
 +    TextVertices[cIndex].sx	= D3DVAL( lCoords[TR_1][0] );
 +    TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
 +  }
 +  else 
 +  {
 +	if ( textBitMasks[asciiChar] & BIT2 )
 +	{
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[TR_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[TR_1][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[TRR][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[TRR][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MRR_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MRR_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MRR_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MRR_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MR_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MR_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[TR_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[TR_1][1] );
 +	}
 +	if ( textBitMasks[asciiChar] & BIT3 )
 +	{
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MR_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MR_1][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MRR_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MRR_1][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[BRR][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[BRR][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[BRR][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[BRR][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[BR_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[BR_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MR_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MR_1][1] );
 +	}
 +  }
 +
 +  /* Handle the TOP/BOTTOM LEFT lines. */
 +  //  if ( textBitMasks[asciiChar] & (BIT5|BIT6) )
 +  if ( 1 == 0 )
 +  {
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[TLL][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[TLL][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[TL_1][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_1][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BL_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BL_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BLL][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BLL][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[TLL][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[TLL][1] );
 +  }
 +  else 
 +  {
 +	if ( textBitMasks[asciiChar] & BIT5 )
 +	{
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MLL_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MLL_1][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[ML_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[ML_1][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[BL_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[BL_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[BL_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[BL_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[BLL][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[BLL][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MLL_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MLL_1][1] );
 +	}
 +	if ( textBitMasks[asciiChar] & BIT6 )
 +	{
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[TLL][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[TLL][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[TL_1][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[TL_1][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[ML_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[ML_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[ML_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[ML_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[MLL_0][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[MLL_0][1] );
 +	  TextVertices[cIndex].sx	= D3DVAL( lCoords[TLL][0] );
 +	  TextVertices[cIndex++].sy	= D3DVAL( lCoords[TLL][1] );
 +	}
 +  }
 +
 +  /* Handle the MIDDLE line. */
 +  if ( textBitMasks[asciiChar] & BIT7 )
 +  {
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[ML_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_0][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[MR_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_0][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[MR_1][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_1][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[MR_1][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_1][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[ML_1][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_1][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[ML_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_0][1] );
 +  }
 +
 +  /* Handle the BOTTOM line. */
 +  if ( textBitMasks[asciiChar] & BIT4 )
 +  {
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BL_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BR_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_0][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BR_1][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_1][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BR_1][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_1][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BL_1][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_1][1] );
 +	TextVertices[cIndex].sx	= D3DVAL( lCoords[BL_0][0] );
 +	TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
 +  }
 +  
 +  return cIndex;
 +}
 +
 +#undef CM
 +#undef CY
 +#undef CX
 +#undef CT
 +
 +#undef TLL
 +#undef TRR
 +#undef TL_0
 +#undef TL_1
 +#undef TR_0
 +#undef TR_1
 +
 +#undef	MLL_0
 +#undef	MLL_1
 +#undef	MRR_0
 +#undef	MRR_1
 +
 +#undef	ML_0
 +#undef	ML_1
 +#undef	MR_0
 +#undef	MR_1
 +
 +#undef	BL_0
 +#undef	BL_1
 +#undef	BR_0
 +#undef	BR_1
 +#undef	BLL
 +#undef	BRR
 +
 +#undef	BIT1
 +#undef	BIT2
 +#undef	BIT3
 +#undef	BIT4
 +#undef	BIT5
 +#undef	BIT6
 +#undef	BIT7
 +
 +#undef TOP
 +#undef MIDDLE
 +#undef BOTTOM
 +#undef TLEFT
 +#undef BLEFT
 +#undef LEFT
 +#undef TRIGHT
 +#undef BRIGHT
 +#undef RIGHT
 +#undef ALL
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.cpp b/src/mesa/drivers/d3d/D3DTextureMgr.cpp new file mode 100644 index 0000000000..9375e51e32 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DTextureMgr.cpp @@ -0,0 +1,948 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "D3DHAL.h"
 +/*===========================================================================*/
 +/* Local function prototypes.                                                */
 +/*===========================================================================*/
 +static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels );
 +static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj );
 +static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
 +static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
 +HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext );
 +/*===========================================================================*/
 +/*  This function will simply set the top of stack to NULL.  I only used it  */
 +/* just incase I want to add something later.                                */
 +/*===========================================================================*/
 +/* RETURN: TRUE.                                                             */
 +/*===========================================================================*/
 +BOOL InitTMgrHAL( PMESAD3DHAL pHAL )
 +{
 +  DPF(( DBG_FUNC, "InitTMgrHAL();" ));
 +
 +  /* Be clean my friend. */
 +  pHAL->pTMList = NULL;
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function will walk the Texture Managers linked list and destroy all */
 +/* surfaces (SYSTEM/VIDEO).  The texture objects themselves also will be     */
 +/* freed.                                                                    */
 +/*  NOTE: this is per/context.                                               */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void TermTMgrHAL( PMESAD3DHAL pHAL )
 +{
 +  DPF(( DBG_FUNC, "TermTMgrHAL();" ));
 +
 +  if ( pHAL && pHAL->pTMList )
 +  {
 +    /* Destroy the surface and remove the TMO from the stack. */
 +    while( DestroyTextureObject(pHAL,NULL) );
 +
 +    /* Be clean my friend. */
 +    pHAL->pTMList = NULL;
 +  }
 +}
 +/*===========================================================================*/
 +/*  This function is a HACK as I don't know how I can disable a texture with-*/
 +/* out booting it out.  Is there know state change?                          */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void DisableTMgrHAL( PMESAD3DSHARED pShared )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +
 +  DPF(( DBG_FUNC, "DisableTMgrHAL();" ));
 +
 +  /* Check too see that we have a valid context. */
 +  if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL)  ) 
 +  {
 +    DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
 +    return;
 +  }
 +
 +  // TODO: This is a hack to shut off textures.
 +  pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +}
 +/*===========================================================================*/
 +/*  This function is the only entry into the TextureManager that Mesa/wgl    */
 +/* will see.  It uses a dwAction to specify what we are doing.  I did this as*/
 +/* depending on the cards resources the action taken can change.             */
 +/*  When this function is called we will always search the Texture Managers  */
 +/* linked list (per context remember) and try and find a structure that has  */
 +/* the same dwName.  If we have a match we pull it out of the list and put it*/
 +/* at the top of the list (TOL).  If we don't find one then we create a struc*/
 +/* and put it a TOL.  This TOL idea makes for some caching as we will always */
 +/* destroy Texture Surfaces from the bottom up...                            */
 +/*  All texture objects at this point will create a texture surface in System*/
 +/* memory (SMEM).  Then we will copy the Mesa texture into the surface using */
 +/* the 'pixel' struc to get the translation info.  So now this means that all*/
 +/* textures that Mesa gives me I will have a Surface with a copy.  If Mesa   */
 +/* changes the texture the I update the surface in (SMEM).                   */
 +/*  Now we have a texture struc and a Texture Surface in SMEM.  At this point*/
 +/* we create another surface on the card (VMEM).  Finally we blt from the    */
 +/* SMEM to the VMEM and set the texture as current.  Why do I need two? First*/
 +/* this solves square textures.  If the cards CAPS is square textures only   */
 +/* then I change the dimensions of the VMEM surface and the blt solves it for*/
 +/* me.  Second it saves me from filling D3D textures over and over if the    */
 +/* card needs to be creating and destroying surfaces because of low memory.  */
 +/*  The surface in SMEM is expected to work always.  When a surface has to be*/
 +/* created in VMEM then we put it in a loop that tries to create the surface.*/
 +/* If we create the surface ok then we brake from the loop.  If we fail then */
 +/* we will call 'FreeTextureMemory' that will return TRUE/FALSE as to whether*/
 +/* memory was freed.  If memory was freed then we can try again. If no memory*/
 +/* was freed then it just can't fit.                                         */
 +/*  'FreeTextureMemory' will find the end of the list and start freeing VMEM */
 +/* (never SMEM) surfaces that are not locked.                                */
 +/*  BIND - when we bind and there is a texture struct with a texture surface */
 +/* in VMEM then we just make it current.  If we have a struct and a surface  */
 +/* in SMEM but no VMEM surface then we create the surface in VMEM and blt    */
 +/* from the SMEM surface.  If we have nothing its just like a creation...    */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +extern "C" BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags, 
 +						 RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels )
 +{
 +  PMESAD3DHAL		pHAL = (PMESAD3DHAL)pShared;
 +  PTM_OBJECT     	pTMObj,
 +                    pTemp;
 +  DDSURFACEDESC2 	ddsd2;
 +  HRESULT        	rc;
 +
 +
 +  DPF(( DBG_FUNC, "CreateTMgrHAL();" ));
 +
 +  DPF(( DBG_TXT_INFO, "Texture:" ));
 +  DPF(( DBG_TXT_INFO, "cx: %d cy: %d", dwWidth, dwHeight ));
 +  DPF(( DBG_TXT_INFO, "Rect:" ));
 +  if ( rectDirty )
 +  {
 +    DPF(( DBG_TXT_INFO, "x0: %d y0: %d", rectDirty->left, rectDirty->top ));
 +    DPF(( DBG_TXT_INFO, "x1: %d y1: %d", rectDirty->right, rectDirty->bottom ));
 +  }
 +
 +  /* Check too see that we have a valid context. */
 +  if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL)  ) 
 +  {
 +    DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
 +    return FALSE;
 +  }
 +
 +  /*=================================================*/
 +  /* See if we can find this texture object by name. */
 +  /*=================================================*/
 +  for( pTMObj = pHAL->pTMList; pTMObj && (pTMObj->dwName != dwName); pTMObj = pTMObj->next );
 +
 +  /*=========================================================*/
 +  /* Allocate a new object if we didn't get a matching name. */
 +  /*=========================================================*/
 +  if ( pTMObj == NULL )
 +  {
 +    pTMObj = (PTM_OBJECT)ALLOC( sizeof(TM_OBJECT) );
 +    if ( pTMObj == NULL )
 +	 return FALSE;
 +    memset( pTMObj, 0, sizeof(TM_OBJECT) );
 +
 +    /* Put the object at the beginning of the list. */
 +    pTMObj->next = pHAL->pTMList;
 +    if ( pTMObj->next )
 +    {
 +	 pTemp = pTMObj->next;
 +	 pTemp->prev = pTMObj;
 +    }
 +    pHAL->pTMList = pTMObj;
 +  }
 +  else
 +  {
 +    /*===============================================================*/
 +    /* Make some caching happen by pulling this object to the front. */ 
 +    /*===============================================================*/
 +    if ( pHAL->pTMList != pTMObj )
 +    {
 +	 /* Pull the object out of the list. */
 +	 if ( pTMObj->prev )
 +	 {
 +	   pTemp = pTMObj->prev;
 +	   pTemp->next = pTMObj->next;
 +	 }
 +	 if ( pTMObj->next )
 +      {
 +	   pTemp = pTMObj->next;
 +	   pTemp->prev = pTMObj->prev;
 +	 }
 +
 +	 pTMObj->prev = NULL;
 +	 pTMObj->next = NULL;
 +
 +	 /* Put the object at the front of the list. */
 +	 pTMObj->next = pHAL->pTMList;
 +	 if ( pTMObj->next )
 +      {
 +	   pTemp = pTMObj->next;
 +	   pTemp->prev = pTMObj;
 +	 }
 +	 pHAL->pTMList = pTMObj;
 +    }
 +  }
 +
 +  /*========================================================*/
 +  /* If we are doing BIND and the texture is in VID memory. */
 +  /*========================================================*/
 +  if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_Video  )
 +  {
 +    DPF(( DBG_TXT_PROFILE, "Cache HIT (%d)", dwName ));
 +	   
 +    /* Make this the current texture. */
 +    rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
 +    if ( FAILED(rc) )
 +    {
 +	 DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
 +	 pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +	 return FALSE;
 +    }	
 +
 +    return TRUE;
 +  }	
 +
 +  /*=================================================================*/
 +  /* If we are doing BIND and the texture is at least in SYS memory. */
 +  /*=================================================================*/
 +  if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_System  )
 +  {
 +    DPF(( DBG_TXT_PROFILE, "Cache MISS (%d)", dwName ));
 +
 +    /* Create the texture on the card. */
 +    rc = LoadTextureInVideo( pHAL, pTMObj );
 +    if ( rc == FALSE )
 +	 return FALSE;
 +	   
 +    /* Make this the current texture. */
 +    rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
 +    if ( FAILED(rc) )
 +    {
 +	 DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
 +	 pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +	 return FALSE;
 +    }	
 +
 +    return TRUE;
 +  }	
 +
 +  /*=========================================================*/
 +  /* If we are doing UPDATE then try in VID first for speed. */
 +  /*=========================================================*/
 +  if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_Video &&
 +	  !(pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) )
 +  {
 +    DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
 +
 +    /* Update the texture on the card. */
 +    UpdateTexture( pTMObj, TRUE, rectDirty, (UCHAR *)pPixels );
 +
 +    /* We updated the texture in VID so kill the SYS so we know its dirty. */
 +    if ( pTMObj->lpDDS_System )
 +    {
 +	 DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
 +	 DX_RESTORE( pTMObj->lpDDS_System );
 +	 pTMObj->lpDDS_System->Release();
 +	 pTMObj->lpDDS_System = NULL;
 +    }
 +
 +    /* Make this the current texture. */
 +    rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
 +    if ( FAILED(rc) )
 +    {
 +	 DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
 +	 pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +	 return FALSE;
 +    }	
 +
 +    return TRUE;
 +  }
 +
 +  /*===========================================================*/
 +  /* If we are doing UPDATE then try in SYS still gives speed. */
 +  /*===========================================================*/
 +  if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_System )
 +  {
 +    DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
 +
 +    /* Update the texture in SYS. */
 +    UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
 +
 +    /* We updated the SYS texture only so now blt to the VID. */
 +    rc = LoadTextureInVideo( pHAL, pTMObj );
 +    if ( rc == FALSE )
 +	 return FALSE;
 +
 +    /* Make this the current texture. */
 +    rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
 +    if ( FAILED(rc) )
 +    {
 +	 DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
 +	 pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +	 return FALSE;
 +    }	
 +
 +    return TRUE;
 +  }
 +
 +  /*  At this point we have a valid Texture Manager Object with updated */
 +  /* links.  We now need to create or update a texture surface that is  */
 +  /* in system memory.  Every texture has a copy in system so we can use*/
 +  /* blt to solve problems with textures allocated on the card (square  */
 +  /* only textures, pixelformats...).                                   */
 +  
 +  // TODO: make support for update also.  Dirty rectangle basicly...
 +
 +  /* Kill the interface if we have one no matter what. */
 +  if ( pTMObj->lpD3DTexture2 )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release Texture2" ));
 +    pTMObj->lpD3DTexture2->Release();
 +    pTMObj->lpD3DTexture2 = NULL;
 +  }	
 +
 +  /* Kill the system surface. TODO: should try to get the SubIMage going again */
 +  if ( pTMObj->lpDDS_System )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
 +    DX_RESTORE( pTMObj->lpDDS_System );
 +    pTMObj->lpDDS_System->Release();
 +    pTMObj->lpDDS_System = NULL;
 +  }
 +
 +  /* Kill the Video surface. TODO: need some reuse system... */
 +  if ( pTMObj->lpDDS_Video )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
 +    DX_RESTORE( pTMObj->lpDDS_Video );
 +    pTMObj->lpDDS_Video->Release();
 +    pTMObj->lpDDS_Video = NULL;
 +  }
 +
 +  /*================================================================*/
 +  /* Translate the the Mesa/OpenGL pixel channels to the D3D flags. */
 +  /*================================================================*/
 +  switch( dwRequestFlags )
 +  {
 +    case GL_ALPHA:
 +	 dwRequestFlags = DDPF_ALPHA; 
 +	 DPF(( DBG_TXT_WARN, "GL_ALPHA not supported!)" ));
 +	 return FALSE;
 +	 
 +    case GL_INTENSITY:
 +    case GL_LUMINANCE:
 +	 DPF(( DBG_TXT_WARN, "GL_INTENSITY/GL_LUMINANCE not supported!)" ));
 +	 dwRequestFlags = DDPF_LUMINANCE; 
 +	 return FALSE;
 +	 
 +    case GL_LUMINANCE_ALPHA:
 +	 DPF(( DBG_TXT_WARN, "GL_LUMINANCE_ALPHA not supported!)" ));
 +	 dwRequestFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS; 
 +	 return FALSE;
 +	 
 +    case GL_RGB:
 +	 DPF(( DBG_TXT_INFO, "Texture -> GL_RGB" ));
 +	 dwRequestFlags = DDPF_RGB; 
 +	 break;
 +
 +    case GL_RGBA:
 +	 DPF(( DBG_TXT_INFO, "Texture -> GL_RGBA" ));
 +	 dwRequestFlags = DDPF_RGB | DDPF_ALPHAPIXELS; 
 +	 break;
 +  }
 +
 +  /*==============================*/
 +  /* Populate the texture object. */
 +  /*==============================*/
 +  pTMObj->dwName      = dwName;
 +  pTMObj->lpD3DDevice = pHAL->lpD3DDevice;
 +  pTMObj->dwFlags     = dwRequestFlags;
 +  if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
 +  {
 +    DPF(( DBG_TXT_INFO, "Convert to Square..." ));
 +    pTMObj->dwSHeight  = dwHeight;
 +    pTMObj->dwSWidth   = dwWidth;
 +
 +    /* Shrink non-square textures. */
 +    pTMObj->dwVHeight  = (dwHeight > dwWidth) ? dwWidth : dwHeight;
 +    pTMObj->dwVWidth	= (dwHeight > dwWidth) ? dwWidth : dwHeight;
 +  }
 +  else
 +  {
 +    pTMObj->dwSHeight  = dwHeight;
 +    pTMObj->dwSWidth   = dwWidth;
 +    pTMObj->dwVHeight  = dwHeight;
 +    pTMObj->dwVWidth   = dwWidth;
 +  }
 +
 +  /*========================*/  
 +  /* Create SYSTEM surface. */
 +  /*========================*/
 +
 +  /*  Request a surface in system memory. */
 +  memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
 +  ddsd2.dwSize          = sizeof( DDSURFACEDESC2 );
 +  ddsd2.dwWidth         = pTMObj->dwSWidth;
 +  ddsd2.dwHeight        = pTMObj->dwSHeight;
 +  ddsd2.dwFlags         = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
 +  ddsd2.ddsCaps.dwCaps  = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
 +  ddsd2.ddsCaps.dwCaps2 = 0L;
 +  memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
 +  ddsd2.ddpfPixelFormat.dwSize  = sizeof( DDPIXELFORMAT );
 +  ddsd2.ddpfPixelFormat.dwFlags = dwRequestFlags;
 +  rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "EnumerTextureFormats (SYSTEM)->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Create the surface using the enumerated pixelformat. */
 +  rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_System, NULL );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "CreateSurface (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Solve the pixel mapping info using the surface pixelformat. */
 +  Solve8BitChannelPixelFormat( &ddsd2.ddpfPixelFormat, &pTMObj->pixel );
 +
 +  /*===================================================================*/
 +  /* Fill the texture using the PixelInfo structure to do the mapping. */
 +  /*===================================================================*/
 +  UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
 +
 +  /*=======================*/
 +  /* Create VIDEO surface. */
 +  /*=======================*/
 +  rc = LoadTextureInVideo( pHAL, pTMObj );
 +  if ( rc == FALSE )
 +    return FALSE;
 +
 +  /* Make this the current texture. */
 +  rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
 +  if ( FAILED(rc) )
 +  {
 +    DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
 +    pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +    return FALSE;
 +  }
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function will handle the creation and destruction of the texture    */
 +/* surfaces on the card.  Using the dw'V'Width/Height dimensions the call    */
 +/* try and create the texture on the card and keep using FreeTextureMemory   */
 +/* until the surace can be created.  Once the surface is created we get the  */
 +/* interface that we will use to make it the current texture.  I didn't put  */
 +/* the code to make the texture current in this function as BIND needs to    */
 +/* use the same code and this function doesn't always get called when we do a*/
 +/* bind.                                                                     */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +static BOOL	LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj )
 +{
 +  DDSURFACEDESC2	ddsd2;
 +  HRESULT       	rc;
 +
 +  DPF(( DBG_FUNC, "LoadTextureInVideo();" ));
 +
 +  /* Kill the interface if we have one no matter what. */
 +  if ( pTMObj->lpD3DTexture2 )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release Texture2" ));
 +    pTMObj->lpD3DTexture2->Release();
 +    pTMObj->lpD3DTexture2 = NULL;
 +  }	
 +
 +  /* Kill the Video surface. TODO: need some reuse system... */
 +  if ( pTMObj->lpDDS_Video )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
 +    DX_RESTORE( pTMObj->lpDDS_Video );
 +    pTMObj->lpDDS_Video->Release();
 +    pTMObj->lpDDS_Video = NULL;
 +  }
 +
 +  /*  Request a surface in Video memory. */
 +  memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
 +  ddsd2.dwSize          = sizeof( DDSURFACEDESC2 );
 +  ddsd2.dwWidth         = pTMObj->dwVWidth;
 +  ddsd2.dwHeight        = pTMObj->dwVHeight;
 +  ddsd2.dwFlags         = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
 +  ddsd2.ddsCaps.dwCaps  = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
 +  ddsd2.ddsCaps.dwCaps2 = 0L;
 +  memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
 +  ddsd2.ddpfPixelFormat.dwSize  = sizeof( DDPIXELFORMAT );
 +  ddsd2.ddpfPixelFormat.dwFlags = pTMObj->dwFlags;
 +  rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "EnumerTextureFormats ->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Make sure we lock so we don't nuke this texture trying to free memory for it. */
 +  pTMObj->bLock = TRUE;
 +
 +  /*  Start a loop that will free all textures until we have created the texture */
 +  /* surface or we can't free up more memory.                                    */
 +  do
 +  {
 +    /* Try to create the texture surface. */
 +    rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_Video, NULL );
 +    if ( !FAILED(rc) )
 +	 break;
 +
 +    DPF(( DBG_TXT_INFO, "Free Texture Memory" ));
 +
 +    /* DestroyTexture will return TRUE if a surface was freed. */
 +  } while( FreeTextureMemory(pHAL,NULL) );
 +
 +  /* Make sure we unlock or we won't be able to nuke the TMO later. */
 +  pTMObj->bLock = FALSE;
 +
 +  /* Did we create a valid texture surface? */
 +  if ( FAILED(rc) )
 +  {
 +    DPF(( DBG_TXT_WARN, "Failed to load texture" ));
 +    pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +    return FALSE;
 +  }
 +
 +  DX_RESTORE( pTMObj->lpDDS_System );
 +  DX_RESTORE( pTMObj->lpDDS_Video );
 +
 +  DPF(( DBG_TXT_INFO, "Texture Blt SYSTEM -> VID" ));
 +
 +  /* Now blt the texture in system memory to the card. */
 +  rc = pTMObj->lpDDS_Video->Blt( NULL, pTMObj->lpDDS_System, NULL, DDBLT_WAIT, NULL );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( pHAL, "Blt (TEXTURE) ->", ErrorStringD3D(rc) );
 +    return FALSE;
 +  }
 +
 +  /* Get the Texture interface that is used to render with. */
 +  pTMObj->lpDDS_Video->QueryInterface( IID_IDirect3DTexture2, (void **)&pTMObj->lpD3DTexture2 ); 
 +  if ( pTMObj->lpD3DTexture2 == NULL )
 +  {
 +    DPF(( DBG_TXT_WARN, "Failed QueryTextureInterface" ));
 +    pHAL->lpD3DDevice->SetTexture( 0, NULL );
 +    return FALSE;
 +  }
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  If this function gets a texture object struc then we will try and free   */
 +/* it.  If we get a NULL then we will search from the bottom up and free one */
 +/* VMEM surface.  I can only free when the surface isn't locked and of course*/
 +/* there must be a VMEM surface.  We never free SMEM surfaces as that isn't  */
 +/* the point.                                                                */
 +/* TODO: should have a pointer to the bottom of the stack really.            */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
 +{
 +  PTM_OBJECT	pCurrent;
 +  BOOL		bFreed = FALSE;
 +
 +  DPF(( DBG_FUNC, "FreeTextureMemory();" ));
 +  DPF(( DBG_TXT_WARN, "FREE TEXTURE!" ));
 +
 +  /* Just to be safe. */
 +  if ( !pHAL || !pHAL->pTMList )
 +  {
 +    DPF(( DBG_TXT_WARN, "FreeTextureMemory() -> NULL pHAL/pHAL->pTMList" ));
 +    return FALSE;
 +  }
 +
 +  /* Free the last texture in the list. */
 +  if ( pTMObject == NULL )
 +  {
 +    DPF(( DBG_TXT_INFO, "Free Last texture in cache" ));
 +
 +    /* Find the last texture object. */
 +    for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
 +
 +    /* Now backup until we find a texture on the card. */
 +    while( pCurrent && (pCurrent->lpDDS_Video == NULL) && (pCurrent->bLock == FALSE) )
 +	 pCurrent = pCurrent->prev;
 +
 +    /* Didn't find anything. */
 +    if ( pCurrent == NULL )
 +    {
 +	 DPF(( DBG_TXT_INFO, "No texture memory freed" ));
 +	 return FALSE;
 +    }
 +  }
 +  else
 +  {
 +    /* See if we can find this texture object. */
 +    for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
 +
 +    /* Didn't find anything. */
 +    if ( pCurrent == NULL )
 +    {
 +	 DPF(( DBG_TXT_INFO, "Requested texture to be freed NOT FOUND" ));
 +	 return FALSE;
 +    }
 +  }
 +
 +  /* Can't free this baby. */
 +  if ( pCurrent->bLock == TRUE )
 +  {
 +    DPF(( DBG_TXT_WARN, "Requested texture LOCKED" ));
 +    return FALSE;
 +  }
 +
 +  /* Free the texture memory. */
 +  if ( pCurrent->lpD3DTexture2 )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release Texture2" ));
 +    pCurrent->lpD3DTexture2->Release();
 +    pCurrent->lpD3DTexture2 = NULL;
 +    bFreed = TRUE;
 +  }
 +  if ( pCurrent->lpDDS_Video )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
 +    DPF(( DBG_TXT_INFO, "dwName: %d", pCurrent->dwName ));
 +    DPF(( DBG_TXT_INFO, "cx: %d, cy: %d", pCurrent->dwVWidth, pCurrent->dwVHeight ));
 +    pCurrent->lpDDS_Video->Release();
 +    pCurrent->lpDDS_Video = NULL;
 +    bFreed = TRUE;
 +  }
 +  
 +  return bFreed;
 +}
 +/*===========================================================================*/
 +/*  This function searches the linked list of texture objects in the supplied*/
 +/* D3Dwrapper structure.  If it finds a match it will free it and pull it out*/
 +/* of the linked list.  The function works on the bases of a matching pointer*/
 +/* to the object (not matching content).                                     */
 +/*  If the function gets passed a NULL then we want to free the last texture */
 +/* object in the list.  Used in a loop to destory all.                       */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
 +{
 +  PTM_OBJECT	pCurrent;
 +
 +  DPF(( DBG_FUNC, "DestoryTextureObject();" ));
 +
 +  /* Just to be safe. */
 +  if ( !pHAL || !pHAL->pTMList )
 +  {
 +    DPF(( DBG_TXT_WARN, "DestroyTextureObject() -> NULL pHAL/pHAL->pTMList" ));
 +    return FALSE;
 +  }
 +
 +  /* Free the last texture in the list. */
 +  if ( pTMObject == NULL )
 +  {
 +    /* Find the last texture object. */
 +    for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
 +  }
 +  else
 +  {
 +    /* See if we can find this texture object. */
 +    for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
 +
 +    /* Didn't find anything. */
 +    if ( pCurrent == NULL )
 +    {
 +	 DPF(( DBG_TXT_WARN, "No textures to be freed" ));
 +	 return FALSE;
 +    }
 +  }
 +
 +  /* Can't free this baby. */
 +  if ( pCurrent->bLock == TRUE )
 +  {
 +    DPF(( DBG_TXT_WARN, "Requested texture to be freed LOCKED" ));
 +    return FALSE;
 +  }
 +
 +  /* Free the texture memory. */
 +  if ( pCurrent->lpD3DTexture2 )
 +  { 
 +    DPF(( DBG_TXT_INFO, "Release Texture2" ));
 +    pCurrent->lpD3DTexture2->Release();
 +    pCurrent->lpD3DTexture2 = NULL;
 +  }
 +  if ( pCurrent->lpDDS_Video )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
 +    pCurrent->lpDDS_Video->Release();
 +    pCurrent->lpDDS_Video = NULL;
 +  }
 +  if ( pCurrent->lpDDS_System )
 +  {
 +    DPF(( DBG_TXT_INFO, "Release texture (SYS):" ));
 +    pCurrent->lpDDS_System->Release();
 +    pCurrent->lpDDS_System = NULL;
 +  }
 +
 +  /* Pull this texture out of the list. */
 +  if ( pCurrent == pHAL->pTMList )
 +    pHAL->pTMList = NULL;
 +  if ( pCurrent->prev )
 +    (pCurrent->prev)->next = pCurrent->next;
 +  if ( pCurrent->next )
 +    (pCurrent->next)->prev = pCurrent->prev;
 +  FREE( pCurrent );
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function is the callback function that gets called when we are doing*/
 +/* an enumeration of the texture formats supported by this device. The choice*/
 +/* is made by checking to see if we have a match with the supplied D3D pixel-*/
 +/* format.  So the enumeration has to pass a desired D3D PF as the user var. */
 +/*===========================================================================*/
 +/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL.                                 */
 +/*===========================================================================*/
 +static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels )
 +{
 +  LPDIRECTDRAWSURFACE4	lpDDS;
 +  DDSURFACEDESC2		ddsd2;
 +  DWORD          		srcPitch,
 +                         dwHeight, 
 +                         dwWidth,
 +                         dwCol,
 +                         dwColor;
 +  UCHAR          		*pSrc,
 +                         *pSrcRow,
 +                         *pDest,
 +                         *pDestRow;
 +  int				rc;
 +
 +  // TODO:  Do I need to pass the h/w when its in the object!
 +  DPF(( DBG_FUNC, "UpdateTexture();" ));
 +
 +  /* Get the surface pointer we are looking for. */
 +  lpDDS = (bVideo) ? pTMObj->lpDDS_Video : pTMObj->lpDDS_System;
 +
 +  /*===================================================================*/
 +  /* Fill the texture using the PixelInfo structure to do the mapping. */
 +  /*===================================================================*/
 +	 
 +  /* Get the surface pointer. */
 +  memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
 +  ddsd2.dwSize = sizeof(DDSURFACEDESC2);
 +  rc = lpDDS->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( NULL, "Lock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
 +    return;
 +  }
 +
 +  /* For now we are only updating the system surface so use its dimensions. */
 +  dwWidth  = (bVideo) ? pTMObj->dwVWidth : pTMObj->dwSWidth;
 +  dwHeight = (bVideo) ? pTMObj->dwVHeight : pTMObj->dwSHeight;
 +
 +  /*  If we are updating the whole surface then the pDest/pSrc will */
 +  /* always be the same.                                            */
 +  if ( pRect == NULL )
 +  {
 +    pDest = (UCHAR *)ddsd2.lpSurface;
 +    pSrc  = pixels;
 +  }
 +
 +  /* Fill the texture surface based on the pixelformat flags. */
 +  if ( pTMObj->dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS) )
 +  {
 +    srcPitch = dwWidth * 4;
 +    if ( pRect )
 +    {
 +	 pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
 +	 pSrc  = pixels + (pRect->top * dwWidth * 4) + (pRect->left * 4);
 +	 dwHeight = (pRect->bottom - pRect->top);
 +	 dwWidth = (pRect->right - pRect->left);
 +    }
 +
 +    for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
 +    {
 +	 for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
 +      {
 +	   dwColor =  ( ((DWORD)(*(pSrc  ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
 +	   dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
 +	   dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
 +	   if ( pTMObj->pixel.aScale == -1.0 )
 +		dwColor |= ( (*(pSrc+3) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
 +	   else
 +		dwColor |= ( ((DWORD)(*(pSrc+3) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
 +	   memcpy( pDest, &dwColor, pTMObj->pixel.cb );
 +	   pDest += pTMObj->pixel.cb;
 +	   pSrc  += 4;
 +	 }
 +    }
 +  }
 +  else if ( pTMObj->dwFlags == DDPF_RGB )
 +  {
 +    srcPitch = dwWidth * 3;
 +    if ( pRect )
 +    {
 +	 pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
 +	 pSrc  = pixels + (pRect->top * dwWidth * 3) + (pRect->left * 3);
 +	 dwHeight = (pRect->bottom - pRect->top);
 +	 dwWidth  = (pRect->right - pRect->left);
 +    }
 +
 +    for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
 +    {
 +	 for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
 +      {
 +	   dwColor =  ( ((DWORD)(*(pSrc  ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
 +	   dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
 +	   dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
 +	   memcpy( pDest, &dwColor, pTMObj->pixel.cb );
 +	   pDest += pTMObj->pixel.cb;
 +	   pSrc  += 3;
 +	 }
 +    }
 +  }
 +  else if ( pTMObj->dwFlags == (DDPF_LUMINANCE | DDPF_ALPHAPIXELS) )
 +  {
 +    srcPitch = dwWidth * 2;
 +    if ( pRect )
 +    {
 +	 pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
 +	 pSrc  = pixels + (pRect->top * dwWidth * 2) + (pRect->left * 2);
 +	 dwHeight = (pRect->bottom - pRect->top);
 +	 dwWidth  = (pRect->right - pRect->left);
 +    }
 +
 +    for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
 +    {
 +	 for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
 +      {
 +	   dwColor =  ( ((DWORD)(*(pSrc  ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
 +	   if ( pTMObj->pixel.aScale == -1.0 )
 +		dwColor |= ( (*(pSrc+1) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
 +	   else
 +		dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
 +	   memcpy( pDest, &dwColor, pTMObj->pixel.cb );
 +	   pDest += pTMObj->pixel.cb;
 +	   pSrc  += 2;
 +	 }
 +    }
 +  }
 +  else if ( pTMObj->dwFlags == DDPF_LUMINANCE )
 +  {
 +    srcPitch = dwWidth;
 +    if ( pRect )
 +    {
 +	 pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
 +	 pSrc  = pixels + (pRect->top * dwWidth) + (pRect->left);
 +	 dwHeight = (pRect->bottom - pRect->top);
 +	 dwWidth  = (pRect->right - pRect->left);
 +    }
 +
 +    for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
 +    {
 +	 for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
 +      {
 +	   dwColor =  ( ((DWORD)(*pSrc * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
 +	   memcpy( pDest, &dwColor, pTMObj->pixel.cb );
 +	   pDest += pTMObj->pixel.cb;
 +	   pSrc++;
 +	 }
 +    }
 +  }
 +  else if ( pTMObj->dwFlags == DDPF_ALPHAPIXELS )
 +  {
 +    srcPitch = dwWidth;
 +    if ( pRect )
 +    {
 +	 pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
 +	 pSrc  = pixels + (pRect->top * dwWidth) + (pRect->left);
 +	 dwHeight = (pRect->bottom - pRect->top);
 +	 dwWidth  = (pRect->right - pRect->left);
 +    }
 +
 +    for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
 +    {
 +	 for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
 +      {
 +	   if ( pTMObj->pixel.aScale == -1.0 )
 +		dwColor = ( (*pSrc & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
 +	   else
 +		dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
 +	   memcpy( pDest, &dwColor, pTMObj->pixel.cb );
 +	   pDest += pTMObj->pixel.cb;
 +	   pSrc++;
 +	 }
 +    }
 +  }
 +
 +  /* Unlock the surface. */
 +  rc = lpDDS->Unlock( NULL );
 +  if ( FAILED(rc) )
 +  {
 +    RIP( NULL, "Unlock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
 +  }
 +}
 +/*===========================================================================*/
 +/*  This function is the callback function that gets called when we are doing*/
 +/* an enumeration of the texture formats supported by this device. The choice*/
 +/* is made by checking to see if we have a match with the supplied D3D pixel-*/
 +/* format.  So the enumeration has to pass a desired D3D PF as the user var. */
 +/*===========================================================================*/
 +/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL.                                 */
 +/*===========================================================================*/
 +HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext )
 +{
 +  LPDDPIXELFORMAT   lpDDPixFmtRequest = (LPDDPIXELFORMAT)lpContext;
 +  PIXELINFO    	pixel;
 +
 +  DPF(( DBG_FUNC, "EnumPFHook();" ));
 +
 +  if ( lpDDPixFmt->dwFlags == lpDDPixFmtRequest->dwFlags )
 +  {
 +    /* Are we looking for an alpha channel? */
 +    if ( lpDDPixFmtRequest->dwFlags & DDPF_ALPHAPIXELS )
 +    {
 +	 /* Try for something that has more then 1bits of Alpha. */
 +	 Solve8BitChannelPixelFormat( lpDDPixFmt, &pixel );
 +	 if ( pixel.aScale == -1.0 )
 +	 {
 +	   /* Save this format no matter what as its a match of sorts. */
 +	   memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
 +	   return D3DENUMRET_OK;
 +	 }
 +    }
 +
 +    /* Save this format as its a good match. */
 +    memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
 +
 +    /* We are happy at this point so lets leave. */
 +    return D3DENUMRET_CANCEL;
 +  }
 +  
 +  return D3DENUMRET_OK;
 +}
 +
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.h b/src/mesa/drivers/d3d/D3DTextureMgr.h new file mode 100644 index 0000000000..6b3ac78560 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DTextureMgr.h @@ -0,0 +1,63 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#ifndef _TEXTURE_MGR_INC
 +#define _TEXTURE_MGR_INC
 +   
 +/*===========================================================================*/
 +/* Includes.                                                                 */
 +/*===========================================================================*/
 +#include <windows.h>
 +#include <ddraw.h>
 +#include <d3d.h>
 +#include <stdlib.h>
 +#include <stdlib.h>
 +#include "GL/gl.h"
 +/*========================================================================*/
 +/* Defines.                                                               */
 +/*========================================================================*/
 +/*========================================================================*/
 +/* Type defines.                                                          */
 +/*========================================================================*/
 +typedef struct _local_texture_object
 +{
 +   DWORD                dwName,
 +                        dwPriority,
 +                        dwFlags,
 +                        dwSWidth,
 +                        dwSHeight,
 +                        dwVWidth,
 +                        dwVHeight;
 +   BOOL                 bLock,
 +	                   bDirty;		/*  I only update VID on SubImage calls so the system */
 +                                        /* texture can get invalid.                           */
 +
 +   LPDIRECT3DDEVICE3    lpD3DDevice;	/* If the device changes we must get new handles... */
 +   LPDIRECTDRAWSURFACE4 lpDDS_System,
 +	                   lpDDS_Video;
 +   LPDIRECT3DTEXTURE2   lpD3DTexture2;
 +
 +   PIXELINFO            pixel;
 +
 +   struct _local_texture_object *next;
 +   struct _local_texture_object *prev;
 +
 +} TM_OBJECT, *PTM_OBJECT;
 +/*========================================================================*/
 +/* Function prototypes.                                                   */
 +/*========================================================================*/
 +void APIENTRY  InitTMD3D( void *pVoid );
 +void APIENTRY  TermTMD3D( void *pVoid );
 +/*========================================================================*/
 +/* Global variables declaration.                                          */
 +/*========================================================================*/
 +
 +#endif 
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3DUTILS.CPP b/src/mesa/drivers/d3d/D3DUTILS.CPP new file mode 100644 index 0000000000..381e09f2a1 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DUTILS.CPP @@ -0,0 +1,639 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "D3DHAL.h"
 +/*===========================================================================*/
 +/* Local only functions.                                                     */
 +/*===========================================================================*/
 +static int  CountTrailingZeros( DWORD dwMask );
 +/*===========================================================================*/
 +/*  This function is used to get the pointer to the surface and the pitch for*/
 +/* the scanline rendering functions.                                         */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack )
 +{
 +  PMESAD3DHAL			pHAL = (PMESAD3DHAL)pShared;
 +  static DDSURFACEDESC2	ddsd2;
 +  HRESULT               	rc;      
 +
 +  DPF(( DBG_FUNC, "LockHAL();" ));
 +
 +  /* Set the request structure up first. */
 +  memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
 +  ddsd2.dwSize = sizeof(DDSURFACEDESC2);
 +
 +  /* Make sure we have enough info. */
 +  if ( pHAL )
 +  {
 +    rc = pHAL->lpDDSRender->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
 +    if ( FAILED(rc) )
 +    {
 +	 RIP( pHAL, "Lock (RENDER) ->", ErrorStringD3D(rc) );
 +    }
 +  }
 +
 +  return &ddsd2;
 +}
 +/*===========================================================================*/
 +/*  This is just a simple wrapper.  I probably don't need to do any error    */
 +/* checking as the Lock must have worked inorder to get here...              */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +  HRESULT		rc;
 +
 +  DPF(( DBG_FUNC, "UnlockHAL();" ));
 +
 +  /* Make sure we have enough info. */
 +  if ( pHAL )
 +  {
 +    rc = pHAL->lpDDSRender->Unlock( NULL );
 +    if ( FAILED(rc) )
 +    {
 +	 RIP( pHAL, "Unlock (RENDER) ->", ErrorStringD3D(rc) );
 +    }
 +  }
 +}
 +/*===========================================================================*/
 +/*  This function will track the main/Primary window that will be used as the*/
 +/* target for the Blt in SwapBuffers.  As a side effect the call will check  */
 +/* to see if the primary surface is the same size and position as the screen.*/
 +/* If they are the same size we will call it fullscreen...                   */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +extern "C" void UpdateScreenPosHAL( PMESAD3DSHARED pShared )
 +{
 +  PMESAD3DHAL	pHAL = (PMESAD3DHAL)pShared;
 +  POINT		pt;
 +  DWORD		dwWidth, dwHeight;
 +
 +  DPF(( DBG_FUNC, "UpdateScreenPosHAL();" ));
 +
 +  /* Make sure we have enough info. */
 +  if ( pHAL != NULL )
 +  {
 +    /* Update the windows screen position. */
 +    GetClientRect( pShared->hwnd, &pShared->rectW );
 +    pt.x = pt.y = 0;
 +    ClientToScreen( pShared->hwnd, &pt );
 +    OffsetRect( &pShared->rectW, pt.x, pt.y);
 +
 +    /* Compare the primary to the screen. */
 +    dwWidth = GetSystemMetrics( SM_CXSCREEN );
 +    dwHeight =  GetSystemMetrics( SM_CYSCREEN );
 +    if ( (pShared->rectW.left > 0) ||  (pShared->rectW.top > 0)  ||
 +	    (pShared->rectW.right > dwWidth) || (pShared->rectW.bottom > dwHeight) )
 +	 pShared->bWindow = TRUE;
 +    else
 +	 pShared->bWindow = FALSE;
 +  }
 +}
 +/*===========================================================================*/
 +/*  This function will fill in the pixel info structure defined in D3Dshared.*/
 +/* Basicly it will take a DirectDraw pixelformat structure and make scaling  */
 +/* values that will convert from 8bit channels to whatever the supplied ddpf */
 +/* uses.  Also we will generate shift values that will be used to get move   */
 +/* each component of the pixel into place.                                   */
 +/*  I have now added a special case for a 1bit alpha channel.  If I find a 1b*/
 +/* alpha then I will set the scale to -1.0 which should be unique.  Later I  */
 +/* can check the alpha scale value too see if its -1.0 and thus handle it.  I*/
 +/* was finding that the case was not working tom my advantage so this is my  */
 +/* HACK for the day.  As a TODO I should work on this...                     */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void	Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel )
 +{
 +  DPF(( DBG_FUNC, "Solve8BitChannelPixelFromat();" ));
 +
 +  memset( pPixel, 0, sizeof(PPIXELINFO) );
 +
 +  /* Check too see if the color space is valid in the PF. */
 +  if ( pddpf->dwFlags & DDPF_RGB )
 +  {
 +    /* Solve the red stuff. */
 +    pPixel->dwRMask = pddpf->dwRBitMask;
 +    pPixel->rShift = CountTrailingZeros( pPixel->dwRMask );
 +    pPixel->rScale = (float)0.00392156 * (float)(pPixel->dwRMask >> pPixel->rShift);
 +
 +    /* Solve the green thingy's. */
 +    pPixel->dwGMask = pddpf->dwGBitMask;
 +    pPixel->gShift = CountTrailingZeros( pPixel->dwGMask );
 +    pPixel->gScale = (float)0.00392156 * (float)(pPixel->dwGMask >> pPixel->gShift);
 +
 +    /* Solve the blues. */
 +    pPixel->dwBMask = pddpf->dwBBitMask;
 +    pPixel->bShift = CountTrailingZeros( pddpf->dwBBitMask );
 +    pPixel->bScale = (float)0.00392156 * (float)(pddpf->dwBBitMask >> pPixel->bShift);
 +  }
 +
 +  /* Do the alpha channel if there is one. */
 +  if ( pddpf->dwFlags & DDPF_ALPHAPIXELS )
 +  {
 +    pPixel->dwAMask = pddpf->dwRGBAlphaBitMask;
 +    pPixel->aShift = CountTrailingZeros( pPixel->dwAMask );
 +
 +    /* Special case a 1bit alpha. */
 +    if ( (pPixel->dwAMask >> pPixel->aShift) == 1 )
 +	 pPixel->aScale = -1.0;
 +    else
 +	 pPixel->aScale = (float)0.00392156 * (float)(pPixel->dwAMask >> pPixel->aShift);
 +  }
 +
 +  /* Get the size of the pixel in bytes. Should work as dwRGBBitCount is in a union. */
 +  pPixel->cb = pddpf->dwRGBBitCount / 8;
 +}
 +/*===========================================================================*/
 +/*  See RETURN :)                                                            */
 +/*===========================================================================*/
 +/* RETURN: number of contiguous zeros starting from the right.               */
 +/*===========================================================================*/
 +static int  CountTrailingZeros( DWORD dwMask )
 +{
 +  DWORD Mask;
 +
 +  if ( dwMask == 0 ) 
 +    return 32;
 +
 +  /* Can't take credit for this one! */
 +  Mask = dwMask & -(int)dwMask;
 +  return ((Mask & 0xFFFF0000)!=0) << 4
 +         | ((Mask & 0xFF00FF00)!=0) << 3
 +         | ((Mask & 0xF0F0F0F0)!=0) << 2
 +         | ((Mask & 0xCCCCCCCC)!=0) << 1
 +         | ((Mask & 0xAAAAAAAA)!=0);
 +}
 +/*===========================================================================*/
 +/*  This function will convert the DDraw error code to its macro string.  The*/
 +/* returned pointer is static so you need not worry about memory managemnet  */
 +/* but the error message gets written over from call to call...              */
 +/*===========================================================================*/
 +/* RETURN: pointer to the single static buffer that hold the error message.  */
 +/*===========================================================================*/
 +char *ErrorStringD3D( HRESULT hr )
 +{
 +  static   char  errorString[128];
 +
 +  switch( hr )
 +    {
 +    case DDERR_ALREADYINITIALIZED:
 +	 strcpy( errorString, "DDERR_ALREADYINITIALIZED" );
 +	 break;
 +	 
 +    case DDERR_CANNOTATTACHSURFACE:
 +	 strcpy( errorString, "DDERR_CANNOTATTACHSURFACE" );
 +	 break;
 +	 
 +    case DDERR_CANNOTDETACHSURFACE:
 +	 strcpy( errorString, "DDERR_CANNOTDETACHSURFACE" );
 +	 break;
 +	 
 +    case DDERR_CURRENTLYNOTAVAIL:
 +	 strcpy( errorString, "DDERR_CURRENTLYNOTAVAIL" );
 +	 break;
 +	 
 +    case DDERR_EXCEPTION:
 +	 strcpy( errorString, "DDERR_EXCEPTION" );
 +	 break;
 +	 
 +    case DDERR_GENERIC:
 +	 strcpy( errorString, "DDERR_GENERIC" );
 +	 break;
 +	 
 +    case DDERR_HEIGHTALIGN:
 +	 strcpy( errorString, "DDERR_HEIGHTALIGN" );
 +	 break;
 +	 
 +    case DDERR_INCOMPATIBLEPRIMARY:
 +	 strcpy( errorString, "DDERR_INCOMPATIBLEPRIMARY" );
 +	 break;
 +	 
 +    case DDERR_INVALIDCAPS:
 +	 strcpy( errorString, "DDERR_INVALIDCAPS" );
 +	 break;
 +	 
 +    case DDERR_INVALIDCLIPLIST:
 +	 strcpy( errorString, "DDERR_INVALIDCLIPLIST" );
 +	 break;
 +	 
 +    case DDERR_INVALIDMODE:
 +	 strcpy( errorString, "DDERR_INVALIDMODE" );
 +	 break;
 +	 
 +    case DDERR_INVALIDOBJECT:
 +	 strcpy( errorString, "DDERR_INVALIDOBJECT" );
 +	 break;
 +	 
 +    case DDERR_INVALIDPARAMS:
 +	 strcpy( errorString, "DDERR_INVALIDPARAMS" );
 +	 break;
 +	 
 +    case DDERR_INVALIDPIXELFORMAT:
 +	 strcpy( errorString, "DDERR_INVALIDPIXELFORMAT" );
 +	 break;
 +	 
 +    case DDERR_INVALIDRECT:
 +	 strcpy( errorString, "DDERR_INVALIDRECT" );
 +	 break;
 +	 
 +    case DDERR_LOCKEDSURFACES:
 +	 strcpy( errorString, "DDERR_LOCKEDSURFACES" );
 +	 break;
 +	 
 +    case DDERR_NO3D:
 +	 strcpy( errorString, "DDERR_NO3D" );
 +	 break;
 +	 
 +    case DDERR_NOALPHAHW:
 +	 strcpy( errorString, "DDERR_NOALPHAHW" );
 +	 break;
 +	 
 +    case DDERR_NOCLIPLIST:
 +	 strcpy( errorString, "DDERR_NOCLIPLIST" );
 +	 break;
 +	 
 +    case DDERR_NOCOLORCONVHW:
 +	 strcpy( errorString, "DDERR_NOCOLORCONVHW" );
 +	 break;
 +	 
 +    case DDERR_NOCOOPERATIVELEVELSET:
 +	 strcpy( errorString, "DDERR_NOCOOPERATIVELEVELSET" );
 +	 break;
 +	 
 +    case DDERR_NOCOLORKEY:
 +	 strcpy( errorString, "DDERR_NOCOLORKEY" );
 +	 break;
 +	 
 +    case DDERR_NOCOLORKEYHW:
 +	 strcpy( errorString, "DDERR_NOCOLORKEYHW" );
 +	 break;
 +	 
 +    case DDERR_NODIRECTDRAWSUPPORT:
 +	 strcpy( errorString, "DDERR_NODIRECTDRAWSUPPORT" );
 +	 break;
 +	 
 +    case DDERR_NOEXCLUSIVEMODE:
 +	 strcpy( errorString, "DDERR_NOEXCLUSIVEMODE" );
 +	 break;
 +	 
 +    case DDERR_NOFLIPHW:
 +	 strcpy( errorString, "DDERR_NOFLIPHW" );
 +	 break;
 +	 
 +    case DDERR_NOGDI:
 +	 strcpy( errorString, "DDERR_NOGDI" );
 +	 break;
 +	 
 +    case DDERR_NOMIRRORHW:
 +	 strcpy( errorString, "DDERR_NOMIRRORHW" );
 +	 break;
 +	 
 +    case DDERR_NOTFOUND:
 +	 strcpy( errorString, "DDERR_NOTFOUND" );
 +	 break;
 +	 
 +    case DDERR_NOOVERLAYHW:
 +	 strcpy( errorString, "DDERR_NOOVERLAYHW" );
 +	 break;
 +	 
 +    case DDERR_OVERLAPPINGRECTS:
 +	 strcpy( errorString, "DDERR_OVERLAPPINGRECTS" );
 +	 break;
 +	 
 +    case DDERR_NORASTEROPHW:
 +	 strcpy( errorString, "DDERR_NORASTEROPHW" );
 +	 break;
 +	 
 +    case DDERR_NOROTATIONHW:
 +	 strcpy( errorString, "DDERR_NOROTATIONHW" );
 +	 break;
 +	 
 +    case DDERR_NOSTRETCHHW:
 +	 strcpy( errorString, "DDERR_NOSTRETCHHW" );
 +	 break;
 +	 
 +    case DDERR_NOT4BITCOLOR:
 +	 strcpy( errorString, "DDERR_NOT4BITCOLOR" );
 +	 break;
 +	 
 +    case DDERR_NOT4BITCOLORINDEX:
 +	 strcpy( errorString, "DDERR_NOT4BITCOLORINDEX" );
 +	 break;
 +	 
 +    case DDERR_NOT8BITCOLOR:
 +	 strcpy( errorString, "DDERR_NOT8BITCOLOR" );
 +	 break;
 +	 
 +    case DDERR_NOTEXTUREHW:
 +	 strcpy( errorString, "DDERR_NOTEXTUREHW" );
 +	 break;
 +	 
 +    case DDERR_NOVSYNCHW:
 +	 strcpy( errorString, "DDERR_NOVSYNCHW" );
 +	 break;
 +	 
 +    case DDERR_NOZBUFFERHW:
 +	 strcpy( errorString, "DDERR_NOZBUFFERHW" );
 +	 break;
 +
 +    case DDERR_NOZOVERLAYHW:
 +	 strcpy( errorString, "DDERR_NOZOVERLAYHW" );
 +	 break;
 +	 
 +    case DDERR_OUTOFCAPS:
 +	 strcpy( errorString, "DDERR_OUTOFCAPS" );
 +	 break;
 +	 
 +    case DDERR_OUTOFMEMORY:
 +	 strcpy( errorString, "DDERR_OUTOFMEMORY" );
 +	 break;
 +	 
 +    case DDERR_OUTOFVIDEOMEMORY:
 +	 strcpy( errorString, "DDERR_OUTOFVIDEOMEMORY" );
 +	 break;
 +	 
 +    case DDERR_OVERLAYCANTCLIP:
 +	 strcpy( errorString, "DDERR_OVERLAYCANTCLIP" );
 +	 break;
 +	 
 +    case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
 +	 strcpy( errorString, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE" );
 +	 break;
 +	 
 +    case DDERR_PALETTEBUSY:
 +	 strcpy( errorString, "DDERR_PALETTEBUSY" );
 +	 break;
 +	 
 +    case DDERR_COLORKEYNOTSET:
 +	 strcpy( errorString, "DDERR_COLORKEYNOTSET" );
 +	 break;
 +	 
 +    case DDERR_SURFACEALREADYATTACHED:
 +	 strcpy( errorString, "DDERR_SURFACEALREADYATTACHED" );
 +	 break;
 +	 
 +    case DDERR_SURFACEALREADYDEPENDENT:
 +	 strcpy( errorString, "DDERR_SURFACEALREADYDEPENDENT" );
 +	 break;
 +	 
 +    case DDERR_SURFACEBUSY:
 +	 strcpy( errorString, "DDERR_SURFACEBUSY" );
 +	 break;
 +	 
 +    case DDERR_CANTLOCKSURFACE:
 +	 strcpy( errorString, "DDERR_CANTLOCKSURFACE" );
 +	 break;
 +
 +    case DDERR_SURFACEISOBSCURED:
 +	 strcpy( errorString, "DDERR_SURFACEISOBSCURED" );
 +	 break;
 +
 +    case DDERR_SURFACELOST:
 +	 strcpy( errorString, "DDERR_SURFACELOST" );
 +	 break;
 +	 
 +    case DDERR_SURFACENOTATTACHED:
 +	 strcpy( errorString, "DDERR_SURFACENOTATTACHED" );
 +	 break;
 +	 
 +    case DDERR_TOOBIGHEIGHT:
 +	 strcpy( errorString, "DDERR_TOOBIGHEIGHT" );
 +	 break;
 +	 
 +    case DDERR_TOOBIGSIZE:
 +	 strcpy( errorString, "DDERR_TOOBIGSIZE" );
 +	 break;
 +	 
 +    case DDERR_TOOBIGWIDTH:
 +	 strcpy( errorString, "DDERR_TOOBIGWIDTH" );
 +	 break;
 +	 
 +    case DDERR_UNSUPPORTED:
 +	 strcpy( errorString, "DDERR_UNSUPPORTED" );
 +	 break;
 +	 
 +    case DDERR_UNSUPPORTEDFORMAT:
 +	 strcpy( errorString, "DDERR_UNSUPPORTEDFORMAT" );
 +	 break;
 +	 
 +    case DDERR_UNSUPPORTEDMASK:
 +	 strcpy( errorString, "DDERR_UNSUPPORTEDMASK" );
 +	 break;
 +	 
 +    case DDERR_INVALIDSTREAM:
 +	 strcpy( errorString, "DDERR_INVALIDSTREAM" );
 +	 break;
 +	 
 +    case DDERR_VERTICALBLANKINPROGRESS:
 +	 strcpy( errorString, "DDERR_VERTICALBLANKINPROGRESS" );
 +	 break;
 +	 
 +    case DDERR_WASSTILLDRAWING:
 +	 strcpy( errorString, "DDERR_WASSTILLDRAWING" );
 +	 break;
 +	 
 +    case DDERR_XALIGN:
 +	 strcpy( errorString, "DDERR_XALIGN" );
 +	 break;
 +	 
 +    case DDERR_INVALIDDIRECTDRAWGUID:
 +	 strcpy( errorString, "DDERR_INVALIDDIRECTDRAWGUID" );
 +	 break;
 +	 
 +    case DDERR_DIRECTDRAWALREADYCREATED:
 +	 strcpy( errorString, "DDERR_DIRECTDRAWALREADYCREATED" );
 +	 break;
 +	 
 +    case DDERR_NODIRECTDRAWHW:
 +	 strcpy( errorString, "DDERR_NODIRECTDRAWHW" );
 +	 break;
 +	 
 +    case DDERR_PRIMARYSURFACEALREADYEXISTS:
 +	 strcpy( errorString, "DDERR_PRIMARYSURFACEALREADYEXISTS" );
 +	 break;
 +	 
 +    case DDERR_NOEMULATION:
 +	 strcpy( errorString, "DDERR_NOEMULATION" );
 +	 break;
 +	 
 +    case DDERR_REGIONTOOSMALL:
 +	 strcpy( errorString, "DDERR_REGIONTOOSMALL" );
 +	 break;
 +	 
 +    case DDERR_CLIPPERISUSINGHWND:
 +	 strcpy( errorString, "DDERR_CLIPPERISUSINGHWND" );
 +	 break;
 +	 
 +    case DDERR_NOCLIPPERATTACHED:
 +	 strcpy( errorString, "DDERR_NOCLIPPERATTACHED" );
 +	 break;
 +	 
 +    case DDERR_NOHWND:
 +	 strcpy( errorString, "DDERR_NOHWND" );
 +	 break;
 +	 
 +    case DDERR_HWNDSUBCLASSED:
 +	 strcpy( errorString, "DDERR_HWNDSUBCLASSED" );
 +	 break;
 +	 
 +    case DDERR_HWNDALREADYSET:
 +	 strcpy( errorString, "DDERR_HWNDALREADYSET" );
 +	 break;
 +	 
 +    case DDERR_NOPALETTEATTACHED:
 +	 strcpy( errorString, "DDERR_NOPALETTEATTACHED" );
 +	 break;
 +	 
 +    case DDERR_NOPALETTEHW:
 +	 strcpy( errorString, "DDERR_NOPALETTEHW" );
 +	 break;
 +	 
 +    case DDERR_BLTFASTCANTCLIP:
 +         strcpy( errorString, "DDERR_BLTFASTCANTCLIP" );
 +         break;
 +
 +      case DDERR_NOBLTHW:
 +         strcpy( errorString, "DDERR_NOBLTHW" );
 +         break;
 +
 +      case DDERR_NODDROPSHW:
 +         strcpy( errorString, "DDERR_NODDROPSHW" );
 +         break;
 +
 +      case DDERR_OVERLAYNOTVISIBLE:
 +         strcpy( errorString, "DDERR_OVERLAYNOTVISIBLE" );
 +         break;
 +
 +      case DDERR_NOOVERLAYDEST:
 +         strcpy( errorString, "DDERR_NOOVERLAYDEST" );
 +         break;
 +
 +      case DDERR_INVALIDPOSITION:
 +         strcpy( errorString, "DDERR_INVALIDPOSITION" );
 +         break;
 +
 +      case DDERR_NOTAOVERLAYSURFACE:
 +         strcpy( errorString, "DDERR_NOTAOVERLAYSURFACE" );
 +         break;
 +
 +      case DDERR_EXCLUSIVEMODEALREADYSET:
 +         strcpy( errorString, "DDERR_EXCLUSIVEMODEALREADYSET" );
 +         break;
 +
 +      case DDERR_NOTFLIPPABLE:
 +         strcpy( errorString, "DDERR_NOTFLIPPABLE" );
 +         break;
 +
 +      case DDERR_CANTDUPLICATE:
 +         strcpy( errorString, "DDERR_CANTDUPLICATE" );
 +         break;
 +
 +      case DDERR_NOTLOCKED:
 +         strcpy( errorString, "DDERR_NOTLOCKED" );
 +         break;
 +
 +      case DDERR_CANTCREATEDC:
 +         strcpy( errorString, "DDERR_CANTCREATEDC" );
 +         break;
 +
 +      case DDERR_NODC:
 +         strcpy( errorString, "DDERR_NODC" );
 +         break;
 +
 +      case DDERR_WRONGMODE:
 +         strcpy( errorString, "DDERR_WRONGMODE" );
 +         break;
 +
 +      case DDERR_IMPLICITLYCREATED:
 +         strcpy( errorString, "DDERR_IMPLICITLYCREATED" );
 +         break;
 +
 +      case DDERR_NOTPALETTIZED:
 +         strcpy( errorString, "DDERR_NOTPALETTIZED" );
 +         break;
 +
 +      case DDERR_UNSUPPORTEDMODE:
 +         strcpy( errorString, "DDERR_UNSUPPORTEDMODE" );
 +         break;
 +
 +      case DDERR_NOMIPMAPHW:
 +         strcpy( errorString, "DDERR_NOMIPMAPHW" );
 +         break;
 +
 +      case DDERR_INVALIDSURFACETYPE:
 +         strcpy( errorString, "DDERR_INVALIDSURFACETYPE" );
 +         break;
 +
 +      case DDERR_NOOPTIMIZEHW:
 +         strcpy( errorString, "DDERR_NOOPTIMIZEHW" );
 +         break;
 +
 +      case DDERR_NOTLOADED:
 +         strcpy( errorString, "DDERR_NOTLOADED" );
 +         break;
 +
 +      case DDERR_NOFOCUSWINDOW:
 +         strcpy( errorString, "DDERR_NOFOCUSWINDOW" );
 +         break;
 +
 +      case DDERR_DCALREADYCREATED:
 +         strcpy( errorString, "DDERR_DCALREADYCREATED" );
 +         break;
 +
 +      case DDERR_NONONLOCALVIDMEM:
 +         strcpy( errorString, "DDERR_NONONLOCALVIDMEM" );
 +         break;
 +
 +      case DDERR_CANTPAGELOCK:
 +         strcpy( errorString, "DDERR_CANTPAGELOCK" );
 +         break;
 +
 +      case DDERR_CANTPAGEUNLOCK:
 +         strcpy( errorString, "DDERR_CANTPAGEUNLOCK" );
 +         break;
 +
 +      case DDERR_NOTPAGELOCKED:
 +         strcpy( errorString, "DDERR_NOTPAGELOCKED" );
 +         break;
 +
 +      case DDERR_MOREDATA:
 +         strcpy( errorString, "DDERR_MOREDATA" );
 +         break;
 +
 +      case DDERR_EXPIRED:
 +         strcpy( errorString, "DDERR_EXPIRED" );
 +         break;
 +
 +      case DDERR_VIDEONOTACTIVE:
 +         strcpy( errorString, "DDERR_VIDEONOTACTIVE" );
 +         break;
 +
 +      case DDERR_DEVICEDOESNTOWNSURFACE:
 +         strcpy( errorString, "DDERR_DEVICEDOESNTOWNSURFACE" );
 +         break;
 +
 +      case DDERR_NOTINITIALIZED:
 +         strcpy( errorString, "DDERR_NOTINITIALIZED" );
 +         break;
 +
 +      default:
 +         strcpy( errorString, "<unknown error code>" );
 +         break;
 +   }
 +
 +   return &errorString[0];
 +} 
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/D3Dvbrender.c b/src/mesa/drivers/d3d/D3Dvbrender.c new file mode 100644 index 0000000000..57c1306d60 --- /dev/null +++ b/src/mesa/drivers/d3d/D3Dvbrender.c @@ -0,0 +1,2150 @@ +/*===========================================================================*/ +/*                                                                           */ +/* Mesa-3.0 DirectX 6 Driver                                                 */ +/*                                                                           */ +/* By Leigh McRae                                                            */ +/*                                                                           */ +/* http://www.altsoftware.com/                                               */ +/*                                                                           */ +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */ +/*===========================================================================*/ +#include <stdio.h> +#include "clip.h" +#include "context.h" +#include "light.h" +#include "lines.h" +#include "macros.h" +#include "matrix.h" +#include "pb.h" +#include "points.h" +#include "types.h" +#include "vb.h" +#include "vbrender.h" +#include "xform.h" +#include "D3DMesa.h" + +static void SetRenderStates( GLcontext *ctx ); +static void DebugRenderStates( GLcontext *ctx, BOOL bForce ); + +static void RenderPointsVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderTriangleVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderTriangleFanVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderTriangleStripVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderQuadVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderQuad( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv ); +void		RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv ); +void 	RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ); + +/*  I went with a D3D vertex buffer that is 6 times that of the Mesa one */ +/* instead of having the D3D one flush when its full.  This way Mesa will*/ +/* handle all the flushing.  I need x6 as points can use 4 vertex each.  */ +D3DTLVERTEX 	D3DTLVertices[ (VB_MAX*6) ];     +GLuint   		VList[VB_SIZE]; +/*===========================================================================*/ +/* Compute Z offsets for a polygon with plane defined by (A,B,C,D)           */ +/* D is not needed. TODO: Currently we are calculating this but not using it.*/ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void OffsetPolygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c ) +{ +  GLfloat	ac,  +          bc,  +          m, +          offset; + +  DPF(( DBG_FUNC, "OffsetPolygon();" )); + +  if ( (c < 0.001F) && (c > - 0.001F) )  +  { +    /* Prevents underflow problems. */ +    ctx->PointZoffset   = 0.0F; +    ctx->LineZoffset    = 0.0F; +    ctx->PolygonZoffset = 0.0F; +  } +  else  +  { +    ac = a / c; +    bc = b / c; +    if ( ac < 0.0F )   +	 ac = -ac; +    if ( bc<0.0F )   +	 bc = -bc; +    m = MAX2( ac, bc );     /* m = sqrt( ac*ac + bc*bc ); */ + +    offset = (m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits); +    ctx->PointZoffset   = ctx->Polygon.OffsetPoint ? offset : 0.0F; +    ctx->LineZoffset    = ctx->Polygon.OffsetLine  ? offset : 0.0F; +    ctx->PolygonZoffset = ctx->Polygon.OffsetFill  ? offset : 0.0F; +  } + +  DPF(( DBG_PRIM_INFO, "OffsetPolygon: %f", offset )); +} +/*===========================================================================*/ +/*  Compute signed area of the n-sided polgyon specified by vertices         */ +/* vb->Win[] and vertex list vlist[].                                        */ +/*  A clockwise polygon will return a negative area.  A counter-clockwise    */ +/* polygon will return a positive area.  I have changed this function to     */ +/* actually calculate twice the area as its faster and still gives the sign. */ +/*===========================================================================*/ +/* RETURN: signed area of the polgon.                                        */ +/*===========================================================================*/ +static GLfloat PolygonArea( const struct vertex_buffer *vb, GLuint n, const GLuint vlist[] ) +{ +  GLfloat	area; +  GLuint  i; + +  DPF(( DBG_FUNC, "PolygonArea();" )); + +#define  j0    vlist[i] +#define  j1    vlist[(i+1)%n] +#define  x0    vb->Win[j0][0] +#define  y0    vb->Win[j0][1] +#define  x1    vb->Win[j1][0] +#define  y1    vb->Win[j1][1] + +  /* area = sum of trapezoids */ +  for( i = 0, area = 0.0; i < n; i++ )  +    area += ((x0 - x1) * (y0 + y1));  /* Note: no divide by two here! */ + +#undef x0 +#undef y0 +#undef x1 +#undef y1 +#undef j1 +#undef j0 + +  // TODO: I don't see the point or * 0.5 as we just want the sign... +  return area; +} +/*===========================================================================*/ +/*  Render a polygon that needs clipping on at least one vertex. The function*/ +/* will first clip the polygon to any user clipping planes then clip to the  */ +/* viewing volume.  The final polygon will be draw as single triangles that  */ +/* first need minor proccessing (culling, offset, etc) before we draw the    */ +/* polygon as a fan.  NOTE: the fan is draw as single triangles as its not   */ +/* formed sequentaly in the VB but is in the vlist[].                        */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void RenderClippedPolygon( GLcontext *ctx, GLuint n, GLuint vlist[] ) +{ +  struct vertex_buffer	*VB = ctx->VB; +  GLfloat 			(*win)[3] = VB->Win, +                         *proj = ctx->ProjectionMatrix, +                         ex, ey,  +                         fx, fy, c, +	                    wInv;  +  GLuint				index, +	                    pv, +                         facing; + +  DPF(( DBG_FUNC, "RenderClippedPolygon();" )); + +  DPF(( DBG_PRIM_INFO, "RenderClippedtPolygon( %d )", n )); + +  /* Which vertex dictates the color when flat shading. */ +  pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1]; + +  /*  Clipping may introduce new vertices.  New vertices will be stored in */ +  /* the vertex buffer arrays starting with location VB->Free.  After we've*/ +  /* rendered the polygon, these extra vertices can be overwritten.        */ +  VB->Free = VB_MAX; + +  /* Clip against user clipping planes in eye coord space. */ +  if ( ctx->Transform.AnyClip )  +  { +    n = gl_userclip_polygon( ctx, n, vlist ); +    if ( n < 3 ) +	 return; + +    /* Transform vertices from eye to clip coordinates:  clip = Proj * eye */ +    for( index = 0; index < n; index++ )  +    { +	 TRANSFORM_POINT( VB->Clip[vlist[index]], proj, VB->Eye[vlist[index]] ); +    } +  } + +  /* Clip against view volume in clip coord space */ +  n = gl_viewclip_polygon( ctx, n, vlist ); +  if ( n < 3 ) +    return; + +  /* Transform new vertices from clip to ndc to window coords.    */ +  /* ndc = clip / W    window = viewport_mapping(ndc)             */ +  /* Note that window Z values are scaled to the range of integer */ +  /* depth buffer values.                                         */ + +  /* Only need to compute window coords for new vertices */ +  for( index = VB_MAX; index < VB->Free; index++ )  +  { +    if ( VB->Clip[index][3] != 0.0F )  +    { +	 wInv = 1.0F / VB->Clip[index][3]; + +	 win[index][0] = VB->Clip[index][0] * wInv * ctx->Viewport.Sx + ctx->Viewport.Tx; +	 win[index][1] = VB->Clip[index][1] * wInv * ctx->Viewport.Sy + ctx->Viewport.Ty; +	 win[index][2] = VB->Clip[index][2] * wInv * ctx->Viewport.Sz + ctx->Viewport.Tz; +    } +    else  +    { +	 /* Can't divide by zero, so... */ +	 win[index][0] = win[index][1] = win[index][2] = 0.0F; +    } +  } + +  /* Draw filled polygon as a triangle fan */ +  for( index = 2; index < n; index++ )  +  { +    /* Compute orientation of triangle */ +    ex = win[vlist[index-1]][0] - win[vlist[0]][0]; +    ey = win[vlist[index-1]][1] - win[vlist[0]][1]; +    fx = win[vlist[index]][0]   - win[vlist[0]][0]; +    fy = win[vlist[index]][1]   - win[vlist[0]][1]; +    c = (ex * fy) - (ey * fx); + +    /* polygon is perpindicular to view plane, don't draw it */ +    if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) +	 continue; + +    /* Backface culling. */ +    facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; +    if ( (facing + 1) & ctx->Polygon.CullBits )   +	 continue; +         +    if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )  +    { +	 if ( facing == 1 )  +	 { +	   /* use back color */ +	   VB->Color   = VB->Bcolor; +	   VB->Specular= VB->Bspec; +	 } +	 else  +	 { +	   /* use front color */ +	   VB->Color   = VB->Fcolor; +	   VB->Specular= VB->Fspec; +	 } +    } + +    if ( ctx->IndirectTriangles & DD_TRI_OFFSET )  +    { +	 /* finish computing plane equation of polygon, compute offset */ +	 GLfloat fz = win[vlist[index]][2]   - win[vlist[0]][2];   +	 GLfloat ez = win[vlist[index-1]][2] - win[vlist[0]][2]; +	 GLfloat a = (ey * fz) - (ez * fy); +	 GLfloat b = (ez * fx) - (ex * fz); +	 OffsetPolygon( ctx, a, b, c ); +    } +    RenderOneTriangle( ctx, vlist[0], vlist[index-1], vlist[index], pv ); +  } +} +/*===========================================================================*/ +/*  This function gets called when either the vertex buffer is full or glEnd */ +/* has been called.  If the we aren't in rendering mode (FEEDBACK) then I    */ +/* pass the vertex buffer back to Mesa to deal with by returning FALSE.      */ +/*  If I can render the primitive types in the buffer directly then I will   */ +/* return TRUE after I render the vertex buffer and reset the vertex buffer. */ +/*                                                                           */ +/* TODO: I don't handle the special case of when the vertex buffer is full   */ +/*      and we have a primitive that bounds this buffer and the next one to  */ +/*      come.  I'm not sure right now if Mesa handles this for me...         */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE.                                                      */ +/*===========================================================================*/ +GLboolean RenderVertexBuffer( GLcontext *ctx, GLboolean allDone ) +{ +  struct vertex_buffer	*VB = ctx->VB; +  GLuint 		    		index, +	                    vlist[VB_SIZE]; + +  DPF(( DBG_FUNC, "RenderVertexBuffer();" )); + +  /* We only need to hook actual tri's that need rendering. */ +  if ( ctx->RenderMode != GL_RENDER ) +  { +	   //	   (ctx->Visual->AccumBits > 0) ) +	   //	   (ctx->Visual->StencilBits > 0) ) +    DPF(( DBG_PRIM_INFO, "Passing VB back to Mesa" )); +    return FALSE; +  } + +  /*  I'm going to set the states here so that all functions will  */ +  /* be assured to have the right states.  If Mesa's vertex bufefr */ +  /* function calls one of my primitive functions (TRI,POINT,LINE) */ +  /* it will need the right states.  So instead of doing it in the */ +  /* primitive function I will always do it here at risk of some   */ +  /* slow down to some cases...                                    */ +  SetRenderStates( ctx ); + +  switch( ctx->Primitive )  +  { +    case GL_POINTS: +	 DPF(( DBG_PRIM_INFO, "GL_POINTS( %d )", VB->Count )); +	 RenderPointsVB( ctx, 0, VB->Count ); +	 break; + +    case GL_LINES: +    case GL_LINE_STRIP: +    case GL_LINE_LOOP: +	 /*  Not supported functions yet so pass back that we failed to */ +	 /* render the vertex buffer and Mesa will have to do it.       */ +	 DPF(( DBG_PRIM_INFO, "GL_LINE_?( %d )", VB->Count )); +	 return FALSE; + +    case GL_TRIANGLES: +	 if ( VB->Count < 3 ) +	 { +	   DPF(( DBG_PRIM_WARN, "GL_TRIANGLES( %d )", VB->Count )); +	   return FALSE; +	 } + +	 DPF(( DBG_PRIM_INFO, "GL_TRIANGLES( %d )", VB->Count )); +      RenderTriangleVB( ctx, 0, VB->Count ); +	 break; + +    case GL_TRIANGLE_STRIP: +	 if ( VB->Count < 3 ) +	 { +	   DPF(( DBG_PRIM_WARN, "GL_TRIANGLE_STRIP( %d )", VB->Count )); +	   return FALSE; +	 } + +	 DPF(( DBG_PRIM_INFO, "GL_TRIANGLE_STRIP( %d )", VB->Count )); +	 RenderTriangleStripVB( ctx, 0, VB->Count ); +	 break; + +    case GL_TRIANGLE_FAN: +	 if ( VB->Count < 3 ) +	 { +	   DPF(( DBG_PRIM_WARN, "GL_TRIANGLE_FAN( %d )", VB->Count )); +	   return FALSE; +	 } + +	 DPF(( DBG_PRIM_INFO, "GL_TRIANGLE_FAN( %d )", VB->Count )); +	 RenderTriangleFanVB( ctx, 0, VB->Count ); +	 break; + +    case GL_QUADS: +	 if ( VB->Count < 4 ) +	 { +	   DPF(( DBG_PRIM_WARN, "GL_QUADS( %d )", VB->Count )); +	   return FALSE; +	 } + +	  DPF(( DBG_PRIM_INFO, "GL_QUADS( %d )", VB->Count )); +	  RenderQuadVB( ctx, 0, VB->Count ); +	  break; + +    case GL_QUAD_STRIP: +	 if ( VB->Count < 4 ) +	 { +	   DPF(( DBG_PRIM_WARN, "GL_QUAD_STRIP( %d )", VB->Count )); +	   return FALSE; +	 } + +	 DPF(( DBG_PRIM_INFO, "GL_QUAD_STRIP( %d )", VB->Count )); + +	 if ( VB->ClipOrMask )  +	 { +	   for( index = 3; index < VB->Count; index += 2 )  +	   { +		if ( VB->ClipMask[index-3] & VB->ClipMask[index-2] & VB->ClipMask[index-1] & VB->ClipMask[index] & CLIP_ALL_BITS )  +		{ +		   /* All points clipped by common plane */ +		  DPF(( DBG_PRIM_WARN, "GL_QUAD_STRIP( %d )", VB->Count )); +		  continue; +		} +		else if ( VB->ClipMask[index-3] | VB->ClipMask[index-2] | VB->ClipMask[index-1] | VB->ClipMask[index] )  +		{ +		  vlist[0] = index - 3; +		  vlist[1] = index - 2; +		  vlist[2] = index; +		  vlist[3] = index - 1; +		  RenderClippedPolygon( ctx, 4, vlist ); +		} +		else  +		{ +		  RenderQuad( ctx, (index-3), (index-2), index, (index-1), index ); +		}	 +	   } +	 } +	 else  +	 { +	   /* No clipping needed */ +	   for( index = 3; index < VB->Count; index += 2 )  +		RenderQuad( ctx, (index-3), (index-2), index, (index-1), index ); +	 }	 +	 break; +	    +    case GL_POLYGON: +	 if ( VB->Count < 3 )  +	 { +	   DPF(( DBG_PRIM_WARN, "GL_POLYGON( %d )", VB->Count )); +	   return FALSE; +	 } + +	 DPF(( DBG_PRIM_INFO, "GL_POLYGON( %d )", VB->Count )); + +	 /* All points clipped by common plane, draw nothing */ +	 if ( !(VB->ClipAndMask & CLIP_ALL_BITS) )  +	   RenderTriangleFanVB( ctx, 0, VB->Count ); +	 break; + +    default: +	 /* should never get here */ +	 gl_problem( ctx, "invalid mode in gl_render_vb" ); +   } +  +  DPF(( DBG_PRIM_INFO, "ResetVB" )); + +  /* We return TRUE to indicate we rendered the VB. */ +  gl_reset_vb( ctx, allDone ); +  return TRUE; +} +/*===========================================================================*/ +/*  This function will render the current vertex buffer as triangles.  The   */ +/* buffer has to be able to be rendered directly.  This means that we are    */ +/* filled, no offsets, no culling and one sided rendering.  Also we must be  */ +/* in render mode of course.                                                 */ +/*  First I will fill the global D3D vertice buffer.  Next I will set all the*/ +/* states for D3D based on the current OGL state.  Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives.                                  */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void RenderTriangleVB( GLcontext *ctx, GLuint start, GLuint end ) +{ +  D3DMESACONTEXT      	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer 	*VB = ctx->VB; +  int                    index, +                         cVertex, +                         height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +   DWORD                	dwPVColor; +   GLfloat              	ex, ey,  +                         fx, fy, c; +   GLuint               	facing; + +   DPF(( DBG_FUNC, "RenderTriangleVB" )); + +   if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask ) +   { +	DPF(( DBG_PRIM_INFO, "DirectTriangles( %d )", (end-start) )); +	for( index = start, cVertex = 0; index < end; ) +	{ +	  dwPVColor = (VB->Color[(index+2)][3]<<24) | (VB->Color[(index+2)][0]<<16) | (VB->Color[(index+2)][1]<<8) | VB->Color[(index+2)][2]; +    +	  /*=====================================*/ +	  /* Populate the the triangle vertices. */ +	  /*=====================================*/ +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[index][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[index][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[index][2] ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[index][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[index][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	  D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? +	                                  dwPVColor : +                                       (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; +	  index++; +    +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[index][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[index][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[index][2] ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[index][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[index][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	  D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? +                                       dwPVColor : +                                       (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; +	  index++; +       +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[index][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[index][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[index][2] ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[index][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[index][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	  D3DTLVertices[cVertex++].color= dwPVColor; +	  index++; +	} +   } +   else +   { +#define v1     index +#define v2     (index+1) +#define v3     (index+2) + +	for( index = start, cVertex = 0; index < end; index += 3 ) +	{ +	  if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS )  +	  { +	    continue; +	  } +	  else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] )  +	  { +	    VList[0] = v1; +	    VList[1] = v2; +	    VList[2] = v3; +	    RenderClippedPolygon( ctx, 3, VList ); +	    continue; +	  } + +	  /* Compute orientation of triangle */ +	  ex = VB->Win[v2][0] - VB->Win[v1][0]; +	  ey = VB->Win[v2][1] - VB->Win[v1][1]; +	  fx = VB->Win[v3][0] - VB->Win[v1][0]; +	  fy = VB->Win[v3][1] - VB->Win[v1][1]; +	  c = (ex * fy) - (ey * fx); + +	  /* polygon is perpindicular to view plane, don't draw it */ +	  if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) +	    continue; + +	  /* Backface culling. */ +	  facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; +	  if ( (facing + 1) & ctx->Polygon.CullBits )   +	    continue; + +	  if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )  +	  { +	    if ( facing == 1 )  +	    { +		 /* use back color */ +		 VB->Color   = VB->Bcolor; +		 VB->Specular= VB->Bspec; +	    } +	    else  +	    { +		 /* use front color */ +		 VB->Color   = VB->Fcolor; +		 VB->Specular= VB->Fspec; +	    } +	  } + +	  if ( ctx->IndirectTriangles & DD_TRI_OFFSET )  +	  { +	    /* Finish computing plane equation of polygon, compute offset */ +	    GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];   +	    GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; +	    GLfloat a = (ey * fz) - (ez * fy); +	    GLfloat b = (ez * fx) - (ex * fz); +	    OffsetPolygon( ctx, a, b, c ); +	  } + +	  /*=====================================*/ +	  /* Populate the the triangle vertices. */ +	  /*=====================================*/ +	  /* Solve the prevoking vertex color as we need it for the 3rd triangle and flat shading. */ +	  dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; +    +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v1][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v1][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v1][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v1][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +	  D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? +                                       dwPVColor : +                                       (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +    +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v2][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v2][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v2][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v2][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +	  D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? +                                       dwPVColor : +                                       (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; +       +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v3][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v3][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v3][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v3][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +	  D3DTLVertices[cVertex++].color= dwPVColor; +	} +#undef v1 +#undef v2 +#undef v3 +   }     + +   /* Render the converted vertex buffer. */   +   if ( cVertex > 2 ) +	DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +} +/*===========================================================================*/ +/*  This function will render the current vertex buffer as a triangle fan.   */ +/* The buffer has to be able to be rendered directly.  This means that we are*/ +/* filled, no offsets, no culling and one sided rendering.  Also we must be  */ +/* in render mode of course.                                                 */ +/*  First I will fill the global D3D vertice buffer.  Next I will set all the*/ +/* states for D3D based on the current OGL state.  Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives.                                  */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void RenderTriangleFanVB( GLcontext *ctx, GLuint start, GLuint end ) +{ +  D3DMESACONTEXT     	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer 	*VB = ctx->VB; +  int                  	index, +                         cVertex, +                         height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +   GLfloat              	ex, ey,  +                         fx, fy, c; +   GLuint               	facing; +   DWORD                	dwPVColor; + +   DPF(( DBG_FUNC, "RenderTriangleFanVB();" )); + +   /* Special case that we can blast the fan without culling, offset, etc... */ +   if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask && (ctx->Light.ShadeModel != GL_FLAT) ) +   { +	DPF(( DBG_PRIM_INFO, "DirectTriangles( %d )", (end-start) )); + +	/* Seed the the fan. */ +	D3DTLVertices[0].sx   = D3DVAL( VB->Win[start][0] ); +	D3DTLVertices[0].sy   = D3DVAL( (height - VB->Win[start][1]) ); +	D3DTLVertices[0].sz   = D3DVAL( VB->Win[start][2] ); +	D3DTLVertices[0].tu   = D3DVAL( VB->TexCoord[start][0] ); +	D3DTLVertices[0].tv   = D3DVAL( VB->TexCoord[start][1] ); +	D3DTLVertices[0].rhw  = D3DVAL( (1.0 / VB->Clip[start][3]) ); +	D3DTLVertices[0].color= (VB->Color[start][3]<<24) | (VB->Color[start][0]<<16) | (VB->Color[start][1]<<8) | VB->Color[start][2]; +    +	/* Seed the the fan. */ +	D3DTLVertices[1].sx   = D3DVAL( VB->Win[(start+1)][0] ); +	D3DTLVertices[1].sy   = D3DVAL( (height - VB->Win[(start+1)][1]) ); +	D3DTLVertices[1].sz   = D3DVAL( VB->Win[(start+1)][2] ); +	D3DTLVertices[1].tu   = D3DVAL( VB->TexCoord[(start+1)][0] ); +	D3DTLVertices[1].tv   = D3DVAL( VB->TexCoord[(start+1)][1] ); +	D3DTLVertices[1].rhw  = D3DVAL( (1.0 / VB->Clip[(start+1)][3]) ); +	D3DTLVertices[1].color= (VB->Color[(start+1)][3]<<24) | (VB->Color[(start+1)][0]<<16) | (VB->Color[(start+1)][1]<<8) | VB->Color[(start+1)][2]; +    +	for( index = (start+2), cVertex = 2; index < end; index++, cVertex++ ) +	{ +	  /*=================================*/ +	  /* Add the next vertex to the fan. */ +	  /*=================================*/ +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[index][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[index][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[index][2] ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[index][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[index][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	  D3DTLVertices[cVertex].color  = (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; +      } + +	/* Render the converted vertex buffer. */   +	if ( cVertex ) +	  DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLEFAN, &D3DTLVertices[0], cVertex ); +   } +   else +   { +#define v1     start +#define v2     (index-1) +#define v3     index + +	for( index = (start+2), cVertex = 0; index < end; index++ ) +	{ +	  if ( VB->ClipOrMask )  +	  { +	    /* All points clipped by common plane */ +	    if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS )  +	    { +		 continue; +	    } +	    else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] )  +	    { +		 VList[0] = v1; +		 VList[1] = v2; +		 VList[2] = v3; +		 RenderClippedPolygon( ctx, 3, VList ); +		 continue; +	    } +	  } + +	  /* Compute orientation of triangle */ +	  ex = VB->Win[v2][0] - VB->Win[v1][0]; +	  ey = VB->Win[v2][1] - VB->Win[v1][1]; +	  fx = VB->Win[v3][0] - VB->Win[v1][0]; +	  fy = VB->Win[v3][1] - VB->Win[v1][1]; +	  c = (ex * fy) - (ey * fx); +    +	  /* polygon is perpindicular to view plane, don't draw it */ +	  if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) +	    continue; + +	  /* Backface culling. */ +	  facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; +	  if ( (facing + 1) & ctx->Polygon.CullBits )   +	    continue; +    +	  if ( ctx->IndirectTriangles & DD_TRI_OFFSET )  +	  { +	    /* Finish computing plane equation of polygon, compute offset */ +	    GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];   +	    GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; +	    GLfloat a = (ey * fz) - (ez * fy); +	    GLfloat b = (ez * fx) - (ex * fz); +	    OffsetPolygon( ctx, a, b, c ); +	  } + +	  /*=====================================*/ +	  /* Populate the the triangle vertices. */ +	  /*=====================================*/ +	  dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v1][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v1][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v1][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v1][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +	  D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                                         (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +       +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v2][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v2][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset)  ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v2][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v2][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +	  D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                                         (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; +          +	  D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v3][0] ); +	  D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v3][1]) ); +	  D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +	  D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v3][0] ); +	  D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v3][1] ); +	  D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +	  D3DTLVertices[cVertex++].color= dwPVColor; +	} + +	/* Render the converted vertex buffer. */   +	if ( cVertex ) +	  DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +#undef v1 +#undef v2 +#undef v3 +   } +} +/*===========================================================================*/ +/*  This function will render the current vertex buffer as a triangle strip. */ +/* The buffer has to be able to be rendered directly.  This means that we are*/ +/* filled, no offsets, no culling and one sided rendering.  Also we must be  */ +/* in render mode of course.                                                 */ +/*  First I will fill the global D3D vertice buffer.  Next I will set all the*/ +/* states for D3D based on the current OGL state.  Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives.                                  */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void RenderTriangleStripVB( GLcontext *ctx, GLuint start, GLuint end ) +{ +  D3DMESACONTEXT     	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer 	*VB = ctx->VB; +  int                    index, +                         cVertex = 0, +	                    v1, v2, v3, +                         height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +  GLfloat              	ex, ey,  +                         fx, fy, c; +  GLuint               	facing; +  DWORD                	dwPVColor; + +  DPF(( DBG_FUNC, "RenderTriangleStripVB();" )); + +  /* Special case that we can blast the fan without culling, offset, etc... */ +  if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask && (ctx->Light.ShadeModel != GL_FLAT) ) +  { +    DPF(( DBG_PRIM_PROFILE, "DirectTriangles" )); + +    /* Seed the the strip. */ +    D3DTLVertices[0].sx   = D3DVAL( VB->Win[start][0] ); +    D3DTLVertices[0].sy   = D3DVAL( (height - VB->Win[start][1]) ); +    D3DTLVertices[0].sz   = D3DVAL( VB->Win[start][2] ); +    D3DTLVertices[0].tu   = D3DVAL( VB->TexCoord[start][0] ); +    D3DTLVertices[0].tv   = D3DVAL( VB->TexCoord[start][1] ); +    D3DTLVertices[0].rhw  = D3DVAL( (1.0 / VB->Clip[start][3]) ); +    D3DTLVertices[0].color= (VB->Color[start][3]<<24) | (VB->Color[start][0]<<16) | (VB->Color[start][1]<<8) | VB->Color[start][2]; + +    /* Seed the the strip. */ +    D3DTLVertices[1].sx   = D3DVAL( VB->Win[(start+1)][0] ); +    D3DTLVertices[1].sy   = D3DVAL( (height - VB->Win[(start+1)][1]) ); +    D3DTLVertices[1].sz   = D3DVAL( VB->Win[(start+1)][2] ); +    D3DTLVertices[1].tu   = D3DVAL( VB->TexCoord[(start+1)][0] ); +    D3DTLVertices[1].tv   = D3DVAL( VB->TexCoord[(start+1)][1] ); +    D3DTLVertices[1].rhw  = D3DVAL( (1.0 / VB->Clip[(start+1)][3]) ); +    D3DTLVertices[1].color= (VB->Color[(start+1)][3]<<24) | (VB->Color[(start+1)][0]<<16) | (VB->Color[(start+1)][1]<<8) | VB->Color[(start+1)][2]; +    +    for( index = (start+2), cVertex = 2; index < end; index++, cVertex++ ) +    { +	 /*===================================*/ +	 /* Add the next vertex to the strip. */ +	 /*===================================*/ +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[index][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[index][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[index][2] ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[index][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[index][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	 D3DTLVertices[cVertex].color  = (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; +    } + +    /* Render the converted vertex buffer. */   +    if ( cVertex ) +	 DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLESTRIP, &D3DTLVertices[0], cVertex ); +  } +  else +  { +    for( index = (start+2); index < end; index++ )  +    { +	 /* We need to switch order so that winding won't be a problem. */ +	 if ( index & 1 ) +	 { +	   v1 = index - 1; +	   v2 = index - 2; +	   v3 = index - 0; +	 } +	 else +	 { +	   v1 = index - 2; +	   v2 = index - 1; +	   v3 = index - 0; +	 } + +	 /* All vertices clipped by common plane */ +	 if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS )  +	   continue; + +	 /* Check if any vertices need clipping. */ +	 if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] )  +	 { +	   VList[0] = v1; +	   VList[1] = v2; +	   VList[2] = v3; +	   RenderClippedPolygon( ctx, 3, VList ); +	 } +	 else  +	 { +	   /* Compute orientation of triangle */ +	   ex = VB->Win[v2][0] - VB->Win[v1][0]; +	   ey = VB->Win[v2][1] - VB->Win[v1][1]; +	   fx = VB->Win[v3][0] - VB->Win[v1][0]; +	   fy = VB->Win[v3][1] - VB->Win[v1][1]; +	   c = (ex * fy) - (ey * fx); + +	   /* Polygon is perpindicular to view plane, don't draw it */ +	   if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) +		continue; + +	   /* Backface culling. */ +	   facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; +	   if ( (facing + 1) & ctx->Polygon.CullBits )   +		continue; + +	   /* Need right color if we have two sided lighting. */ +	   if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )  +	   { +		if ( facing == 1 )  +		{ +		  /* use back color */ +		  VB->Color   = VB->Bcolor; +		  VB->Specular= VB->Bspec; +		} +		else  +		{ +		  /* use front color */ +		  VB->Color   = VB->Fcolor; +		  VB->Specular= VB->Fspec; +		} +	   } + +	   if ( ctx->IndirectTriangles & DD_TRI_OFFSET )  +	   { +		/* Finish computing plane equation of polygon, compute offset */ +		GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];   +		GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; +		GLfloat a = (ey * fz) - (ez * fy); +		GLfloat b = (ez * fx) - (ex * fz); +		OffsetPolygon( ctx, a, b, c ); +	   } +	   /*=====================================*/ +	   /* Populate the the triangle vertices. */ +	   /*=====================================*/ + +	   /* Solve the prevoking vertex color as we need it for the 3rd triangle and flat shading. */ +	   dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; +    +	   D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v1][0] ); +	   D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v1][1]) ); +	   D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +	   D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v1][0] ); +	   D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v1][1] ); +	   D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +	   D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? +                                        dwPVColor : +                                        (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +    +	   D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v2][0] ); +	   D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v2][1]) ); +	   D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); +	   D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v2][0] ); +	   D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v2][1] ); +	   D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +	   D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? +                                          dwPVColor : +                                          (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; +       +	   D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v3][0] ); +	   D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v3][1]) ); +	   D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +	   D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v3][0] ); +	   D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v3][1] ); +	   D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +	   D3DTLVertices[cVertex++].color= dwPVColor; +	 } +    } + +    /* Render the converted vertex buffer. */   +    if ( cVertex )	 +	 DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +  }	 +} +/*===========================================================================*/ +/*  This function will render the current vertex buffer as Quads.  The buffer*/ +/* has to be able to be rendered directly.  This means that we are filled, no*/ +/* offsets, no culling and one sided rendering.  Also we must be in render   */ +/* mode of cource.                                                           */ +/*  First I will fill the global D3D vertice buffer.  Next I will set all the*/ +/* states for D3D based on the current OGL state.  Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives.                                  */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void RenderQuadVB( GLcontext *ctx, GLuint start, GLuint end ) +{ +  D3DMESACONTEXT       	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer	*VB = ctx->VB; +  int                  	index, +                         cVertex, +                         height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +  DWORD                	dwPVColor; +  GLfloat             	ex, ey,  +                         fx, fy, c; +  GLuint				facing;  /* 0=front, 1=back */ + +  DPF(( DBG_FUNC, "RenderQuadVB();" )); + +#define  v1 (index) +#define  v2 (index+1) +#define  v3 (index+2) +#define  v4 (index+3) + +  if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask ) +  { +    DPF(( DBG_PRIM_PROFILE, "DirectTriangles" )); + +    for( cVertex = 0, index = start; index < end; index += 4 ) +    { +	 if ( ctx->Light.ShadeModel == GL_FLAT ) +	   dwPVColor = (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; +    +	 /*=====================================*/ +	 /* Populate the the triangle vertices. */ +	 /*=====================================*/ +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v1][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v1][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[v1][2] ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v1][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v1][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                      dwPVColor : +	                                 (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v2][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v2][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[v2][2] ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v2][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v2][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                      dwPVColor : +                                      (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; +       +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v3][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v3][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[v3][2] ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v3][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v3][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +	                                 dwPVColor : +                                      (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v1][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v1][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[v1][2] ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v1][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v1][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +	                                 dwPVColor : +                                      (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v3][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v3][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[v3][2] ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v3][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v3][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                      dwPVColor : +                                      (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v4][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v4][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( VB->Win[v4][2] ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v4][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v4][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v4][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                      dwPVColor : +                                      (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; +    } +  } +  else +  { +    for( cVertex = 0, index = start; index < end; index += 4 ) +    { +	 if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3]  & VB->ClipMask[v4] & CLIP_ALL_BITS )  +	 { +	   continue; +	 }	 +	 else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] | VB->ClipMask[v4] )  +	 { +	   VList[0] = v1; +	   VList[1] = v2; +	   VList[2] = v3; +	   VList[3] = v4; +	   RenderClippedPolygon( ctx, 4, VList ); +	   continue; +	 } + +	 /* Compute orientation of triangle */ +	 ex = VB->Win[v2][0] - VB->Win[v1][0]; +	 ey = VB->Win[v2][1] - VB->Win[v1][1]; +	 fx = VB->Win[v3][0] - VB->Win[v1][0]; +	 fy = VB->Win[v3][1] - VB->Win[v1][1]; +	 c = (ex * fy) - (ey * fx); + +	 /* polygon is perpindicular to view plane, don't draw it */ +	 if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) +	   continue; + +	 /* Backface culling. */ +	 facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; +	 if ( (facing + 1) & ctx->Polygon.CullBits )  +	   continue; + +	 if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )  +	 { +	   if ( facing == 1 )  +	   { +		/* use back color */ +		VB->Color   = VB->Bcolor; +		VB->Specular= VB->Bspec; +	   } +	   else  +	   { +		/* use front color */ +		VB->Color   = VB->Fcolor; +		VB->Specular= VB->Fspec; +	   }	 +	 }	 + +	 if ( ctx->IndirectTriangles & DD_TRI_OFFSET )  +	 { +	   /* Finish computing plane equation of polygon, compute offset */ +	   GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];   +	   GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; +	   GLfloat a = (ey * fz) - (ez * fy); +	   GLfloat b = (ez * fx) - (ex * fz); +	   OffsetPolygon( ctx, a, b, c ); +	 } + +	 if ( ctx->Light.ShadeModel == GL_FLAT ) +	   dwPVColor = (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; +    +	 /*=====================================*/ +	 /* Populate the the triangle vertices. */ +	 /*=====================================*/ +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v1][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v1][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v1][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v1][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                       dwPVColor : +                                       (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v2][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v2][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v2][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v2][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                       dwPVColor : +                                       (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; +       +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v3][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v3][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v3][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v3][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                       dwPVColor : +                                       (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v1][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v1][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v1][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v1][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +	                                  dwPVColor : +                                       (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v3][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v3][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v3][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v3][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                       dwPVColor : +                                       (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; +    +	 D3DTLVertices[cVertex].sx     = D3DVAL( VB->Win[v4][0] ); +	 D3DTLVertices[cVertex].sy     = D3DVAL( (height - VB->Win[v4][1]) ); +	 D3DTLVertices[cVertex].sz     = D3DVAL( (VB->Win[v4][2] + ctx->PolygonZoffset) ); +	 D3DTLVertices[cVertex].tu     = D3DVAL( VB->TexCoord[v4][0] ); +	 D3DTLVertices[cVertex].tv     = D3DVAL( VB->TexCoord[v4][1] ); +	 D3DTLVertices[cVertex].rhw    = D3DVAL( (1.0 / VB->Clip[v4][3]) ); +	 D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?  +                                       dwPVColor : +                                       (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; +    } +  } + +#undef   v4 +#undef   v3 +#undef   v2 +#undef   v1 + +  /* Render the converted vertex buffer. */   +  if ( cVertex ) +    DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +} +/*===========================================================================*/ +/*                                                                           */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE.                                                      */ +/*===========================================================================*/ +static void RenderQuad( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv ) +{ +  D3DMESACONTEXT     	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer 	*VB = ctx->VB; +  int                  	height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +  DWORD                	dwPVColor; +  GLfloat              	ex, ey,  +                         fx, fy, c; +  GLuint               	facing;  /* 0=front, 1=back */ +  static D3DTLVERTEX   	TLVertices[6]; + +  DPF(( DBG_FUNC, "RenderQuad" )); +  DPF(( DBG_PRIM_INFO, "RenderQuad( 1 )" )); + +  /* Compute orientation of triangle */ +  ex = VB->Win[v2][0] - VB->Win[v1][0]; +  ey = VB->Win[v2][1] - VB->Win[v1][1]; +  fx = VB->Win[v3][0] - VB->Win[v1][0]; +  fy = VB->Win[v3][1] - VB->Win[v1][1]; +  c = (ex * fy) - (ey * fx); + +  /* polygon is perpindicular to view plane, don't draw it */ +  if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) +    return; + +  /* Backface culling. */ +  facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; +  if ( (facing + 1) & ctx->Polygon.CullBits )   +    return; + +  if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )  +  { +    if ( facing == 1 )  +    { +	 /* use back color */ +	 VB->Color   = VB->Bcolor; +	 VB->Specular= VB->Bspec; +    } +    else  +    { +	 /* use front color */ +	 VB->Color   = VB->Fcolor; +	 VB->Specular= VB->Fspec; +    } +  } + +  if ( ctx->IndirectTriangles & DD_TRI_OFFSET )  +  { +    /* Finish computing plane equation of polygon, compute offset */ +    GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];   +    GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; +    GLfloat a = (ey * fz) - (ez * fy); +    GLfloat b = (ez * fx) - (ex * fz); +    OffsetPolygon( ctx, a, b, c ); +  } +   +  if ( ctx->Light.ShadeModel == GL_FLAT ) +    dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2]; + +  /*=====================================*/ +  /* Populate the the triangle vertices. */ +  /*=====================================*/ +  TLVertices[0].sx      = D3DVAL( VB->Win[v1][0] ); +  TLVertices[0].sy      = D3DVAL( (height - VB->Win[v1][1]) ); +  TLVertices[0].sz      = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +  TLVertices[0].tu      = D3DVAL( VB->TexCoord[v1][0] ); +  TLVertices[0].tv      = D3DVAL( VB->TexCoord[v1][1] ); +  TLVertices[0].rhw     = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +  TLVertices[0].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + +   TLVertices[1].sx      = D3DVAL( VB->Win[v2][0] ); +   TLVertices[1].sy      = D3DVAL( (height - VB->Win[v2][1]) ); +   TLVertices[1].sz      = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); +   TLVertices[1].tu      = D3DVAL( VB->TexCoord[v2][0] ); +   TLVertices[1].tv      = D3DVAL( VB->TexCoord[v2][1] ); +   TLVertices[1].rhw     = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +   TLVertices[1].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; +    +   TLVertices[2].sx      = D3DVAL( VB->Win[v3][0] ); +   TLVertices[2].sy      = D3DVAL( (height - VB->Win[v3][1]) ); +   TLVertices[2].sz      = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +   TLVertices[2].tu      = D3DVAL( VB->TexCoord[v3][0] ); +   TLVertices[2].tv      = D3DVAL( VB->TexCoord[v3][1] ); +   TLVertices[2].rhw     = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +   TLVertices[2].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + +   TLVertices[3].sx      = D3DVAL( VB->Win[v3][0] ); +   TLVertices[3].sy      = D3DVAL( (height - VB->Win[v3][1]) ); +   TLVertices[3].sz      = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +   TLVertices[3].tu      = D3DVAL( VB->TexCoord[v3][0] ); +   TLVertices[3].tv      = D3DVAL( VB->TexCoord[v3][1] ); +   TLVertices[3].rhw     = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +   TLVertices[3].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + +   TLVertices[4].sx      = D3DVAL( VB->Win[v4][0] ); +   TLVertices[4].sy      = D3DVAL( (height - VB->Win[v4][1]) ); +   TLVertices[4].sz      = D3DVAL( (VB->Win[v4][2] + ctx->PolygonZoffset) ); +   TLVertices[4].tu      = D3DVAL( VB->TexCoord[v4][0] ); +   TLVertices[4].tv      = D3DVAL( VB->TexCoord[v4][1] ); +   TLVertices[4].rhw     = D3DVAL( (1.0 / VB->Clip[v4][3]) ); +   TLVertices[4].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; + +   TLVertices[5].sx      = D3DVAL( VB->Win[v1][0] ); +   TLVertices[5].sy      = D3DVAL( (height - VB->Win[v1][1]) ); +   TLVertices[5].sz      = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +   TLVertices[5].tu      = D3DVAL( VB->TexCoord[v1][0] ); +   TLVertices[5].tv      = D3DVAL( VB->TexCoord[v1][1] ); +   TLVertices[5].rhw     = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +   TLVertices[5].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + +   /* Draw the two triangles. */   +   DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &TLVertices[0], 6 ); +} +/*===========================================================================*/ +/*                                                                           */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE.                                                      */ +/*===========================================================================*/ +void	RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv ) +{ +  D3DMESACONTEXT       	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer 	*VB = ctx->VB; +  int                  	height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +  DWORD                	dwPVColor; +  static D3DTLVERTEX   	TLVertices[3]; + +  DPF(( DBG_FUNC, "RenderOneTriangle" )); +  DPF(( DBG_PRIM_INFO, "RenderTriangle( 1 )" )); + +  /*=====================================*/ +  /* Populate the the triangle vertices. */ +  /*=====================================*/ +  if ( ctx->Light.ShadeModel == GL_FLAT ) +    dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2]; + +  TLVertices[0].sx      = D3DVAL( VB->Win[v1][0] ); +  TLVertices[0].sy      = D3DVAL( (height - VB->Win[v1][1]) ); +  TLVertices[0].sz      = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); +  TLVertices[0].tu      = D3DVAL( VB->TexCoord[v1][0] ); +  TLVertices[0].tv      = D3DVAL( VB->TexCoord[v1][1] ); +  TLVertices[0].rhw     = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +  TLVertices[0].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                          (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; +  DPF(( DBG_PRIM_INFO, "V1 -> x:%f y:%f z:%f c:%x", +	   TLVertices[0].sx, +	   TLVertices[0].sy, +	   TLVertices[0].sz, +	   TLVertices[0].color )); + +  TLVertices[1].sx      = D3DVAL( VB->Win[v2][0] ); +  TLVertices[1].sy      = D3DVAL( (height - VB->Win[v2][1]) ); +  TLVertices[1].sz      = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); +  TLVertices[1].tu      = D3DVAL( VB->TexCoord[v2][0] ); +  TLVertices[1].tv      = D3DVAL( VB->TexCoord[v2][1] ); +  TLVertices[1].rhw     = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +  TLVertices[1].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                          (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; +  DPF(( DBG_PRIM_INFO, "V2 -> x:%f y:%f z:%f c:%x", +	   TLVertices[1].sx, +	   TLVertices[1].sy, +	   TLVertices[1].sz, +	   TLVertices[1].color )); +    +  TLVertices[2].sx      = D3DVAL( VB->Win[v3][0] ); +  TLVertices[2].sy      = D3DVAL( (height - VB->Win[v3][1]) ); +  TLVertices[2].sz      = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); +  TLVertices[2].tu      = D3DVAL( VB->TexCoord[v3][0] ); +  TLVertices[2].tv      = D3DVAL( VB->TexCoord[v3][1] ); +  TLVertices[2].rhw     = D3DVAL( (1.0 / VB->Clip[v3][3]) ); +  TLVertices[2].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                          (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; +  DPF(( DBG_PRIM_INFO, "V3 -> x:%f y:%f z:%f c:%x", +	   TLVertices[2].sx, +	   TLVertices[2].sy, +	   TLVertices[2].sz, +	   TLVertices[2].color )); + +  /* Draw the triangle. */   +  DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &TLVertices[0], 3 ); +} +/*===========================================================================*/ +/*                                                                           */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE.                                                      */ +/*===========================================================================*/ +void RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ) +{ +  D3DMESACONTEXT     	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer 	*VB = ctx->VB; +  int                  	height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +  DWORD                	dwPVColor; +  static D3DTLVERTEX	TLVertices[2]; + +  DPF(( DBG_FUNC, "RenderOneLine" )); +  DPF(( DBG_PRIM_INFO, "RenderLine( 1 )" )); + +  if ( VB->MonoColor )  +    dwPVColor = (pContext->aCurrent<<24) | (pContext->rCurrent<<16) | (pContext->gCurrent<<8) | pContext->bCurrent; +  else 	 +    dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2]; + +   TLVertices[0].sx      = D3DVAL( VB->Win[v1][0] ); +   TLVertices[0].sy      = D3DVAL( (height - VB->Win[v1][1]) ); +   TLVertices[0].sz      = D3DVAL( (VB->Win[v1][2] + ctx->LineZoffset) ); +   TLVertices[0].tu      = D3DVAL( VB->TexCoord[v1][0] ); +   TLVertices[0].tv      = D3DVAL( VB->TexCoord[v1][1] ); +   TLVertices[0].rhw     = D3DVAL( (1.0 / VB->Clip[v1][3]) ); +   TLVertices[0].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + +   TLVertices[1].sx      = D3DVAL( VB->Win[v2][0] ); +   TLVertices[1].sy      = D3DVAL( (height - VB->Win[v2][1]) ); +   TLVertices[1].sz      = D3DVAL( (VB->Win[v2][2] + ctx->LineZoffset) ); +   TLVertices[1].tu      = D3DVAL( VB->TexCoord[v2][0] ); +   TLVertices[1].tv      = D3DVAL( VB->TexCoord[v2][1] ); +   TLVertices[1].rhw     = D3DVAL( (1.0 / VB->Clip[v2][3]) ); +   TLVertices[1].color   = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : +                           (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + +   /* Draw line from (x0,y0) to (x1,y1) with current pixel color/index */ +   DrawPrimitiveHAL( pContext->pShared, D3DPT_LINELIST, &TLVertices[0], 2 ); +} +/*===========================================================================*/ +/*  This function was written to convert points into triangles.  I did this  */ +/* as all card accelerate triangles and most drivers do this anyway.  In hind*/ +/* thought this might be a bad idea as some cards do better.                 */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void RenderPointsVB( GLcontext *ctx, GLuint start, GLuint end ) +{ +  D3DMESACONTEXT 		*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +  struct vertex_buffer 	*VB = ctx->VB; +  struct pixel_buffer 	*PB = ctx->PB; +  GLuint 				index; +  GLfloat                radius, z, +                         xmin, ymin,  +                         xmax, ymax; +  GLint				cVertex, +                         height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); +  DWORD				dwPVColor; +   +  DPF(( DBG_FUNC, "RenderPointsVB();" )); + +  radius = CLAMP( ctx->Point.Size, MIN_POINT_SIZE, MAX_POINT_SIZE ) * 0.5F; + +  for( index = start, cVertex = 0; index <= end; index++ )  +  { +    if ( VB->ClipMask[index] == 0 )  +    { +	 xmin = D3DVAL( VB->Win[index][0] - radius ); +	 xmax = D3DVAL( VB->Win[index][0] + radius ); +	 ymin = D3DVAL( height - VB->Win[index][1] - radius ); +	 ymax = D3DVAL( height - VB->Win[index][1] + radius ); +	 z    = D3DVAL( (VB->Win[index][2] + ctx->PointZoffset) ); + +	 dwPVColor = (VB->Color[index][3]<<24) |  +	             (VB->Color[index][0]<<16) |  +	             (VB->Color[index][1]<<8) |  +                  VB->Color[index][2]; + +	 D3DTLVertices[cVertex].sx	  = xmin; +	 D3DTLVertices[cVertex].sy      = ymax; +	 D3DTLVertices[cVertex].sz      = z; +	 D3DTLVertices[cVertex].tu      = 0.0; +	 D3DTLVertices[cVertex].tv      = 0.0; +	 D3DTLVertices[cVertex].rhw     = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	 D3DTLVertices[cVertex++].color = dwPVColor; + +	 D3DTLVertices[cVertex].sx      = xmin; +	 D3DTLVertices[cVertex].sy      = ymin; +	 D3DTLVertices[cVertex].sz      = z; +	 D3DTLVertices[cVertex].tu      = 0.0; +	 D3DTLVertices[cVertex].tv      = 0.0; +	 D3DTLVertices[cVertex].rhw     = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	 D3DTLVertices[cVertex++].color = dwPVColor; +    +	 D3DTLVertices[cVertex].sx      = xmax; +	 D3DTLVertices[cVertex].sy      = ymin; +	 D3DTLVertices[cVertex].sz      = z; +	 D3DTLVertices[cVertex].tu      = 0.0; +	 D3DTLVertices[cVertex].tv      = 0.0; +	 D3DTLVertices[cVertex].rhw     = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	 D3DTLVertices[cVertex++].color = dwPVColor; +    +	 D3DTLVertices[cVertex].sx      = xmax; +	 D3DTLVertices[cVertex].sy      = ymin; +	 D3DTLVertices[cVertex].sz      = z; +	 D3DTLVertices[cVertex].tu      = 0.0; +	 D3DTLVertices[cVertex].tv      = 0.0; +	 D3DTLVertices[cVertex].rhw     = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	 D3DTLVertices[cVertex++].color = dwPVColor; + +	 D3DTLVertices[cVertex].sx	  = xmax; +	 D3DTLVertices[cVertex].sy      = ymax; +	 D3DTLVertices[cVertex].sz      = z; +	 D3DTLVertices[cVertex].tu      = 0.0; +	 D3DTLVertices[cVertex].tv      = 0.0; +	 D3DTLVertices[cVertex].rhw     = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	 D3DTLVertices[cVertex++].color = dwPVColor; + +	 D3DTLVertices[cVertex].sx	  = xmin; +	 D3DTLVertices[cVertex].sy      = ymax; +	 D3DTLVertices[cVertex].sz      = z; +	 D3DTLVertices[cVertex].tu      = 0.0; +	 D3DTLVertices[cVertex].tv      = 0.0; +	 D3DTLVertices[cVertex].rhw     = D3DVAL( (1.0 / VB->Clip[index][3]) ); +	 D3DTLVertices[cVertex++].color = dwPVColor; +    } +  } + +  /* Render the converted vertex buffer. */   +  if ( cVertex ) +    DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +} +/*===========================================================================*/ +/*  This gets call before we render any primitives so that the current OGL   */ +/* states will be mapped the D3D context.  I'm still not sure how D3D works  */ +/* but I'm finding that it doesn't act like a state machine as OGL is.  It   */ +/* looks like the state gets set back to the defaults after a DrawPrimitives */ +/* or an EndScene.  Also I set states that are the default even though this  */ +/* is redundant as the defaults seem screwed up.                             */ +/* TODO: make a batch call.                                                  */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void SetRenderStates( GLcontext *ctx ) +{ +   D3DMESACONTEXT	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +   DWORD          	dwFunc; +   static	BOOL		bTexture = FALSE; +   static int		texName = -1; + +   DPF(( DBG_FUNC, "SetRenderStates();" )); + +   if ( g_DBGMask & DBG_STATES ) +	DebugRenderStates( ctx, FALSE ); + +   SetStateHAL( pContext->pShared, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE ); +   SetStateHAL( pContext->pShared, D3DRENDERSTATE_DITHERENABLE, (ctx->Color.DitherFlag) ? TRUE : FALSE ); + +   /*================================================*/ +   /* Check too see if there are new TEXTURE states. */ +   /*================================================*/ +   if ( ctx->Texture.Enabled ) +   { +      switch( ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode ) +      { +        case GL_MODULATE: +		if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format == GL_RGBA ) +		  dwFunc = pContext->pShared->dwTexFunc[d3dtblend_modulatealpha]; +		else +		  dwFunc = pContext->pShared->dwTexFunc[d3dtblend_modulate]; +		break; + +	   case GL_BLEND: +		dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decalalpha]; +		break; +   +        case GL_REPLACE: +		dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decal]; +		break; + +        case GL_DECAL: +		if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format == GL_RGBA ) +		  dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decalalpha]; +		else +		  dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decal]; +		break; +      } +      SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMAPBLEND, dwFunc ); +       +      switch( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter ) +      { +	   case GL_NEAREST: +		dwFunc = D3DFILTER_NEAREST; +		break; +        case GL_LINEAR: +		dwFunc = D3DFILTER_LINEAR; +		break; +        case GL_NEAREST_MIPMAP_NEAREST: +		dwFunc = D3DFILTER_MIPNEAREST; +		break; +        case GL_LINEAR_MIPMAP_NEAREST: +		dwFunc = D3DFILTER_LINEARMIPNEAREST; +		break; +        case GL_NEAREST_MIPMAP_LINEAR: +		dwFunc = D3DFILTER_MIPLINEAR; +		break; +        case GL_LINEAR_MIPMAP_LINEAR: +		dwFunc = D3DFILTER_LINEARMIPLINEAR; +		break; +      } +      SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMAG, dwFunc ); + +      switch( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter ) +      { +	   case GL_NEAREST: +		dwFunc = D3DFILTER_NEAREST; +		break; +        case GL_LINEAR: +		dwFunc = D3DFILTER_LINEAR; +		break; +        case GL_NEAREST_MIPMAP_NEAREST: +		dwFunc = D3DFILTER_MIPNEAREST; +		break; +        case GL_LINEAR_MIPMAP_NEAREST: +		dwFunc = D3DFILTER_LINEARMIPNEAREST; +		break; +        case GL_NEAREST_MIPMAP_LINEAR: +		dwFunc = D3DFILTER_MIPLINEAR; +		break; +        case GL_LINEAR_MIPMAP_LINEAR: +		dwFunc = D3DFILTER_LINEARMIPLINEAR; +		break; +      } +      SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMIN, dwFunc  ); + +	 /* Another hack to cut down on redundant texture binding. */ +	 //	 if ( texName != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name ) +	 //	 { +	   texName = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name; +	   CreateTMgrHAL( pContext->pShared,  +				   texName, +				   0, +				   ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format, +				   (RECT *)NULL, +				   ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Width,  +				   ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Height, +				   TM_ACTION_BIND, +				   (void *)ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Data ); +	   //	 } +	 bTexture = TRUE; +   } +   else +   { +	/* This is nasty but should cut down on the number of redundant calls. */ +	if ( bTexture == TRUE ) +	{ +	  DisableTMgrHAL( pContext->pShared ); +	  bTexture = FALSE; +	} +   } + +   /*===============================================*/ +   /* Check too see if there are new RASTER states. */ +   /*===============================================*/ + +   // TODO: no concept of front & back. +   switch( ctx->Polygon.FrontMode ) +   { +     case GL_POINT: +	  SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_POINT ); +	  break; +     case GL_LINE: +	  SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME ); +	  break; +     case GL_FILL: +	  SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID ); +	  break; +   } + +   /*************/ +   /* Z-Buffer. */ +   /*************/ +   if ( ctx->Depth.Test == GL_TRUE ) +   { +	switch( ctx->Depth.Func ) +	{   +	  case GL_NEVER:     +	    dwFunc = D3DCMP_NEVER;         +	    break; +	  case GL_LESS:      +	    dwFunc = D3DCMP_LESS;          +	    break; +  	  case GL_GEQUAL:    +	    dwFunc = D3DCMP_GREATEREQUAL;  +	    break; +  	  case GL_LEQUAL:    +	    dwFunc = D3DCMP_LESSEQUAL;     +	    break; +	  case GL_GREATER:   +	    dwFunc = D3DCMP_GREATER;       +	    break; +	  case GL_NOTEQUAL:  +	    dwFunc = D3DCMP_NOTEQUAL;      +	    break; +	  case GL_EQUAL:     +	    dwFunc = D3DCMP_EQUAL;         +	    break; +	  case GL_ALWAYS:    +	    dwFunc = D3DCMP_ALWAYS;        +	    break; +	} +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZFUNC, dwFunc ); +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZENABLE, TRUE ); +   }	 +   else +   { +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZENABLE, FALSE ); +   } + +   /*******************/ +   /* Z-Write Enable. */ +   /*******************/ +   SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZWRITEENABLE , (ctx->Depth.Mask == GL_TRUE) ? TRUE : FALSE ); + +   /***************/ +   /* Alpha test. */ +   /***************/ +   if ( ctx->Color.AlphaEnabled == GL_TRUE ) +   { +	switch( ctx->Color.AlphaFunc ) +     {   +	  case GL_NEVER:     +	    dwFunc = D3DCMP_NEVER;         +	    break; +	  case GL_LESS:      +	    dwFunc = D3DCMP_LESS;          +	    break; +  	  case GL_GEQUAL:    +	    dwFunc = D3DCMP_GREATEREQUAL;  +	    break; +  	  case GL_LEQUAL:    +	    dwFunc = D3DCMP_LESSEQUAL;     +	    break; +	  case GL_GREATER:   +	    dwFunc = D3DCMP_GREATER;       +	    break; +	  case GL_NOTEQUAL:  +	    dwFunc = D3DCMP_NOTEQUAL;      +	    break; +	  case GL_EQUAL:     +	    dwFunc = D3DCMP_EQUAL;         +	    break; +	  case GL_ALWAYS:    +	    dwFunc = D3DCMP_ALWAYS;        +	    break; +	} +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHAFUNC , dwFunc ); +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); +   } +   else +   { +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); +   } + +   /****************/ +   /* Alpha blend. */ +   /****************/ +   if ( ctx->Color.BlendEnabled == GL_TRUE ) +   { +	switch( ctx->Color.BlendSrc )  +	{ +	  case GL_ZERO:	    			 +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_zero]; +	    break; +       case GL_ONE:                      +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_one]; +	    break; +       case GL_DST_COLOR:                +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_dst_color]; +	    break; +       case GL_ONE_MINUS_DST_COLOR:      +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_dst_color]; +	    break; +       case GL_SRC_ALPHA:                +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_src_alpha]; +	    break; +       case GL_ONE_MINUS_SRC_ALPHA:      +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_src_alpha]; +	    break; +       case GL_DST_ALPHA:                +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_dst_alpha]; +	    break; +       case GL_ONE_MINUS_DST_ALPHA:      +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_dst_alpha]; +	    break; +       case GL_SRC_ALPHA_SATURATE:       +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_src_alpha_saturate]; +	    break; +       case GL_CONSTANT_COLOR:           +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_constant_color]; +	    break; +       case GL_ONE_MINUS_CONSTANT_COLOR: +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_constant_color]; +	    break; +       case GL_CONSTANT_ALPHA:           +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_constant_alpha]; +	    break; +       case GL_ONE_MINUS_CONSTANT_ALPHA: +	    dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_constant_alpha]; +	    break; +	} +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_SRCBLEND, dwFunc ); + +	switch( ctx->Color.BlendDst )  +	{ +       case GL_ZERO:                  	 +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_zero]; +	    break; +       case GL_ONE:                      +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_one]; +	    break; +       case GL_SRC_COLOR:                +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_src_color]; +	    break; +       case GL_ONE_MINUS_SRC_COLOR:      +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_src_color]; +	    break; +       case GL_SRC_ALPHA:                +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_src_alpha]; +	    break; +       case GL_ONE_MINUS_SRC_ALPHA:      +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_src_alpha]; +	    break; +       case GL_DST_ALPHA:                +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_dst_alpha]; +	    break; +       case GL_ONE_MINUS_DST_ALPHA:      +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_dst_alpha]; +	    break; +       case GL_CONSTANT_COLOR:           +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_constant_color]; +	    break; +       case GL_ONE_MINUS_CONSTANT_COLOR: +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_constant_color]; +	    break; +       case GL_CONSTANT_ALPHA:           +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_constant_alpha]; +	    break; +       case GL_ONE_MINUS_CONSTANT_ALPHA: +	    dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_constant_alpha]; +	    break; +	} +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_DESTBLEND, dwFunc ); +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE ); +   } +   else +   { +	SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE ); +   } +} +/*===========================================================================*/ +/*  If this function is called it will track the changes to the current      */ +/* states that I'm setting in Direct3D.  I did this so that the DPF's would  */ +/* be under control!                                                         */ +/*===========================================================================*/ +/* RETURN:                                                                   */ +/*===========================================================================*/ +static void DebugRenderStates( GLcontext *ctx, BOOL bForce ) +{ +   D3DMESACONTEXT	*pContext = (D3DMESACONTEXT *)ctx->DriverCtx; +   DWORD			dwFunc; +   static int		dither = -1, +	               texture = -1, +                    textName = -1, +	               textEnv = -1, +                    textMin = -1, +                    textMag = -1, +                    polyMode = -1, +	               depthTest = -1, +	               depthFunc = -1, +	               depthMask = -1, +	               alphaTest = -1, +                    alphaFunc = -1, +	               blend = -1, +                    blendSrc = -1, +                    blendDest = -1; + +   /* Force a displayed update of all current states. */ +   if ( bForce ) +   { +	dither = texture = textName = textEnv = textMin = textMag = -1; +	polyMode = depthTest = depthFunc = depthMask = -1; +	alphaTest = alphaFunc = blend = blendSrc = blendDest = -1; +   } + +   if ( dither != ctx->Color.DitherFlag ) +   { +	dither = ctx->Color.DitherFlag; +	DPF(( 0, "\tDither\t\t%s", (dither) ? "ENABLED" : "--------" )); +   } +   if ( depthTest != ctx->Depth.Test ) +   { +	depthTest = ctx->Depth.Test; +	DPF(( 0, "\tDepth Test\t%s", (depthTest) ? "ENABLED" : "--------" )); +   } +   if ( alphaTest != ctx->Color.AlphaEnabled ) +   {	 +	alphaTest = ctx->Color.AlphaEnabled; +	 +	DPF(( 0, "\tAlpha Test\t%s", (alphaTest) ? "ENABLED" : "--------" )); +   } +   if ( blend != ctx->Color.BlendEnabled ) +   {	 +	blend = ctx->Color.BlendEnabled; +	 +	DPF(( 0, "\tBlending\t%s", (blend) ? "ENABLED" : "--------" )); +   } + +   /*================================================*/ +   /* Check too see if there are new TEXTURE states. */ +   /*================================================*/ +   if ( texture != ctx->Texture.Enabled ) +   { +	texture = ctx->Texture.Enabled; +	DPF(( 0, "\tTexture\t\t%s", (texture) ? "ENABLED" : "--------" )); +   }	 + +   if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current ) +   { +	if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name != textName ) +	{ +	  textName = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name; +	  DPF(( 0, "\tTexture Name:\t%d", textName )); +	  DPF(( 0, "\tTexture Format:\t%s",  +		   (ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format == GL_RGBA) ?  +		   "GL_RGBA" : "GLRGB" )); +	} + +	if ( textEnv != ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode ) +	{ +	  textEnv = ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode; + +	  switch( textEnv ) +	  { +       case GL_MODULATE: +	    DPF(( 0, "\tTexture\tMode\tGL_MODULATE" )); +	    break; +       case GL_BLEND: +	    DPF(( 0, "\tTexture\tMode\tGL_BLEND" )); +	    break; +       case GL_REPLACE: +	    DPF(( 0, "\tTexture\tMode\tGL_REPLACE" )); +	    break; +       case GL_DECAL: +	    DPF(( 0, "\tTexture\tMode\tGL_DECAL" )); +	    break; +	  } +	} + +	if ( textMag != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter ) +	{ +	  textMag = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter; +	   +	  switch( textMag ) +	  { +       case GL_NEAREST: +	    DPF(( 0, "\tTexture MAG\tGL_NEAREST" )); +	    break; +       case GL_LINEAR: +	    DPF(( 0, "\tTexture MAG\tGL_LINEAR" )); +	    break; +       case GL_NEAREST_MIPMAP_NEAREST: +	    DPF(( 0, "\tTexture MAG\tGL_NEAREST_MIPMAP_NEAREST" )); +	    break; +       case GL_LINEAR_MIPMAP_NEAREST: +	    DPF(( 0, "\tTexture MAG\tGL_LINEAR_MIPMAP_NEAREST" )); +	    break; +       case GL_NEAREST_MIPMAP_LINEAR: +	    DPF(( 0, "\tTexture MAG\tGL_NEAREST_MIPMAP_LINEAR" )); +	    break; +       case GL_LINEAR_MIPMAP_LINEAR: +	    DPF(( 0, "\tTexture MAG\tGL_LINEAR_MIPMAP_LINEAR" )); +	    break; +	  } +	} + +	if ( textMin != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter ) +	{ +	  textMin = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter; + +	  switch( textMin ) +	  { +       case GL_NEAREST: +	    DPF(( 0, "\tTexture MIN\tGL_NEAREST" )); +	    break; +       case GL_LINEAR: +	    DPF(( 0, "\tTexture MIN\tGL_LINEAR" )); +	    break; +       case GL_NEAREST_MIPMAP_NEAREST: +	    DPF(( 0, "\tTexture MIN\tGL_NEAREST_MIPMAP_NEAREST" )); +	    break; +       case GL_LINEAR_MIPMAP_NEAREST: +	    DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_NEAREST" )); +	    break; +       case GL_NEAREST_MIPMAP_LINEAR: +	    DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_LINEAR" )); +	    break; +       case GL_LINEAR_MIPMAP_LINEAR: +	    DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_LINEAR" )); +	    break; +	  } +	}	 +   } + +   if ( ctx->Polygon.FrontMode != polyMode ) +   { +	polyMode = ctx->Polygon.FrontMode; + +	switch( polyMode ) +	{ +       case GL_POINT: +	    DPF(( 0, "\tMode\t\tGL_POINT" )); +	    break; +       case GL_LINE: +	    DPF(( 0, "\tMode\t\tGL_LINE" )); +	    break; +       case GL_FILL: +	    DPF(( 0, "\tMode\t\tGL_FILL" )); +	    break; +	} +   } + +   if ( depthFunc != ctx->Depth.Func ) +   { +	depthFunc = ctx->Depth.Func; + +	switch( depthFunc ) +	{   +       case GL_NEVER:     +	    DPF(( 0, "\tDepth Func\tGL_NEVER" )); +	    break; +       case GL_LESS:      +	    DPF(( 0, "\tDepth Func\tGL_LESS" )); +	    break; +       case GL_GEQUAL:    +	    DPF(( 0, "\tDepth Func\tGL_GEQUAL" )); +	    break; +       case GL_LEQUAL:    +	    DPF(( 0, "\tDepth Func\tGL_LEQUAL" )); +	    break; +       case GL_GREATER:   +	    DPF(( 0, "\tDepth Func\tGL_GREATER" )); +	    break; +       case GL_NOTEQUAL:  + 	    DPF(( 0, "\tDepth Func\tGL_NOTEQUAL" )); +	    break; +       case GL_EQUAL:     +	    DPF(( 0, "\tDepth Func\tGL_EQUAL" )); +	    break; +       case GL_ALWAYS:    +	    DPF(( 0, "\tDepth Func\tGL_ALWAYS" )); +	    break; +	} +   }	 + +   if ( depthMask != ctx->Depth.Mask ) +   { +	depthMask = ctx->Depth.Mask; +	DPF(( 0, "\tZWrite\t\t%s", (depthMask) ? "ENABLED" : "--------" )); +   } + +   if ( alphaFunc != ctx->Color.AlphaFunc ) +   { +	alphaFunc = ctx->Color.AlphaFunc; + +	switch( alphaFunc ) +     {   +	  case GL_NEVER:     +	    DPF(( 0, "\tAlpha Func\tGL_NEVER" )); +	    break; +	  case GL_LESS:      +	    DPF(( 0, "\tAlpha Func\tGL_LESS" )); +	    break; +  	  case GL_GEQUAL:    +	    DPF(( 0, "\tAlpha Func\tGL_GEQUAL" )); +	    break; +  	  case GL_LEQUAL:    +	    DPF(( 0, "\tAlpha Func\tGL_LEQUAL" )); +	    break; +	  case GL_GREATER:   +	    DPF(( 0, "\tAlpha Func\tGL_GREATER" )); +	    break; +	  case GL_NOTEQUAL:  +	    DPF(( 0, "\tAlpha Func\tGL_NOTEQUAL" )); +	    break; +	  case GL_EQUAL:     +	    DPF(( 0, "\tAlpha Func\tGL_EQUAL" )); +	    break; +	  case GL_ALWAYS:    +	    DPF(( 0, "\tAlpha Func\tGL_ALWAYS" )); +	    break; +	} +   } + +   if ( blendSrc != ctx->Color.BlendSrc )  +   { +	blendSrc = ctx->Color.BlendSrc; + +	switch( blendSrc )  +	{ +	  case GL_ZERO:	    			 +	    DPF(( 0, "\tSRC Blend\tGL_ZERO" )); +	    break; +       case GL_ONE:                      +	    DPF(( 0, "\tSRC Blend\tGL_ONE" )); +	    break; +       case GL_DST_COLOR:                +	    DPF(( 0, "\tSRC Blend\tGL_DST_COLOR" )); +	    break; +       case GL_ONE_MINUS_DST_COLOR:      +	    DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_DST_COLOR" )); +	    break; +       case GL_SRC_ALPHA:                +	    DPF(( 0, "\tSRC Blend\tGL_SRC_ALPHA" )); +	    break; +       case GL_ONE_MINUS_SRC_ALPHA:      +	    DPF(( 0, "\tSRC Blend\tGL_MINUS_SRC_ALPHA" )); +	    break; +       case GL_DST_ALPHA:                +	    DPF(( 0, "\tSRC Blend\tGL_DST_ALPHA" )); +	    break; +       case GL_ONE_MINUS_DST_ALPHA:      +	    DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_DST_ALPHA" )); +	    break; +       case GL_SRC_ALPHA_SATURATE:       +	    DPF(( 0, "\tSRC Blend\tGL_SRC_ALPHA_SATURATE" )); +	    break; +       case GL_CONSTANT_COLOR:           +	    DPF(( 0, "\tSRC Blend\tGL_CONSTANT_COLOR" )); +	    break; +       case GL_ONE_MINUS_CONSTANT_COLOR: +	    DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_CONSTANT_COLOR" )); +	    break; +       case GL_CONSTANT_ALPHA:           +	    DPF(( 0, "\tSRC Blend\tGL_CONSTANT_ALPHA" )); +	    break; +       case GL_ONE_MINUS_CONSTANT_ALPHA: +	    DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_CONSTANT_ALPHA" )); +	    break; +	} +   } + +   if ( blendDest != ctx->Color.BlendDst )  +   { +	blendDest = ctx->Color.BlendDst; + +	switch( blendDest )  +	{ +       case GL_ZERO:                  	 +	    DPF(( 0, "\tDST Blend\tGL_ZERO" )); +	    break; +       case GL_ONE:                      +	    DPF(( 0, "\tDST Blend\tGL_ONE" )); +	    break; +       case GL_SRC_COLOR:                +	    DPF(( 0, "\tDST Blend\tGL_SRC_COLOR" )); +	    break; +       case GL_ONE_MINUS_SRC_COLOR:      +	    DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_SRC_COLOR" )); +	    break; +       case GL_SRC_ALPHA:                +	    DPF(( 0, "\tDST Blend\tGL_SRC_ALPHA" )); +	    break; +       case GL_ONE_MINUS_SRC_ALPHA:      +	    DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_SRC_ALPHA" )); +	    break; +       case GL_DST_ALPHA:                +	    DPF(( 0, "\tDST Blend\tGL_DST_ALPHA" )); +	    break; +       case GL_ONE_MINUS_DST_ALPHA:      +	    DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_DST_ALPHA" )); +	    break; +       case GL_CONSTANT_COLOR:           +	    DPF(( 0, "\tDST Blend\tGL_CONSTANT_COLOR" )); +	    break; +       case GL_ONE_MINUS_CONSTANT_COLOR: +	    DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_CONSTANT_COLOR" )); +	    break; +       case GL_CONSTANT_ALPHA:           +	    DPF(( 0, "\tDST Blend\tGL_CONSTANT_ALPHA" )); +	    break; +       case GL_ONE_MINUS_CONSTANT_ALPHA: +	    DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_CONSTANT_ALPHA" )); +	    break; +	} +   }	 +} + diff --git a/src/mesa/drivers/d3d/DDrawPROCS.c b/src/mesa/drivers/d3d/DDrawPROCS.c new file mode 100644 index 0000000000..33a1e47bba --- /dev/null +++ b/src/mesa/drivers/d3d/DDrawPROCS.c @@ -0,0 +1,400 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                	             */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "D3DMesa.h"
 +/*===========================================================================*/
 +/*  This call will clear the render surface using the pixel info built from  */
 +/* the surface at creation time.  The call uses Lock/Unlock to access the    */
 +/* surface.  The call also special cases a full clear or a dirty rectangle.  */
 +/*  Finally the call returns the new clear mask that reflects that the color */
 +/* buffer was cleared.                                                       */
 +/*===========================================================================*/
 +/* RETURN: the original mask with the bits cleared that represents the buffer*/
 +/* or buffers we just cleared.                                               */
 +/*===========================================================================*/
 +GLbitfield ClearBuffers( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   UCHAR          *pBuffer,
 +                  *pScanLine;
 +   int            index,
 +	              index2;
 +   DWORD          dwColor;
 +
 +   if ( mask & GL_COLOR_BUFFER_BIT )
 +   {
 +	/* Lock the surface to get the surface pointer. */
 +	pddsd2 = LockHAL( pContext->pShared, TRUE );
 +   
 +	/* Solve the color once only. */
 +	dwColor =  ( ((DWORD)((float)pContext->rClear * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +	dwColor |= ( ((DWORD)((float)pContext->gClear * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +	dwColor |= ( ((DWORD)((float)pContext->bClear * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +   
 +	if ( all ) 
 +	{
 +	  for( index = 0, pScanLine = (UCHAR *)pddsd2->lpSurface; index < pContext->pShared->dwHeight; index++, pScanLine += pddsd2->lPitch )
 +	    for( pBuffer = pScanLine, index2 = 0; index2 < pContext->pShared->dwWidth; index2++, pBuffer += pContext->pShared->pixel.cb )
 +               memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	}
 +	else
 +	{
 +	  pScanLine = ((UCHAR *)pddsd2->lpSurface) +
 +          	    ( (FLIP( pContext->pShared->dwHeight, (y+height)) * pddsd2->lPitch) + (x * pContext->pShared->pixel.cb) );
 +
 +	  for( index = 0; index < height; index++, pScanLine += pddsd2->lPitch )
 +	  {
 +	    for( index2 = 0, pBuffer = pScanLine; index2 < width; index2++, pBuffer += pContext->pShared->pixel.cb )
 +		 memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	  }
 +	}
 +   
 +	UnlockHAL( pContext->pShared, TRUE );
 +   }
 +   
 +   return (mask & ~GL_COLOR_BUFFER_BIT);
 +}
 +/*===========================================================================*/
 +/*  This proc (as all others) has been written for the general case. I use   */
 +/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
 +/* Screen render surface uses.  The alpha is ignored as Mesa does it in SW.  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */ 
 +/*===========================================================================*/
 +void WSpanRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   UCHAR          *pBuffer;
 +   int            index;
 +   DWORD          dwColor;
 +
 +   /* Get the surface pointer and the pitch. */
 +   pddsd2 = LockHAL( pContext->pShared, TRUE );
 +
 +   /* Find the start of the span. Invert y for Windows. */
 +   pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
 +
 +   if ( mask ) 
 +   {
 +	for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
 +	{
 +	  if ( mask[index] )
 +	  {
 +	    /* Pack the color components. */
 +	    dwColor =  ( ((DWORD)((float)rgb[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +	    dwColor |= ( ((DWORD)((float)rgb[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +	    dwColor |= ( ((DWORD)((float)rgb[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +	    memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	  }
 +	}	
 +   }
 +   else
 +   {
 +	for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
 +	{
 +	  /* Pack the color components. */
 +	  dwColor =  ( ((DWORD)((float)rgb[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +	  dwColor |= ( ((DWORD)((float)rgb[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +	  dwColor |= ( ((DWORD)((float)rgb[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +	  memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	}
 +   }
 +
 +   /* Giver back. */
 +   UnlockHAL( pContext->pShared, TRUE );
 +}
 +/*===========================================================================*/
 +/*  This proc (as all others) has been written for the general case. I use   */
 +/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
 +/* Screen render surface uses.  The alpha is ignored as Mesa does it in SW.  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */ 
 +/*===========================================================================*/
 +void WSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   UCHAR          *pBuffer;
 +   int            index;
 +   DWORD          dwColor;
 +
 +   /* Get the surface pointer and the pitch. */
 +   pddsd2 = LockHAL( pContext->pShared, TRUE );
 +
 +   /* Find the start of the span. Invert y for Windows. */
 +   pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
 +
 +   if ( mask ) 
 +   {
 +	for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
 +	{
 +	  if ( mask[index] )
 +	  {
 +         /* Pack the color components. */
 +	    dwColor =  ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +	    dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +	    dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +	    memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	  }
 +	}	
 +   }
 +   else
 +   {
 +	for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
 +	{
 +	  /* Pack the color components. */
 +	  dwColor =  ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +	  dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +	  dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +	  memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	}
 +   }
 +
 +   /* Giver back. */
 +   UnlockHAL( pContext->pShared, TRUE );
 +}
 +/*===========================================================================*/
 +/*  This proc (as all others) has been written for the general case. I use   */
 +/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
 +/* Screen render surface uses.  The color is solved once from the current    */
 +/* color components.  The alpha is ignored as Mesa is doing it in SW.        */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */ 
 +/*===========================================================================*/
 +void WSpanRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   UCHAR          *pBuffer;
 +   int            index;
 +   DWORD          dwColor;
 +
 +   /* Lock the surface to get the surface pointer and the pitch. */
 +   pddsd2 = LockHAL( pContext->pShared, TRUE );
 +
 +   /* Solve the color once only. (no alpha) */
 +   dwColor =  ( ((DWORD)((float)pContext->rCurrent * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +   dwColor |= ( ((DWORD)((float)pContext->gCurrent * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +   dwColor |= ( ((DWORD)((float)pContext->bCurrent * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +
 +   /* Find the start of the span. Invert y for Windows. */
 +   pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
 +
 +   if ( mask ) 
 +   {
 +	for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
 +	  if ( mask[index] )
 +	    memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +   }
 +   else
 +   {
 +	for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
 +	  memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +   }
 +
 +   /* Giver back. */
 +   UnlockHAL( pContext->pShared, TRUE );
 +}
 +/*===========================================================================*/
 +/*  This proc (as all others) has been written for the general case. I use   */
 +/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
 +/* Screen render surface uses.  The alpha is ignored as Mesa does it in SW.  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */ 
 +/*===========================================================================*/
 +void WPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   UCHAR          *pBuffer;
 +   int            index;
 +   DWORD          dwColor;
 +
 +   /* Get the surface pointer and the pitch. */
 +   pddsd2 = LockHAL( pContext->pShared, TRUE );
 +
 +   if ( mask ) 
 +   {
 +	for( index = 0; index < n; index++ )
 +	{
 +	  if ( mask[index] )
 +	  {
 +	    /* Pack the color components. */
 +	    dwColor =  ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +	    dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +	    dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +
 +	    /* Find the pixel. Invert y for Windows. */
 +	    pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
 +	    memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	  }
 +	}
 +   }
 +   else
 +   {
 +	for( index = 0; index < n; index++ )
 +	{
 +	  /* Pack the color components. */
 +	  dwColor =  ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +	  dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +	  dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +
 +	  /* Find the pixel. Invert y for Windows. */
 +	  pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
 +	  memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	}
 +   }
 +
 +   /* Giver back. */
 +   UnlockHAL( pContext->pShared, TRUE );
 +}
 +/*===========================================================================*/
 +/*  This proc (as all others) has been written for the general case. I use   */
 +/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
 +/* Screen render surface uses.  The color is solved once from the current    */
 +/* color components.  The alpha is ignored as Mesa is doing it in SW.        */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */ 
 +/*===========================================================================*/
 +void WPixelsRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   UCHAR          *pBuffer;
 +   int            index;
 +   DWORD          dwColor;
 +
 +   /* Get the surface pointer and the pitch. */
 +   pddsd2 = LockHAL( pContext->pShared, TRUE );
 +
 +   /* Solve the color once only. I don't uses the alpha. */
 +   dwColor =  ( ((DWORD)((float)pContext->rCurrent * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
 +   dwColor |= ( ((DWORD)((float)pContext->gCurrent * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
 +   dwColor |= ( ((DWORD)((float)pContext->bCurrent * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
 +
 +   if ( mask ) 
 +   {
 +	/* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
 +	for( index = 0; index < n; index++ )
 +	{
 +	  if ( mask[index] )
 +	  {
 +	    /* Find the pixel. Invert y for Windows. */
 +	    pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
 +	    memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	  }
 +	}
 +   }
 +   else
 +   {
 +	/* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
 +	for( index = 0; index < n; index++ )
 +	{
 +	  /* Find the pixel. Invert y for Windows. */
 +	  pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
 +	  memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
 +	}
 +   }
 +
 +   /* Giver back. */
 +   UnlockHAL( pContext->pShared, TRUE );
 +}
 +/*===========================================================================*/
 +/*  This proc isn't written for speed rather its to handle the general case. */
 +/* I grab each pixel from the surface and unpack the info using the PIXELINFO*/
 +/* structure that was generated from the OffScreen surface pixelformat.  The */
 +/* function will not fill in the alpha value as Mesa I have Mesa allocate its*/
 +/* own alpha channel when the context was created.  I did this as I didn't   */
 +/* feel that it was worth the effort to try and get HW to work (bus bound).  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void RSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   UCHAR          *pBuffer;
 +   int            index;
 +   DWORD          *pdwColor;
 +
 +   /* Get the surface pointer and the pitch. */
 +   pddsd2 = LockHAL( pContext->pShared, TRUE );
 +
 +   /* Find the start of the span. Invert y for Windows. */
 +   pBuffer = (UCHAR *)pddsd2->lpSurface + 
 +	                 (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + 
 +	                 (x*pContext->pShared->pixel.cb);
 +
 +   /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
 +   for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
 +   {
 +	pdwColor = (DWORD *)pBuffer;
 +	rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
 +	rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
 +	rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
 +   }
 +
 +   /* Giver back. */
 +   UnlockHAL( pContext->pShared, TRUE );
 +}
 +/*===========================================================================*/
 +/*  This proc isn't written for speed rather its to handle the general case. */
 +/* I grab each pixel from the surface and unpack the info using the PIXELINFO*/
 +/* structure that was generated from the OffScreen surface pixelformat.  The */
 +/* function will not fill in the alpha value as Mesa I have Mesa allocate its*/
 +/* own alpha channel when the context was created.  I did this as I didn't   */
 +/* feel that it was worth the effort to try and get HW to work (bus bound).  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void RPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   DDSURFACEDESC2 *pddsd2;
 +   int            index;
 +   DWORD          *pdwColor;
 +
 +   /* Get the surface pointer and the pitch. */
 +   pddsd2 = LockHAL( pContext->pShared, TRUE );
 +
 +   if ( mask )
 +   {
 +	/* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
 +	for( index = 0; index < n; index++ )
 +	{
 +	  if ( mask[index] )
 +	  {
 +	    /* Find the start of the pixel. Invert y for Windows. */
 +	    pdwColor = (DWORD *)((UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb));
 +	    rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
 +	    rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
 +	    rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
 +	  }
 +	}
 +   }
 +   else
 +   {
 +	/* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
 +	for( index = 0; index < n; index++ )
 +	{
 +	  /* Find the start of the pixel. Invert y for Windows. */
 +	  pdwColor = (DWORD *)((UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb));
 +	  rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
 +	  rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
 +	  rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
 +	}
 +   }
 +
 +   /* Giver back. */
 +   UnlockHAL( pContext->pShared, TRUE );
 +}
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/DEBUG.C b/src/mesa/drivers/d3d/DEBUG.C new file mode 100644 index 0000000000..26c2c25be7 --- /dev/null +++ b/src/mesa/drivers/d3d/DEBUG.C @@ -0,0 +1,144 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "Debug.h"
 +/*===========================================================================*/
 +/* Global variables.                                                         */
 +/*===========================================================================*/
 +DWORD	g_DBGMask = DBG_ALL_ERROR;
 +/*===========================================================================*/
 +/*  This is your basic DPF function with printf like support.  The function  */
 +/* also works with a global debug mask variable.  I have written support that*/
 +/* allows for the user's enviroment variable space to be read and set the    */
 +/* masks.  This is done when the dll starts and is only in the debug version.*/
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void _cdecl DebugPrint( int mask, char *pszFormat, ... )
 +{
 +  char	buffer[512];
 +  va_list	args;
 +
 +  /* A mask of 0 will always pass. Easy to remeber. */
 +  if ( (mask == 0) || (mask & g_DBGMask) ) 
 +  {
 +    va_start( args, pszFormat );
 +
 +    if ( mask & DBG_ALL_ERROR ) 
 +	 OutputDebugString( "MesaD3D: (ERROR)" ); 
 +    else
 +	 OutputDebugString( "MesaD3D: " ); 
 +
 +    vsprintf( buffer, pszFormat, args );
 +    strcat( buffer, "\n" );
 +    OutputDebugString( buffer );
 +
 +    va_end( args );
 +  }
 +}
 +/*===========================================================================*/
 +/*  This call reads the users enviroment variables and sets any debug mask   */
 +/* that they have set to TRUE.  Now the value must be "TRUE".                */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void	ReadDBGEnv( void )
 +{
 +  g_DBGMask = DBG_ALL_ERROR;
 +
 +#define IS_VAR_SET(v)	if ( getenv( # v ) && !strcmp(getenv( # v ),"TRUE") ) g_DBGMask |= v;
 +  
 +  IS_VAR_SET( DBG_FUNC );
 +  IS_VAR_SET( DBG_STATES );
 +
 +  IS_VAR_SET( DBG_CNTX_INFO );
 +  IS_VAR_SET( DBG_CNTX_WARN );
 +  IS_VAR_SET( DBG_CNTX_PROFILE );
 +  IS_VAR_SET( DBG_CNTX_ERROR );
 +  IS_VAR_SET( DBG_CNTX_ALL );
 +
 +  IS_VAR_SET( DBG_PRIM_INFO );
 +  IS_VAR_SET( DBG_PRIM_WARN );
 +  IS_VAR_SET( DBG_PRIM_PROFILE );
 +  IS_VAR_SET( DBG_PRIM_ERROR );
 +  IS_VAR_SET( DBG_PRIM_ALL );
 +
 +  IS_VAR_SET( DBG_TXT_INFO );
 +  IS_VAR_SET( DBG_TXT_WARN );
 +  IS_VAR_SET( DBG_TXT_PROFILE );
 +  IS_VAR_SET( DBG_TXT_ERROR );
 +  IS_VAR_SET( DBG_TXT_ALL );
 +
 +  IS_VAR_SET( DBG_ALL_INFO );
 +  IS_VAR_SET( DBG_ALL_WARN );
 +  IS_VAR_SET( DBG_ALL_PROFILE );
 +  IS_VAR_SET( DBG_ALL_ERROR );
 +  IS_VAR_SET( DBG_ALL );
 +
 +#undef IS_VAR_SET
 +}
 +/*===========================================================================*/
 +/*  This function will take a pointer to a DDSURFACEDESC2 structure & display*/
 +/* the parsed information using a DPF call.                                  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void	DebugPixelFormat( char *pszSurfaceName, DDPIXELFORMAT *pddpf )
 +{
 +  char	buffer[256];
 +
 +  /* Parse the flag type and write the string equivalent. */
 +  if ( pddpf->dwFlags & DDPF_ALPHA )
 +	strcat( buffer, "DDPF_ALPHA " );
 +  if ( pddpf->dwFlags & DDPF_ALPHAPIXELS )
 +	strcat( buffer, "DDPF_ALPHAPIXELS " );
 +  if ( pddpf->dwFlags & DDPF_ALPHAPREMULT )
 +	strcat( buffer, "DDPF_ALPHAPREMULT " );
 +  if ( pddpf->dwFlags & DDPF_BUMPLUMINANCE )
 +	strcat( buffer, "DDPF_BUMPLUMINANCE " );
 +  if ( pddpf->dwFlags & DDPF_BUMPDUDV )
 +	strcat( buffer, "DDPF_BUMPDUDV " );
 +  if ( pddpf->dwFlags & DDPF_COMPRESSED )
 +	strcat( buffer, "DDPF_COMPRESSED " );
 +  if ( pddpf->dwFlags & DDPF_FOURCC )
 +	strcat( buffer, "DDPF_FOURCC " );
 +  if ( pddpf->dwFlags & DDPF_LUMINANCE )
 +	strcat( buffer, "DDPF_LUMINANCE " );
 +  if ( pddpf->dwFlags & DDPF_PALETTEINDEXED1 )
 +	strcat( buffer, "DDPF_PALETTEINDEXED1 " );
 +  if ( pddpf->dwFlags & DDPF_PALETTEINDEXED2 )
 +	strcat( buffer, "DDPF_PALETTEINDEXED2 " );
 +  if ( pddpf->dwFlags & DDPF_PALETTEINDEXED4 )
 +	strcat( buffer, "DDPF_PALETTEINDEXED4 " );
 +  if ( pddpf->dwFlags & DDPF_PALETTEINDEXED8 )
 +	strcat( buffer, "DDPF_PALETTEINDEXED8 " );
 +  if ( pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8 )
 +	strcat( buffer, "DDPF_PALETTEINDEXEDTO8 " );
 +  if ( pddpf->dwFlags & DDPF_RGB )
 +	strcat( buffer, "DDPF_RGB  " );
 +  if ( pddpf->dwFlags & DDPF_RGBTOYUV )
 +	strcat( buffer, "DDPF_RGBTOYUV  " );
 +  if ( pddpf->dwFlags & DDPF_STENCILBUFFER )
 +	strcat( buffer, "DDPF_STENCILBUFFER  " );
 +  if ( pddpf->dwFlags & DDPF_YUV )
 +	strcat( buffer, "DDPF_YUV  " );
 +  if ( pddpf->dwFlags & DDPF_ZBUFFER )
 +	strcat( buffer, "DDPF_ZBUFFER  " );
 +  if ( pddpf->dwFlags & DDPF_ZPIXELS )
 +	strcat( buffer, "DDPF_ZPIXELS  " );
 +
 +  DPF(( (DBG_TXT_INFO|DBG_CNTX_INFO),"%s", buffer ));
 +}
 +
 +
 +
 +
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/DEBUG.H b/src/mesa/drivers/d3d/DEBUG.H new file mode 100644 index 0000000000..e63d6c500c --- /dev/null +++ b/src/mesa/drivers/d3d/DEBUG.H @@ -0,0 +1,91 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#ifndef _DEBUG_H
 +#define _DEBUG_H
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +/*===========================================================================*/
 +/* Includes.                                                                 */
 +/*===========================================================================*/
 +#include <stdio.h>
 +#include <string.h>
 +#include <ddraw.h>
 +#include <d3d.h>
 +#include "D3DShared.h"
 +/*===========================================================================*/
 +/* Magic numbers.                                                            */
 +/*===========================================================================*/
 +/*===========================================================================*/
 +/* Macros defines.                                                           */
 +/*===========================================================================*/
 +#define DBG_FUNC                        0x00000001
 +#define DBG_STATES              0x00000002
 +
 +#define DBG_CNTX_INFO           0x00000010
 +#define DBG_CNTX_WARN           0x00000020
 +#define DBG_CNTX_PROFILE        0x00000040
 +#define DBG_CNTX_ERROR          0x00000080
 +#define DBG_CNTX_ALL            0x000000F0
 +
 +#define DBG_PRIM_INFO           0x00000100
 +#define DBG_PRIM_WARN           0x00000200
 +#define DBG_PRIM_PROFILE        0x00000400
 +#define DBG_PRIM_ERROR          0x00000800
 +#define DBG_PRIM_ALL            0x00000F00
 +
 +#define DBG_TXT_INFO            0x00001000
 +#define DBG_TXT_WARN            0x00002000
 +#define DBG_TXT_PROFILE 0x00004000
 +#define DBG_TXT_ERROR           0x00008000
 +#define DBG_TXT_ALL             0x0000F000
 +
 +#define DBG_ALL_INFO            0x11111110
 +#define DBG_ALL_WARN            0x22222220
 +#define DBG_ALL_PROFILE 0x44444440
 +#define DBG_ALL_ERROR           0x88888880
 +#define DBG_ALL                 0xFFFFFFFF
 +
 +#ifdef D3D_DEBUG
 +#       define  DPF(arg)                        DebugPrint arg 
 +#       define  RIP(pH,msg,err) OutputDebugString(msg); \
 +							OutputDebugString(err); \
 +							OutputDebugString("\n"); \
 +							FatalShutDown(pH)
 +#else
 +#       define  DPF(arg)
 +#       define  RIP(pH,msg,err) FatalShutDown(pH)
 +#endif
 +/*===========================================================================*/
 +/* Type defines.                                                             */
 +/*===========================================================================*/
 +/*===========================================================================*/
 +/* Function prototypes.                                                      */
 +/*===========================================================================*/
 +extern void ReadDBGEnv( void );
 +extern void _cdecl DebugPrint( int mask, char *pszFormat, ... );
 +extern void DebugPixelFormat( char *pszSurfaceName, DDPIXELFORMAT *pddpf );
 +/*===========================================================================*/
 +/* Global variables.                                                         */
 +/*===========================================================================*/
 +extern DWORD    g_DBGMask;
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif
 +
 +
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/DbgEnv.bat b/src/mesa/drivers/d3d/DbgEnv.bat new file mode 100644 index 0000000000..40858e6684 --- /dev/null +++ b/src/mesa/drivers/d3d/DbgEnv.bat @@ -0,0 +1,25 @@ +SET DBG_FUNC=FALSE
 +
 +SET DBG_CNTX_INFO=TRUE
 +SET DBG_CNTX_WARN=TRUE
 +SET DBG_CNTX_PROFILE=FALSE
 +SET DBG_CNTX_ERROR=TRUE
 +SET DBG_CNTX_ALL=TRUE
 +
 +SET DBG_PRIM_INFO=FALSE
 +SET DBG_PRIM_WARN=FALSE
 +SET DBG_PRIM_PROFILE=FALSE
 +SET DBG_PRIM_ERROR=TRUE
 +SET DBG_PRIM_ALL=FALSE
 +
 +SET DBG_TXT_INFO=FALSE
 +SET DBG_TXT_WARN=TRUE
 +SET DBG_TXT_PROFILE=FALSE
 +SET DBG_TXT_ERROR=TRUE
 +SET DBG_TXT_ALL=FALSE
 +
 +SET DBG_ALL_INFO=FALSE
 +SET DBG_ALL_WARN=TRUE
 +SET DBG_ALL_PROFILE=FALSE
 +SET DBG_ALL_ERROR=TRUE
 +SET DBG_ALL=FALSE
 diff --git a/src/mesa/drivers/d3d/MAKEFILE b/src/mesa/drivers/d3d/MAKEFILE new file mode 100644 index 0000000000..59734cfd32 --- /dev/null +++ b/src/mesa/drivers/d3d/MAKEFILE @@ -0,0 +1,102 @@ +##############################################################################
 +# 
 +# Mesa-3.0 Makefile for DirectX 6 Driver                             
 +#
 +# By Leigh McRae
 +#
 +# http://www.altsoftware.com/
 +#
 +# Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved     
 +##############################################################################
 +NAME=
 +TARGET= WGL Driver (D3DHAL)
 +
 +D3D_DIR=$(MAKEDIR)\D3D
 +TARGET_DIR=e:\WinNT\System32
 +TEMP_DIR=c:\Temp
 +
 +SPACE=-
 +LINKER=link.exe
 +
 +INCLUDE=$(SDKROOT)\include;$(INCLUDE)
 +LIB=$(SDKROOT)\lib;$(LIB)
 +##############################################################################
 +CFLAGS  = /c /nologo /W1 /G5 /I..\ /I..\..\Include \
 +		/D "_WIN32" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__"  /D "MESAD3D"
 +CPPFLAGS= /c /nologo /W1 /G5 /I..\ /I..\..\Include \
 +		/D "_WIN32" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__"  /D "MESAD3D"
 +
 +!IF "$(DEBUG)" == "1"
 +
 +CFLAGS   = /MTd /Od /Z7 /Yd /D "_DEBUG" /D "D3D_DEBUG" $(CFLAGS)
 +CPPFLAGS = /MTd /Od /Z7 /Yd /D "_DEBUG" /D "D3D_DEBUG" $(CPPFLAGS)
 +BUILD_TYPE=debug
 +
 +!ELSE
 +
 +CFLAGS   = /MT /Ox /D "NDEBUG" $(CFLAGS)
 +CPPFLAGS = /MT /Ox /D "NDEBUG" $(CPPFLAGS)
 +BUILD_TYPE=release
 +
 +!ENDIF
 +##############################################################################
 +SRCS_WGL = wgl.c D3Dvbrender.c DDrawPROCS.c NULLProcs.c Debug.c
 +SRCS_HAL = D3DInit.cpp D3DRaster.cpp D3DTextureMgr.cpp D3DUtils.cpp D3DCaps.cpp
 +OBJS_WGL = $(SRCS_WGL:.c=.obj)
 +OBJS_HAL = $(SRCS_HAL:.cpp=.obj)
 +
 +WINLIBS = kernel32.lib user32.lib gdi32.lib oldnames.lib 
 +DXLIBS = 
 +LIBS = $(WINLIBS) $(DXLIBS) 
 +###############################################################################
 +# Primary Targets                                                             #
 +###############################################################################
 +
 +default: header WGL HAL footer
 +
 +all: default 
 +
 +WGL : $(OBJS_WGL) 
 +        
 +HAL : $(OBJS_HAL)
 +
 +install : forceit
 +	@echo $(SPACE)
 +	@echo ========================================
 +	@echo Install files created.
 +	@echo ========================================
 +
 +        
 +###############################################################################
 +# Secondary Targets                                                           #
 +###############################################################################
 +
 +clean:
 +	@echo ========================================
 +	@echo Cleaning $(TARGET)
 +	@del *.obj 
 +	@del *.dep 
 +	@del *.exp 
 +	@del *.ncb
 +	@del *.plg
 +	@del *.lib
 +	@echo ========================================
 +
 +header:
 +	@echo ============================================================
 +	@echo Building $(TARGET)  ($(BUILD_TYPE) version)
 +	@echo ============================================================
 +	@echo $(SPACE)
 +
 +footer:
 +	@echo $(SPACE)
 +	@echo ============================================================
 +	@echo DONE building $(TARGET)  ($(BUILD_TYPE) version)
 +	@echo ============================================================
 +
 +forceit:
 +
 +
 +
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/NULLProcs.h b/src/mesa/drivers/d3d/NULLProcs.h new file mode 100644 index 0000000000..f0bbd2162d --- /dev/null +++ b/src/mesa/drivers/d3d/NULLProcs.h @@ -0,0 +1,49 @@ +/*===========================================================================*/ +/*                                                                           */ +/* Mesa-3.0 DirectX 6 Driver                                                 */ +/*                                                                           */ +/* By Leigh McRae                                                            */ +/*                                                                           */ +/* http://www.altsoftware.com/                                               */ +/*                                                                           */ +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */ +/*===========================================================================*/ +#ifndef NULL_MESA_PROCS_INC +#define NULL_MESA_PROCS_INC +/*===========================================================================*/ +/* Includes.                                                                 */ +/*===========================================================================*/ +#include "matrix.h" +#include "context.h" +#include "types.h" +#include "vb.h" +/*===========================================================================*/ +/* Macros.                                                                   */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Magic numbers.                                                            */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Type defines.                                                             */ +/*===========================================================================*/ +void NULLSetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ); +void NULLClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ); +GLboolean NULLSetBuffer( GLcontext *ctx, GLenum mode ); +void NULLGetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height ); +GLbitfield NULLClearBuffers( GLcontext *ctx, GLbitfield m, GLboolean a, GLint x, GLint y, GLint w, GLint h ); +void NULLWrSpRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][3], const GLubyte m[] ); +void NULLWrSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][4], const GLubyte m[] ); +void NULLWrSpRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte m[] ); +void NULLWrPiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte r[][4], const GLubyte m[] ); +void NULLWrPiRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte m[] ); +void NULLReSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte r[][4] ); +void NULLRePiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte r[][4], const GLubyte m[] ); +/*===========================================================================*/ +/* Extern function prototypes.                                               */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Global variables.                                                         */ +/*===========================================================================*/ + +#endif + diff --git a/src/mesa/drivers/d3d/NullProcs.c b/src/mesa/drivers/d3d/NullProcs.c new file mode 100644 index 0000000000..e8f18545d1 --- /dev/null +++ b/src/mesa/drivers/d3d/NullProcs.c @@ -0,0 +1,130 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 DirectX 6 Driver                                                 */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "NULLProcs.h"
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLSetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +GLboolean NULLSetBuffer( GLcontext *ctx, GLenum mode )
 +{
 +   return TRUE;
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLGetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height )
 +{
 +  *width = 1;
 +  *height = 1;
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +GLbitfield NULLClearBuffers( GLcontext *ctx, GLbitfield m, GLboolean a, GLint x, GLint y, GLint w, GLint h )
 +{
 +   return m;
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLWrSpRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][3], const GLubyte m[] )
 +{
 +
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLWrSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][4], const GLubyte m[] )
 +{
 +
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLWrSpRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte m[] )
 +{
 +
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLWrPiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte r[][4], const GLubyte m[] )
 +{
 +
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLWrPiRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte m[] )
 +{
 +
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLReSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte r[][4] )
 +{
 +
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +void NULLRePiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte r[][4], const GLubyte m[] )
 +{
 +
 +}
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/OPENGL32.DEF b/src/mesa/drivers/d3d/OPENGL32.DEF new file mode 100644 index 0000000000..19762bbebe --- /dev/null +++ b/src/mesa/drivers/d3d/OPENGL32.DEF @@ -0,0 +1,443 @@ +;===========================================================================
 +;                                                                           
 +; Mesa-3.0 DirectX 6 Driver                                       
 +;                                                                           
 +; By Leigh McRae                                                            
 +;                                                                           
 +; http://www.altsoftware.com/                                               
 +;                                                                           
 +; Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           
 +;===========================================================================
 +NAME OpenGL32.DLL
 +DESCRIPTION "Mesa-3.0 DX6 Driver Version 0.5"
 +
 +EXPORTS
 +	DllMain
 +	glAccum
 +	glAlphaFunc
 +	glAreTexturesResident
 +	glAreTexturesResidentEXT
 +	glArrayElement
 +	glArrayElementEXT
 +	glBegin
 +	glBindTexture
 +	glBindTextureEXT
 +	glBitmap
 +	glBlendColorEXT
 +	glBlendEquationEXT
 +	glBlendFunc
 +	glCallList
 +	glCallLists
 +	glClear
 +	glClearAccum
 +	glClearColor
 +	glClearDepth
 +	glClearIndex
 +	glClearStencil
 +	glClipPlane
 +	glColor3b
 +	glColor3bv
 +	glColor3d
 +	glColor3dv
 +	glColor3f
 +	glColor3fv
 +	glColor3i
 +	glColor3iv
 +	glColor3s
 +	glColor3sv
 +	glColor3ub
 +	glColor3ubv
 +	glColor3ui
 +	glColor3uiv
 +	glColor3us
 +	glColor3usv
 +	glColor4b
 +	glColor4bv
 +	glColor4d
 +	glColor4dv
 +	glColor4f
 +	glColor4fv
 +	glColor4i
 +	glColor4iv
 +	glColor4s
 +	glColor4sv
 +	glColor4ub
 +	glColor4ubv
 +	glColor4ui
 +	glColor4uiv
 +	glColor4us
 +	glColor4usv
 +	glColorMask
 +	glColorMaterial
 +	glColorPointer
 +	glColorPointerEXT
 +	glColorSubTableEXT
 +	glColorTableEXT
 +	glCopyPixels
 +	glCopyTexImage1D
 +	glCopyTexImage2D
 +	glCopyTexSubImage1D
 +	glCopyTexSubImage2D
 +	glCopyTexSubImage3DEXT
 +	glCullFace
 +	glDeleteLists
 +	glDeleteTextures
 +	glDeleteTexturesEXT
 +	glDepthFunc
 +	glDepthMask
 +	glDepthRange
 +	glDisable
 +	glDisableClientState
 +	glDrawArrays
 +	glDrawArraysEXT
 +	glDrawBuffer
 +	glDrawElements
 +	glDrawPixels
 +	glEdgeFlag
 +	glEdgeFlagPointer
 +	glEdgeFlagPointerEXT
 +	glEdgeFlagv
 +	glEnable
 +	glEnableClientState
 +	glEnd
 +	glEndList
 +	glEvalCoord1d
 +	glEvalCoord1dv
 +	glEvalCoord1f
 +	glEvalCoord1fv
 +	glEvalCoord2d
 +	glEvalCoord2dv
 +	glEvalCoord2f
 +	glEvalCoord2fv
 +	glEvalMesh1
 +	glEvalMesh2
 +	glEvalPoint1
 +	glEvalPoint2
 +	glFeedbackBuffer
 +	glFinish
 +	glFlush
 +	glFogf
 +	glFogfv
 +	glFogi
 +	glFogiv
 +	glFrontFace
 +	glFrustum
 +	glGenLists
 +	glGenTextures
 +	glGenTexturesEXT
 +	glGetBooleanv
 +	glGetClipPlane
 +	glGetColorTableEXT
 +	glGetColorTableParameterfvEXT
 +	glGetColorTableParameterivEXT
 +	glGetDoublev
 +	glGetError
 +	glGetFloatv
 +	glGetIntegerv
 +	glGetLightfv
 +	glGetLightiv
 +	glGetMapdv
 +	glGetMapfv
 +	glGetMapiv
 +	glGetMaterialfv
 +	glGetMaterialiv
 +	glGetPixelMapfv
 +	glGetPixelMapuiv
 +	glGetPixelMapusv
 +	glGetPointerv
 +	glGetPointervEXT
 +	glGetPolygonStipple
 +	glGetString
 +	glGetTexEnvfv
 +	glGetTexEnviv
 +	glGetTexGendv
 +	glGetTexGenfv
 +	glGetTexGeniv
 +	glGetTexImage
 +	glGetTexLevelParameterfv
 +	glGetTexLevelParameteriv
 +	glGetTexParameterfv
 +	glGetTexParameteriv
 +	glHint
 +	glIndexd
 +	glIndexdv
 +	glIndexf
 +	glIndexfv
 +	glIndexi
 +	glIndexiv
 +	glIndexMask
 +	glIndexPointer
 +	glIndexPointerEXT
 +	glIndexs
 +	glIndexsv
 +	glIndexub
 +	glIndexubv
 +	glInitNames
 +	glInterleavedArrays
 +	glIsEnabled
 +	glIsList
 +	glIsTexture
 +	glIsTextureEXT
 +	glLightf
 +	glLightfv
 +	glLighti
 +	glLightiv
 +	glLightModelf
 +	glLightModelfv
 +	glLightModeli
 +	glLightModeliv
 +	glLineStipple
 +	glLineWidth
 +	glListBase
 +	glLoadIdentity
 +	glLoadMatrixd
 +	glLoadMatrixf
 +	glLoadName
 +	glLogicOp
 +	glMap1d
 +	glMap1f
 +	glMap2d
 +	glMap2f
 +	glMapGrid1d
 +	glMapGrid1f
 +	glMapGrid2d
 +	glMapGrid2f
 +	glMaterialf
 +	glMaterialfv
 +	glMateriali
 +	glMaterialiv
 +	glMatrixMode
 +	glMultMatrixd
 +	glMultMatrixf
 +	glNewList
 +	glNormal3b
 +	glNormal3bv
 +	glNormal3d
 +	glNormal3dv
 +	glNormal3f
 +	glNormal3fv
 +	glNormal3i
 +	glNormal3iv
 +	glNormal3s
 +	glNormal3sv
 +	glNormalPointer
 +	glNormalPointerEXT
 +	glOrtho
 +	glPassThrough
 +	glPixelMapfv
 +	glPixelMapuiv
 +	glPixelMapusv
 +	glPixelStoref
 +	glPixelStorei
 +	glPixelTransferf
 +	glPixelTransferi
 +	glPixelZoom
 +	glPointParameterfEXT
 +	glPointParameterfvEXT
 +	glPointSize
 +	glPolygonMode
 +	glPolygonOffset
 +	glPolygonOffsetEXT
 +	glPolygonStipple
 +	glPopAttrib
 +	glPopClientAttrib
 +	glPopMatrix
 +	glPopName
 +	glPrioritizeTextures
 +	glPrioritizeTexturesEXT
 +	glPushAttrib
 +	glPushClientAttrib
 +	glPushMatrix
 +	glPushName
 +	glRasterPos2d
 +	glRasterPos2dv
 +	glRasterPos2f
 +	glRasterPos2fv
 +	glRasterPos2i
 +	glRasterPos2iv
 +	glRasterPos2s
 +	glRasterPos2sv
 +	glRasterPos3d
 +	glRasterPos3dv
 +	glRasterPos3f
 +	glRasterPos3fv
 +	glRasterPos3i
 +	glRasterPos3iv
 +	glRasterPos3s
 +	glRasterPos3sv
 +	glRasterPos4d
 +	glRasterPos4dv
 +	glRasterPos4f
 +	glRasterPos4fv
 +	glRasterPos4i
 +	glRasterPos4iv
 +	glRasterPos4s
 +	glRasterPos4sv
 +	glReadBuffer
 +	glReadPixels
 +	glRectd
 +	glRectdv
 +	glRectf
 +	glRectfv
 +	glRecti
 +	glRectiv
 +	glRects
 +	glRectsv
 +	glRenderMode
 +	glResizeBuffersMESA
 +	glRotated
 +	glRotatef
 +	glScaled
 +	glScalef
 +	glScissor
 +	glSelectBuffer
 +	glShadeModel
 +	glStencilFunc
 +	glStencilMask
 +	glStencilOp
 +	glTexCoord1d
 +	glTexCoord1dv
 +	glTexCoord1f
 +	glTexCoord1fv
 +	glTexCoord1i
 +	glTexCoord1iv
 +	glTexCoord1s
 +	glTexCoord1sv
 +	glTexCoord2d
 +	glTexCoord2dv
 +	glTexCoord2f
 +	glTexCoord2fv
 +	glTexCoord2i
 +	glTexCoord2iv
 +	glTexCoord2s
 +	glTexCoord2sv
 +	glTexCoord3d
 +	glTexCoord3dv
 +	glTexCoord3f
 +	glTexCoord3fv
 +	glTexCoord3i
 +	glTexCoord3iv
 +	glTexCoord3s
 +	glTexCoord3sv
 +	glTexCoord4d
 +	glTexCoord4dv
 +	glTexCoord4f
 +	glTexCoord4fv
 +	glTexCoord4i
 +	glTexCoord4iv
 +	glTexCoord4s
 +	glTexCoord4sv
 +	glTexCoordPointer
 +	glTexCoordPointerEXT
 +	glTexEnvf
 +	glTexEnvfv
 +	glTexEnvi
 +	glTexEnviv
 +	glTexGend
 +	glTexGendv
 +	glTexGenf
 +	glTexGenfv
 +	glTexGeni
 +	glTexGeniv
 +	glTexImage1D
 +	glTexImage2D
 +	glTexImage3DEXT
 +	glTexParameterf
 +	glTexParameterfv
 +	glTexParameteri
 +	glTexParameteriv
 +	glTexSubImage1D
 +	glTexSubImage2D
 +	glTexSubImage3DEXT
 +	glTranslated
 +	glTranslatef
 +	glVertex2d
 +	glVertex2dv
 +	glVertex2f
 +	glVertex2fv
 +	glVertex2i
 +	glVertex2iv
 +	glVertex2s
 +	glVertex2sv
 +	glVertex3d
 +	glVertex3dv
 +	glVertex3f
 +	glVertex3fv
 +	glVertex3i
 +	glVertex3iv
 +	glVertex3s
 +	glVertex3sv
 +	glVertex4d
 +	glVertex4dv
 +	glVertex4f
 +	glVertex4fv
 +	glVertex4i
 +	glVertex4iv
 +	glVertex4s
 +	glVertex4sv
 +	glVertexPointer
 +	glVertexPointerEXT
 +	glViewport
 +	glWindowPos2dMESA
 +	glWindowPos2dvMESA
 +	glWindowPos2fMESA
 +	glWindowPos2fvMESA
 +	glWindowPos2iMESA
 +	glWindowPos2ivMESA
 +	glWindowPos2sMESA
 +	glWindowPos2svMESA
 +	glWindowPos3dMESA
 +	glWindowPos3dvMESA
 +	glWindowPos3fMESA
 +	glWindowPos3fvMESA
 +	glWindowPos3iMESA
 +	glWindowPos3ivMESA
 +	glWindowPos3sMESA
 +	glWindowPos3svMESA
 +	glWindowPos4dMESA
 +	glWindowPos4dvMESA
 +	glWindowPos4fMESA
 +	glWindowPos4fvMESA
 +	glWindowPos4iMESA
 +	glWindowPos4ivMESA
 +	glWindowPos4sMESA
 +	glWindowPos4svMESA
 +;    WMesaCreateContext
 +;    WMesaDestroyContext
 +;    WMesaMakeCurrent
 +;    WMesaPaletteChange
 +;    WMesaSwapBuffers
 +;    OSMesaCreateContext
 +;    OSMesaDestroyContext
 +;    OSMesaMakeCurrent
 +;    OSMesaGetCurrentContext
 +;    OSMesaPixelStore
 +;    OSMesaGetIntegerv
 +;    OSMesaGetDepthBuffer
 +	wglCopyContext
 +	wglCreateContext
 +	wglCreateLayerContext
 +	wglDeleteContext
 +;	wglDescribeLayerPlane
 +	wglGetCurrentContext
 +	wglGetCurrentDC
 +;	wglGetLayerPaletteEntries
 +	wglGetProcAddress
 +	wglMakeCurrent
 +;	wglRealizeLayerPalette
 +;	wglSetLayerPaletteEntries
 +	wglShareLists
 +	wglSwapLayerBuffers
 +	wglUseFontBitmapsA
 +	wglUseFontBitmapsW
 +	wglUseFontOutlinesA
 +	wglUseFontOutlinesW
 +	wglChoosePixelFormat
 +	wglDescribePixelFormat
 +	wglGetPixelFormat
 +	wglSetPixelFormat
 +	wglSwapBuffers
 +    
 +
 +
 +
\ No newline at end of file diff --git a/src/mesa/drivers/d3d/WGL.C b/src/mesa/drivers/d3d/WGL.C new file mode 100644 index 0000000000..2d1a6a0c4d --- /dev/null +++ b/src/mesa/drivers/d3d/WGL.C @@ -0,0 +1,1262 @@ +/*===========================================================================*/
 +/*                                                                           */
 +/* Mesa-3.0 Makefile for DirectX 6                                           */
 +/*                                                                           */
 +/* By Leigh McRae                                                            */
 +/*                                                                           */
 +/* http://www.altsoftware.com/                                               */
 +/*                                                                           */
 +/* Copyright (c) 1998-1997  alt.software inc.  All Rights Reserved           */
 +/*===========================================================================*/
 +#include "D3DMesa.h"
 +/*===========================================================================*/
 +/* Window managment.                                                         */
 +/*===========================================================================*/
 +static BOOL    InitOpenGL( HINSTANCE hInst );
 +static BOOL    TermOpenGL( HINSTANCE hInst );
 +static BOOL     ResizeContext( GLcontext *ctx );
 +static BOOL    MakeCurrent( D3DMESACONTEXT *pContext );
 +static void    DestroyContext( D3DMESACONTEXT *pContext );
 +static BOOL    UnBindWindow( D3DMESACONTEXT *pContext );
 +LONG APIENTRY  wglMonitorProc( HWND hwnd, UINT message, UINT wParam, LONG lParam );
 +/*===========================================================================*/
 +/* Mesa hooks.                                                               */
 +/*===========================================================================*/
 +static void SetupDDPointers( GLcontext *ctx );
 +static void SetupSWDDPointers( GLcontext *ctx );
 +static void SetupHWDDPointers( GLcontext *ctx );
 +static void SetupNULLDDPointers( GLcontext *ctx );
 +static const char *RendererString( void );
 +
 +/* State Management hooks. */
 +static void       SetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
 +static void       ClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
 +static GLboolean SetBuffer( GLcontext *ctx, GLenum buffer );
 +
 +/* Window Management hooks. */
 +static void GetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height );
 +static void SetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h );
 +static void Flush( GLcontext *ctx );
 +
 +/* Span rendering hooks. */
 +void WSpanRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] );
 +void WSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
 +void WSpanRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] );
 +void WPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
 +void WPixelsRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] );
 +void RSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
 +void RPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
 +GLbitfield ClearBuffers( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
 +
 +/* Primitve rendering hooks. */
 +GLboolean  RenderVertexBuffer( GLcontext *ctx, GLboolean allDone );
 +void             RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv );
 +void     RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv );
 +GLbitfield ClearBuffersD3D( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
 +
 +/* Texture Management hooks. */
 +static void TextureBind( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj );
 +static void TextureLoad( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint internalFormat, const struct gl_texture_image *image );
 +static void TextureSubImage( 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 );
 +/*===========================================================================*/
 +/* Global variables.                                                         */
 +/*===========================================================================*/
 +D3DMESACONTEXT *pD3DCurrent,     
 +	       *pD3DDefault;     /* Thin support context. */
 +
 +struct __extensions__   ext[] = {
 +
 +    { (PROC)glPolygonOffsetEXT,        "glPolygonOffsetEXT"       },
 +    { (PROC)glBlendEquationEXT,        "glBlendEquationEXT"       },
 +    { (PROC)glBlendColorEXT,           "glBlendColorExt"          },
 +    { (PROC)glVertexPointerEXT,        "glVertexPointerEXT"       },
 +    { (PROC)glNormalPointerEXT,        "glNormalPointerEXT"       },
 +    { (PROC)glColorPointerEXT,         "glColorPointerEXT"        },
 +    { (PROC)glIndexPointerEXT,         "glIndexPointerEXT"        },
 +    { (PROC)glTexCoordPointerEXT,      "glTexCoordPointer"        },
 +    { (PROC)glEdgeFlagPointerEXT,      "glEdgeFlagPointerEXT"     },
 +    { (PROC)glGetPointervEXT,          "glGetPointervEXT"         },
 +    { (PROC)glArrayElementEXT,         "glArrayElementEXT"        },
 +    { (PROC)glDrawArraysEXT,           "glDrawArrayEXT"           },
 +    { (PROC)glAreTexturesResidentEXT,  "glAreTexturesResidentEXT" },
 +    { (PROC)glBindTextureEXT,          "glBindTextureEXT"         },
 +    { (PROC)glDeleteTexturesEXT,       "glDeleteTexturesEXT"      },
 +    { (PROC)glGenTexturesEXT,          "glGenTexturesEXT"         },
 +    { (PROC)glIsTextureEXT,            "glIsTextureEXT"           },
 +    { (PROC)glPrioritizeTexturesEXT,   "glPrioritizeTexturesEXT"  },
 +    { (PROC)glCopyTexSubImage3DEXT,    "glCopyTexSubImage3DEXT"   },
 +    { (PROC)glTexImage3DEXT,           "glTexImage3DEXT"          },
 +    { (PROC)glTexSubImage3DEXT,        "glTexSubImage3DEXT"       },
 +};
 +
 +int             qt_ext = sizeof(ext) / sizeof(ext[0]);
 +float   g_DepthScale,
 +	  g_MaxDepth;
 +/*===========================================================================*/
 +/*  When a process loads this DLL we will setup the linked list for context  */
 +/* management and create a default context that will support the API until   */
 +/* the user creates and binds thier own.  This THIN default context is useful*/
 +/* to have around.                                                           */
 +/*  When the process terminates we will clean up all resources here.         */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +BOOL APIENTRY   DllMain( HINSTANCE hInst, DWORD reason, LPVOID reserved )
 +{
 +  switch( reason ) 
 +  {
 +    case DLL_PROCESS_ATTACH:
 +	 return InitOpenGL( hInst );
 +
 +    case DLL_PROCESS_DETACH:
 +	 return TermOpenGL( hInst );
 +  }     
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  The first thing we do when this dll is hit is connect to the dll that has*/
 +/* handles all the DirectX 6 rendering.  I decided to use another dll as DX6 */
 +/* is all C++ and Mesa-3.0 is C (thats a good thing).  This way I can write  */
 +/* the DX6 in C++ and Mesa-3.0 in C without having to worry about linkage.   */
 +/* I feel this is easy and better then using static wrappers as it is likely */
 +/* faster and it allows me to just develope the one without compiling the    */
 +/* other.                                                                    */
 +/*  NOTE that at this point we don't have much other than a very thin context*/
 +/* that will support the API calls only to the point of not causing the app  */
 +/* to crash from the API table being empty.                                  */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +static BOOL  InitOpenGL( HINSTANCE hInst )
 +{
 +  /* Allocate and clear the default context. */
 +  pD3DDefault = (PD3DMESACONTEXT)ALLOC( sizeof(D3DMESACONTEXT) );
 +  if ( pD3DDefault == NULL )
 +    return FALSE;
 +  memset( pD3DDefault, 0, sizeof(D3DMESACONTEXT) );
 +
 +  /*  Clear the D3D vertex buffer so that values not used will be zero.  This */
 +  /* save me from some redundant work.                                        */
 +  memset( &D3DTLVertices, 0, sizeof(D3DTLVertices) );
 +
 +  /*  Update the link.  We uses a circular list so that it is easy to  */
 +  /* add and search.  This context will also be used for head and tail.*/
 +  pD3DDefault->next = pD3DDefault;
 +
 +  /*========================================================================*/
 +  /* Do all core Mesa stuff.                                                */
 +  /*========================================================================*/
 +  pD3DDefault->gl_visual = gl_create_visual( TRUE,
 +									GL_FALSE,   /* software alpha */
 +									FALSE,      /* db_flag */
 +									GL_FALSE,   /* stereo */
 +									16,         /* depth_bits */
 +									8,          /* stencil_bits */
 +									8,          /* accum_bits */
 +									0,          /* index bits */
 +									8,8,8,8 );  /* r, g, b, a bits */
 +
 +  if ( pD3DDefault->gl_visual == NULL)  
 +  {
 +    FREE( pD3DDefault );
 +    return FALSE;
 +  }
 +
 +  /* Allocate a new Mesa context */
 +  pD3DDefault->gl_ctx = gl_create_context( pD3DDefault->gl_visual, NULL, pD3DDefault, GL_TRUE );
 +  if ( pD3DDefault->gl_ctx == NULL ) 
 +  {
 +    gl_destroy_visual( pD3DDefault->gl_visual );
 +    FREE( pD3DDefault );
 +    return FALSE;
 +  }
 +
 +  /* Allocate a new Mesa frame buffer */
 +  pD3DDefault->gl_buffer = gl_create_framebuffer( pD3DDefault->gl_visual );
 +  if ( pD3DDefault->gl_buffer == NULL )
 +  {
 +    gl_destroy_visual( pD3DDefault->gl_visual );
 +    gl_destroy_context( pD3DDefault->gl_ctx );
 +    FREE( pD3DDefault );
 +    return FALSE;
 +  }
 +  SetupDDPointers( pD3DDefault->gl_ctx );
 +  gl_make_current( pD3DDefault->gl_ctx, pD3DDefault->gl_buffer );
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function will create a new D3D context but will not create the D3D  */
 +/* surfaces or even an instance of D3D (see at GetBufferSize). The only stuff*/
 +/* done here is the internal Mesa stuff and some Win32 handles.              */
 +/*===========================================================================*/
 +/* RETURN: casted pointer to the context, NULL.                              */
 +/*===========================================================================*/
 +HGLRC APIENTRY wglCreateContext( HDC hdc )
 +{
 +  D3DMESACONTEXT        *pNewContext;
 +  DWORD                 dwCoopFlags = DDSCL_NORMAL;
 +  RECT                  rectClient;
 +  POINT                 pt;
 +
 +  /* ALLOC and clear the new context. */
 +  pNewContext = (PD3DMESACONTEXT)ALLOC( sizeof(D3DMESACONTEXT) );
 +  if ( pNewContext == NULL )
 +  {
 +    SetLastError( 0 );
 +    return (HGLRC)NULL;
 +  }
 +  memset( pNewContext, 0, sizeof(D3DMESACONTEXT) );
 +
 +  /*========================================================================*/
 +  /* Do all core Mesa stuff.                                                */
 +  /*========================================================================*/
 +
 +  /* TODO: support more then one visual. */
 +  pNewContext->gl_visual = gl_create_visual( TRUE,
 +									GL_TRUE,   /* software alpha */
 +									TRUE,       /* db_flag */
 +									GL_FALSE,   /* stereo */
 +									16,         /* depth_bits */
 +									8,          /* stencil_bits */
 +									8,          /* accum_bits */
 +									0,          /* index bits */
 +									8,8,8,8 );  /* r, g, b, a bits */
 +  if ( pNewContext->gl_visual == NULL) 
 +  {
 +    FREE( pNewContext );
 +    SetLastError( 0 );
 +    return (HGLRC)NULL;
 +  }
 +
 +  /* Allocate a new Mesa context */
 +  pNewContext->gl_ctx = gl_create_context( pNewContext->gl_visual, NULL, pNewContext, GL_TRUE );
 +  if ( pNewContext->gl_ctx == NULL ) 
 +  {
 +    gl_destroy_visual( pNewContext->gl_visual );
 +    FREE( pNewContext );
 +    SetLastError( 0 );
 +    return (HGLRC)NULL;
 +  }
 +
 +  /* Allocate a new Mesa frame buffer */
 +  pNewContext->gl_buffer = gl_create_framebuffer( pNewContext->gl_visual );
 +  if ( pNewContext->gl_buffer == NULL )
 +  {
 +    gl_destroy_visual( pNewContext->gl_visual );
 +    gl_destroy_context( pNewContext->gl_ctx );
 +    FREE( pNewContext );
 +    SetLastError( 0 );
 +    return (HGLRC)NULL;
 +  }
 +
 +  /*========================================================================*/
 +  /* Do all the driver stuff.                                               */
 +  /*========================================================================*/
 +  pNewContext->hdc  = hdc;
 +  pNewContext->next = pD3DDefault->next;
 +  pD3DDefault->next = pNewContext; /* Add to circular list. */
 +
 +  /* Create the HAL for the new context. */
 +  pNewContext->pShared = InitHAL( WindowFromDC(hdc) );
 +
 +  return (HGLRC)pNewContext;
 +}
 +/*===========================================================================*/
 +/*  This is a wrapper function that is supported by MakeCurrent.             */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglMakeCurrent( HDC hdc, HGLRC hglrc )
 +{
 +   return MakeCurrent((D3DMESACONTEXT *)hglrc);
 +}
 +/*===========================================================================*/
 +/*  MakeCurrent will unbind whatever context is current (if any) & then bind */
 +/* the supplied context.  A context that is bound has it's window proc hooked*/
 +/* with the wglMonitorProc and the context pointer is saved in pD3DCurrent.    */
 +/* Once the context is bound we update the Mesa-3.0 hooks (SetDDPointers) and*/
 +/* the viewport (Mesa-.30 and DX6).                                          */
 +/*                                                                           */
 +/* TODO: this function can't fail.                                           */
 +/*===========================================================================*/
 +/* RETURN: TRUE                                                              */
 +/*===========================================================================*/
 +static BOOL MakeCurrent( D3DMESACONTEXT *pContext )
 +{
 +   D3DMESACONTEXT *pNext;
 +
 +   /*====================================================================*/
 +   /* This is a special case that is a request to have no context bound. */
 +   /*====================================================================*/
 +   if ( pContext == NULL )
 +   {
 +	/* Walk the whole list. We start and end at the Default context. */
 +	for( pNext = pD3DDefault->next; pNext != pD3DDefault; pNext = pNext->next )
 +	  UnBindWindow( pNext );
 +      
 +	return TRUE;
 +   }
 +
 +   /*=================================================*/
 +   /* Make for a fast redundant use of this function. */
 +   /*=================================================*/
 +   if ( pD3DCurrent == pContext )
 +      return TRUE;
 +
 +   /*=============================*/
 +   /* Unbind the current context. */
 +   /*=============================*/
 +   UnBindWindow( pD3DCurrent );
 +
 +   /*=====================================*/
 +   /* Let Mesa-3.0 we have a new context. */
 +   /*=====================================*/
 +   SetupDDPointers( pContext->gl_ctx );
 +   gl_make_current( pContext->gl_ctx, pContext->gl_buffer );
 +
 +   /*  We are done so set the internal current context. */
 +   if ( pContext != pD3DDefault )
 +   {
 +	ResizeContext( pContext->gl_ctx );
 +	pContext->hOldProc = (WNDPROC)GetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC );
 +	SetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC, (LONG)wglMonitorProc );
 +   }
 +   pD3DCurrent = pContext;
 +
 +   return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function will only return the current window size.  I have re-done  */   
 +/* this function so that it doesn't check the current size and react to it as*/   
 +/* I should be able to have all the react code in the WM_SIZE message.  The  */   
 +/* old version would check the current window size and create/resize the HAL */   
 +/* surfaces if they have changed.  I needed to delay the creation if the     */   
 +/* surfaces because sometimes I wouldn't have a window size so this is where */   
 +/* I delayed it.  If you are reading this then all went ok!                  */   
 +/*  The default context will return a zero sized window and I'm not sure if  */
 +/* this is ok at this point (TODO).                                          */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void GetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height )
 +{
 +  D3DMESACONTEXT        *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +  /* Fall through for the default because that is one of the uses for it. */
 +  if ( pContext == pD3DDefault )
 +  {
 +    *width  = 0;
 +    *height = 0;
 +  }
 +  else
 +  {
 +    *width  = pContext->pShared->dwWidth;
 +    *height = pContext->pShared->dwHeight;
 +  }
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static BOOL ResizeContext( GLcontext *ctx )
 +{
 +  D3DMESACONTEXT        *pContext = (D3DMESACONTEXT *)ctx->DriverCtx,
 +		    *pCurrentTemp;
 +  RECT                  rectClient;
 +  POINT                 pt;
 +  DWORD                 dwWidth,
 +		    dwHeight;
 +  static BOOL           bDDrawLock = FALSE;
 +
 +  /* Make sure we have some values. */
 +  if ( (pContext->hdc == NULL ) || 
 +	  (pContext->pShared->hwnd != WindowFromDC(pContext->hdc)) ||
 +       (pContext == pD3DDefault) )
 +    return FALSE;
 +
 +  /* Having problems with DDraw sending resize messages before I was done. */
 +  if( bDDrawLock == TRUE )
 +    return FALSE;
 +
 +  // TODO: don't think I need this anymore.
 +  pCurrentTemp = pD3DCurrent;
 +  pD3DCurrent = pD3DDefault;
 +  bDDrawLock = TRUE;
 +
 +  /* Get the current window dimentions. */
 +  UpdateScreenPosHAL( pContext->pShared );
 +  dwWidth  = pContext->pShared->rectW.right - pContext->pShared->rectW.left;
 +  dwHeight = pContext->pShared->rectW.bottom - pContext->pShared->rectW.top;
 +
 +  /* Is the size of the OffScreen Render different? */
 +  if ( (dwWidth != pContext->pShared->dwWidth) || (dwHeight != pContext->pShared->dwHeight) )
 +  {
 +    /* Create all the D3D surfaces and device. */
 +    CreateHAL( pContext->pShared );
 +
 +    /*  I did this so that software rendering would still work as */
 +    /* I don't need to scale the z values twice.                  */
 +    g_DepthScale        = (pContext->pShared->bHardware) ? 1.0 : ((float)0x00FFFFFF);
 +    g_MaxDepth          = (pContext->pShared->bHardware) ? 1.0 : ((float)0x00FFFFFF);
 +    gl_DepthRange( pContext->gl_ctx, ctx->Viewport.Near, ctx->Viewport.Far );
 +
 +    /* Make sure we have a viewport. */
 +    gl_Viewport( pContext->gl_ctx, 0, 0, dwWidth, dwHeight );
 +
 +    /* Update Mesa as we might have changed from SW <-> HW. */
 +    SetupDDPointers( pContext->gl_ctx );
 +    gl_make_current( pContext->gl_ctx, pContext->gl_buffer );
 +
 +    /*  If we are in HW we need to load the current texture if there is one already. */
 +    //    if ( (ctx->Texture.Set[ctx->Texture.CurrentSet].Current != NULL) &&
 +    //      (pContext->pShared->bHardware == TRUE) )
 +    //    {
 +    //   CreateTMgrHAL( pContext->pShared,
 +    //                           ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name,
 +    //                           0,     
 +    //                           ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format,
 +    //                           (RECT *)NULL,
 +    //                           ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Width,
 +    //                           ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Height,
 +    //                           TM_ACTION_BIND,
 +    //                           (void *)ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Data );
 +    //    }
 +  }
 +
 +  // TODO: don't think I need this anymore.
 +  pD3DCurrent = pCurrentTemp;
 +  bDDrawLock = FALSE;
 +
 +  return TRUE;
 +}
 +
 +/*===========================================================================*
 +/*  This function will Blt the render buffer to the PRIMARY surface. I repeat*/
 +/* this code for the other SwapBuffer like functions and the flush (didn't   */
 +/* want the function calling overhead).  Thsi could have been a macro...     */
 +/*                                                                           */
 +/* TODO: there are some problems with viewport/scissoring.                   */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglSwapBuffers( HDC hdc )
 +{
 +  /* Fall through for the default because that is one of the uses for it. */
 +  if ( pD3DCurrent == pD3DDefault )
 +    return FALSE;
 +
 +  SwapBuffersHAL( pD3DCurrent->pShared );
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  Same as wglSwapBuffers.                                                  */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +BOOL APIENTRY  SwapBuffers( HDC hdc )
 +{
 +  /* Fall through for the default because that is one of the uses for it. */
 +  if ( pD3DCurrent == pD3DDefault )
 +    return FALSE;
 +
 +  SwapBuffersHAL( pD3DCurrent->pShared );
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This should be ok as none of the SwapBuffers will cause a redundant Blt  */
 +/* as none of my Swap functions will call flush.  This should also allow     */
 +/* sinlge buffered applications to work (not really worried though).  Some   */
 +/* applications may flush then swap but then this is there fault IMHO.       */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void Flush( GLcontext *ctx )
 +{
 +  /* Fall through for the default because that is one of the uses for it. */
 +  if ( pD3DCurrent == pD3DDefault )
 +    return;
 +
 +  SwapBuffersHAL( pD3DCurrent->pShared );
 +}
 +/*===========================================================================*/
 +/*  For now this function will ignore the supplied PF. If I'm going to allow */
 +/* the user to choice the mode and device at startup I'm going to have to do */
 +/* something different.                                                      */
 +/*                                                                           */
 +/* TODO: use the linked list of modes to build a pixel format to be returned */
 +/*      to the caller.                                                       */
 +/*===========================================================================*/
 +/* RETURN: 1.                                                                */
 +/*===========================================================================*/
 +int APIENTRY   wglChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd )
 +{
 +   return 1;
 +}
 +/*===========================================================================*/
 +/*  See wglChoosePixelFormat.                                                */
 +/*===========================================================================*/
 +/* RETURN: 1.                                                                */
 +/*===========================================================================*/
 +int APIENTRY   ChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd )
 +{
 +  return wglChoosePixelFormat(hdc,ppfd);
 +}
 +/*===========================================================================*/
 +/*  This function (for now) returns a static PF everytime.  This is just to  */
 +/* allow things to continue.                                                 */
 +/*===========================================================================*/
 +/* RETURN: 1.                                                                */
 +/*===========================================================================*/
 +int APIENTRY   wglDescribePixelFormat( HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd )
 +{
 +   static PIXELFORMATDESCRIPTOR  pfd = 
 +   {
 +      sizeof(PIXELFORMATDESCRIPTOR),   /* size */
 +      1,                               /* version */
 +      PFD_SUPPORT_OPENGL |
 +      PFD_DRAW_TO_WINDOW |
 +      PFD_DOUBLEBUFFER,                /* support double-buffering */
 +      PFD_TYPE_RGBA,                   /* color type */
 +      16,                              /* prefered color depth */
 +      0, 0, 0, 0, 0, 0,                /* color bits (ignored) */
 +      0,                               /* no alpha buffer */
 +      0,                               /* alpha bits (ignored) */
 +      0,                               /* no accumulation buffer */
 +      0, 0, 0, 0,                      /* accum bits (ignored) */
 +      16,                              /* depth buffer */
 +      0,                               /* no stencil buffer */
 +      0,                               /* no auxiliary buffers */
 +      PFD_MAIN_PLANE,                  /* main layer */
 +      0,                               /* reserved */
 +      0, 0, 0,                         /* no layer, visible, damage masks */
 +   };
 +
 +   /* Return the address of this static PF if one was requested. */
 +   if ( ppfd != NULL )
 +      memcpy( ppfd, &pfd, sizeof(PIXELFORMATDESCRIPTOR) );
 +
 +  return 1;
 +}
 +/*===========================================================================*/
 +/*  See wglDescribePixelFormat.                                              */
 +/*===========================================================================*/
 +/* RETURN: 1.                                                                */
 +/*===========================================================================*/
 +int APIENTRY   DescribePixelFormat( HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd )
 +{
 +  return wglDescribePixelFormat(hdc,iPixelFormat,nBytes,ppfd);
 +}
 +/*===========================================================================*/
 +/*  This function will always return 1 for now.  Just to allow for support.  */
 +/*===========================================================================*/
 +/* RETURN: 1.                                                                */
 +/*===========================================================================*/
 +int APIENTRY   wglGetPixelFormat( HDC hdc )
 +{
 +   return 1;
 +}
 +/*===========================================================================*/
 +/*  See wglGetPixelFormat.                                                   */
 +/*===========================================================================*/
 +/* RETURN: 1.                                                                */
 +/*===========================================================================*/
 +int APIENTRY   GetPixelFormat( HDC hdc )
 +{
 +   return wglGetPixelFormat(hdc);
 +}
 +/*===========================================================================*/
 +/*  This will aways work for now.                                            */
 +/*===========================================================================*/
 +/* RETURN: TRUE.                                                             */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglSetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR *ppfd )
 +{
 +   return TRUE;
 +}
 +/*===========================================================================*/
 +/*  See wglSetPixelFormat.                                                   */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +BOOL APIENTRY  SetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR *ppfd )
 +{
 +   return wglSetPixelFormat(hdc,iPixelFormat,ppfd);
 +}
 +/*===========================================================================*/
 +/*  This is a wrapper function that is supported by my own internal function.*/
 +/* that takes my own D3D Mesa context structure.  This so I can reuse the    */
 +/* function (no need for speed).                                             */
 +/*===========================================================================*/
 +/* RETURN: TRUE.                                                             */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglDeleteContext( HGLRC hglrc )
 +{
 +   DestroyContext( (D3DMESACONTEXT *)hglrc );
 +
 +   return TRUE;
 +}
 +/*===========================================================================*/
 +/*  Simple getter function that uses a cast.                                 */
 +/*===========================================================================*/
 +/* RETURN: casted pointer to the context, NULL.                              */
 +/*===========================================================================*/
 +HGLRC APIENTRY wglGetCurrentContext( VOID )
 +{
 +   return (pD3DCurrent) ? (HGLRC)pD3DCurrent : (HGLRC)NULL;
 +}
 +/*===========================================================================*/
 +/* No support.                                                               */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask )
 +{
 +   SetLastError( 0 );
 +   return FALSE;
 +}
 +/*===========================================================================*/
 +/* No support.                                                               */
 +/*===========================================================================*/
 +/* RETURN: NULL.                                                             */
 +/*===========================================================================*/
 +HGLRC APIENTRY wglCreateLayerContext( HDC hdc,int iLayerPlane )
 +{
 +   SetLastError( 0 );
 +   return (HGLRC)NULL;
 +}
 +/*===========================================================================*/
 +/*  Simple getter function.                                                  */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +HDC APIENTRY   wglGetCurrentDC( VOID )
 +{
 +   return (pD3DCurrent) ? pD3DCurrent->hdc : (HDC)NULL;
 +}
 +/*===========================================================================*/
 +/*  Simply call that searches the supported extensions for a match & returns */
 +/* the pointer to the function that lends support.                           */
 +/*===========================================================================*/
 +/* RETURN: pointer to API call, NULL.                                        */
 +/*===========================================================================*/
 +PROC APIENTRY  wglGetProcAddress( LPCSTR lpszProc )
 +{
 +   int   index;
 +
 +   for( index = 0; index < qt_ext; index++ )
 +      if( !strcmp(lpszProc,ext[index].name) )
 +	 return ext[index].proc;
 +
 +   SetLastError( 0 );
 +   return NULL;
 +}
 +/*===========================================================================*/
 +/*  No support.                                                              */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglShareLists( HGLRC hglrc1, HGLRC hglrc2 )
 +{
 +   SetLastError( 0 );
 +   return FALSE;
 +}
 +/*===========================================================================*/
 +/*  No support.                                                              */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglUseFontBitmaps( HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase )
 +{
 +   SetLastError( 0 );
 +   return FALSE;
 +}
 +/*===========================================================================*/
 +/*  No support.                                                              */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglUseFontBitmapsW( HDC hdc,DWORD first,DWORD count,DWORD listBase )
 +{
 +   SetLastError( 0 );
 +   return FALSE;
 +}
 +/*===========================================================================*/
 +/*  No support.                                                              */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglUseFontOutlinesA( HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf )
 +{
 +   SetLastError( 0 );
 +   return FALSE;
 +}
 +/*===========================================================================*/
 +/*  No support.                                                              */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglUseFontOutlinesW( HDC hdc,DWORD first,DWORD count, DWORD listBase,FLOAT deviation, FLOAT extrusion,int format, LPGLYPHMETRICSFLOAT lpgmf )
 +{
 +   SetLastError( 0 );
 +   return FALSE ;
 +}
 +/*===========================================================================*/
 +/*  No support.                                                              */
 +/*===========================================================================*/
 +/* RETURN: FALSE.                                                            */
 +/*===========================================================================*/
 +BOOL APIENTRY  wglSwapLayerBuffers( HDC hdc, UINT fuPlanes )
 +{
 +   SetLastError( 0 );
 +   return FALSE;
 +}
 +/*===========================================================================*/
 +/*  This function will be hooked into the window that has been bound.  Right */
 +/* now it is used to track the window size and position.  Also the we clean  */
 +/* up the currrent context when the window is close/destroyed.               */
 +/*                                                                           */
 +/* TODO: there might be something wrong here as some games (Heretic II) don't*/
 +/*      track the window quit right.                                         */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +LONG APIENTRY  wglMonitorProc( HWND hwnd, UINT message, UINT wParam, LONG lParam )
 +{
 +  WNDPROC       hOldProc;
 +  GLint width,
 +	  height;
 +
 +  switch( message ) 
 +  {
 +//      case WM_PAINT:
 +//        break;
 +//      case WM_ACTIVATE:
 +//         break;
 +//      case WM_SHOWWINDOW:
 +//         break;
 +
 +    case UM_FATALSHUTDOWN:
 +	 /* Support the API until we die... */
 +	 MakeCurrent( pD3DDefault );
 +	 break;
 +
 +    case WM_MOVE:
 +    case WM_DISPLAYCHANGE:
 +    case WM_SIZE:
 +	 ResizeContext( pD3DCurrent->gl_ctx );
 +	 break;
 +
 +    case WM_CLOSE:
 +    case WM_DESTROY:
 +	 /* Support the API until we die... */
 +	 hOldProc = pD3DCurrent->hOldProc;
 +	 DestroyContext( pD3DCurrent );
 +	 return (hOldProc)(hwnd,message,wParam,lParam);
 +  }
 +
 +  return (pD3DCurrent->hOldProc)(hwnd,message,wParam,lParam);
 +}
 +
 +/**********************************************************************/
 +/*****              Miscellaneous device driver funcs             *****/
 +/**********************************************************************/
 +
 +/*===========================================================================*/
 +/*  Not reacting to this as I'm only supporting drawing to the back buffer   */
 +/* right now.                                                                */
 +/*===========================================================================*/
 +/* RETURN: TRUE.                                                             */
 +/*===========================================================================*/
 +static GLboolean SetBuffer( GLcontext *ctx, GLenum buffer )
 +{
 +   if (buffer == GL_BACK_LEFT)
 +      return GL_TRUE;
 +   else
 +      return GL_FALSE;
 +}
 +/*===========================================================================*/
 +/*  This proc will be called by Mesa when the viewport has been set.  So if  */
 +/* we have a context and it isn't the default then we should let D3D know of */
 +/* the change.                                                               */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void SetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +   RECT           rect;
 +
 +   /* Make sure we can set a viewport. */
 +   if ( pContext->pShared && (pContext != pD3DDefault) )
 +   {
 +	 // TODO: might be needed.
 +     UpdateScreenPosHAL( pContext->pShared );
 +	rect.left   = x;
 +	rect.right  = x + w;
 +	rect.top    = y;
 +	rect.bottom = y + h;
 +
 +	// TODO: shared struct should make this call smaller
 +     SetViewportHAL( pContext->pShared, &rect, 0.0F, 1.0F );
 +   }
 +}
 +/*===========================================================================*/
 +/*  This function could be better I guess but I decided just to grab the four*/
 +/* components and store then seperately.  Makes it easier to use IMHO.       */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void ClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +   pContext->aClear = a;
 +   pContext->bClear = b;
 +   pContext->gClear = g;
 +   pContext->rClear = r;
 +}
 +/*===========================================================================*/
 +/*  This function could be better I guess but I decided just to grab the four*/
 +/* components and store then seperately.  Makes it easier to use IMHO.       */
 +/* (is there an echo in here?)                                               */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void SetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +   pContext->aCurrent = a;
 +   pContext->bCurrent = b;
 +   pContext->gCurrent = g;
 +   pContext->rCurrent = r;
 +}
 +/*===========================================================================*/
 +/*                                                                           */
 +/*                                                                           */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static const char *RendererString( void )
 +{
 +  static char pszRender[64];
 +
 +  strcpy( pszRender, "altD3D " );
 +
 +  if ( pD3DCurrent->pShared->bHardware )
 +    strcat( pszRender, "(HW)");
 +  else
 +    strcat( pszRender, "(SW)");
 +
 +  return (const char *)pszRender;
 +}
 +/*===========================================================================*/
 +/*  This function will choose which set of pointers Mesa will use based on   */
 +/* whether we hard using hardware or software.  I have added another set of  */
 +/* pointers that will do nothing but stop the API from crashing.             */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void SetupDDPointers( GLcontext *ctx )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +   // TODO: write a generic NULL support for the span render. 
 +   if ( pContext->pShared && pContext->pShared->bHardware )
 +   {
 +	ctx->Driver.UpdateState = SetupHWDDPointers;
 +   }
 +   else if ( pContext == pD3DDefault )
 +   {
 +	ctx->Driver.UpdateState = SetupNULLDDPointers;
 +   }
 +   else
 +   {
 +	ctx->Driver.UpdateState = SetupSWDDPointers;
 +   }
 +}
 +/*===========================================================================*/
 +/*  This function will populate all the Mesa driver hooks. This version of   */
 +/* hooks will do nothing but support the API when we don't have a valid      */
 +/* context bound.  This is mostly for applications that don't behave right   */
 +/* and also to help exit as clean as possable when we have a FatalError.     */
 +/*===========================================================================*/
 +/* RETURN: pointer to the specific function.                                 */
 +/*===========================================================================*/
 +static void SetupNULLDDPointers( GLcontext *ctx )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +   /* Initialize all the pointers in the DD struct.  Do this whenever */
 +   /* a new context is made current or we change buffers via set_buffer! */
 +   ctx->Driver.UpdateState          = SetupNULLDDPointers;
 +
 +   /* State management hooks. */
 +   ctx->Driver.Color                = NULLSetColor;
 +   ctx->Driver.ClearColor           = NULLClearColor;
 +   ctx->Driver.Clear                = NULLClearBuffers;
 +   ctx->Driver.SetBuffer            = NULLSetBuffer;
 +
 +   /* Window management hooks. */
 +   ctx->Driver.GetBufferSize        = NULLGetBufferSize;
 +
 +   /* Primitive rendering hooks. */
 +   ctx->Driver.TriangleFunc         = NULL;
 +   ctx->Driver.RenderVB             = NULL;
 +
 +   /* Pixel/span writing functions: */
 +   ctx->Driver.WriteRGBASpan        = NULLWrSpRGBA;
 +   ctx->Driver.WriteRGBSpan         = NULLWrSpRGB;
 +   ctx->Driver.WriteMonoRGBASpan    = NULLWrSpRGBAMono;
 +   ctx->Driver.WriteRGBAPixels      = NULLWrPiRGBA;
 +   ctx->Driver.WriteMonoRGBAPixels  = NULLWrPiRGBAMono;
 +
 +   /* Pixel/span reading functions: */
 +   ctx->Driver.ReadRGBASpan         = NULLReSpRGBA;
 +   ctx->Driver.ReadRGBAPixels       = NULLRePiRGBA;
 +
 +   /* Misc. hooks. */
 +   ctx->Driver.RendererString    = RendererString;
 +}
 +/*===========================================================================*/
 +/*  This function will populate all the Mesa driver hooks. There are two of  */
 +/* these functions.  One if we have hardware support and one is there is only*/
 +/* software.  These functions will be called by Mesa and by the wgl.c when we*/
 +/* have resized (or created) the buffers.  The thing is that if a window gets*/
 +/* resized we may loose hardware support or gain it...                       */
 +/*===========================================================================*/
 +/* RETURN: pointer to the specific function.                                 */
 +/*===========================================================================*/
 +static void SetupSWDDPointers( GLcontext *ctx )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +   /* Initialize all the pointers in the DD struct.  Do this whenever */
 +   /* a new context is made current or we change buffers via set_buffer! */
 +   ctx->Driver.UpdateState          = SetupSWDDPointers;
 +
 +   /* State management hooks. */
 +   ctx->Driver.Color                = SetColor;
 +   ctx->Driver.ClearColor           = ClearColor;
 +   ctx->Driver.Clear                = ClearBuffers;
 +   ctx->Driver.SetBuffer            = SetBuffer;
 +
 +   /* Window management hooks. */
 +   ctx->Driver.GetBufferSize        = GetBufferSize;
 +   ctx->Driver.Viewport             = SetViewport;
 +
 +   /* Primitive rendering hooks. */
 +   ctx->Driver.TriangleFunc         = NULL;
 +   ctx->Driver.RenderVB             = NULL;
 +
 +   /* Texture management hooks. */
 +
 +   /* Pixel/span writing functions: */
 +   ctx->Driver.WriteRGBASpan        = WSpanRGBA;
 +   ctx->Driver.WriteRGBSpan         = WSpanRGB;
 +   ctx->Driver.WriteMonoRGBASpan    = WSpanRGBAMono;
 +   ctx->Driver.WriteRGBAPixels      = WPixelsRGBA;
 +   ctx->Driver.WriteMonoRGBAPixels  = WPixelsRGBAMono;
 +
 +   /* Pixel/span reading functions: */
 +   ctx->Driver.ReadRGBASpan         = RSpanRGBA;
 +   ctx->Driver.ReadRGBAPixels       = RPixelsRGBA;
 +
 +   /* Misc. hooks. */
 +   ctx->Driver.Flush                = Flush;
 +   ctx->Driver.RendererString    = RendererString;
 +}
 +/*===========================================================================*/
 +/*  This function will populate all the Mesa driver hooks. There are two of  */
 +/* these functions.  One if we have hardware support and one is there is only*/
 +/* software.  These functions will be called by Mesa and by the wgl.c when we*/
 +/* have resized (or created) the buffers.  The thing is that if a window gets*/
 +/* resized we may loose hardware support or gain it...                       */
 +/*===========================================================================*/
 +/* RETURN: pointer to the specific function.                                 */
 +/*===========================================================================*/
 +static void SetupHWDDPointers( GLcontext *ctx )
 +{
 +   D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +   /* Initialize all the pointers in the DD struct.  Do this whenever */
 +   /* a new context is made current or we change buffers via set_buffer! */
 +   ctx->Driver.UpdateState          = SetupHWDDPointers;
 +
 +   /* State management hooks. */
 +   ctx->Driver.Color                = SetColor;
 +   ctx->Driver.ClearColor           = ClearColor;
 +   ctx->Driver.Clear                = ClearBuffersD3D;
 +   ctx->Driver.SetBuffer            = SetBuffer;
 +
 +   /* Window management hooks. */
 +   ctx->Driver.GetBufferSize        = GetBufferSize;
 +   ctx->Driver.Viewport             = SetViewport;
 +
 +   /* Primitive rendering hooks. */
 +   ctx->Driver.TriangleFunc         = RenderOneTriangle;
 +   ctx->Driver.LineFunc                          = RenderOneLine;
 +   ctx->Driver.RenderVB             = RenderVertexBuffer;
 +
 +   /* Pixel/span writing functions: */
 +   ctx->Driver.WriteRGBASpan        = WSpanRGBA;
 +   ctx->Driver.WriteRGBSpan         = WSpanRGB;
 +   ctx->Driver.WriteMonoRGBASpan    = WSpanRGBAMono;
 +   ctx->Driver.WriteRGBAPixels      = WPixelsRGBA;
 +   ctx->Driver.WriteMonoRGBAPixels  = WPixelsRGBAMono;
 +
 +   /* Pixel/span reading functions: */
 +   ctx->Driver.ReadRGBASpan         = RSpanRGBA;
 +   ctx->Driver.ReadRGBAPixels       = RPixelsRGBA;
 +
 +   /* Texture management hooks. */
 +   //   ctx->Driver.BindTexture          = TextureBind;
 +   ctx->Driver.TexImage             = TextureLoad;
 +   ctx->Driver.TexSubImage          = TextureSubImage;
 +
 +   /* Misc. hooks. */
 +   ctx->Driver.Flush                = Flush;
 +   ctx->Driver.RendererString    = RendererString;
 +}
 +/*===========================================================================*/
 +/*  This function will release all resources used by the DLL.  Every context */
 +/* will be clobbered by releaseing all driver desources and then freeing the */
 +/* context memory.  Most all the work is done in DestroyContext.             */
 +/*===========================================================================*/
 +/* RETURN: TRUE.                                                             */
 +/*===========================================================================*/
 +static BOOL  TermOpenGL( HINSTANCE hInst )
 +{
 +  D3DMESACONTEXT *pTmp,
 +		 *pNext;
 +
 +  /* Just incase we are still getting paint msg. */
 +  MakeCurrent( pD3DDefault );
 +
 +  /* Walk the list until we get back to the default context. */
 +  for( pTmp = pD3DDefault->next; pTmp != pD3DDefault; pTmp = pNext )
 +  {
 +    pNext = pTmp->next;
 +    DestroyContext( pTmp );
 +  }
 +  DestroyContext( pD3DDefault );
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  This function is an internal function that will clean up all the Mesa    */
 +/* context bound to this D3D context.  Also any D3D stuff that this context  */
 +/* uses will be unloaded.                                                    */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +static void DestroyContext( D3DMESACONTEXT *pContext )
 +{
 +  D3DMESACONTEXT        *pTmp;
 +
 +  /* Walk the list until we find the context before this one. */
 +  for( pTmp = pD3DDefault; pTmp && (pTmp->next != pContext); pTmp = pTmp->next )
 +    if ( pTmp == pTmp->next )
 +	 break;
 +
 +  /* If we never found it it must already be deleted. */
 +  if ( pTmp->next != pContext )
 +    return;
 +
 +  /* Make sure we are not using this context. */
 +  if ( pContext == pD3DCurrent )
 +    MakeCurrent( pD3DDefault );
 +
 +   /* Free the Mesa stuff. */
 +   if ( pContext->gl_visual ) 
 +   {
 +      gl_destroy_visual( pContext->gl_visual );
 +      pContext->gl_visual = NULL;
 +   }
 +   if ( pContext->gl_buffer ) 
 +   {
 +      gl_destroy_framebuffer( pContext->gl_buffer );
 +      pContext->gl_buffer = NULL;
 +   }
 +   if ( pContext->gl_ctx )    
 +   {
 +      gl_destroy_context( pContext->gl_ctx );
 +      pContext->gl_ctx = NULL;
 +   }
 +
 +   /* Now dump the D3D. */
 +   if ( pContext->pShared )
 +	TermHAL( pContext->pShared );
 +
 +   /* Update the previous context's link. */
 +   pTmp->next = pContext->next;
 +
 +   /* Gonzo. */
 +   FREE( pContext );
 +}
 +/*===========================================================================*/
 +/*  This function will pull the supplied context away from Win32.  Basicly it*/
 +/* will remove the hook from the window Proc.                                */
 +/*                                                                           */
 +/* TODO: might want to serialize this stuff...                               */
 +/*===========================================================================*/
 +/* RETURN: TRUE, FALSE.                                                      */
 +/*===========================================================================*/
 +static BOOL UnBindWindow( D3DMESACONTEXT *pContext )
 +{
 +  if ( pContext == NULL )
 +    return FALSE;
 +
 +  if ( pContext == pD3DDefault )
 +    return TRUE;
 +
 +  /* Make sure we always have a context bound. */
 +  if ( pContext == pD3DCurrent )
 +    pD3DCurrent = pD3DDefault;
 +
 +  SetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC, (LONG)pContext->hOldProc );
 +  pContext->hOldProc   = NULL;
 +
 +  return TRUE;
 +}
 +/*===========================================================================*/
 +/*  There are two cases that allow for a faster clear when we know that the  */
 +/* whole buffer is cleared and that there is no clipping.                    */
 +/*===========================================================================*/
 +/* RETURN: the original mask with the bits cleared that represents the buffer*
 +/* or buffers we just cleared.                                               */
 +/*===========================================================================*/
 +GLbitfield ClearBuffersD3D( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height )
 +{
 +  D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +  DWORD          dwFlags = 0;
 +
 +  if ( mask & GL_COLOR_BUFFER_BIT )
 +  {
 +    dwFlags |= D3DCLEAR_TARGET;
 +    mask &= ~GL_COLOR_BUFFER_BIT;
 +  }
 +  if ( mask & GL_DEPTH_BUFFER_BIT )
 +  {
 +    dwFlags |= D3DCLEAR_ZBUFFER;
 +    mask &= ~GL_DEPTH_BUFFER_BIT;
 +  }
 +  if ( dwFlags == 0 )
 +    return mask;
 +
 +  ClearHAL( pContext->pShared, 
 +		  dwFlags, 
 +		  all, 
 +		  x, y, 
 +		  width, height, 
 +		  ((pContext->aClear<<24) | (pContext->rClear<<16) | (pContext->gClear<<8) | (pContext->bClear)), 
 +		  ctx->Depth.Clear, 
 +		  0 );
 +
 +  return mask;
 +}
 +
 +
 +
 +/*===========================================================================*/
 +/*  TEXTURE MANAGER: ok here is how I did textures.  Mesa-3.0 will keep track*/
 +/* of all the textures for us.  So this means that at anytime we can go to   */
 +/* the Mesa context and get the current texture.  With this in mind this is  */
 +/* what I did.  I really don't care about what textures get or are loaded    */
 +/* until I actually have to draw a tri that is textured.  At this point I    */
 +/* must have the texture so I demand the texture by destorying all other     */
 +/* texture surfaces if need be and load the current one.  This allows for the*/
 +/* best preformance on low memory cards as time is not wasted loading and    */
 +/* unload textures.                                                          */
 +/*===========================================================================*/
 +
 +
 +
 +
 +
 +/*===========================================================================*/
 +/*  TextureLoad will try and create a D3D surface from the supplied texture  */
 +/* object if its level 0 (first).  The surface will be fully filled with the */
 +/* texture.                                                                  */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void TextureLoad( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint internalFormat, const struct gl_texture_image *image )
 +{
 +  D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +  /* TODO: only doing first LOD. */
 +  if ( (ctx->DriverCtx == NULL) || (level != 0) )
 +    return;
 +
 +  CreateTMgrHAL( pContext->pShared, 
 +			  tObj->Name, 
 +			  level,
 +			  tObj->Image[level]->Format,
 +			  (RECT *)NULL,
 +			  tObj->Image[level]->Width, 
 +			  tObj->Image[level]->Height,
 +			  TM_ACTION_LOAD,
 +			  (void *)tObj->Image[level]->Data );
 +}
 +/*===========================================================================*/
 +/*  TextureBind make sure that the texture is on the card.  Thats it.        */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void TextureBind( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj )
 +{
 +  D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +
 +  /* TODO: only doing first LOD. */
 +  if ( (tObj->Image[0] == NULL) || (ctx->DriverCtx == NULL) )
 +    return;
 +
 +  CreateTMgrHAL( pContext->pShared, 
 +			  tObj->Name, 
 +			  0,
 +			  tObj->Image[0]->Format,
 +			  (RECT *)NULL,
 +			  tObj->Image[0]->Width, 
 +			  tObj->Image[0]->Height,
 +			  TM_ACTION_BIND,
 +			  (void *)tObj->Image[0]->Data );
 +}
 +/*===========================================================================*/
 +/*  TextureSubImage will make sure that the texture being updated is updated */
 +/* if its on the card.                                                       */
 +/*===========================================================================*/
 +/* RETURN:                                                                   */
 +/*===========================================================================*/
 +static void TextureSubImage( 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 )
 +{
 +  D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
 +  RECT           rect;
 +
 +  /* TODO: only doing first LOD. */
 +  if ( (ctx->DriverCtx == NULL) || (level > 0) )
 +    return;
 +
 +  /* Create a dirty rectangle structure. */
 +  rect.left   = xoffset;
 +  rect.right  = xoffset + width;
 +  rect.top    = yoffset;
 +  rect.bottom = yoffset + height;
 +  
 +  CreateTMgrHAL( pContext->pShared, 
 +			  tObj->Name, 
 +			  0,
 +			  tObj->Image[0]->Format, 
 +			  &rect,
 +			  tObj->Image[0]->Width, 
 +			  tObj->Image[0]->Height,
 +			  TM_ACTION_UPDATE,
 +			  (void *)tObj->Image[0]->Data );
 +}
 +
 diff --git a/src/mesa/drivers/d3d/d3dText.h b/src/mesa/drivers/d3d/d3dText.h new file mode 100644 index 0000000000..9ff0650518 --- /dev/null +++ b/src/mesa/drivers/d3d/d3dText.h @@ -0,0 +1,53 @@ +#ifndef D3D_TEXT_H +#define D3D_TEXT_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ +/* Includes.                                                                 */ +/*===========================================================================*/ +#include <windows.h> +#include <ddraw.h> +#include <d3d.h> +/*===========================================================================*/ +/* Magic numbers.                                                            */ +/*===========================================================================*/ +#define	D3DLTEXT_BITSUSED		0xFFFFFFFF +#define	MAX_VERTICES			700  // (14*40) 14 per character, 40 characters +/*===========================================================================*/ +/* Macros defines.                                                           */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Type defines.                                                             */ +/*===========================================================================*/ +typedef struct _d3dText_metrics +{ +  float		   	fntYScale, +                    fntXScale; + +  int		   	fntXSpacing, +	               fntYSpacing; + +  DWORD			dwColor; +  LPDIRECT3DDEVICE3 lpD3DDevice; + +} D3DFONTMETRICS, *PD3DFONTMETRICS; +/*===========================================================================*/ +/* Function prototypes.                                                      */ +/*===========================================================================*/ +extern BOOL InitD3DText( void ); +extern void d3dTextDrawCharacter( char *c, int x, int y, PD3DFONTMETRICS pfntMetrics ); +extern void d3dTextDrawString( char *pszString, int x, int y, PD3DFONTMETRICS pfntMetrics ); +/*===========================================================================*/ +/* Global variables.                                                         */ +/*===========================================================================*/ + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/mesa/drivers/dos/DEPEND.DOS b/src/mesa/drivers/dos/DEPEND.DOS new file mode 100644 index 0000000000..60a0fdcc28 --- /dev/null +++ b/src/mesa/drivers/dos/DEPEND.DOS @@ -0,0 +1,119 @@ +# DO NOT DELETE
 +
 +accum.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +accum.obj: dlist.h macros.h
 +alpha.obj: alpha.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +alpha.obj: dlist.h macros.h
 +alphabuf.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +alphabuf.obj: context.h macros.h
 +api1.obj: api.h bitmap.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +api1.obj: eval.h image.h macros.h matrix.h teximage.h
 +api2.obj: api.h bitmap.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +api2.obj: eval.h image.h macros.h matrix.h teximage.h
 +attrib.obj: attrib.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +attrib.obj: draw.h dlist.h macros.h
 +bitmap.obj: bitmap.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +bitmap.obj: feedback.h image.h macros.h pb.h
 +blend.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h blend.h
 +blend.obj: context.h dlist.h macros.h pb.h span.h
 +bresenhm.obj: bresenhm.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +clip.obj: clip.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +clip.obj: dlist.h macros.h matrix.h vb.h xform.h
 +context.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
 +context.obj: draw.h eval.h light.h lines.h dlist.h macros.h pb.h points.h
 +context.obj: pointers.h triangle.h teximage.h texobj.h texture.h vb.h vertex.h
 +copypix.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +copypix.obj: copypix.h depth.h feedback.h dlist.h macros.h pixel.h span.h
 +copypix.obj: stencil.h
 +depth.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
 +depth.obj: dlist.h macros.h
 +dlist.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alpha.h
 +dlist.obj: attrib.h bitmap.h blend.h clip.h context.h copypix.h depth.h draw.h
 +dlist.obj: drawpix.h enable.h eval.h feedback.h fog.h image.h light.h lines.h
 +dlist.obj: dlist.h logic.h macros.h masking.h matrix.h misc.h pixel.h points.h
 +dlist.obj: polygon.h scissor.h stencil.h texobj.h teximage.h texture.h vb.h
 +dlist.obj: vertex.h winpos.h
 +draw.obj: clip.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +draw.obj: draw.h feedback.h fog.h light.h lines.h dlist.h macros.h matrix.h
 +draw.obj: pb.h points.h texture.h vb.h xform.h
 +drawpix.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +drawpix.obj: drawpix.h feedback.h dlist.h macros.h pixel.h span.h stencil.h
 +enable.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
 +enable.obj: draw.h enable.h light.h dlist.h macros.h stencil.h
 +eval.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h draw.h
 +eval.obj: eval.h dlist.h macros.h
 +feedback.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +feedback.obj: feedback.h dlist.h macros.h
 +fog.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h fog.h
 +fog.obj: dlist.h macros.h
 +get.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h get.h
 +get.obj: dlist.h macros.h
 +hash.obj: hash.h
 +interp.obj: interp.h types.h ..\include\GL\gl.h config.h fixed.h dd.h macros.h
 +image.obj: image.h types.h ..\include\GL\gl.h config.h fixed.h dd.h macros.h
 +image.obj: pixel.h
 +light.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h light.h
 +light.obj: dlist.h macros.h matrix.h vb.h xform.h
 +lines.obj: bresenhm.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +lines.obj: context.h feedback.h interp.h lines.h dlist.h macros.h pb.h vb.h
 +logic.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
 +logic.obj: logic.h macros.h pb.h
 +masking.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +masking.obj: context.h macros.h masking.h pb.h
 +matrix.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
 +matrix.obj: context.h depth.h dlist.h macros.h matrix.h stencil.h
 +misc.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
 +misc.obj: context.h depth.h macros.h masking.h misc.h stencil.h
 +pb.obj: alpha.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
 +pb.obj: blend.h depth.h fog.h logic.h macros.h masking.h pb.h scissor.h
 +pb.obj: stencil.h texture.h
 +pixel.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
 +pixel.obj: macros.h pixel.h image.h span.h stencil.h
 +points.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +points.obj: feedback.h dlist.h macros.h pb.h span.h vb.h
 +pointers.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alpha.h
 +pointers.obj: attrib.h bitmap.h blend.h clip.h context.h copypix.h depth.h
 +pointers.obj: draw.h drawpix.h enable.h eval.h feedback.h fog.h get.h light.h
 +pointers.obj: lines.h dlist.h logic.h macros.h masking.h matrix.h misc.h
 +pointers.obj: pixel.h points.h polygon.h readpix.h scissor.h stencil.h
 +pointers.obj: teximage.h texobj.h texture.h varray.h vb.h vertex.h winpos.h
 +polygon.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +polygon.obj: macros.h polygon.h
 +readpix.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +readpix.obj: context.h depth.h feedback.h dlist.h macros.h image.h readpix.h
 +readpix.obj: span.h stencil.h
 +scissor.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +scissor.obj: macros.h dlist.h scissor.h
 +span.obj: alpha.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
 +span.obj: blend.h depth.h fog.h logic.h macros.h masking.h scissor.h span.h
 +span.obj: stencil.h texture.h
 +stencil.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
 +stencil.obj: macros.h pb.h stencil.h
 +teximage.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +teximage.obj: image.h macros.h pixel.h span.h teximage.h
 +texobj.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h macros.h
 +texobj.obj: teximage.h texobj.h
 +texture.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
 +texture.obj: macros.h pb.h teximage.h texture.h
 +triangle.obj: depth.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
 +triangle.obj: feedback.h macros.h span.h triangle.h vb.h tritemp.h
 +varray.obj: draw.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
 +varray.obj: enable.h dlist.h macros.h varray.h vb.h xform.h
 +vb.obj: types.h ..\include\GL\gl.h config.h fixed.h dd.h vb.h
 +vertex.obj: draw.h types.h ..\include\GL\gl.h config.h fixed.h dd.h light.h
 +vertex.obj: dlist.h macros.h vb.h vertex.h
 +winpos.obj: ..\include\GL\gl.h draw.h types.h config.h fixed.h dd.h dlist.h
 +winpos.obj: macros.h winpos.h
 +xform.obj: types.h ..\include\GL\gl.h config.h fixed.h dd.h xform.h
 +glx.obj: ..\include\GL\gl.h ..\include\GL\glx.h ..\include\GL\xmesa.h context.h
 +glx.obj: types.h config.h fixed.h dd.h macros.h xmesaP.h
 +osmesa.obj: ..\include\GL\osmesa.h ..\include\GL\gl.h context.h types.h
 +osmesa.obj: config.h fixed.h dd.h depth.h macros.h matrix.h vb.h tritemp.h
 +xfonts.obj: ..\include\GL\gl.h ..\include\GL\xmesa.h macros.h xmesaP.h types.h
 +xfonts.obj: config.h fixed.h dd.h context.h
 +xmesa1.obj: ..\include\GL\xmesa.h ..\include\GL\gl.h xmesaP.h types.h config.h
 +xmesa1.obj: fixed.h dd.h context.h macros.h matrix.h
 +xmesa2.obj: ..\include\GL\xmesa.h ..\include\GL\gl.h macros.h types.h config.h
 +xmesa2.obj: fixed.h dd.h xmesaP.h
 +xmesa3.obj: bresenhm.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
 +xmesa3.obj: interp.h macros.h vb.h xmesaP.h ..\include\GL\xmesa.h tritemp.h
 diff --git a/src/mesa/drivers/dos/dosmesa.c b/src/mesa/drivers/dos/dosmesa.c new file mode 100644 index 0000000000..2f3973284a --- /dev/null +++ b/src/mesa/drivers/dos/dosmesa.c @@ -0,0 +1,1513 @@ +/* $Id: dosmesa.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
 +
 +/*
 + * Mesa 3-D graphics library
 + * Version:  2.3
 + * Copyright (C) 1995-1997  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: dosmesa.c,v $ + * Revision 1.1  1999/08/19 00:55:41  jtg + * Initial revision + * + * Revision 1.2  1999/03/28 21:11:57  brianp + * updated SetBuffer driver function + * + * Revision 1.1  1999/02/24 03:56:31  brianp + * initial check-in + *
 + * + * Revision 1.5  1997/06/19  22:00:00  Brian Paul
 + * Removed all ColorShift stuff + *
 + * Revision 1.4  1997/06/03  19:00:00  Brian Paul
 + * Replaced VB->Unclipped[] with VB->ClipMask[]
 + *
 + * Revision 1.3  1997/05/28  07:00:00  Phil Frisbie, Jr.
 + * Now pass red/green/blue/alpha bits to gl_create_visual()
 + * Fixed DJGPP mode 13 support.
 + *
 + * Revision 1.2  1996/12/08  16:13:45  Charlie
 + * Added VESA support via Scitechs SVGA kit.
 + *
 + * Revision 1.1  1996/12/08  16:09:52  Charlie
 + * Initial revision
 + *
 + */
 +
 +
 +/*
 + * DOS VGA/VESA/MGL/Mesa interface.
 + *
 + */
 +
 +/*
 + *
 + * TODO: (cw)
 + *	 Improve the colour matcher for rgb non vesa modes, its pretty bad and incorrect
 + *	 Keyboard interrupt.
 + *  Comments and tidy up.
 + *  Add support for VESA without SVGAKIT.
 + *  DirectX Support.
 + *  Better GLIDE Support.
 + *  Clear up the #ifdef madness.
 + */
 +
 +#ifdef DOSVGA
 +
 +#if defined(DOSVGA) && !defined(GLIDE) && defined(DJGPP) && !defined(UNIVBE) && !defined(MGL)
 +
 +/* Should help cut down on the crazy #if`s */
 +#define MODE13 1
 +
 +#else
 +#undef MODE13
 +#endif
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <string.h>
 +#include <dos.h>
 +
 +#ifdef DJGPP
 +#include <go32.h>
 +#endif
 +
 +#ifdef MGL
 +#include <mgraph.h>
 +#endif
 +
 +#include "GL/DOSmesa.h"
 +#include "context.h"
 +#include "matrix.h"
 +#include "types.h"
 +
 +#ifdef GLIDE
 +
 +static void glideshutdown( void );
 +#include "vb.h"
 +#include "glide.h"
 +
 +/* the glide modes available, set one */
 +
 +//#define GLIDE_MODE GR_RESOLUTION_
 +#define GLIDE_MODE GR_RESOLUTION_800x600
 +//#define GLIDE_MODE GR_RESOLUTION_640x480
 +
 +static GrVertex gr_vtx,gr_vtx1,gr_vtx2;
 +
 +#endif
 +
 +#ifdef UNIVBE
 +/* You get this file from Scitechs VESA development kit */
 +#include "svga.h"
 +
 +/*
 +   Set these to the VESA mode you require, the first is for 256 colour modes,
 +   the other is High colour modes, they must both be the same XRes and YRes.
 + */
 +
 +#define VESA_256COLOUR_MODE 0x11c
 +#define VESA_HICOLOUR_MODE 0x11f
 +
 +#endif
 +
 +struct DOSmesa_context {
 +   GLcontext *gl_ctx;			/* the core Mesa context */
 +   GLvisual *gl_vis;				/* describes the color buffer */
 +   GLframebuffer *gl_buffer;	/* the ancillary buffers */
 +   GLuint index;					/* current color index */
 +   GLint red, green, blue;		/* current rgb color */
 +   GLint width, height;			/* size of color buffer */
 +   GLint depth;					/* bits per pixel (8,16,24 or 32) */
 +};
 +
 +static DOSMesaContext DOSMesa = NULL;    /* the current context */
 +
 +#ifdef UNIVBE
 +SV_devCtx *DC=NULL;
 +int useLinear = TRUE;
 +SV_modeInfo *mi=NULL;
 +unsigned long modeNumber = 0;
 +
 +int activePage = 0;
 +int visualPage = 1;
 +
 +#endif
 +
 +#if defined(MODE13)
 +
 +/* DOSVGA With no UniVBE support */
 +
 +unsigned char *video_buffer;
 +
 +#define VID_BUF(x,y) *(video_buffer+x+(y*320))
 +
 +#if defined(__WATCOMC__) && defined(__386__) && defined(__DOS__)
 +
 +void setupcopy(void);
 +void copyscr(void);
 +
 +/* Watcom C specfic, screen copy and clear */
 +
 +#pragma aux setupcopy = \
 +	".386P"\
 +	"push ebp" \
 +	"mov esi,video_buffer" \
 +	"mov edi,0xa0000" \
 +	"mov ecx,2000" \
 +	"xor ebp,ebp";
 +
 +#pragma aux copyscr = \
 +	".386P" \
 +	"lop1: mov eax,[esi]"\
 +	"mov ebx,[esi+4]"\
 +	"mov edx,[esi+8]"\
 +	"mov [edi],eax"\
 +	"mov eax,[esi+12]"\
 +	"mov dword ptr [esi],ebp"\
 +	"mov dword ptr [esi+4],ebp"\
 +	"mov dword ptr [esi+8],ebp"\
 +	"mov dword ptr [esi+12],ebp"\
 +	"mov [edi+4],ebx"\
 +	"mov [edi+8],edx"\
 +	"mov [edi+12],eax"\
 +	"mov eax,[esi+16]"\
 +	"mov ebx,[esi+4+16]"\
 +	"mov edx,[esi+8+16]"\
 +	"mov [edi+16],eax"\
 +	"mov eax,[esi+12+16]"\
 +	"mov dword ptr [esi+16],ebp"\
 +	"mov dword ptr [esi+4+16],ebp"\
 +	"mov dword ptr [esi+8+16],ebp"\
 +	"mov dword ptr [esi+12+16],ebp"\
 +	"mov [edi+4+16],ebx"\
 +	"mov [edi+8+16],edx"\
 +	"mov [edi+12+16],eax"\
 +	"add esi,32"\
 +	"add edi,32"\
 +	"dec ecx"\
 +	"jnz lop1"\
 +	"pop ebp"\
 +	modify exact [edi esi eax ebx ecx] ;
 +
 +#endif // WATCOM
 +
 +#endif // MODE13
 +
 +/*
 + * Convert Mesa window Y coordinate to VGA screen Y coordinate:
 + */
 +#define FLIP(Y)  (DOSMesa->height-(Y)-1)
 +
 +unsigned short vga_cindex = 32768 ;
 +
 +static points_func choose_points_function( void );
 +static line_func choose_line_function( void );
 +static triangle_func choose_polygon_function( void );
 +static void fast_tri(GLcontext *ctx,GLuint v0, GLuint v1, GLuint v2, GLuint pv );
 +
 +static points_func choose_points_function( void )
 +{
 +	return NULL;
 +}
 +
 +static line_func choose_line_function( void )
 +{
 +	return NULL;
 +}
 +
 +static triangle_func choose_triangle_function( void )
 +{
 +	#if defined(MODE13)
 +		return	NULL;
 +	#endif
 +
 +	#if defined(GLIDE)
 +		return fast_tri;
 +	#endif
 +
 +	return	NULL;
 +}
 +
 +
 +#if defined(MODE13)
 +
 +void setgfxmode(void);
 +void settextmode(void);
 +
 +#ifndef DJGPP
 +#pragma aux setgfxmode = \
 +	"mov	ax,13h" \
 +	"int	10h" \
 +	modify [eax];
 +
 +#pragma aux settextmode = \
 +	"mov	ax,3h" \
 +	"int	10h" \
 +	modify [eax];
 +#else
 +void setgfxmode(void)
 +{
 +	union REGS in_regs,out_regs;
 +
 +	in_regs.x.ax = 0x13;
 +	int386(0x10,&in_regs,&out_regs);
 +}
 +
 +void settextmode(void)
 +{
 +	union REGS in_regs,out_regs;
 +
 +	in_regs.x.ax = 0x3;
 +	int386(0x10,&in_regs,&out_regs);
 +}
 +
 +#endif
 +
 +int set_video_mode(unsigned short x,unsigned short y,char mode)
 +{
 +	setgfxmode();
 +	return 1;	/* likelyhood of this failing is very small */
 +}
 +
 +void restore_video_mode(void)
 +{
 +	settextmode();
 +}
 +
 +int vga_getcolors(void)
 +{
 +	return vga_cindex;
 +}
 +
 +int vga_getxdim(void)
 +{
 +	return 320;
 +}
 +
 +int vga_getydim(void)
 +{
 +	return 200;
 +}
 +
 +static unsigned short num_rgb_alloc = 1; /* start from 1, zero is black */
 +
 +/* an unlikely colour */
 +static unsigned char last_r=1,last_g=255,last_b=99;
 +
 +extern void set_onecolor(int index,int R,int G,int B);
 +
 +static unsigned char rgbtable[64][64][64];
 +
 +void vga_setrgbcolor(int r,int g,int b)
 +{
 +
 +/*
 + * make this into a translation table
 + */
 +
 +	DOSMesa->red = r;
 +	DOSMesa->green = g ;
 +	DOSMesa->blue = b ;
 +
 +	r/=4; g/=4; b/=4;
 +
 +	if( (r == last_r) && (g == last_g) && (b == last_b) ) return;
 +
 +	last_r = r ;
 +	last_g = g ;
 +	last_b = b ;
 +
 +	if(r+g+b == 0 ) {
 +		DOSMesa->index = 0 ;
 +		return ;
 +	}
 +
 +	if( rgbtable[r][g][b] == 0 ) {
 +		/* not allocated yet */
 +		if(num_rgb_alloc<256) {
 +			DOSMesa->index = num_rgb_alloc;
 +			set_onecolor(num_rgb_alloc,r,g,b);
 +			rgbtable[r][g][b] = num_rgb_alloc;
 +			num_rgb_alloc++;
 +			return;
 +
 +		} else {
 +			/* need to search for a close colour */
 +			{
 +				unsigned short pass ;
 +
 +				for(pass=0;pass<64;pass++) {
 +					if(r-pass>0) {
 +						if( rgbtable[r-pass][g][b] !=0 ) {
 +							rgbtable[r][g][b] = rgbtable[r-pass][g][b];
 +							DOSMesa->index = rgbtable[r-pass][g][b];
 +							return;
 +						}
 +					}
 +					if(r+pass<64) {
 +						if( rgbtable[r+pass][g][b] !=0 ) {
 +							rgbtable[r][g][b] = rgbtable[r+pass][g][b];
 +							DOSMesa->index = rgbtable[r+pass][g][b];
 +							return;
 +						}
 +					}
 +				}
 +			}
 +			rgbtable[r][g][b] = rand()%255;
 +		}
 +	}
 +	DOSMesa->index = rgbtable[r][g][b];
 +}
 +
 +#if defined(DJGPP)
 +static int dos_seg;
 +#endif
 +
 +void vga_clear(void)
 +{
 +
 +/* Check if we`re using watcom and DOS */
 +#if defined(__WATCOMC__) && defined(__386__) && defined(__DOS__)
 +	setupcopy();
 +	copyscr();
 +#else
 +
 +#if defined (DJGPP)
 +
 +
 +	asm ("
 +		pusha
 +		pushw	%es
 +
 +		movw	_dos_seg, %es
 +
 +		movl	_video_buffer, %esi
 +		movl	$0xa0000, %edi
 +
 +		movl	$64000, %ecx
 +
 +		rep	; movsb
 +
 +		popw	%es
 +		popa
 +	");
 +
 +#else
 +
 +	/* copy the RAM buffer to the Video memory */
 +	memcpy((unsigned char *)0xa0000,video_buffer, vga_getxdim()*vga_getydim() );
 +
 +#endif //DJGPP
 +
 +	/* clear the RAM buffer */
 +	memset(video_buffer,0, vga_getxdim()*vga_getydim() );
 +
 +#endif //WATCOMC
 +
 +}
 +
 +#ifndef DEBUG
 +#define vga_drawpixel(x,y) { VID_BUF(x,y) = DOSMesa->index; }
 +#else
 +void vga_drawpixel(x,y)
 +{
 +	VID_BUF(x,y) = DOSMesa->index;
 +}
 +#endif
 +
 +int vga_getpixel(int x,int y)
 +{
 +	return 1;
 +}
 +
 +void vga_flip(void)
 +{
 +
 +}
 +
 +void vga_setcolor(int index)
 +{
 +	/* does something, what i`ve no idea */
 +	DOSMesa->index = index;
 +
 +}
 +
 +#endif
 +
 +#if defined(UNIVBE)
 +
 +/* UniVBE VESA support */
 +
 +void set_video_mode(unsigned short x,unsigned short y,char mode)
 +{
 +	if( setup_vesa_mode(x,y,mode) == FALSE ) {
 +		fprintf(stderr,"VESA: Set mode failed\n");
 +		exit(1);
 +	}
 +}
 +
 +/*
 +   This is problematic as we don`t know what resolution the user program
 +   wants when we reach here. This is why the 256 colour and HiColour modes
 +	should be the same resolution, perhaps i`ll make this an environment
 +	variable
 + */
 +
 +
 +void check_mi(void)
 +{
 +	if(mi!=0) return;
 +
 +	if(DC==NULL) {
 +		DC = SV_init( TRUE );
 +	}
 +
 +	if(modeNumber == 0 ) {
 +		modeNumber = VESA_HICOLOUR_MODE;
 +	}
 +
 +	SV_getModeInfo(modeNumber,mi);
 +
 +	return;
 +}
 +
 +int setup_vesa_mode(short height,short width,short depth)
 +{
 +	if(DC==NULL) {
 +		DC = SV_init( TRUE );
 +		/* how many bits per pixel */
 +		if( depth == 0)
 +			modeNumber = VESA_256COLOUR_MODE;
 +		else
 +			modeNumber = VESA_HICOLOUR_MODE;
 +	}
 +
 +	/* Check if correct VESA Version is available */
 +	if( !DC || DC->VBEVersion < 0x0102) {
 +		fprintf(stderr,"Require a VESA VBE version 1.2 or higher\n");
 +		return FALSE;
 +	}
 +
 +	/* Check for LFB Supprt */
 +	if(DC->VBEVersion < 0x0200 ) {
 +		useLinear = FALSE;
 +	} else {
 +		useLinear = TRUE ;
 +	}
 +
 + 	/* Get desired mode info */
 +   if(!SV_getModeInfo( modeNumber, mi))
 +		return FALSE;
 +
 +	/* Set VESA mode */
 +	if(!SV_setMode(modeNumber | svMultiBuffer, FALSE, TRUE, mi->NumberOfPages) )
 +		return FALSE;
 +
 +	return TRUE;
 +}
 +
 +void restore_video_mode(void)
 +{
 +	SV_restoreMode();
 +}
 +
 +void vga_clear(void)
 +{
 +	SV_clear(0);
 +}
 +
 +void vga_flip(void)
 +{
 +	activePage = 1-activePage;
 +	visualPage = 1-activePage;
 +
 +	SV_setActivePage(activePage);
 +
 +	/*
 +	   Change false to true if you`re getting flickering
 +	   even in double buffer mode, ( sets wait for Vertical retrace  )
 +	*/
 +	SV_setVisualPage(visualPage,false);
 +}
 +
 +int vga_getcolors(void)
 +{
 +	check_mi();
 +	switch ( mi->BitsPerPixel ) {
 +		case 8:
 +			return 256;
 +		case 15:
 +		case 16:
 +			return 32768;
 +		default:
 +			return 64000;
 +	 }
 +}
 +
 +int vga_getxdim(void)
 +{
 +	check_mi();
 +	return mi->XResolution;
 +}
 +
 +int vga_getydim(void)
 +{
 +	check_mi();
 +	return mi->YResolution;
 +}
 +
 +unsigned long current_color = 255;
 +
 +void vga_setrgbcolor(int r,int g,int b)
 +{
 +	DOSMesa->red = r;
 +	DOSMesa->green = g ;
 +	DOSMesa->blue = b ;
 +	current_color = SV_rgbColor(r,g,b);
 +}
 +
 +void vga_setcolor(int index)
 +{
 +	DOSMesa->index = index;
 +	current_color = index;
 +}
 +
 +void vga_drawpixel(x,y)
 +{
 +	SV_putPixel(x,y,current_color);
 +}
 +
 +/* TODO: */
 +int vga_getpixel(x,y)
 +{
 +/*	return (int)SV_getPixel(x,y); */
 +	fprintf(stderr,"vga_getpixel: Not implemented yet\n");
 +	return 1;
 +}
 +
 +/* End of UNIVBE section */
 +#endif
 +
 +/* Scitechs MegaGraphicsLibrary http://www.scitechsoft.com/ */
 +
 +#if defined(MGL)
 +
 +/* MGL support */
 +struct MI {
 +	unsigned short BitsPerPixel;
 +	unsigned long XResolution;
 +	unsigned long YResolution;
 +};
 +
 +struct MI*mi;
 +
 +static MGLDC*DC;
 +static int activePage = 0;
 +static int visualPage = 1;
 +static int modeNumber = 0;
 +
 +void set_video_mode(unsigned short xres,unsigned short yres,char mode)
 +{
 +    int     i,driver = grDETECT,dmode = grDETECT;
 +    event_t evt;
 +
 +	/* Start the MGL with only the SVGA 16m driver active */
 +	MGL_registerDriver(MGL_SVGA16NAME,SVGA16_driver);
 +	if (!MGL_init(&driver,&dmode,"..\\..\\"))
 +		MGL_fatalError(MGL_errorMsg(MGL_result()));
 +	if ((DC = MGL_createDisplayDC(false)) == NULL)
 +		MGL_fatalError(MGL_errorMsg(MGL_result()));
 +	MGL_makeCurrentDC(DC);
 +}
 +
 +/*
 +   This is problematic as we don`t know what resolution the user program
 +   wants when we reach here. This is why the 256 colour and HiColour modes
 +	should be the same resolution, perhaps i`ll make this an environment
 +	variable
 + */
 +
 +#define MGL_HICOLOUR_MODE 0
 +
 +
 +void check_mi(void)
 +{
 +	if(mi!=0) return;
 +
 +	if(DC==NULL) {
 +//		DC = SV_init( TRUE );
 +	}
 +
 +	if(modeNumber == 0 ) {
 +		modeNumber = MGL_HICOLOUR_MODE;
 +	}
 +
 +//	SV_getModeInfo(modeNumber,mi);
 +
 +	return;
 +}
 +
 +void restore_video_mode(void)
 +{
 +	MGL_exit();
 +}
 +
 +void vga_clear(void)
 +{
 +	MGL_clearDevice();
 +}
 +
 +void vga_flip(void)
 +{
 +	activePage = 1-activePage;
 +	visualPage = 1-activePage;
 +
 +//	SV_setActivePage(activePage);
 +
 +	/*
 +	   Change false to true if you`re getting flickering
 +	   even in double buffer mode, ( sets wait for Vertical retrace  )
 +	*/
 +//	SV_setVisualPage(visualPage,false);
 +}
 +
 +int vga_getcolors(void)
 +{
 +	check_mi();
 +	switch ( mi->BitsPerPixel ) {
 +		case 8:
 +			return 256;
 +		case 15:
 +		case 16:
 +			return 32768;
 +		default:
 +			return 64000;
 +	 }
 +}
 +
 +int vga_getxdim(void)
 +{
 +	check_mi();
 +	return mi->XResolution;
 +}
 +
 +int vga_getydim(void)
 +{
 +	check_mi();
 +	return mi->YResolution;
 +}
 +
 +unsigned long current_color = 255;
 +
 +void vga_setrgbcolor(int r,int g,int b)
 +{
 +	DOSMesa->red = r;
 +	DOSMesa->green = g ;
 +	DOSMesa->blue = b ;
 +	current_color = MGL_rgbColor(DC,r,g,b);
 +}
 +
 +void vga_setcolor(int index)
 +{
 +	DOSMesa->index = index;
 +	current_color = index;
 +}
 +
 +void vga_drawpixel(x,y)
 +{
 +	MGL_pixelCoord(x,y);
 +}
 +
 +/* TODO: */
 +int vga_getpixel(x,y)
 +{
 +/*	return (int)SV_getPixel(x,y); */
 +	fprintf(stderr,"vga_getpixel: Not implemented yet\n");
 +	return 1;
 +}
 +
 +/* End of UNIVBE section */
 +#endif
 +
 +#ifdef GLIDE
 +
 +/* GLIDE support */
 +
 +static GrHwConfiguration hwconfig;
 +
 +void set_video_mode(unsigned short x,unsigned short y,char mode)
 +{
 +	grGlideInit();
 +	if( grSstQueryHardware( &hwconfig ) ) {
 +		grSstSelect( 0 ) ;
 +		if( !grSstOpen( GLIDE_MODE,
 +							GR_REFRESH_60Hz,
 +							GR_COLORFORMAT_ABGR,
 +							GR_ORIGIN_UPPER_LEFT,
 +							GR_SMOOTHING_ENABLE,
 +							2 ) ) {
 +			fprintf(stderr,"Detected 3DFX board, but couldn`t initialize!");
 +			exit(1);
 +		}
 +
 +		grBufferClear( 0, 0, GR_WDEPTHVALUE_FARTHEST);
 +
 +		grDisableAllEffects();
 +		atexit( glideshutdown );
 +
 +//		guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
 +//		grTexCombineFunction( GR_TMU0, GR_TEXTURECOMBINE_ZERO);
 +	}
 +}
 +
 +void restore_video_mode(void)
 +{
 +}
 +
 +static void glideshutdown( void )
 +{
 +	grGlideShutdown() ;
 +}
 +
 +void vga_clear(void)
 +{
 +	grBufferSwap(0);
 +	grBufferClear( 0, 0, GR_WDEPTHVALUE_FARTHEST);
 +}
 +
 +void vga_flip(void)
 +{
 +}
 +
 +int vga_getcolors(void)
 +{
 +	return 32768;
 +}
 +
 +int vga_getxdim(void)
 +{
 +#if GLIDE_MODE == GR_RESOLUTION_800x600
 +		return 800;
 +#else
 +		return 640;
 +#endif
 +}
 +
 +int vga_getydim(void)
 +{
 +#if GLIDE_MODE == GR_RESOLUTION_800x600
 +		return 600;
 +#else
 +		return 480;
 +#endif
 +}
 +
 +unsigned long current_color = 255;
 +
 +void vga_setrgbcolor(int r,int g,int b)
 +{
 +	DOSMesa->red = r;
 +	DOSMesa->green = g ;
 +	DOSMesa->blue = b ;
 +}
 +
 +void vga_setcolor(int index)
 +{
 +	DOSMesa->index = index;
 +}
 +
 +void vga_drawpixel(x,y)
 +{
 +
 +	gr_vtx.x = x;
 +	gr_vtx.y = y;
 +	gr_vtx.z = 0;
 +	gr_vtx.r	= DOSMesa->red;
 +	gr_vtx.g	= DOSMesa->green;
 +	gr_vtx.b	= DOSMesa->blue;
 +
 +	grDrawPoint( &gr_vtx );
 +}
 +
 +static void fast_tri(GLcontext *ctx,GLuint v0, GLuint v1, GLuint v2, GLuint pv )
 +{
 +   struct vertex_buffer *VB = ctx->VB;
 +
 +	gr_vtx.z = 0;
 +	gr_vtx1.z = 0;
 +	gr_vtx2.z = 0;
 +
 +   if (VB->MonoColor) {
 +	  	gr_vtx.r = DOSMesa->red;
 +   	gr_vtx.g = DOSMesa->green;
 +   	gr_vtx.b = DOSMesa->blue;
 +   	gr_vtx1.r = DOSMesa->red;
 +   	gr_vtx1.g = DOSMesa->green;
 +   	gr_vtx1.b = DOSMesa->blue;
 +   	gr_vtx2.r = DOSMesa->red;
 +   	gr_vtx2.g = DOSMesa->green;
 +   	gr_vtx2.b = DOSMesa->blue;
 +   } else {
 +		if(ctx->Light.ShadeModel == GL_SMOOTH ) {
 +		  	gr_vtx.r  = FixedToInt( VB->Color[v0][0] );
 +		  	gr_vtx.g  = FixedToInt( VB->Color[v0][1] );
 +		  	gr_vtx.b  = FixedToInt( VB->Color[v0][2] );
 +
 +		  	gr_vtx1.r = FixedToInt( VB->Color[v1][0] );
 +		  	gr_vtx1.g = FixedToInt( VB->Color[v1][1] );
 +		  	gr_vtx1.b = FixedToInt( VB->Color[v1][2] );
 +
 +		  	gr_vtx2.r = FixedToInt( VB->Color[v2][0] );
 +		  	gr_vtx2.g = FixedToInt( VB->Color[v2][1] );
 +		  	gr_vtx2.b = FixedToInt( VB->Color[v2][2] );
 +		} else {
 +		  	gr_vtx.r  = VB->Color[pv][0];
 +		  	gr_vtx.g  = VB->Color[pv][1];
 +		  	gr_vtx.b  = VB->Color[pv][2];
 +
 +		  	gr_vtx1.r = VB->Color[pv][0];
 +		  	gr_vtx1.g = VB->Color[pv][1];
 +		  	gr_vtx1.b = VB->Color[pv][2];
 +
 +		  	gr_vtx2.r = VB->Color[pv][0];
 +		  	gr_vtx2.g = VB->Color[pv][1];
 +		  	gr_vtx2.b = VB->Color[pv][2];
 +		}
 +	}
 +
 +   gr_vtx.x  =       (VB->Win[v0][0] );
 +   gr_vtx.y  = FLIP( (VB->Win[v0][1] ) );
 +   gr_vtx1.x =       (VB->Win[v1][0] );
 +   gr_vtx1.y = FLIP( (VB->Win[v1][1] ) );
 +   gr_vtx2.x =       (VB->Win[v2][0] );
 +   gr_vtx2.y = FLIP( (VB->Win[v2][1] ) );
 +
 +	if(gr_vtx.x <0 || gr_vtx.x > 639 )
 +		return;
 +	if(gr_vtx1.x <0 || gr_vtx1.x > 639 )
 +		return;
 +	if(gr_vtx2.x <0 || gr_vtx2.x > 639 )
 +		return;
 +
 +	if(gr_vtx.y <0 || gr_vtx.y > 479 )
 +		return;
 +	if(gr_vtx1.y <0 || gr_vtx1.y > 479 )
 +		return;
 +	if(gr_vtx2.y <0 || gr_vtx2.y > 479 )
 +		return;
 +
 +	grDrawTriangle( &gr_vtx,&gr_vtx1,&gr_vtx2);
 +}
 +
 +void fast_plot(GLcontext *ctx,GLuint first,GLuint last )
 +{
 +	struct vertex_buffer *VB = ctx->VB;
 +	register GLuint i;
 +
 +	if(VB->MonoColor) {
 +		/* all same color */
 +
 +		gr_vtx.r = DOSMesa->red;
 +		gr_vtx.g = DOSMesa->green;
 +		gr_vtx.b = DOSMesa->blue;
 +
 +		for(i=first;i<last;i++) {
 +			if(VB->ClipMask[i]==0) {
 +				gr_vtx.x = VB->Win[i][0];
 +				gr_vtx.y = FLIP(VB->Win[i][1]);
 +			}
 +		}
 +	}
 +}
 +
 +/* TODO: */
 +int vga_getpixel(x,y)
 +{
 +/*	return (int)SV_getPixel(x,y); */
 +	fprintf(stderr,"vga_getpixel: Not implemented yet\n");
 +	return 1;
 +}
 +
 +/* End of GLIDE section */
 +
 +#endif // GLIDE
 +/**********************************************************************/
 +/*****                 Miscellaneous functions                    *****/
 +/**********************************************************************/
 +
 +
 +static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
 +{
 +   *width = DOSMesa->width = vga_getxdim();
 +   *height = DOSMesa->height = vga_getydim();
 +}
 +
 +
 +/* Set current color index */
 +static void set_index( GLcontext *ctx, GLuint index )
 +{
 +   DOSMesa->index = index;
 +   /*vga_setcolor( index );*/
 +}
 +
 +
 +/* Set current drawing color */
 +static void set_color( GLcontext *ctx,
 +                       GLubyte red, GLubyte green,
 +                       GLubyte blue, GLubyte alpha )
 +{
 +   DOSMesa->red = red;
 +   DOSMesa->green = green;
 +   DOSMesa->blue = blue;
 +   vga_setrgbcolor( red, green, blue );
 +}
 +
 +
 +static void clear_index( GLcontext *ctx, GLuint index )
 +{
 +   /* TODO: Implements glClearIndex() */
 +}
 +
 +
 +static void clear_color( GLcontext *ctx,
 +                         GLubyte red, GLubyte green,
 +                         GLubyte blue, GLubyte alpha )
 +{
 +   /* TODO: Implements glClearColor() */
 +}
 +
 +
 +static void clear( GLcontext *ctx,
 +                   GLboolean all,
 +                   GLint x, GLint y, GLint width, GLint height )
 +{
 +   vga_clear();
 +}
 +
 +
 +static GLboolean set_buffer( GLcontext *ctx,
 +                             GLenum mode )
 +{
 +   /* TODO: implement double buffering and use this function to select */
 +   /* between front and back buffers. */
 +   if (buffer == GL_FRONT_LEFT)
 +      return GL_TRUE;
 +   else if (buffer == GL_BACK_LEFT)
 +      return GL_TRUE;
 +   else
 +      return GL_FALSE;
 +}
 +
 +
 +
 +
 +/**********************************************************************/
 +/*****            Write spans of pixels                           *****/
 +/**********************************************************************/
 +
 +
 +static void write_index_span( GLcontext *ctx,
 +                              GLuint n, GLint x, GLint y,
 +                              const GLuint index[],
 +                              const GLubyte mask[] )
 +{
 +   int i;
 +   y = FLIP(y);
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   for (i=0;i<n;i++,x++) {
 +      if (mask[i]) {
 +#ifdef UNIVBE
 +		SV_putPixelFast(x,y,current_color);
 +#else
 +         vga_setcolor( index[i] );
 +         vga_drawpixel( x, y );
 +#endif
 +      }
 +   }
 +
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +
 +}
 +
 +
 +
 +static void write_monoindex_span( GLcontext *ctx,
 +                                  GLuint n, GLint x, GLint y,
 +                                  const GLubyte mask[] )
 +{
 +   int i;
 +   y = FLIP(y);
 +   /* use current color index */
 +   vga_setcolor( DOSMesa->index );
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   for (i=0;i<n;i++,x++) {
 +      if (mask[i]) {
 +#ifdef UNIVBE
 +			SV_putPixelFast(x,y,current_color);
 +#else
 +         vga_drawpixel( x, y );
 +#endif
 +      }
 +   }
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +}
 +
 +
 +
 +static void write_color_span( GLcontext *ctx,
 +                              GLuint n, GLint x, GLint y,
 +                              const GLubyte red[], const GLubyte green[],
 +                              const GLubyte blue[], const GLubyte alpha[],
 +                              const GLubyte mask[] )
 +{
 +   int i;
 +   y=FLIP(y);
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   if (mask) {
 +      /* draw some pixels */
 +      for (i=0; i<n; i++, x++) {
 +         if (mask[i]) {
 +#ifdef UNIVBE
 +				SV_putPixelFast(x,y,SV_rgbColor(red[i], green[i], blue[i]) );
 +#else
 +            vga_setrgbcolor( red[i], green[i], blue[i] );
 +            vga_drawpixel( x, y );
 +#endif
 +         }
 +      }
 +   }
 +   else {
 +      /* draw all pixels */
 +      for (i=0; i<n; i++, x++) {
 +#ifdef UNIVBE
 +			SV_putPixelFast(x,y,SV_rgbColor(red[i], green[i], blue[i]) );
 +#else
 +         vga_setrgbcolor( red[i], green[i], blue[i] );
 +         vga_drawpixel( x, y );
 +#endif
 +      }
 +   }
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +}
 +
 +
 +
 +static void write_monocolor_span( GLcontext *ctx,
 +                                  GLuint n, GLint x, GLint y,
 +                                  const GLubyte mask[])
 +{
 +   int i;
 +   y=FLIP(y);
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   /* use current rgb color */
 +   vga_setrgbcolor( DOSMesa->red, DOSMesa->green, DOSMesa->blue );
 +   for (i=0; i<n; i++, x++) {
 +      if (mask[i]) {
 +#ifdef UNIVBE
 +			SV_putPixelFast(x,y,current_color);
 +#else
 +         vga_drawpixel( x, y );
 +#endif
 +      }
 +   }
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****                 Read spans of pixels                       *****/
 +/**********************************************************************/
 +
 +
 +static void read_index_span( GLcontext *ctx,
 +                             GLuint n, GLint x, GLint y, GLuint index[])
 +{
 +   int i;
 +   y = FLIP(y);
 +   for (i=0; i<n; i++,x++) {
 +      index[i] = vga_getpixel( x, y );
 +   }
 +}
 +
 +
 +
 +static void read_color_span( GLcontext *ctx,
 +                             GLuint n, GLint x, GLint y,
 +                             GLubyte red[], GLubyte green[],
 +                             GLubyte blue[], GLubyte alpha[] )
 +{
 +   int i;
 +   for (i=0; i<n; i++, x++) {
 +      /* TODO */
 +   }
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****                  Write arrays of pixels                    *****/
 +/**********************************************************************/
 +
 +
 +static void write_index_pixels( GLcontext *ctx,
 +                                GLuint n, const GLint x[], const GLint y[],
 +                                const GLuint index[], const GLubyte mask[] )
 +{
 +   int i;
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +#ifdef UNIVBE
 +			SV_putPixelFast(x[i], FLIP(y[i]), index[i] );
 +#else
 +         vga_setcolor( index[i] );
 +         vga_drawpixel( x[i], FLIP(y[i]) );
 +#endif
 +      }
 +   }
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +}
 +
 +
 +
 +static void write_monoindex_pixels( GLcontext *ctx,
 +                                    GLuint n,
 +                                    const GLint x[], const GLint y[],
 +                                    const GLubyte mask[] )
 +{
 +   int i;
 +   /* use current color index */
 +   vga_setcolor( DOSMesa->index );
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +#ifdef UNIVBE
 +			SV_putPixelFast(x[i], FLIP(y[i]), DOSMesa->index);
 +#else
 +         vga_drawpixel( x[i], FLIP(y[i]) );
 +#endif
 +      }
 +   }
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +}
 +
 +
 +
 +static void write_color_pixels( GLcontext *ctx,
 +                                GLuint n, const GLint x[], const GLint y[],
 +                                const GLubyte r[], const GLubyte g[],
 +                                const GLubyte b[], const GLubyte a[],
 +                                const GLubyte mask[] )
 +{
 +   int i;
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +#ifdef UNIVBE
 +			SV_putPixelFast(x[i], FLIP(y[i]), SV_rgbColor(r[i], g[i], b[i]) );
 +#else
 +         vga_setrgbcolor( r[i], g[i], b[i] );
 +         vga_drawpixel( x[i], FLIP(y[i]) );
 +#endif
 +      }
 +   }
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +}
 +
 +static void write_monocolor_pixels( GLcontext *ctx,
 +                                    GLuint n,
 +                                    const GLint x[], const GLint y[],
 +                                    const GLubyte mask[] )
 +{
 +   int i;
 +   /* use current rgb color */
 +   vga_setrgbcolor( DOSMesa->red, DOSMesa->green, DOSMesa->blue );
 +#ifdef UNIVBE
 +	SV_beginPixel();
 +#endif
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +#ifdef UNIVBE
 +			SV_putPixelFast(x[i], FLIP(y[i]), current_color );
 +#else
 +         vga_drawpixel( x[i], FLIP(y[i]) );
 +#endif
 +      }
 +   }
 +#ifdef UNIVBE
 +	SV_endPixel();
 +#endif
 +}
 +
 +/**********************************************************************/
 +/*****                   Read arrays of pixels                    *****/
 +/**********************************************************************/
 +
 +/* Read an array of color index pixels. */
 +static void read_index_pixels( GLcontext *ctx,
 +                               GLuint n, const GLint x[], const GLint y[],
 +                               GLuint index[], const GLubyte mask[] )
 +{
 +   int i;
 +   for (i=0; i<n; i++) {
 +      index[i] = vga_getpixel( x[i], FLIP(y[i]) );
 +   }
 +}
 +
 +
 +
 +static void read_color_pixels( GLcontext *ctx,
 +                               GLuint n, const GLint x[], const GLint y[],
 +                               GLubyte red[], GLubyte green[],
 +                               GLubyte blue[], GLubyte alpha[],
 +                               const GLubyte mask[] )
 +{
 +   /* TODO */
 +}
 +
 +static void DOSmesa_setup_DD_pointers( GLcontext *ctx )
 +{
 +   /* Initialize all the pointers in the DD struct.  Do this whenever */
 +   /* a new context is made current or we change buffers via set_buffer! */
 +
 +   ctx->Driver.UpdateState = DOSmesa_setup_DD_pointers;
 +
 +   ctx->Driver.ClearIndex = clear_index;
 +   ctx->Driver.ClearColor = clear_color;
 +   ctx->Driver.Clear = clear;
 +
 +   ctx->Driver.Index = set_index;
 +   ctx->Driver.Color = set_color;
 +
 +   ctx->Driver.SetBuffer = set_buffer;
 +   ctx->Driver.GetBufferSize = get_buffer_size;
 +
 +   ctx->Driver.PointsFunc = choose_points_function();
 +   ctx->Driver.LineFunc = choose_line_function();
 +   ctx->Driver.TriangleFunc = choose_triangle_function();
 +
 +
 +   /* Pixel/span writing functions: */
 +   /* TODO: use different funcs for 8, 16, 32-bit depths */
 +   ctx->Driver.WriteColorSpan       = write_color_span;
 +   ctx->Driver.WriteMonocolorSpan   = write_monocolor_span;
 +   ctx->Driver.WriteColorPixels     = write_color_pixels;
 +   ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
 +   ctx->Driver.WriteIndexSpan       = write_index_span;
 +   ctx->Driver.WriteMonoindexSpan   = write_monoindex_span;
 +   ctx->Driver.WriteIndexPixels     = write_index_pixels;
 +   ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
 +
 +   /* Pixel/span reading functions: */
 +   /* TODO: use different funcs for 8, 16, 32-bit depths */
 +   ctx->Driver.ReadIndexSpan = read_index_span;
 +   ctx->Driver.ReadColorSpan = read_color_span;
 +   ctx->Driver.ReadIndexPixels = read_index_pixels;
 +   ctx->Driver.ReadColorPixels = read_color_pixels;
 +}
 +
 +/*
 + * Create a new VGA/Mesa context and return a handle to it.
 + */
 +DOSMesaContext DOSMesaCreateContext( void )
 +{
 +   DOSMesaContext ctx;
 +   GLboolean rgb_flag;
 +   GLfloat redscale, greenscale, bluescale, alphascale;
 +   GLboolean db_flag = GL_FALSE;
 +   GLboolean alpha_flag = GL_FALSE;
 +   int colors;
 +   GLint index_bits;
 +   GLint redbits, greenbits, bluebits, alphabits;
 +
 +#if !defined(UNIVBE) && !defined(GLIDE) && !defined(MGL)
 +	video_buffer = (unsigned char *) malloc( vga_getxdim() * vga_getydim() );
 +
 +	memset(video_buffer,0, vga_getxdim() * vga_getydim() );
 +
 +	memset(rgbtable,0,sizeof( rgbtable ) );
 +#endif
 +
 +#if defined( DJGPP ) && !defined(UNIVBE) && !defined(GLIDE)
 +	dos_seg = _go32_conventional_mem_selector();
 +#endif
 +
 +   /* determine if we're in RGB or color index mode */
 +   colors = vga_getcolors();
 +   if (colors==32768) {
 +      rgb_flag = GL_TRUE;
 +      redscale = greenscale = bluescale = alphascale = 255.0;
 +      redbits = greenbits = bluebits = 8;
 +      alphabits = 0;
 +      index_bits = 0;
 +   }
 +   else if (colors==256) {
 +      rgb_flag = GL_FALSE;
 +      redscale = greenscale = bluescale = alphascale = 0.0;
 +      redbits = greenbits = bluebits = alphabits = 0;
 +      index_bits = 8;
 +   }
 +   else {
 +		restore_video_mode();
 +      fprintf(stderr,"[%d] >16 bit color not implemented yet!\n",colors);
 +      return NULL;
 +   }
 +
 +   ctx = (DOSMesaContext) calloc( 1, sizeof(struct DOSmesa_context) );
 +   if (!ctx) {
 +      return NULL;
 +   }
 +
 +   ctx->gl_vis = gl_create_visual( rgb_flag,
 +                                   alpha_flag,
 +                                   db_flag,
 +                                   16,   /* depth_size */
 +                                   8,    /* stencil_size */
 +                                   16,   /* accum_size */
 +                                   index_bits,
 +                                   redscale,
 +                                   greenscale,
 +                                   bluescale,
 +                                   alphascale,
 +                                   redbits, greenbits,
 +                                   bluebits, alphabits);
 +
 +   ctx->gl_ctx = gl_create_context( ctx->gl_vis,
 +                                    NULL,  /* share list context */
 +                                    (void *) ctx
 +                                  );
 +
 +   ctx->gl_buffer = gl_create_framebuffer( ctx->gl_vis );
 +
 +   ctx->index = 1;
 +   ctx->red = ctx->green = ctx->blue = 255;
 +
 +   ctx->width = ctx->height = 0;  /* temporary until first "make-current" */
 +
 +   return ctx;
 +}
 +
 +/*
 + * Destroy the given VGA/Mesa context.
 + */
 +void DOSMesaDestroyContext( DOSMesaContext ctx )
 +{
 +   if (ctx) {
 +      gl_destroy_visual( ctx->gl_vis );
 +      gl_destroy_context( ctx->gl_ctx );
 +      gl_destroy_framebuffer( ctx->gl_buffer );
 +      free( ctx );
 +      if (ctx==DOSMesa) {
 +         DOSMesa = NULL;
 +      }
 +   }
 +}
 +
 +
 +
 +/*
 + * Make the specified VGA/Mesa context the current one.
 + */
 +void DOSMesaMakeCurrent( DOSMesaContext ctx )
 +{
 +   DOSMesa = ctx;
 +   gl_make_current( ctx->gl_ctx, ctx->gl_buffer );
 +   DOSmesa_setup_DD_pointers( ctx->gl_ctx );
 +
 +   if (ctx->width==0 || ctx->height==0) {
 +      /* setup initial viewport */
 +      ctx->width = vga_getxdim();
 +      ctx->height = vga_getydim();
 +      gl_Viewport( ctx->gl_ctx, 0, 0, ctx->width, ctx->height );
 +   }
 +}
 +
 +
 +
 +/*
 + * Return a handle to the current VGA/Mesa context.
 + */
 +DOSMesaContext DOSMesaGetCurrentContext( void )
 +{
 +   return DOSMesa;
 +}
 +
 +
 +/*
 + * Swap front/back buffers for current context if double buffered.
 + */
 +void DOSMesaSwapBuffers( void )
 +{
 +#if !defined(UNIVBE)
 +/* Assume double buffering is available if in UNIVBE,
 +   if it isn`t its taken care of anyway */
 +//   if (DOSMesa->gl_vis->DBflag)
 +#endif
 + 	{
 +      vga_flip();
 +   }
 +}
 +
 +
 +#else
 +
 +/*
 + * Need this to provide at least one external definition when DOS is
 + * not defined on the compiler command line.
 + */
 +
 +int gl_DOS_dummy_function(void)
 +{
 +   return 0;
 +}
 +
 +#endif  /*DOS*/
 +
 diff --git a/src/mesa/drivers/ggi/ggimesa.conf.in b/src/mesa/drivers/ggi/ggimesa.conf.in new file mode 100644 index 0000000000..72132334fd --- /dev/null +++ b/src/mesa/drivers/ggi/ggimesa.conf.in @@ -0,0 +1,13 @@ +# GGIMesa global configuration +.root: @ggi_libdir@/ggi/mesa + +generic-stubs-mesa		default/stubs.so +generic-linear-8-mesa		default/linear_8.so +generic-linear-15-mesa		default/linear_15.so +generic-linear-16-mesa		default/linear_16.so +generic-linear-24-mesa		default/linear_24.so +generic-linear-32-mesa		default/linear_32.so + +display-fbdev-mesa		display/fbdev.so + +# .include @ggi_confdir@/ggi/mesa/targets/fbdev.conf diff --git a/src/mesa/drivers/glide/fxapi.c b/src/mesa/drivers/glide/fxapi.c new file mode 100644 index 0000000000..fbc586e757 --- /dev/null +++ b/src/mesa/drivers/glide/fxapi.c @@ -0,0 +1,1411 @@ +/* -*- mode: C; tab-width:8;  -*- + +             fxapi.c - 3Dfx VooDoo/Mesa interface +*/ + +/* + * 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. + * + ******************************************************************** + * + * Function names: + *  fxMesa....     (The driver API) + *  fxDD....       (Mesa device driver functions) + *  fxTM....       (Texture manager functions) + *  fxSetup....    (Voodoo units setup functions) + *  fx....         (Internal driver functions) + * + * Data type names: + *  fxMesa....     (Public driver data types) + *  tfx....        (Private driver data types) + * + ******************************************************************** + * + * V0.30 - David Bucciarelli (davibu@tin.it) Humanware s.r.l. + *         - introduced a new MESA_GLX_FX related behavior + *         - the Glide fog table was built in a wrong way (using + *           gu* Glide function). Added the code for building the + *           table following the OpenGL specs. Thanks to Steve Baker + *           for highlighting the problem. + *         - fixed few problems in my and Keith's fxDDClear code + *         - merged my code with the Keith's one + *         - used the new BlendFunc Mesa device driver function  + *         - used the new AlphaFunc Mesa device driver function  + *         - used the new Enable Mesa device driver function  + *         - fixed a bug related to fog in the Mesa core. Fog + *           were applied two times: at vertex level and at fragment + *           level (thanks to Steve Baker for reporting the problem) + *         - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE) now works + *           (thanks to Jiri Pop for reporting the problem) + *         - the driver works fine with OpenGL Unreal + *         - fixed a bug in the Mesa core clipping code (related + *           to the q texture coordinate) + *         - introduced the support for the q texture coordinate + * + *         Keith Whitwell (keithw@cableinet.co.uk) + *         - optimized the driver and written all the new code + *           required by the new Mesa-3.1 device driver API + *           and by the new Mesa-3.1 core changes + *         - written the cva support and many other stuff + * + *         Brian Paul (brian_paul@avid.com) Avid Technology + *         - fixed display list share bug for MESA_GLX_FX = window/fullscreen + *         - fixed glClear/gl...Mask related problem + * + *         Bert Schoenwaelder (bert@prinz-atm.CS.Uni-Magdeburg.De) + *         - the driver is now able to sleep when waiting for the completation + *           of multiple swapbuffer operations instead of wasting + *           CPU time (NOTE: you must uncomment the lines in the + *           fxMesaSwapBuffers function in order to enable this option) + * + *         Eero Pajarre (epajarre@koti.tpo.fi) + *         - enabled the macro FLOAT_COLOR_TO_UBYTE_COLOR under + *           windows + *         - written an asm x86 optimized float->integer conversions + *           for windows + * + *         Theodore Jump (tjump@cais.com) + *         - fixed a small problem in the __wglMonitor function of the + *           wgl emulator + *         - written the in-window-rendering hack support for windows + *           and Vooodoo1/2 cards + * + * V0.29 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - included in Mesa-3.0 + *         - now glGetString(GL_RENDERER) returns more information + *           about the hardware configuration: "Mesa Glide <version> + *           <Voodoo_Graphics|Voodoo_Rush|UNKNOWN> <num> CARD/<num> FB/ + *           <num> TM/<num> TMU/<NOSLI|SLI>" + *           where: <num> CARD is the card used for the current context, + *           <num> FB is the number of MB for the framebuffer, + *           <num> TM is the number of MB for the texture memory, + *           <num> TMU is the number of TMU. You can try to run + *           Mesa/demos/glinfo in order to have an example of the + *           output + *         - fixed a problem of the WGL emulator with the + *           OpenGL Optimizer 1.1 (thanks to Erwin Coumans for + *           the bug report) + *         - fixed some bug in the fxwgl.c code (thanks to   + *           Peter Pettersson for a patch and a bug report) + * + *         Theodore Jump (tjump@cais.com) + *         - written the SST_DUALHEAD support in the WGL emulator + * + *         Daryll Strauss (daryll@harlot.rb.ca.us) + *         - fixed the Voodoo Rush support for the in window rendering + * + * V0.28 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - the only supported multitexture functions are GL_MODULATE + *           for texture set 0 and GL_MODULATE for texture set 1. In + *           all other cases, the driver falls back to pure software + *           rendering + *         - written the support for the new  GL_EXT_multitexture + *         - written the DD_MAX_TEXTURE_COORD_SETS support in the + *           fxDDGetParameteri() function + *         - the driver falls back to pure software rendering when + *           texture mapping function is GL_BLEND + * + * V0.27 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - inluded in the Mesa-3.0beta5 + *         - written a smal extension (GL_FXMESA_global_texture_lod_bias) in + *           order to expose the LOD bias related Glide function + *         - fixed a bug fxDDWriteMonoRGBAPixels() + *         - the driver is now able to fallback to software rendering in + *           any case not directly supported by the hardware + *         - written the support for enabling/disabling dithering + *         - the in-window-rendering hack now works with any X11 screen + *           depth + *         - fixed a problem related to color/depth/alpha buffer clears + *         - fixed a problem when clearing buffer for a context with the + *           alpha buffer + *         - fixed a problem in the fxTMReloadSubMipMapLevel() function, + *           I have forget a "break;" (thanks to Joe Waters for the bug report) + *         - fixed a problem in the color format for the in window + *           rendering hack + *         - written the fxDDReadRGBAPixels function + *         - written the fxDDDepthTestPixelsGeneric function + *         - written the fxDDDepthTestSpanGeneric function + *         - written the fxDDWriteMonoRGBAPixels function + *         - written the fxDDWriteRGBAPixels function + *         - removed the multitexture emulation code for Voodoo board + *         with only one TMU + * + *         Chris Prince <cprince@cs.washington.edu> + *         - fixed a new bug in the wglUseFontBitmaps code + * + *         Ralf Knoesel (rknoesel@Stormfront.com) + *         - fixed a bug in the wglUseFontBitmaps code + * + *         Rune Hasvold (runeh@ifi.uio.no) + *         - fixed a problem related to the aux usage in the fxBestResolution + *           function + *         - fixed the order of pixel formats in the WGL emulator + * + *         Fredrik Hubinette (hubbe@hubbe.net) + *         - the driver shutdown the Glide for most common signals + * + * V0.26 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - included in the Mesa-3.0beta4 + *         - fixed a problem related to a my optimization for the Rune's + *           pixel-span optimization + *         - fixed a problem related to fxDDSetNearFar() and ctx->ProjectionMatrixType + *           (thanks to Ben "Ctrl-Alt-Delete" and the Raul Alonso's ssystem) + *         - fixed a small bug in the Rune's pixel-span optimization + *         - fixed a problem with GL_CCW (thanks to Curt Olson for and example + *           of the problem) + *         - grVertex setup code is now ready for the internal thread support + *         - fixed a no used optimization with clipped vertices in + *           grVertex setup code + *         - fixed a problem in the GL_LIGHT_MODEL_TWO_SIDE support (thanks + *           to Patrick H. Madden for a complete example of the bug) + * + *         Rune Hasvold (runeh@ifi.uio.no) + *         - highly optimized the driver functions for writing pixel + *           span (2-3 times faster !) + * + *         Axel W. Volley (volley@acm.org) Krauss-Maffei Wehrtechnik + *         - written the fxDDReadDepthSpanFloat() and fxDDReadDepthSpanInt() + *           functions + * + * V0.25 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - fixed a problem with Voodoo boards with only one TMU + *         - fixed a bug in the fxMesaCreateContext() + *         - now the GL_FRONT_AND_BACK works fine also with + *           the alpha buffer and/or antialiasing + *         - written the support for GL_FRONT_AND_BACK drawing but + *           it doesn't works with the alpha buffer and/or antialiasing + *         - fixed some bug in the Mesa core for glCopyTexSubImage + *           and glCopyTexImage functions (thanks to Mike Connell + *           for an example of the problem) + *         - make some small optimizations in the Mesa core in order + *           to save same driver call and state change for not very + *           well written applications + *         - introduced the NEW_DRVSTATE and make other optimizations + *           for minimizing state changes + *         - made a lot of optimizations in order to minimize state + *           changes + *         - it isn't more possible to create a context with the + *           depth buffer and the stancil buffer (it isn't yet supported) + *         - now the partial support for the Multitexture extension + *           works with Quake2 for windows + *         - vertex snap is not longer used for the Voodoo2 (FX_V2 + *           must be defined) + *         - done a lot of cleanup in the fxsetup.c file + *         - now the partial support for the Multitexture extension + *           works with GLQuake for windows + * + *         Dieter Nuetzel (nuetzel@kogs.informatik.uni-hamburg.de) University of Hamburg + *         - fixed a problem in the asm code for Linux of the fxvsetup.c file + *           highlighted by the binutils-2.8.1.0.29. 'fildw' asm instruction + *           changed in 'fild' + * + *         Kevin Hester (kevinh@glassworks.net) + *         - written the wglUseFontBitmaps() function in the WGL emulator + * + * V0.24 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - now the drive always uses per fragment fog + *         - written a small optimization in the points drawing function + *         - written the support for trilinear filtering with 2 TMUs + *         - written the first partial support for the Multitexture extension. + *           This task is quite hard because the color combine units work after + *           the two texture combine units and not before as required by the  + *           Multitexture extension + *         - written a workaround in fxBestResolution() in order to solve a + *           problem with bzflag (it asks for 1x1 window !) + *         - changed the fxBestResolution() behavior. It now returns the larger + *           screen resolution supported by the hardware (instead of 640x480) + *           when it is unable to find an appropriate resolution that is large + *           enough for the requested size  + *         - the driver is now able to use also the texture memory attached to + *           second TMU + *         - the texture memory manager is now able to work with two TMUs and + *           store texture maps in the memory attached to TMU0, TMU1 or to split + *           the mimpmap levels across TMUs in order to support trilinear filtering + *         - I have bought a Voodoo2 board ! + *         - the amount of frambuffer ram is now doubled when an SLI configuration + *           is detected + *         - solved a problem related to the fxDDTexParam() and fxTexInvalidate() + *           functions (thanks to Rune Hasvold for highlighting the problem) + *         - done some cleanup in the fxvsetup.c file, written + *           the FXVSETUP_FUNC macro + *         - done a lot of cleanup in data types and field names + * + *         Rune Hasvold (runeh@ifi.uio.no) + *         - written the support for a right management of the auxiliary buffer. + *           You can now use an 800x600 screen without the depth and alpha + *           buffer + *         - written the support for a new pixel format (without the depth + *           and alpha buffer) in the WGL emulator + *         - fixed a bug in the window version of the GLUT (it was ever asking + *           for depth buffer) + * + * V0.23 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - included in the Mesa-3.0beta2 release + *         - written the support for the OpenGL 1.2 GL_TEXTURE_BASE_LEVEL + *           and GL_TEXTURE_MAX_LEVEL + *         - rewritten several functions for a more clean support of texture + *           mapping and in order to solve some bug + *         - the accumulation buffer works (it is  bit slow beacuase it requires + *           to read/write from/to the Voodoo frame buffer but it works) + *         - fixed a bug in the fxDDReadRGBASpan driver function (the R and + *           B channels were read in the wrong order). Thanks to Jason Heym + *           for highlighting the problem + *         - written the support for multiple contexts on multiple boards. + *           you can now use the Mesa/Voodoo with multiple Voodoo Graphics + *           boards (for example with multiple screens or an HMD) + *         - the fxBestResolution() now check all available resolutions + *           and it is able to check the amount of framebuffer memory + *           before return a resolution + *         - modified the GLX/X11 driver in order to support all the + *           resolution available + *         - changed all function names. They should be now a bit more + *           readable + *         - written the Glide grVertex setup code for two TMU or + *           for Multitexture support with emulationa dn one TMU + *         - written the support for the new Mesa driver + *           function GetParametri + *         - small optimization/clean up in the texbind() function + *         - fixed a FPU precision problem for glOrtho and texture + *           mapping (thanks to Antti Juhani Huovilainen for an example + *           of the problem) + *         - written some small SGI OpenGL emulation code for the wgl, + *           the OpenGL Optimizer and Cosmo3D work fine under windows ! + *         - moved the point/line/triangle/quad support in the fxmesa7.c + *         - fixed a bug in the clear_color_depth() (thanks to Henk Kok + *           for an example of the problem) + *         - written a small workaround for Linux GLQuake, it asks + *           for the alpha buffer and the depth buffer at the some time + *           (but it never uses the alpha buffer) + *         - checked the antialiasing points, lines and polygons support. + *           It works fine + *         - written the support for standard OpenGL antialiasing using + *           blending. Lines support works fine (tested with BZflag) + *           while I have still to check the polygons and points support + *         - written the support for the alpha buffer. The driver is now + *           able to use the Voodoo auxiliary buffer as an alpha buffer + *           instead of a depth buffer. Also all the OpenGL blending + *           modes are now supported. But you can't request a context + *           with an alpha buffer AND a depth buffer at the some time + *           (this is an hardware limitation) + *         - written the support for switching between the fullscreen + *           rendering and the in-window-rendering hack on the fly + * + *         Rune Hasvold (runeh@ifi.uio.no) + *         - fixed a bug in the texparam() function + * + *         Brian Paul (brianp@elastic.avid.com) Avid Technology + *         - sources accomodated for the new Mesa 3.0beta1 + * + * V0.22 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - included with some v0.23 bug fix in the final release + *           of the Mesa-2.6 + *         - written the support for the MESA_WGL_FX env. var. but + *           not tested because I have only Voodoo Graphics boards + *         - fixed a bug in the backface culling code + *           (thanks to David Farrell for an example of the problem) + *         - fixed the "Quake2 elevator" bug + *         - GL_POLYGONS with 3/4 vertices are now drawn as + *           GL_TRIANLGES/GL_QUADS (a small optimization for GLQuake) + *         - fixed a bug in fxmesa6.h for GL_LINE_LOOP + *         - fixed a NearFarStack bug in the Mesa when applications + *           directly call glLoadMatrix to load a projection matrix  + *         - done some cleanup in the fxmesa2.c file + *         - the driver no longer translates the texture maps + *           when the Mesa internal format and the Voodoo + *           format are the some (usefull for 1 byte texture maps + *           where the driver can directly use the Mesa texture + *           map). Also the amount of used memory is halfed + *         - fixed a bug for GL_DECAL and GL_RGBA + *         - fixed a bug in the clear_color_depth() + *         - tested the v0.22 with the Mesa-2.6beta2. Impressive + *           performances improvement thanks to the new Josh's + *           asm code (+10fps in the isosurf demo, +5fps in GLQuake + *           TIMEREFRESH) + *         - written a optimized version of the RenderVB Mesa driver + *           function. The Voodoo driver is now able to upload polygons + *           in the most common cases at a very good speed. Good + *           performance improvement for large set of small polygons + *         - optimized the asm code for setting up the color information + *           in the Glide grVertex structure + *         - fixed a bug in the fxmesa2.c asm code (the ClipMask[] + *           wasn't working) + * + *         Josh Vanderhoof (joshv@planet.net) + *         - removed the flush() function because it isn't required + *         - limited the maximum number of swapbuffers in the Voodoo + *           commands FIFO (controlled by the env. var. MESA_FX_SWAP_PENDING) + * + *         Holger Kleemiss (holger.kleemiss@metronet.de) STN Atlas Elektronik GmbH + *         - applied some patch for the Voodoo Rush + * + * V0.21 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - the driver is now able to take advantage of the ClipMask[], + *           ClipOrMask and ClipAndMask information also under Windows + *         - introduced a new function in the Mesa driver interface + *           ClearColorAndDepth(). Now the glClear() function is + *           2 times faster (!) when you have to clear the color buffer + *           and the depth buffer at some time + *         - written the first version of the fxRenderVB() driver + *           function + *         - optimized the glTexImage() path + *         - removed the fxMesaTextureUsePalette() support + *         - fixed a bug in the points support (thanks to David Farrell + *           for an example of the problem) + *         - written the optimized path for glSubTexImage(), + *           introduced a new function in the Mesa driver interface + *           TexSubImage(...) + *         - fixed a bug for glColorMask and glDepthMask + *         - the wbuffer is not more used. The Voodoo driver uses + *           a standard 16bit zbuffer in all cases. It is more consistent + *           and now GLQuake and GLQuake2test work also with a GL_ZTRICK 0 + *         - the driver is now able to take advantage of the ClipMask[], + *           ClipOrMask and ClipAndMask information (under Linux); + *         - rewritten the setup_fx_units() function, now the texture + *           mapping support is compliant to the OpenGL specs (GL_BLEND + *           support is still missing). The LinuxGLQuake console correctly + *           fade in/out and transparent water of GLQuake2test works fine + *         - written the support for the env. var. FX_GLIDE_SWAPINTERVAL + *         - found a bug in the Mesa core. There is a roundup problem for + *           color values out of the [0.0,1.0] range + * + *         Wonko <matt@khm.de> + *         - fixed a Voodoo Rush related problem in the fxwgl.c + * + *         Daryll Strauss <daryll@harlot.rb.ca.us> + *         - written the scissor test support + * + * V0.20 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - written the closetmmanger() function in order to free all the memory + *           allocated by the Texture Memory Manager (it will be useful + *           when the support for multiple contexts/boards will be ready) + *         - now the Voodoo driver runs without printing any information, + *           define the env. var. MESA_FX_INFO if you want to read some + *           information about the hardware and some statistic + *         - written a small workaround for the "GLQuake multiplayer white box bug" + *           in the setup_fx_units() funxtions. I'm already rewriting + *           this function because it is the source of nearly all the current + *           Voodoo driver problems + *         - fixed the GLQuake texture misalignment problem (the texture + *           coordinates must be scaled between 0.0 and 256.0 and not + *           between 0.0 and 255.0) + *         - written the support for the GL_EXT_shared_texture_palette + *         - some small change for supporting the automatic building of the + *           OpenGL32.dll under the Windows platform + *         - the redefinition of a mipmap level is now a LOT faster. This path + *           is used by GLQuake for dynamic lighting with some call to glTexSubImage2D() + *         - the texture memory is now managed a set of 2MB blocks so + *           texture maps can't be allocated on a 2MB boundary. The new Pure3D + *           needs this kind of support (and probably any other Voodoo Graphics + *           board with more than 2MB of texture memory) + * + *         Brian Paul (brianp@elastic.avid.com) Avid Technology + *         - added write_monocolor_span(), fixed bug in write_color_span() + *         - added test for stenciling in choosepoint/line/triangle functions + * + *         Joe Waters (falc@attila.aegistech.com) Aegis + *         - written the support for the env. var. SST_SCREENREFRESH + * + * V0.19 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - written the 3Dfx Global Palette extension for GLQuake + *         - written the support for the GL_EXT_paletted_texture (it works only with GL_RGBA + *           palettes and the alpha value is ignored ... this is a limitation of the + *           the current Glide version and Voodoo hardware) + *         - fixed the amount of memory allocated for 8bit textures + *         - merged the under construction v0.19 driver with the Mesa 2.5 + *         - finally written the support for deleting textures + *         - introduced a new powerful texture memory manager: the texture memory + *           is used as a cache of the set of all defined texture maps. You can + *           now define several MB of texture maps also with a 2MB of texture memory + *           (the texture memory manager will do automatically all the swap out/swap in + *           work). The new texture memory manager has also + *           solved a lot of other bugs/no specs compliance/problems + *           related to the texture memory usage. The texture + *           manager code is inside the new fxmesa3.c file + *         - broken the fxmesa.c file in two files (fxmesa1.c and fxmesa2.c) + *           and done some code cleanup + *         - now is possible to redefine texture mipmap levels already defined + *         - fixed a problem with the amount of texture memory allocated for textures + *           with not all mipmap levels defined + *         - fixed a small problem with single buffer rendering + * + *         Brian Paul (brianp@elastic.avid.com) Avid Technology + *         - read/write_color_span() now use front/back buffer correctly + *         - create GLvisual with 5,6,5 bits per pixel, not 8,8,8 + *         - removed a few ^M characters from fxmesa2.c file + * + * V0.18 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - the Mesa-2.4beta3 is finally using the driver quads support (the + *           previous Mesa versions have never taken any advantage from the quads support !) + *         - tested with the Glide 2.4 for Win + *         - ported all asm code to Linux + *         - ported the v0.18 to Linux (without asm code) + *         - back to Linux !!! + *         - optimized the SETUP macro (no more vertex snap for points and lines) + *         - optimized the SETUP macro (added one argument) + *         - the Mesa/Voodoo is now 20/30% for points, lines and small triangles ! + *         - performance improvement setting VBSIZE to 72  + *         - the GrVertex texture code is now written in asm + *         - the GrVertex zbuffer code is now written in asm + *         - the GrVertex wbuffer code is now written in asm + *         - the GrVertex gouraud code is now written in asm + *         - the GrVertex snap code is now written in asm + *         - changed the 8bit compressed texture maps in 8bit palette texture maps + *           support (it has the some advantage of compressed texture maps without the + *           problem of a fixed NCC table for all mipmap levels) + *         - written the support for 8bit compressed texture maps (but texture maps with + *           more than one mipmap level aren't working fine) + *         - finnaly everthing is working fine in MesaQuake ! + *         - fixed a bug in the computation of texture mapping coordinates (I have found + *           the bug thanks to MesaQuake !) + *         - written the GL_REPLACE support (mainly for MesaQuake) + *         - written the support for textures with not all mipmap levels defined + *         - rewritten all the Texture memory stuff + *         - written the MesaQuake support (define MESAQUAKE) + *         - working with a ZBuffer if glOrtho or not int the default glDepthRange, + *           otherwise working with the WBuffer + *         written the glDepthRange support + * + *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l. + *         - written the fxCloseHardware() and the fxQuaryHardware() (mainly + *           for the VoodooWGL emulator) + * + *         Brian Paul (brianp@elastic.avid.com) Avid Technology + *         - implemented read/write_color_span() so glRead/DrawPixels() works + *         - now needs Glide 2.3 or later.  Removed GLIDE_FULL_SCREEN and call to grSstOpen() + * + * V0.17 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - optimized the bitmap support (66% faster) + *         - tested with the Mesa 2.3beta2 + * + *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l. + *         - solved a problem with the drawbitmap() and the Voodoo Rush + *           (GR_ORIGIN_LOWER_LEFT did not work with the Stingray) + * + *         Brian Paul (brianp@elastic.avid.com) Avid Technology + *         - linux stuff + *         - general code clean-up + *         - added attribList parameter to fxMesaCreateContext() + *         - single buffering works now + *         - VB colors are now GLubytes, removed ColorShift stuff + * + *         Paul Metzger + *         - linux stuff + * + * V0.16 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - written the quadfunc support (no performance improvement) + *         - written the support for the new Mesa 2.3beta1 driver interface (Wow ! It is faaaster) + *         - rewritten the glBitmap support for the Glide 2.3 (~35% slower !) + *         - written the glBitmap support for the most common case (fonts) + * + *         Jack Palevich + *         - Glide 2.3 porting + * + *         Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l. + *         - extended the fxMesaCreateContext() and fxMesaCreateBestContext() + *           functions in order to support also the Voodoo Rush + *         - tested with the Hercules Stingray 128/3D (The rendering in a window works !) + * + * V0.15 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - written the GL_LUMINANCE_ALPHA support + *         - written the GL_ALPHA support + *         - written the GL_LUMINANCE support + *         - now SETUP correctly set color for mono color sequences + *         - written the 9x1,10x1,...,1x9,1x10,... texture map ratio support + *         - written the no square texture map support + *         - the fog table is no more rebuilt inside setup_fx_units() each time + * + *         Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation + *         - written (not yet finished: no texture mapping) support for glOrtho + *         - some change to setup functions + *         - the fog support is now fully compatible with the standard OpenGL + *         - rewritten several parts of the driver in order to take + *           advantage of meshes (40% faster !!!) + * + * V0.14 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - now glAlphaFunc() works + *         - now glDepthMask() works + *         - solved a mipmap problem when using more than one texture + *         - moved ti, texid and wscale inside the fxMesaContext (now we can + *           easy support more ctx and more boards) + *         - the management of the fxMesaContext was completly broken ! + *         - solved several problems about Alpha and texture Alpha + *         - 4 (RGBA) texture channels supported + *         - setting the default color to white + * + *         Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation + *         - small change to fxMesaCreateContext() and fxMesaMakeCurrent() + *         - written the fog support + *         - setting the default clear color to black + *         - written cleangraphics() for the onexit() function + *         - written fxMesaCreateBestContext() + * + * V0.13 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - now glBlendFunc() works for all glBlendFunc without DST_ALPHA + *           (because the alpha buffer is not yet implemented)  + *         - now fxMesaCreateContext() accept resolution and refresh rate + *         - fixed a bug for texture mapping: the w (alias z) must be set + *           also without depth buffer + *         - fixed a bug for texture image with width!=256 + *         - written texparam() + *         - written all point, line and triangle functions for all possible supported + *           contexts and the driver is slight faster with points, lines and small triangles + *         - fixed a small bug in fx/fxmesa.h (glOrtho) + * + * V0.12 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - glDepthFunc supported + *         - introduced a trick to discover the far plane distance + *           (see fxMesaSetFar and fx/fxmesa.h) + *         - now the wbuffer works with homogeneous coordinate (and it + *           doesn't work with a glOrtho projection :) + *         - solved several problems with homogeneous coordinate and texture mapping + *         - fixed a bug in all line functions + *         - fixed a clear framebuffer bug + *         - solved a display list/teximg problem (but use + *           glBindTexture: it is several times faster) + * + * V0.11 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - introduced texture mapping support (not yet finished !) + *         - tested with Mesa2.2b6 + *         - the driver is faster  + *         - written glFlush/glFinish + *         - the driver print a lot of info about the Glide lib + * + * v0.1  - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + *         - Initial revision + * + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) +#include "fxdrv.h" + +fxMesaContext fxMesaCurrentCtx=NULL; + +/* + * Status of 3Dfx hardware initialization + */ + +static int glbGlideInitialized=0; +static int glb3DfxPresent=0; +static int glbTotNumCtx=0; + +GrHwConfiguration glbHWConfig; +int glbCurrentBoard=0; + + +#if defined(__WIN32__) +static int cleangraphics(void) +{ +  glbTotNumCtx=1; +  fxMesaDestroyContext(fxMesaCurrentCtx); + +  return 0; +} +#elif defined(__linux__) +static void cleangraphics(void) +{ +  glbTotNumCtx=1; +  fxMesaDestroyContext(fxMesaCurrentCtx); +} + +static void cleangraphics_handler(int s) +{ +  fprintf(stderr,"fxmesa: Received a not handled signal %d\n",s); + +  cleangraphics(); +/*    abort(); */ +  exit(1); +} +#endif + + +/* + * Select the Voodoo board to use when creating + * a new context. + */ +GLboolean GLAPIENTRY fxMesaSelectCurrentBoard(int n) +{ +  fxQueryHardware(); + +  if((n<0) || (n>=glbHWConfig.num_sst)) +    return GL_FALSE; + +  glbCurrentBoard=n; + +  return GL_TRUE; +} + + +fxMesaContext GLAPIENTRY fxMesaGetCurrentContext(void) +{ +  return fxMesaCurrentCtx; +} + + +void GLAPIENTRY fxMesaSetNearFar(GLfloat n, GLfloat f) +{ +  if(fxMesaCurrentCtx) +    fxDDSetNearFar(fxMesaCurrentCtx->glCtx,n,f); +} + + +/* + * The extension GL_FXMESA_global_texture_lod_bias + */ +void GLAPIENTRY glGlobalTextureLODBiasFXMESA(GLfloat biasVal) +{ +  grTexLodBiasValue(GR_TMU0,biasVal); + +  if(fxMesaCurrentCtx->haveTwoTMUs) +    grTexLodBiasValue(GR_TMU1,biasVal); +} + + +/* + * The 3Dfx Global Palette extension for GLQuake. + * More a trick than a real extesion, use the shared global + * palette extension.  + */ +void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *pal) +{ +  fxMesaContext fxMesa =fxMesaCurrentCtx; +   +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    int i; + +    fprintf(stderr,"fxmesa: gl3DfxSetPaletteEXT()\n"); + +    for(i=0;i<256;i++) +      fprintf(stderr,"%x\n",pal[i]); +  } +   +  if(fxMesa) { +    fxMesa->haveGlobalPaletteTexture=1; +     +    FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal); +    if (fxMesa->haveTwoTMUs) +    	 FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal); +  } +} + + +static GrScreenResolution_t fxBestResolution(int width, int height, int aux) +{ +  static int resolutions[][5]={  +    { 512, 384, GR_RESOLUTION_512x384, 2, 2 }, +    { 640, 400, GR_RESOLUTION_640x400, 2, 2 }, +    { 640, 480, GR_RESOLUTION_640x480, 2, 2 }, +    { 800, 600, GR_RESOLUTION_800x600, 4, 2 }, +    { 960, 720, GR_RESOLUTION_960x720, 6, 4 } +#ifdef GR_RESOLUTION_1024x768 +    ,{ 1024, 768, GR_RESOLUTION_1024x768, 8, 4 } +#endif +#ifdef GR_RESOLUTION_1280x1024 +    ,{ 1024, 768, GR_RESOLUTION_1280x1024, 8, 8 } +#endif +#ifdef GR_RESOLUTION_1600x1200 +    ,{ 1024, 768, GR_RESOLUTION_1600x1200, 16, 8 } +#endif +  }; +  int NUM_RESOLUTIONS = sizeof(resolutions) / (sizeof(int)*5); +  int i,fbmem; +  GrScreenResolution_t lastvalidres=resolutions[1][2]; + +  fxQueryHardware(); + +  if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) { +    fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam; + +    if(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect) +      fbmem*=2; +  } else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) +    fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam; +  else +    fbmem=2; + +  /* A work around for BZFlag */ + +  if((width==1) && (height==1)) { +    width=640; +    height=480; +  } + +  for(i=0;i<NUM_RESOLUTIONS;i++) +    if(resolutions[i][4-aux]<=fbmem) { +      if((width<=resolutions[i][0]) && (height<=resolutions[i][1])) +        return resolutions[i][2]; + +      lastvalidres=resolutions[i][2]; +    } + +  return lastvalidres; +} + + +fxMesaContext GLAPIENTRY fxMesaCreateBestContext(GLuint win,GLint width, GLint height, +					       const GLint attribList[]) +{ +  GrScreenRefresh_t refresh; +  int i; +  int res,aux; +  refresh=GR_REFRESH_75Hz; + +  if(getenv("SST_SCREENREFRESH")) { +    if(!strcmp(getenv("SST_SCREENREFRESH"),"60")) +      refresh=GR_REFRESH_60Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"70")) +      refresh=GR_REFRESH_70Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"72")) +      refresh=GR_REFRESH_72Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"75")) +      refresh=GR_REFRESH_75Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"80")) +      refresh=GR_REFRESH_80Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"85")) +      refresh=GR_REFRESH_85Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"90")) +      refresh=GR_REFRESH_90Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"100")) +      refresh=GR_REFRESH_100Hz; +    if(!strcmp(getenv("SST_SCREENREFRESH"),"120")) +      refresh=GR_REFRESH_120Hz; +  } + +  aux=0; +  for(i=0;attribList[i]!=FXMESA_NONE;i++) +    if((attribList[i]==FXMESA_ALPHA_SIZE) || +       (attribList[i]==FXMESA_DEPTH_SIZE)) { +      if(attribList[++i]>0) { +        aux=1; +        break; +      } +    } + +  res=fxBestResolution(width,height,aux); + +  return fxMesaCreateContext(win,res,refresh,attribList); +} + + +#if 0 +void fxsignals() +{ +   signal(SIGINT,SIG_IGN); +   signal(SIGHUP,SIG_IGN); +   signal(SIGPIPE,SIG_IGN); +   signal(SIGFPE,SIG_IGN); +   signal(SIGBUS,SIG_IGN); +   signal(SIGILL,SIG_IGN); +   signal(SIGSEGV,SIG_IGN); +   signal(SIGTERM,SIG_IGN); +} +#endif + +/* + * Create a new FX/Mesa context and return a handle to it. + */ +fxMesaContext GLAPIENTRY fxMesaCreateContext(GLuint win,GrScreenResolution_t res, +					   GrScreenRefresh_t ref, +					   const GLint attribList[]) +{ +  fxMesaContext fxMesa; +  int i,type; +  int aux; +  GLboolean doubleBuffer=GL_FALSE; +  GLboolean alphaBuffer=GL_FALSE; +  GLboolean verbose=GL_FALSE; +  GLint depthSize=0; +  GLint stencilSize=0; +  GLint accumSize=0; +  GLcontext *shareCtx = NULL; +  GLcontext *ctx = 0; +  FX_GrContext_t glideContext = 0; +  char *errorstr; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxMesaCreateContext() Start\n"); +  } + +  if(getenv("MESA_FX_INFO")) +    verbose=GL_TRUE; + +  aux=0; +  i=0; +  while(attribList[i]!=FXMESA_NONE) { +    switch (attribList[i]) { +    case FXMESA_DOUBLEBUFFER: +      doubleBuffer=GL_TRUE; +      break; +    case FXMESA_ALPHA_SIZE: +      i++; +      alphaBuffer=attribList[i]>0; +      if(alphaBuffer) +        aux=1; +      break; +    case FXMESA_DEPTH_SIZE: +      i++; +      depthSize=attribList[i]; +      if(depthSize) +        aux=1; +      break; +    case FXMESA_STENCIL_SIZE: +      i++; +      stencilSize=attribList[i]; +      break; +    case FXMESA_ACCUM_SIZE: +      i++; +      accumSize=attribList[i]; +      break; +      /* XXX ugly hack here for sharing display lists */ +#define FXMESA_SHARE_CONTEXT 990099  /* keep in sync with xmesa1.c! */ +    case FXMESA_SHARE_CONTEXT: +      i++; +      { +        const void *vPtr = &attribList[i]; +        GLcontext **ctx = (GLcontext **) vPtr; +        shareCtx = *ctx; +      } +      break; +    default: +      if (MESA_VERBOSE&VERBOSE_DRIVER) { +	fprintf(stderr,"fxmesa: fxMesaCreateContext() End (defualt)\n"); +      } +      return NULL; +    } +    i++; +  } + +  /* A workaround for Linux GLQuake */ +  if(depthSize && alphaBuffer) +    alphaBuffer=0; + +  if(verbose) +    fprintf(stderr,"Mesa fx Voodoo Device Driver v0.30\nWritten by David Bucciarelli (davibu@tin.it.it)\n"); + +  if((type=fxQueryHardware()) >= 0) { +    if(type==GR_SSTTYPE_VOODOO) +      win=0; + +    grSstSelect(glbCurrentBoard); + +#if  FXMESA_USE_ARGB +    glideContext = FX_grSstWinOpen((FxU32)win,res,ref, +                     GR_COLORFORMAT_ARGB,GR_ORIGIN_LOWER_LEFT,2,aux); + +#else +    glideContext = FX_grSstWinOpen((FxU32)win,res,ref, +                     GR_COLORFORMAT_ABGR,GR_ORIGIN_LOWER_LEFT,2,aux); +#endif +   if (!glideContext){ +      errorstr = "grSstWinOpen";  +      goto errorhandler; +    } + +    if(verbose) +      fprintf(stderr,"Glide screen size: %dx%d\n", +              (int)FX_grSstScreenWidth(),(int)FX_grSstScreenHeight()); +  } else { +    fprintf(stderr,"fx Driver: ERROR no Voodoo1/2 Graphics or Voodoo Rush !\n"); +    return NULL; +  } + +  fxMesa=(fxMesaContext)calloc(1,sizeof(struct tfxMesaContext)); +  if(!fxMesa) { +    errorstr = "malloc"; +    goto errorhandler; +  } +   +  FX_setupGrVertexLayout(); +   +  fxMesa->glideContext = glideContext; +  fxMesa->board=glbCurrentBoard; +  fxMesa->width=FX_grSstScreenWidth(); +  fxMesa->height=FX_grSstScreenHeight(); + +  fxMesa->verbose=verbose; + +  if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) +    fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx > 1); +  else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) +    fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx > 1); +  else +    fxMesa->haveTwoTMUs=GL_FALSE; + +  if (getenv("FX_EMULATE_SINGLE_TMU")) { +     if (MESA_VERBOSE&VERBOSE_DRIVER)  +       fprintf(stderr, "\n\nEmulating single tmu\n\n"); +     fxMesa->haveTwoTMUs = GL_FALSE; +  } + +  fxMesa->emulateTwoTMUs = fxMesa->haveTwoTMUs; +   +  if (!getenv("FX_DONT_FAKE_MULTITEX")) { +     if (MESA_VERBOSE&VERBOSE_DRIVER) { +	  if (!fxMesa->haveTwoTMUs) +	    fprintf(stderr, "\n\nEmulating multitexture\n\n"); +     } +     fxMesa->emulateTwoTMUs = GL_TRUE; +  } + + +  fxMesa->haveDoubleBuffer=doubleBuffer; +  fxMesa->haveAlphaBuffer=alphaBuffer; +  fxMesa->haveGlobalPaletteTexture=GL_FALSE; + +  if(getenv("FX_GLIDE_SWAPINTERVAL")) +    fxMesa->swapInterval=atoi(getenv("FX_GLIDE_SWAPINTERVAL")); +  else +    fxMesa->swapInterval=1; + +  if(getenv("MESA_FX_SWAP_PENDING")) +    fxMesa->maxPendingSwapBuffers=atoi(getenv("MESA_FX_SWAP_PENDING")); +  else +    fxMesa->maxPendingSwapBuffers=2; + +  fxMesa->color=0xffffffff; +  fxMesa->clearC=0; +  fxMesa->clearA=0; + +  fxMesa->stats.swapBuffer=0; +  fxMesa->stats.reqTexUpload=0; +  fxMesa->stats.texUpload=0; +  fxMesa->stats.memTexUpload=0; + +  fxMesa->tmuSrc=FX_TMU_NONE; +  fxMesa->lastUnitsMode=FX_UM_NONE; +  fxTMInit(fxMesa); + +  /* FX units setup */ + +  fxMesa->unitsState.alphaTestEnabled=GL_FALSE; +  fxMesa->unitsState.alphaTestFunc=GR_CMP_ALWAYS; +  fxMesa->unitsState.alphaTestRefValue=0; + +  fxMesa->unitsState.blendEnabled=GL_FALSE; +  fxMesa->unitsState.blendSrcFuncRGB=GR_BLEND_ONE; +  fxMesa->unitsState.blendDstFuncRGB=GR_BLEND_ZERO; +  fxMesa->unitsState.blendSrcFuncAlpha=GR_BLEND_ONE; +  fxMesa->unitsState.blendDstFuncAlpha=GR_BLEND_ZERO; + +  fxMesa->unitsState.depthTestEnabled	=GL_FALSE; +  fxMesa->unitsState.depthMask		=GL_TRUE; +  fxMesa->unitsState.depthTestFunc	=GR_CMP_LESS; + +  grColorMask(FXTRUE,alphaBuffer ? FXTRUE : FXFALSE); +  if(doubleBuffer) { +    fxMesa->currentFB=GR_BUFFER_BACKBUFFER; +    grRenderBuffer(GR_BUFFER_BACKBUFFER); +  } else { +    fxMesa->currentFB=GR_BUFFER_FRONTBUFFER; +    grRenderBuffer(GR_BUFFER_FRONTBUFFER); +  } +   +  fxMesa->state 	= NULL; +  fxMesa->fogTable 	= NULL; +   +  fxMesa->state 	= malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE)); +  fxMesa->fogTable 	= malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES)*sizeof(GrFog_t)); +   +  if (!fxMesa->state || !fxMesa->fogTable) { +     errorstr = "malloc"; +     goto errorhandler; +  } + +  if(depthSize) +    grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER); +     +#if (!FXMESA_USE_ARGB) +  grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); /* Not every Glide supports this  */ +#endif + +  fxMesa->glVis=gl_create_visual(GL_TRUE,     /* RGB mode */ +                                 alphaBuffer, +                                 doubleBuffer, +                                 GL_FALSE,    /* stereo */ +                                 depthSize,   /* depth_size */ +                                 stencilSize, /* stencil_size */ +                                 accumSize,   /* accum_size */ +                                 0,           /* index bits */ +                                 5,6,5,0);    /* RGBA bits */ +  if (!fxMesa->glVis) { +     errorstr = "gl_create_visual"; +     goto errorhandler; +  } + +  ctx = fxMesa->glCtx=gl_create_context(fxMesa->glVis, +					shareCtx,  /* share list context */ +					(void *) fxMesa, GL_TRUE); +  if (!ctx) { +     errorstr = "gl_create_context"; +     goto errorhandler; +  } + +  fxMesa->glBuffer=gl_create_framebuffer(fxMesa->glVis); +  if (!fxMesa->glBuffer) { +    errorstr = "gl_create_framebuffer"; +    goto errorhandler; +  } + +  fxMesa->glCtx->Const.MaxTextureLevels=9; +  fxMesa->glCtx->Const.MaxTextureSize=256; +  fxMesa->glCtx->Const.MaxTextureUnits=fxMesa->emulateTwoTMUs ? 2 : 1; + +  fxMesa->glCtx->NewState|=NEW_DRVSTATE1; +  fxMesa->new_state = NEW_ALL; +   +  fxDDSetupInit(); +  fxDDCvaInit(); +  fxDDClipInit(); +  fxDDTrifuncInit(); +  fxDDFastPathInit(); + +  fxSetupDDPointers(fxMesa->glCtx); +  fxDDRenderInit(fxMesa->glCtx); +  fxDDInitExtensions(fxMesa->glCtx);   + +  fxDDSetNearFar(fxMesa->glCtx,1.0,100.0); +   +  grGlideGetState((GrState*)fxMesa->state); + +  /* XXX Fix me: callback not registered when main VB is created. +   */ +  if (fxMesa->glCtx->VB)  +     fxDDRegisterVB( fxMesa->glCtx->VB ); +   +  /* XXX Fix me too: need to have the 'struct dd' prepared prior to +   * creating the context... The below is broken if you try to insert +   * new stages.   +   */ +  if (ctx->NrPipelineStages) +     ctx->NrPipelineStages = fxDDRegisterPipelineStages( ctx->PipelineStage, +							 ctx->PipelineStage, +							 ctx->NrPipelineStages); + +   +  glbTotNumCtx++; + +  /* Run the config file */ +  gl_context_initialize( fxMesa->glCtx ); + +  /* install signal handlers */ +#if defined(__linux__) +  if (fxMesa->glCtx->CatchSignals) { +     signal(SIGINT,cleangraphics_handler); +     signal(SIGHUP,cleangraphics_handler); +     signal(SIGPIPE,cleangraphics_handler); +     signal(SIGFPE,cleangraphics_handler); +     signal(SIGBUS,cleangraphics_handler); +     signal(SIGILL,cleangraphics_handler); +     signal(SIGSEGV,cleangraphics_handler); +     signal(SIGTERM,cleangraphics_handler); +  } +#endif + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxMesaCreateContext() End\n"); +  } + +  return fxMesa; + +errorhandler: +   if (fxMesa) { +      if (fxMesa->glideContext) +      	FX_grSstWinClose(fxMesa->glideContext); +      fxMesa->glideContext = 0; +       +      if (fxMesa->state)   +     	free(fxMesa->state); +      if (fxMesa && fxMesa->fogTable) +     	free(fxMesa->fogTable); +      if (fxMesa->glBuffer) +      	gl_destroy_framebuffer(fxMesa->glBuffer); +      if (fxMesa->glVis) +      	gl_destroy_visual(fxMesa->glVis); +      if (fxMesa->glCtx) +      	gl_destroy_context(fxMesa->glCtx); +      free(fxMesa); +   } + + + +      + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +      fprintf(stderr,"fxmesa: fxMesaCreateContext() End (%s)\n",errorstr); +  } +  return NULL; +} + + +/* + * Function to set the new window size in the context (mainly for the Voodoo Rush) + */ +void GLAPIENTRY fxMesaUpdateScreenSize(fxMesaContext fxMesa) +{ +  fxMesa->width=FX_grSstScreenWidth(); +  fxMesa->height=FX_grSstScreenHeight(); +} + + +/* + * Destroy the given FX/Mesa context. + */ +void GLAPIENTRY fxMesaDestroyContext(fxMesaContext fxMesa) +{ +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxMesaDestroyContext()\n"); +  } + +  if(fxMesa) { +    gl_destroy_visual(fxMesa->glVis); +    gl_destroy_context(fxMesa->glCtx); +    gl_destroy_framebuffer(fxMesa->glBuffer); + +    glbTotNumCtx--; + +    fxCloseHardware(); +    FX_grSstWinClose(fxMesa->glideContext); + +    if(fxMesa->verbose) { +      fprintf(stderr,"Misc Stats:\n"); +      fprintf(stderr,"  # swap buffer: %u\n",fxMesa->stats.swapBuffer); + +      if(!fxMesa->stats.swapBuffer) +        fxMesa->stats.swapBuffer=1; + +      fprintf(stderr,"Textures Stats:\n"); +      fprintf(stderr,"  Free texture memory on TMU0: %d:\n",fxMesa->freeTexMem[FX_TMU0]); +      if(fxMesa->haveTwoTMUs) +        fprintf(stderr,"  Free texture memory on TMU1: %d:\n",fxMesa->freeTexMem[FX_TMU1]); +      fprintf(stderr,"  # request to TMM to upload a texture objects: %u\n", +              fxMesa->stats.reqTexUpload); +      fprintf(stderr,"  # request to TMM to upload a texture objects per swapbuffer: %.2f\n", +              fxMesa->stats.reqTexUpload/(float)fxMesa->stats.swapBuffer); +      fprintf(stderr,"  # texture objects uploaded: %u\n", +              fxMesa->stats.texUpload); +      fprintf(stderr,"  # texture objects uploaded per swapbuffer: %.2f\n", +              fxMesa->stats.texUpload/(float)fxMesa->stats.swapBuffer); +      fprintf(stderr,"  # MBs uploaded to texture memory: %.2f\n", +              fxMesa->stats.memTexUpload/(float)(1<<20)); +      fprintf(stderr,"  # MBs uploaded to texture memory per swapbuffer: %.2f\n", +              (fxMesa->stats.memTexUpload/(float)fxMesa->stats.swapBuffer)/(float)(1<<20)); +    } +    if (fxMesa->state)   +       free(fxMesa->state); +    if (fxMesa->fogTable) +       free(fxMesa->fogTable); +    fxTMClose(fxMesa); +     +    free(fxMesa); +  } + +  if(fxMesa==fxMesaCurrentCtx) +    fxMesaCurrentCtx=NULL; +} + + +/* + * Make the specified FX/Mesa context the current one. + */ +void GLAPIENTRY fxMesaMakeCurrent(fxMesaContext fxMesa) +{ +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) Start\n"); +  } + +  if(!fxMesa) { +    gl_make_current(NULL,NULL); +    fxMesaCurrentCtx=NULL; + +    if (MESA_VERBOSE&VERBOSE_DRIVER) { +      fprintf(stderr,"fxmesa: fxMesaMakeCurrent(NULL) End\n"); +    } + +    return; +  } + +  /* if this context is already the current one, we can return early */ +  if (fxMesaCurrentCtx == fxMesa +      && fxMesaCurrentCtx->glCtx == gl_get_current_context()) { +     if (MESA_VERBOSE&VERBOSE_DRIVER) { +        fprintf(stderr,"fxmesa: fxMesaMakeCurrent(fxMesaCurrentCtx==fxMesa) End\n"); +    } + +    return; +  } + +  if(fxMesaCurrentCtx) +    grGlideGetState((GrState*)fxMesaCurrentCtx->state); + +  fxMesaCurrentCtx=fxMesa; + +  grSstSelect(fxMesa->board); +  grGlideSetState((GrState*)fxMesa->state); + +  gl_make_current(fxMesa->glCtx,fxMesa->glBuffer); + +  fxSetupDDPointers(fxMesa->glCtx); + +  /* The first time we call MakeCurrent we set the initial viewport size */ +  if(fxMesa->glCtx->Viewport.Width==0) +    gl_Viewport(fxMesa->glCtx,0,0,fxMesa->width,fxMesa->height); + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) End\n"); +  } +} + + +/* + * Swap front/back buffers for current context if double buffered. + */ +void GLAPIENTRY fxMesaSwapBuffers(void) +{ +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: ------------------------------- fxMesaSwapBuffers() -------------------------------\n"); +  } + +  if(fxMesaCurrentCtx) { +   FLUSH_VB( fxMesaCurrentCtx->glCtx, "swap buffers" ); + +    if(fxMesaCurrentCtx->haveDoubleBuffer) { + +      grBufferSwap(fxMesaCurrentCtx->swapInterval); + +      /* +       * Don't allow swap buffer commands to build up! +       */ +      while(FX_grGetInteger(FX_PENDING_BUFFERSWAPS)>fxMesaCurrentCtx->maxPendingSwapBuffers) +        /* The driver is able to sleep when waiting for the completation +           of multiple swapbuffer operations instead of wasting +           CPU time (NOTE: you must uncomment the following line in the +           in order to enable this option) */ +        /* usleep(10000); */ +        ; + +      fxMesaCurrentCtx->stats.swapBuffer++; +    } +  } +} + + +/* + * Query 3Dfx hardware presence/kind + */ +int GLAPIENTRY fxQueryHardware(void) +{ +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxQueryHardware() Start\n"); +  } + +  if(!glbGlideInitialized) { +    grGlideInit(); +    if(FX_grSstQueryHardware(&glbHWConfig)) { +      grSstSelect(glbCurrentBoard); +      glb3DfxPresent=1; + +      if(getenv("MESA_FX_INFO")) { +        char buf[80]; +                         +        FX_grGlideGetVersion(buf); +        fprintf(stderr,"Using Glide V%s\n",0); +        fprintf(stderr,"Number of boards: %d\n",glbHWConfig.num_sst); + +        if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) { +          fprintf(stderr,"Framebuffer RAM: %d\n", +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ? +                  (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam*2) : +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam); +          fprintf(stderr,"Number of TMUs: %d\n", +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx); +          fprintf(stderr,"SLI detected: %d\n", +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect); +        } else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) { +          fprintf(stderr,"Framebuffer RAM: %d\n", +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam); +          fprintf(stderr,"Number of TMUs: %d\n", +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx); +        } + +      } +    } else +      glb3DfxPresent=0; + +    glbGlideInitialized=1; + +#if defined(__WIN32__) +    onexit((_onexit_t)cleangraphics); +#elif defined(__linux__) +    atexit(cleangraphics); +#endif +  } + +  if(!glb3DfxPresent) { +    if (MESA_VERBOSE&VERBOSE_DRIVER) { +      fprintf(stderr,"fxmesa: fxQueryHardware() End (-1)\n"); +    } +    return(-1); +  } + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxQueryHardware() End (voodooo)\n"); +  } +  return(glbHWConfig.SSTs[glbCurrentBoard].type); +} + + +/* + * Shutdown Glide library + */ +void GLAPIENTRY fxCloseHardware(void) +{ +  if(glbGlideInitialized) { +    if(getenv("MESA_FX_INFO")) { +      GrSstPerfStats_t          st; + +      FX_grSstPerfStats(&st); +      fprintf(stderr,"Pixels Stats:\n"); +      fprintf(stderr,"  # pixels processed (minus buffer clears): %u\n",(unsigned)st.pixelsIn); +      fprintf(stderr,"  # pixels not drawn due to chroma key test failure: %u\n",(unsigned)st.chromaFail); +      fprintf(stderr,"  # pixels not drawn due to depth test failure: %u\n",(unsigned)st.zFuncFail); +      fprintf(stderr,"  # pixels not drawn due to alpha test failure: %u\n",(unsigned)st.aFuncFail); +      fprintf(stderr,"  # pixels drawn (including buffer clears and LFB writes): %u\n",(unsigned)st.pixelsOut); +    } + +    if(glbTotNumCtx==0) { +      grGlideShutdown(); +      glbGlideInitialized=0; +    } +  } +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_api(void) +{ +  return 0; +} + +#endif  /* FX */ diff --git a/src/mesa/drivers/glide/fxdd.c b/src/mesa/drivers/glide/fxdd.c new file mode 100644 index 0000000000..b2f3a7a43c --- /dev/null +++ b/src/mesa/drivers/glide/fxdd.c @@ -0,0 +1,632 @@ +/* -*- mode: C; tab-width:8;  -*- + +             fxdd.c - 3Dfx VooDoo Mesa device driver functions +*/ + +/* + * 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. + * + * See the file fxapi.c for more informations about authors + * + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "enums.h" + +/**********************************************************************/ +/*****                 Miscellaneous functions                    *****/ +/**********************************************************************/ + +/* Enalbe/Disable dithering */ +void fxDDDither(GLcontext *ctx, GLboolean enable) +{ +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxDDDither()\n"); +  } + +  if(enable) +    grDitherMode(GR_DITHER_4x4); +  else +    grDitherMode(GR_DITHER_DISABLE); +} + + +/* Return buffer size information */ +void fxDDBufferSize(GLcontext *ctx, GLuint *width, GLuint *height) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxDDBufferSize(...) Start\n"); +  } + +  *width=fxMesa->width; +  *height=fxMesa->height; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxDDBufferSize(...) End\n"); +  } +} + + +/* Set current drawing color */ +static void fxDDSetColor(GLcontext *ctx, GLubyte red, GLubyte green, +                         GLubyte blue, GLubyte alpha ) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLubyte col[4]; +  ASSIGN_4V( col, red, green, blue, alpha ); +   +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red,green,blue,alpha); +  } + +  fxMesa->color=FXCOLOR4(col); +} + + +/* Implements glClearColor() */ +static void fxDDClearColor(GLcontext *ctx, GLubyte red, GLubyte green, +                           GLubyte blue, GLubyte alpha ) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLubyte col[4]; + + + +  ASSIGN_4V( col, red, green, blue, 255 ); + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red,green,blue,alpha); +  } +  +  fxMesa->clearC=FXCOLOR4( col ); +  fxMesa->clearA=alpha; +} + +/* Clear the color and/or depth buffers */ +static GLbitfield fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, +                            GLint x, GLint y, GLint width, GLint height ) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLbitfield newmask; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxDDClear(%d,%d,%d,%d)\n",x,y,width,height); +  } + +  switch(mask & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) { +  case (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT): +    /* clear color and depth buffer */ + +    if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) { +      grRenderBuffer(GR_BUFFER_BACKBUFFER); +      grBufferClear(fxMesa->clearC, fxMesa->clearA, +                    (FxU16)(ctx->Depth.Clear*0xffff)); +    } +    if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) { +       grRenderBuffer(GR_BUFFER_FRONTBUFFER); +       grBufferClear(fxMesa->clearC, fxMesa->clearA, +                     (FxU16)(ctx->Depth.Clear*0xffff)); +    } + +    newmask=mask & (~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)); +    break; +  case (GL_COLOR_BUFFER_BIT): +    /* clear color buffer */ + +    if(ctx->Color.ColorMask) { +      grDepthMask(FXFALSE); + +      if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) { +        grRenderBuffer(GR_BUFFER_BACKBUFFER); +        grBufferClear(fxMesa->clearC, fxMesa->clearA, 0); +      } +      if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) { +        grRenderBuffer(GR_BUFFER_FRONTBUFFER); +        grBufferClear(fxMesa->clearC, fxMesa->clearA, 0); +      } + +      if(ctx->Depth.Mask) +        grDepthMask(FXTRUE); +    } + +    newmask=mask & (~(GL_COLOR_BUFFER_BIT)); +    break; +  case (GL_DEPTH_BUFFER_BIT): +    /* clear depth buffer */ + +    if(ctx->Depth.Mask) { +      grColorMask(FXFALSE,FXFALSE); +      grBufferClear(fxMesa->clearC, fxMesa->clearA, +                    (FxU16)(ctx->Depth.Clear*0xffff)); + +      grColorMask(ctx->Color.ColorMask[RCOMP] || +                  ctx->Color.ColorMask[GCOMP] || +                  ctx->Color.ColorMask[BCOMP], +                  ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); +    } + +    newmask=mask & (~(GL_DEPTH_BUFFER_BIT)); +    break; +  default: +    newmask=mask; +    break; +  } +    +  return newmask; +} + + +/*  Set the buffer used in double buffering */ +static GLboolean fxDDSetBuffer(GLcontext *ctx, GLenum mode ) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxDDSetBuffer(%x)\n",mode); +  } + +  if (mode == GL_FRONT_LEFT) { +    fxMesa->currentFB = GR_BUFFER_FRONTBUFFER; +    grRenderBuffer(fxMesa->currentFB); +    return GL_TRUE; +  } +  else if (mode == GL_BACK_LEFT) { +    fxMesa->currentFB = GR_BUFFER_BACKBUFFER; +    grRenderBuffer(fxMesa->currentFB); +    return GL_TRUE; +  } +  else { +    return GL_FALSE; +  } +} + + +static GLboolean fxDDDrawBitMap(GLcontext *ctx, GLint px, GLint py, +                                GLsizei width, GLsizei height, +                                const struct gl_pixelstore_attrib *unpack, +                                const GLubyte *bitmap) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  FxU16 *p; +  GrLfbInfo_t info; +  const GLubyte *pb; +  int x,y; +  GLint r,g,b,a,scrwidth,scrheight,stride; +  FxU16 color; + +  /* TODO: with a little work, these bitmap unpacking parameter restrictions +   * could be removed. +   */ +  if((unpack->Alignment!=1) || +     (unpack->RowLength!=0) || +     (unpack->SkipPixels!=0) || +     (unpack->SkipRows!=0) || +     (unpack->SwapBytes) || +     (unpack->LsbFirst)) +    return GL_FALSE; + +#define ISCLIPPED(rx) ( ((rx)<0) || ((rx)>=scrwidth) ) +#define DRAWBIT(i) {	   \ +  if(!ISCLIPPED(x+px))	   \ +    if( (*pb) & (1<<(i)) ) \ +      (*p)=color;	   \ +  p++;                     \ +  x++;			   \ +  if(x>=width) {           \ +    pb++;                  \ +    break;                 \ +  }                        \ +} + +  scrwidth=fxMesa->width; +  scrheight=fxMesa->height; + +  if((px>=scrwidth) || (px+width<=0) || (py>=scrheight) || (py+height<=0)) +    return GL_TRUE; + +  pb=bitmap; + +  if(py<0) { +    pb+=(height*(-py)) >> (3+1); +    height+=py; +    py=0; +  } + +  if(py+height>=scrheight) +    height-=(py+height)-scrheight; + +  info.size=sizeof(info); +  if(!grLfbLock(GR_LFB_WRITE_ONLY, +                fxMesa->currentFB, +                GR_LFBWRITEMODE_565, +                GR_ORIGIN_UPPER_LEFT, +                FXFALSE, +                &info)) { +#ifndef FX_SILENT +    fprintf(stderr,"fx Driver: error locking the linear frame buffer\n"); +#endif +    return GL_TRUE; +  } + +  r=(GLint)(ctx->Current.RasterColor[0]*255.0f); +  g=(GLint)(ctx->Current.RasterColor[1]*255.0f); +  b=(GLint)(ctx->Current.RasterColor[2]*255.0f); +  a=(GLint)(ctx->Current.RasterColor[3]*255.0f); +  color=(FxU16) +    ( ((FxU16)0xf8 & b) <<(11-3))  | +    ( ((FxU16)0xfc & g) <<(5-3+1)) | +    ( ((FxU16)0xf8 & r) >> 3); + +  stride=info.strideInBytes>>1; + +  /* This code is a bit slow... */ + +  for(y=0;y<height;y++) { +    p=((FxU16 *)info.lfbPtr)+px+((scrheight-(y+py))*stride); + +    for(x=0;;) { +      DRAWBIT(7);       DRAWBIT(6);     DRAWBIT(5);     DRAWBIT(4); +      DRAWBIT(3);       DRAWBIT(2);     DRAWBIT(1);     DRAWBIT(0); +      pb++; +    } +  } + +  grLfbUnlock(GR_LFB_WRITE_ONLY,fxMesa->currentFB); + +#undef ISCLIPPED +#undef DRAWBIT + +  return GL_TRUE; +} + +static void fxDDFinish(GLcontext *ctx) +{ +  FX_grFlush(); +} + + +static GLint fxDDGetParameteri(const GLcontext *ctx, GLint param) +{ +  switch(param) { +  case DD_HAVE_HARDWARE_FOG: +    return 1; +  default: +    fprintf(stderr,"fx Driver: internal error in fxDDGetParameteri(): %x\n",param); +    fxCloseHardware(); +    exit(-1); +  } +} + + +void fxDDSetNearFar(GLcontext *ctx, GLfloat n, GLfloat f) +{ +   FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG; +   ctx->Driver.RenderStart = fxSetupFXUnits; +} + +/* KW: Put the word Mesa in the render string because quakeworld + * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE). + * Why? + */ +static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name) +{ +  static char *extensions="GL_EXT_blend_color GL_EXT_blend_minmax GL_EXT_blend_logic_op GL_EXT_blend_subtract GL_EXT_paletted_texture GL_EXT_point_parameters GL_EXT_polygon_offset GL_EXT_vertex_array GL_EXT_texture_object GL_EXT_texture3D GL_MESA_window_pos GL_MESA_resize_buffers GL_EXT_shared_texture_palette GL_EXT_rescale_normal GL_EXT_abgr GL_SGIS_texture_edge_clamp 3DFX_set_global_palette GL_FXMESA_global_texture_lod_bias"; + +  static char buf[MAX_NUM_SST][64]; + +  fxQueryHardware(); + +  switch (name) { +    case GL_RENDERER: +      if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) { +        sprintf(buf[glbCurrentBoard],"Mesa Glide v0.30 Voodoo_Graphics %d CARD/%d FB/%d TM/%d TMU/%s", +                glbCurrentBoard, + +                (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ? +                 (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam*2) : +                 glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam), + +                glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.tmuConfig[GR_TMU0].tmuRam+ +                ((glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx>1) ? +                 glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.tmuConfig[GR_TMU1].tmuRam : +                 0), + +                glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx, + +                (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ? "SLI" : "NOSLI") +                ); +      } +      else { +        if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) +          sprintf(buf[glbCurrentBoard],"Glide v0.30 Voodoo_Rush %d CARD/%d FB/%d TM/%d TMU/NOSLI", +                  glbCurrentBoard, + +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam, + +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.tmuConfig.tmuRam, + +                  glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx	       +                  ); +        else +          strcpy(buf[glbCurrentBoard],"Glide v0.30 UNKNOWN"); +      } +      return (GLubyte *) buf[glbCurrentBoard]; +    case GL_EXTENSIONS: +      return (GLubyte *) extensions; +    default: +      return NULL; +  } +} + + +void fxDDInitExtensions( GLcontext *ctx ) +{ +   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +   gl_extensions_add( ctx, DEFAULT_ON, "3DFX_set_global_palette", 0 ); +   gl_extensions_add( ctx, DEFAULT_ON, "GL_FXMESA_global_texture_lod_bias", 0); +    +   if (!fxMesa->emulateTwoTMUs)  +      gl_extensions_disable( ctx, "GL_ARB_multitexture" ); +} + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +/* This is a no-op, since the z-buffer is in hardware */ +static void fxAllocDepthBuffer(GLcontext *ctx) +{ +   if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxAllocDepthBuffer()\n"); +   } +} + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +/* Check if the hardware supports the current context  + * + * Performs similar work to fxDDChooseRenderState() - should be merged. + */ +static GLboolean fxIsInHardware(GLcontext *ctx) +{ +   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +  if (!ctx->Hint.AllowDrawMem) +     return GL_TRUE;		/* you'll take it and like it */ + +  if((ctx->RasterMask & STENCIL_BIT) || +     ((ctx->Color.BlendEnabled) && (ctx->Color.BlendEquation!=GL_FUNC_ADD_EXT)) || +     ((ctx->Color.ColorLogicOpEnabled) && (ctx->Color.LogicOp!=GL_COPY)) || +     (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) || +     (!((ctx->Color.ColorMask[RCOMP]==ctx->Color.ColorMask[GCOMP]) && +        (ctx->Color.ColorMask[GCOMP]==ctx->Color.ColorMask[BCOMP]) && +        (ctx->Color.ColorMask[ACOMP]==ctx->Color.ColorMask[ACOMP]))) +     ) +    return GL_FALSE; + +  /* Unsupported texture/multitexture cases */ + +  if(fxMesa->emulateTwoTMUs) { +    if((ctx->Enabled & (TEXTURE0_3D | TEXTURE1_3D)) || +       /* Not very well written ... */ +       ((ctx->Enabled & (TEXTURE0_1D | TEXTURE1_1D)) &&  +        ((ctx->Enabled & (TEXTURE0_2D | TEXTURE1_2D))!=(TEXTURE0_2D | TEXTURE1_2D))) +       ) +      return GL_FALSE; + +    if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) && +       (ctx->Texture.Unit[0].EnvMode==GL_BLEND)) +      return GL_FALSE; + +    if((ctx->Texture.ReallyEnabled & TEXTURE1_2D) && +       (ctx->Texture.Unit[1].EnvMode==GL_BLEND)) +      return GL_FALSE; + + +    if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) +       fprintf(stderr, "fxMesa: fxIsInHardware, envmode is %s/%s\n", +	       gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode), +	       gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode)); + +    /* KW: This was wrong (I think) and I changed it... which doesn't mean +     * it is now correct... +     */ +    if((ctx->Enabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) && +       (ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D))) +    { +       /* Can't use multipass to blend a multitextured triangle - fall +	* back to software. +	*/ +       if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled)  +	  return GL_FALSE; +	   +       if ((ctx->Texture.Unit[0].EnvMode!=ctx->Texture.Unit[1].EnvMode) && +	   (ctx->Texture.Unit[0].EnvMode!=GL_MODULATE) && +	   (ctx->Texture.Unit[0].EnvMode!=GL_REPLACE)) /* q2, seems ok... */ +       { +	  if (MESA_VERBOSE&VERBOSE_DRIVER) +	    fprintf(stderr, "fxMesa: unsupported multitex env mode\n"); + +	  return GL_FALSE; +       } +    } +  } else { +    if((ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) || +       /* Not very well written ... */ +       ((ctx->Enabled & TEXTURE0_1D) &&  +        (!(ctx->Enabled & TEXTURE0_2D))) +       ) +      return GL_FALSE; + +     +    if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) && +       (ctx->Texture.Unit[0].EnvMode==GL_BLEND)) +      return GL_FALSE; +  } + +  return GL_TRUE; +} + + + +#define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|NEW_PROJECTION|NEW_TEXTURE_MATRIX|NEW_USER_CLIP|NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE)) + +static void fxDDUpdateDDPointers(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint new_state = ctx->NewState; + +  if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_STATE))  +    fprintf(stderr,"fxmesa: fxDDUpdateDDPointers(...)\n"); + +  if (new_state & (NEW_RASTER_OPS|NEW_TEXTURING)) +     fxMesa->is_in_hardware = fxIsInHardware(ctx); + +  if (fxMesa->is_in_hardware) { +    if (fxMesa->new_state) +      fxSetupFXUnits(ctx); + +    if(new_state & INTERESTED) { +      fxDDChooseRenderState( ctx ); +      fxMesa->RenderVBTables=fxDDChooseRenderVBTables(ctx); +      ctx->Driver.RasterSetup=fxDDChooseSetupFunction(ctx); +    } +       +    ctx->Driver.PointsFunc=fxMesa->PointsFunc; +    ctx->Driver.LineFunc=fxMesa->LineFunc; +    ctx->Driver.TriangleFunc=fxMesa->TriangleFunc; +    ctx->Driver.QuadFunc=fxMesa->QuadFunc; +    ctx->Driver.RenderVBClippedTab=fxMesa->RenderVBTables[0]; +    ctx->Driver.RenderVBCulledTab=fxMesa->RenderVBTables[1]; +    ctx->Driver.RenderVBRawTab=fxMesa->RenderVBTables[2]; + +  } + +  ctx->Driver.AllocDepthBuffer=fxAllocDepthBuffer; +  ctx->Driver.DepthTestSpan=fxDDDepthTestSpanGeneric; +  ctx->Driver.DepthTestPixels=fxDDDepthTestPixelsGeneric; +  ctx->Driver.ReadDepthSpanFloat=fxDDReadDepthSpanFloat; +  ctx->Driver.ReadDepthSpanInt=fxDDReadDepthSpanInt; +  ctx->Driver.RenderStart = 0; +} + + +void fxSetupDDPointers(GLcontext *ctx) +{ +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +    fprintf(stderr,"fxmesa: fxSetupDDPointers()\n"); +  } + +  ctx->Driver.UpdateState=fxDDUpdateDDPointers; +          +  ctx->Driver.GetString=fxDDGetString; + +  ctx->Driver.Dither=fxDDDither; + +  ctx->Driver.NearFar=fxDDSetNearFar; + +  ctx->Driver.GetParameteri=fxDDGetParameteri; + +  ctx->Driver.ClearIndex=NULL; +  ctx->Driver.ClearColor=fxDDClearColor; +  ctx->Driver.Clear=fxDDClear; + +  ctx->Driver.Index=NULL; +  ctx->Driver.Color=fxDDSetColor; + +  ctx->Driver.SetBuffer=fxDDSetBuffer; +  ctx->Driver.GetBufferSize=fxDDBufferSize; + +  ctx->Driver.Bitmap=fxDDDrawBitMap; +  ctx->Driver.DrawPixels=NULL; + +  ctx->Driver.Finish=fxDDFinish; +  ctx->Driver.Flush=NULL; + +  ctx->Driver.RenderStart=NULL; +  ctx->Driver.RenderFinish=NULL; + +  ctx->Driver.TexEnv=fxDDTexEnv; +  ctx->Driver.TexImage=fxDDTexImg; +  ctx->Driver.TexSubImage=fxDDTexSubImg; +  ctx->Driver.TexParameter=fxDDTexParam; +  ctx->Driver.BindTexture=fxDDTexBind; +  ctx->Driver.DeleteTexture=fxDDTexDel; +  ctx->Driver.UpdateTexturePalette=fxDDTexPalette; +  ctx->Driver.UseGlobalTexturePalette=fxDDTexUseGlbPalette; + +  ctx->Driver.RectFunc=NULL; + +  ctx->Driver.AlphaFunc=fxDDAlphaFunc; +  ctx->Driver.BlendFunc=fxDDBlendFunc; +  ctx->Driver.DepthFunc=fxDDDepthFunc; +  ctx->Driver.DepthMask=fxDDDepthMask; +  ctx->Driver.ColorMask=fxDDColorMask; +  ctx->Driver.Fogfv=fxDDFogfv; +  ctx->Driver.Scissor=fxDDScissor; +  ctx->Driver.FrontFace=fxDDFrontFace; +  ctx->Driver.CullFace=fxDDCullFace; +  ctx->Driver.ShadeModel=fxDDShadeModel; +  ctx->Driver.Enable=fxDDEnable; +   + +  ctx->Driver.RegisterVB=fxDDRegisterVB; +  ctx->Driver.UnregisterVB=fxDDUnregisterVB; + +  ctx->Driver.RegisterPipelineStages = fxDDRegisterPipelineStages; + +  ctx->Driver.OptimizeImmediatePipeline = 0; /* nothing done yet */ +  ctx->Driver.OptimizePrecalcPipeline = 0; + +/*    if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */ +/*       ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */ + +  if (!getenv("FX_NO_FAST"))  +      ctx->Driver.BuildPrecalcPipeline = fxDDBuildPrecalcPipeline;  + +  ctx->Driver.TriangleCaps = DD_TRI_CULL|DD_TRI_OFFSET|DD_TRI_LIGHT_TWOSIDE; + +  fxSetupDDSpanPointers(ctx); + +  FX_CONTEXT(ctx)->render_index = 1; /* force an update */ +  fxDDUpdateDDPointers(ctx); +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_dd(void) +{ +  return 0; +} + +#endif  /* FX */ diff --git a/src/mesa/drivers/glide/fxddspan.c b/src/mesa/drivers/glide/fxddspan.c new file mode 100644 index 0000000000..fc7c38d5c4 --- /dev/null +++ b/src/mesa/drivers/glide/fxddspan.c @@ -0,0 +1,817 @@ +/* -*- mode: C; tab-width:8;  -*- + +             fxdd.c - 3Dfx VooDoo Mesa span and pixel functions +*/ + +/* + * 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. + * + * See the file fxapi.c for more informations about authors + * + */ + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" + +#ifdef _MSC_VER +#ifdef _WIN32 +#pragma warning( disable : 4090 4022 ) +/* 4101 : "different 'const' qualifier" + * 4022 : "pointer mistmatch for actual parameter 'n' + */ +#endif +#endif + + +#if !defined(FXMESA_USE_ARGB)  + +    #define LFB_WRITE_SPAN_MESA(dst_buffer,dst_x,dst_y,src_width,src_stride,src_data)	\ +	  grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_width,1,GR_LFB_SRC_FMT_8888,src_stride,src_data) +#else /* defined(FXMESA_USE_RGBA) */ + +       #define MESACOLOR_TO_ARGB(c) (       \ +             ( ((unsigned int)(c[ACOMP]))<<24 ) | \ +             ( ((unsigned int)(c[RCOMP]))<<16 ) | \ +             ( ((unsigned int)(c[GCOMP]))<<8 )  | \ +             (  (unsigned int)(c[BCOMP])) ) +   +      /* inline */ void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,  +                  		  FxU32 dst_x, FxU32 dst_y,  +                  		  /* GrLfbSrcFmt_t src_format, format is GR_LFB_SRC_FMT_8888 */ +                  		  FxU32 src_width,/* FxU32 src_height,  height is 1 */ +                  		  FxI32 src_stride, void *src_data ) +       { +             /* Covert to ARGB */ +             GLubyte (*rgba)[4] = src_data; +             GLuint argb[MAX_WIDTH]; +             int i; +    +             for (i = 0; i < src_width; i++) +             { +                argb[i] = MESACOLOR_TO_ARGB(rgba[i]); +             } +           FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,GR_LFB_SRC_FMT_8888,src_width,1,src_stride,(void*)argb); +       } +#endif + +/************************************************************************/ +/*****                    Span functions                            *****/ +/************************************************************************/ + +static void fxDDWriteRGBASpan(const GLcontext *ctx,  +                              GLuint n, GLint x, GLint y, +                              const GLubyte rgba[][4], const GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint i; +  GLint bottom=fxMesa->height-1; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDWriteRGBASpan(...)\n"); +  } + +  if (mask) { +    int span=0; + +    for (i=0;i<n;i++) { +      if (mask[i]) { +        ++span;  +      } else { +        if (span > 0) { +          LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y, +                           /* GR_LFB_SRC_FMT_8888,*/ span, /*1,*/ 0, (void *) rgba[i-span] ); +          span = 0; +        } +      } +    } + +    if (span > 0) +      LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y, +                        /* GR_LFB_SRC_FMT_8888, */ span, /*1,*/ 0, (void *) rgba[n-span] ); +  } else +    LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/ +                      n,/* 1,*/ 0, (void *) rgba ); +} + + +static void fxDDWriteRGBSpan(const GLcontext *ctx,  +                             GLuint n, GLint x, GLint y, +                             const GLubyte rgb[][3], const GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint i; +  GLint bottom=fxMesa->height-1; +  GLubyte rgba[MAX_WIDTH][4]; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDWriteRGBSpan()\n"); +  } + +  if (mask) { +    int span=0; + +    for (i=0;i<n;i++) { +      if (mask[i]) { +        rgba[span][RCOMP] = rgb[i][0]; +        rgba[span][GCOMP] = rgb[i][1]; +        rgba[span][BCOMP] = rgb[i][2]; +        rgba[span][ACOMP] = 255; +        ++span; +      } else { +        if (span > 0) { +          LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y, +                            /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba ); +          span = 0; +        } +      } +    } + +    if (span > 0) +      LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y, +                        /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba ); +  } else { +    for (i=0;i<n;i++) { +      rgba[i][RCOMP]=rgb[i][0]; +      rgba[i][GCOMP]=rgb[i][1]; +      rgba[i][BCOMP]=rgb[i][2]; +      rgba[i][ACOMP]=255; +    } + +    LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/ +                      n,/* 1,*/ 0, (void *) rgba ); +  } +} + + +static void fxDDWriteMonoRGBASpan(const GLcontext *ctx,  +                                  GLuint n, GLint x, GLint y, +                                  const GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint i; +  GLint bottom=fxMesa->height-1; +  GLuint data[MAX_WIDTH]; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDWriteMonoRGBASpan(...)\n"); +  } + +  if (mask) { +    int span=0; + +    for (i=0;i<n;i++) { +      if (mask[i]) { +        data[span] = (GLuint) fxMesa->color; +        ++span; +      } else { +        if (span > 0) { +          FX_grLfbWriteRegion( fxMesa->currentFB, x+i-span, bottom-y, +                            GR_LFB_SRC_FMT_8888, span, 1, 0, +                            (void *) data ); +          span = 0; +        } +      } +    } + +    if (span > 0) +      FX_grLfbWriteRegion( fxMesa->currentFB, x+n-span, bottom-y, +                        GR_LFB_SRC_FMT_8888, span, 1, 0, +                        (void *) data ); +  } else { +    for (i=0;i<n;i++) { +      data[i]=(GLuint) fxMesa->color; +    } + +    FX_grLfbWriteRegion( fxMesa->currentFB, x, bottom-y, GR_LFB_SRC_FMT_8888, +                      n, 1, 0, (void *) data ); +  } +} + + +static void fxDDReadRGBASpan(const GLcontext *ctx,  +                             GLuint n, GLint x, GLint y, GLubyte rgba[][4]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLushort data[MAX_WIDTH]; +  GLuint i; +  GLint bottom=fxMesa->height-1; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDReadRGBASpan(...)\n"); +  } + +  assert(n < MAX_WIDTH); + +  grLfbReadRegion( fxMesa->currentFB, x, bottom-y, n, 1, 0, data); +  for (i=0;i<n;i++) { +#if FXMESA_USE_ARGB +    rgba[i][RCOMP]=(data[i] & 0xF800) >> 8; +    rgba[i][GCOMP]=(data[i] & 0x07E0) >> 3; +    rgba[i][BCOMP]=(data[i] & 0x001F) << 3; +#else +    rgba[i][RCOMP]=(data[i] & 0x001f) << 3; +    rgba[i][GCOMP]=(data[i] & 0x07e0) >> 3; +    rgba[i][BCOMP]=(data[i] & 0xf800) >> 8; +#endif +    rgba[i][ACOMP]=255; +  } + +} + +/************************************************************************/ +/*****                    Pixel functions                           *****/ +/************************************************************************/ + +static void fxDDWriteRGBAPixels(const GLcontext *ctx, +                                GLuint n, const GLint x[], const GLint y[], +                                CONST GLubyte rgba[][4], const GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint i; +  GLint bottom=fxMesa->height-1; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDWriteRGBAPixels(...)\n"); +  } + +  for(i=0;i<n;i++) +    if(mask[i]) +       LFB_WRITE_SPAN_MESA(fxMesa->currentFB,x[i],bottom-y[i], +                       /*GR_LFB_SRC_FMT_8888,*/1,/*1,*/0,(void *)rgba[i]); +} + +static void fxDDWriteMonoRGBAPixels(const GLcontext *ctx, +                                    GLuint n, const GLint x[], const GLint y[], +                                    const GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint i; +  GLint bottom=fxMesa->height-1; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDWriteMonoRGBAPixels(...)\n"); +  } + +  for(i=0;i<n;i++) +    if(mask[i]) +      FX_grLfbWriteRegion(fxMesa->currentFB,x[i],bottom-y[i], +                       GR_LFB_SRC_FMT_8888,1,1,0,(void *) &fxMesa->color); +} + +static void fxDDReadRGBAPixels(const GLcontext *ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               GLubyte rgba[][4], const GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint i; +  GLint bottom=fxMesa->height-1; +  GLushort data; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDReadRGBAPixels(...)\n"); +  } + +  for(i=0;i<n;i++) +    if(mask[i]) { +      grLfbReadRegion(fxMesa->currentFB,x[i],bottom-y[i],1,1,0,&data); +   #if FXMESA_USE_ARGB  +      rgba[i][RCOMP]=(data & 0xF800) >> 8; +      rgba[i][GCOMP]=(data & 0x07E0) >> 3; +      rgba[i][BCOMP]=(data & 0x001F) >> 8; +   #else +      rgba[i][RCOMP]=(data & 0x001f) << 3; +      rgba[i][GCOMP]=(data & 0x07e0) >> 3; +      rgba[i][BCOMP]=(data & 0xf800) >> 8; +   #endif +      /* the alpha value should be read from the auxiliary buffer when required */ + +      rgba[i][ACOMP]=255; +    } +} + +/************************************************************************/ +/*****                    Depth functions                           *****/ +/************************************************************************/ + +void fxDDReadDepthSpanFloat(GLcontext *ctx, +			    GLuint n, GLint x, GLint y, GLfloat depth[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint i; +  GLint bottom=fxMesa->height-1; +  GLushort data[MAX_WIDTH]; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDReadDepthSpanFloat(...)\n"); +  } + +  grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,data); + +  /* +    convert the read values to float values [0.0 .. 1.0]. +  */ +  for(i=0;i<n;i++) +    depth[i]=data[i]/65535.0f; +} + +void fxDDReadDepthSpanInt(GLcontext *ctx, +			  GLuint n, GLint x, GLint y, GLdepth depth[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLint bottom=fxMesa->height-1; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDReadDepthSpanInt(...)\n"); +  } + +  grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,depth); +} + +GLuint fxDDDepthTestSpanGeneric(GLcontext *ctx, +                                       GLuint n, GLint x, GLint y, const GLdepth z[], +                                       GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLushort depthdata[MAX_WIDTH]; +  GLdepth *zptr=depthdata; +  GLubyte *m=mask; +  GLuint i; +  GLuint passed=0; +  GLint bottom=fxMesa->height-1; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDDepthTestSpanGeneric(...)\n"); +  } + +  grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,depthdata); + +  /* 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: +    ; +  } /*switch*/ + +  if(passed) +    FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,GR_LFB_SRC_FMT_ZA16,n,1,0,depthdata); + +  return passed; +} + +void fxDDDepthTestPixelsGeneric(GLcontext* ctx, +                                       GLuint n, const GLint x[], const GLint y[], +                                       const GLdepth z[], GLubyte mask[]) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLdepth zval; +  GLuint i; +  GLint bottom=fxMesa->height-1; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDDepthTestPixelsGeneric(...)\n"); +  } + +  /* 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]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] < zval) { +            /* pass */ +            FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]); +          } else { +            /* fail */ +            mask[i] = 0; +          } +        } +      } +    } else { +      /* Don't update Z buffer */ +      for (i=0; i<n; i++) { +        if (mask[i]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] < zval) { +            /* 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]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] <= zval) { +            /* pass */ +            FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]); +          } else { +            /* fail */ +            mask[i] = 0; +          } +        } +      } +    } else { +      /* Don't update Z buffer */ +      for (i=0; i<n; i++) { +        if (mask[i]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] <= zval) { +            /* 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]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] >= zval) { +            /* pass */ +            FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]); +          } else { +            /* fail */ +            mask[i] = 0; +          } +        } +      } +    } else { +      /* Don't update Z buffer */ +      for (i=0; i<n; i++) { +        if (mask[i]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] >= zval) { +            /* 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]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] > zval) { +            /* pass */ +            FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]); +          } else { +            /* fail */ +            mask[i] = 0; +          } +        } +      } +    } else { +      /* Don't update Z buffer */ +      for (i=0; i<n; i++) { +        if (mask[i]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] > zval) { +            /* 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]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] != zval) { +            /* pass */ +            FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]); +          } else { +            /* fail */ +            mask[i] = 0; +          } +        } +      } +    } else { +      /* Don't update Z buffer */ +      for (i=0; i<n; i++) { +        if (mask[i]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] != zval) { +            /* 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]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] == zval) { +            /* pass */ +            FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]); +          } else { +            /* fail */ +            mask[i] = 0; +          } +        } +      } +    } else { +      /* Don't update Z buffer */ +      for (i=0; i<n; i++) { +        if (mask[i]) { +          grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval); +          if (z[i] == zval) { +            /* 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]) { +          FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&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: +    ; +  } /*switch*/ +} + +/************************************************************************/ + + +void fxSetupDDSpanPointers(GLcontext *ctx) +{ +  ctx->Driver.WriteRGBASpan       =fxDDWriteRGBASpan; +  ctx->Driver.WriteRGBSpan        =fxDDWriteRGBSpan; +  ctx->Driver.WriteMonoRGBASpan   =fxDDWriteMonoRGBASpan; +  ctx->Driver.WriteRGBAPixels     =fxDDWriteRGBAPixels; +  ctx->Driver.WriteMonoRGBAPixels =fxDDWriteMonoRGBAPixels; + +  ctx->Driver.WriteCI8Span        =NULL; +  ctx->Driver.WriteCI32Span       =NULL; +  ctx->Driver.WriteMonoCISpan     =NULL; +  ctx->Driver.WriteCI32Pixels     =NULL; +  ctx->Driver.WriteMonoCIPixels   =NULL; + +  ctx->Driver.ReadRGBASpan        =fxDDReadRGBASpan; +  ctx->Driver.ReadRGBAPixels      =fxDDReadRGBAPixels; + +  ctx->Driver.ReadCI32Span        =NULL; +  ctx->Driver.ReadCI32Pixels      =NULL; +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_span(void) +{ +  return 0; +} + +#endif  /* FX */ diff --git a/src/mesa/drivers/glide/fxddtex.c b/src/mesa/drivers/glide/fxddtex.c new file mode 100644 index 0000000000..05ef77570c --- /dev/null +++ b/src/mesa/drivers/glide/fxddtex.c @@ -0,0 +1,1299 @@ +/* -*- mode: C; tab-width:8;  -*- + +             fxddtex.c - 3Dfx VooDoo Texture mapping functions +*/ + +/* + * 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. + * + * See the file fxapi.c for more informations about authors + * + */ + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" + +/************************************************************************/ +/*************************** Texture Mapping ****************************/ +/************************************************************************/ + +static void fxTexInvalidate(GLcontext *ctx, struct gl_texture_object *tObj) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxTexInfo *ti; + +  fxTMMoveOutTM(fxMesa,tObj); /* TO DO: SLOW but easy to write */ + +  ti=(tfxTexInfo *)tObj->DriverData; +  ti->validated=GL_FALSE; +  fxMesa->new_state|=FX_NEW_TEXTURING; +  ctx->Driver.RenderStart = fxSetupFXUnits; +} + +static tfxTexInfo *fxAllocTexObjData(fxMesaContext fxMesa) +{ +  tfxTexInfo *ti; +  int i; + +  if(!(ti=malloc(sizeof(tfxTexInfo)))) { +    fprintf(stderr,"fx Driver: out of memory !\n"); +    fxCloseHardware(); +    exit(-1); +  } + +  ti->validated=GL_FALSE; +  ti->tmi.isInTM=GL_FALSE; + +  ti->tmi.whichTMU=FX_TMU_NONE; + +  ti->tmi.tm[FX_TMU0]=NULL; +  ti->tmi.tm[FX_TMU1]=NULL; + +  ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; +  ti->maxFilt=GR_TEXTUREFILTER_BILINEAR; + +  ti->sClamp=GR_TEXTURECLAMP_WRAP; +  ti->tClamp=GR_TEXTURECLAMP_WRAP; + +  if(fxMesa->haveTwoTMUs) { +    ti->mmMode=GR_MIPMAP_NEAREST; +    ti->LODblend=FXTRUE; +  } else { +    ti->mmMode=GR_MIPMAP_NEAREST_DITHER; +    ti->LODblend=FXFALSE; +  } + +  for(i=0;i<MAX_TEXTURE_LEVELS;i++) { +    ti->tmi.mipmapLevel[i].used=GL_FALSE; +    ti->tmi.mipmapLevel[i].data=NULL; +  } + +  return ti; +} + +void fxDDTexBind(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxTexInfo *ti; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDTexBind(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData); +  } + +  if(target!=GL_TEXTURE_2D) +    return; + +  if(!tObj->DriverData) +    tObj->DriverData=fxAllocTexObjData(fxMesa); + +  ti=(tfxTexInfo *)tObj->DriverData; + +  fxMesa->texBindNumber++; +  ti->tmi.lastTimeUsed=fxMesa->texBindNumber; + +  fxMesa->new_state|=FX_NEW_TEXTURING; +  ctx->Driver.RenderStart = fxSetupFXUnits; +} + +void fxDDTexEnv(GLcontext *ctx, GLenum pname, const GLfloat *param) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +   if (MESA_VERBOSE&VERBOSE_DRIVER) { +      if(param) +	 fprintf(stderr,"fxmesa: texenv(%x,%x)\n",pname,(GLint)(*param)); +      else +	 fprintf(stderr,"fxmesa: texenv(%x)\n",pname); +   } + +   fxMesa->new_state|=FX_NEW_TEXTURING; +   ctx->Driver.RenderStart = fxSetupFXUnits; +} + +void fxDDTexParam(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, +                  GLenum pname, const GLfloat *params) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLenum param=(GLenum)(GLint)params[0]; +  tfxTexInfo *ti; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDTexParam(%d,%x,%x,%x)\n",tObj->Name,(GLuint)tObj->DriverData,pname,param); +  } + +  if(target!=GL_TEXTURE_2D) +    return; + +  if(!tObj->DriverData) +    tObj->DriverData=fxAllocTexObjData(fxMesa); + +  ti=(tfxTexInfo *)tObj->DriverData; + +  switch(pname) { + +  case GL_TEXTURE_MIN_FILTER: +    switch(param) { +    case GL_NEAREST: +      ti->mmMode=GR_MIPMAP_DISABLE; +      ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; +      ti->LODblend=FXFALSE; +      break; +    case GL_LINEAR: +      ti->mmMode=GR_MIPMAP_DISABLE; +      ti->minFilt=GR_TEXTUREFILTER_BILINEAR; +      ti->LODblend=FXFALSE; +      break; +    case GL_NEAREST_MIPMAP_NEAREST: +      ti->mmMode=GR_MIPMAP_NEAREST; +      ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; +      ti->LODblend=FXFALSE; +      break; +    case GL_LINEAR_MIPMAP_NEAREST: +      ti->mmMode=GR_MIPMAP_NEAREST; +      ti->minFilt=GR_TEXTUREFILTER_BILINEAR; +      ti->LODblend=FXFALSE; +      break; +    case GL_NEAREST_MIPMAP_LINEAR: +      if(fxMesa->haveTwoTMUs) { +        ti->mmMode=GR_MIPMAP_NEAREST; +        ti->LODblend=FXTRUE; +      } else { +        ti->mmMode=GR_MIPMAP_NEAREST_DITHER; +        ti->LODblend=FXFALSE; +      } +      ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; +      break; +    case GL_LINEAR_MIPMAP_LINEAR: +      if(fxMesa->haveTwoTMUs) { +        ti->mmMode=GR_MIPMAP_NEAREST; +        ti->LODblend=FXTRUE; +      } else { +        ti->mmMode=GR_MIPMAP_NEAREST_DITHER; +        ti->LODblend=FXFALSE; +      } +      ti->minFilt=GR_TEXTUREFILTER_BILINEAR; +      break; +    default: +      break; +    } +    fxTexInvalidate(ctx,tObj); +    break; + +  case GL_TEXTURE_MAG_FILTER: +    switch(param) { +    case GL_NEAREST: +      ti->maxFilt=GR_TEXTUREFILTER_POINT_SAMPLED; +      break; +    case GL_LINEAR: +      ti->maxFilt=GR_TEXTUREFILTER_BILINEAR; +      break; +    default: +      break; +    } +    fxTexInvalidate(ctx,tObj); +    break; + +  case GL_TEXTURE_WRAP_S: +    switch(param) { +    case GL_CLAMP: +      ti->sClamp=GR_TEXTURECLAMP_CLAMP; +      break; +    case GL_REPEAT: +      ti->sClamp=GR_TEXTURECLAMP_WRAP; +      break; +    default: +      break; +    } +    fxMesa->new_state|=FX_NEW_TEXTURING; +    ctx->Driver.RenderStart = fxSetupFXUnits; +    break; + +  case GL_TEXTURE_WRAP_T: +    switch(param) { +    case GL_CLAMP: +      ti->tClamp=GR_TEXTURECLAMP_CLAMP; +      break; +    case GL_REPEAT: +      ti->tClamp=GR_TEXTURECLAMP_WRAP; +      break; +    default: +      break; +    } +    fxMesa->new_state|=FX_NEW_TEXTURING; +    ctx->Driver.RenderStart = fxSetupFXUnits; +    break; + +  case GL_TEXTURE_BORDER_COLOR: +    /* TO DO */ +    break; + +  case GL_TEXTURE_MIN_LOD: +    /* TO DO */ +    break; +  case GL_TEXTURE_MAX_LOD: +    /* TO DO */ +    break; +  case GL_TEXTURE_BASE_LEVEL: +    fxTexInvalidate(ctx,tObj); +    break; +  case GL_TEXTURE_MAX_LEVEL: +    fxTexInvalidate(ctx,tObj); +    break; + +  default: +    break; +  } +} + +void fxDDTexDel(GLcontext *ctx, struct gl_texture_object *tObj) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDTexDel(%d,%x)\n",tObj->Name,(GLuint)ti); +  } + +  if(!ti) +    return; + +  fxTMFreeTexture(fxMesa,tObj); + +  free(ti); +  tObj->DriverData=NULL; + +  ctx->NewState|=NEW_TEXTURING; +} + +void fxDDTexPalette(GLcontext *ctx, struct gl_texture_object *tObj) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  int i; +  FxU32 r,g,b,a; +  tfxTexInfo *ti; + +  if(tObj) {   +     if (MESA_VERBOSE&VERBOSE_DRIVER) { +	fprintf(stderr,"fxmesa: fxDDTexPalette(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData); +     } + +    if(tObj->PaletteFormat!=GL_RGBA) { +#ifndef FX_SILENT +      fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n"); +#endif +      return; +    } + +    if(tObj->PaletteSize>256) { +#ifndef FX_SILENT +      fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n"); +#endif +      return; +    } + +    if(!tObj->DriverData) +      tObj->DriverData=fxAllocTexObjData(fxMesa); +   +    ti=(tfxTexInfo *)tObj->DriverData; + +    for(i=0;i<tObj->PaletteSize;i++) { +      r=tObj->Palette[i*4]; +      g=tObj->Palette[i*4+1]; +      b=tObj->Palette[i*4+2]; +      a=tObj->Palette[i*4+3]; +      ti->palette.data[i]=(a<<24)|(r<<16)|(g<<8)|b; +    } + +    fxTexInvalidate(ctx,tObj); +  } else { +     if (MESA_VERBOSE&VERBOSE_DRIVER) { +	fprintf(stderr,"fxmesa: fxDDTexPalette(global)\n"); +     } +    if(ctx->Texture.PaletteFormat!=GL_RGBA) { +#ifndef FX_SILENT +      fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n"); +#endif +      return; +    } + +    if(ctx->Texture.PaletteSize>256) { +#ifndef FX_SILENT +      fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n"); +#endif +      return; +    } + +    for(i=0;i<ctx->Texture.PaletteSize;i++) { +      r=ctx->Texture.Palette[i*4]; +      g=ctx->Texture.Palette[i*4+1]; +      b=ctx->Texture.Palette[i*4+2]; +      a=ctx->Texture.Palette[i*4+3]; +      fxMesa->glbPalette.data[i]=(a<<24)|(r<<16)|(g<<8)|b; +    } + +    fxMesa->new_state|=FX_NEW_TEXTURING; +    ctx->Driver.RenderStart = fxSetupFXUnits; +  } +} + +void fxDDTexUseGlbPalette(GLcontext *ctx, GLboolean state) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDTexUseGlbPalette(%d)\n",state); +  } + +  if(state) { +    fxMesa->haveGlobalPaletteTexture=1; + +    FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(fxMesa->glbPalette)); +    if (fxMesa->haveTwoTMUs) +       FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(fxMesa->glbPalette)); +  } else { +    fxMesa->haveGlobalPaletteTexture=0; + +    if((ctx->Texture.Unit[0].Current==ctx->Texture.Unit[0].CurrentD[2]) && +       (ctx->Texture.Unit[0].Current!=NULL)) { +      struct gl_texture_object *tObj=ctx->Texture.Unit[0].Current; +      tfxTexInfo *ti; + +      if(!tObj->DriverData) +        tObj->DriverData=fxAllocTexObjData(fxMesa); +   +      ti=(tfxTexInfo *)tObj->DriverData; + +      fxTexInvalidate(ctx,tObj); +    } +  } +} + +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; +  } +} + +/* Need different versions for different cpus. + */ +#define INT_TRICK(l2) (0x800000 * l2) + + +int fxTexGetInfo(int w, int h, GrLOD_t *lodlevel, GrAspectRatio_t *ar, +                 float *sscale, float *tscale, +                 int *i_sscale, int *i_tscale, +                 int *wscale, int *hscale) +{ + +  static GrLOD_t lod[9]={GR_LOD_256,GR_LOD_128,GR_LOD_64,GR_LOD_32, +                         GR_LOD_16,GR_LOD_8,GR_LOD_4,GR_LOD_2,GR_LOD_1}; + +  int logw,logh,ws,hs; +  GrLOD_t l; +  GrAspectRatio_t aspectratio; +  float s,t; +  int is,it; + +  logw=logbase2(w); +  logh=logbase2(h); + +  switch(logw-logh) { +  case 0: +    aspectratio=GR_ASPECT_1x1; +    l=lod[8-logw]; +    s=t=256.0f; +    is=it=INT_TRICK(8); +    ws=hs=1; +    break; +  case 1: +    aspectratio=GR_ASPECT_2x1; +    l=lod[8-logw]; +    s=256.0f; +    t=128.0f; +    is=INT_TRICK(8);it=INT_TRICK(7); +    ws=1; +    hs=1; +    break; +  case 2: +    aspectratio=GR_ASPECT_4x1; +    l=lod[8-logw]; +    s=256.0f; +    t=64.0f; +    is=INT_TRICK(8);it=INT_TRICK(6); +    ws=1; +    hs=1; +    break; +  case 3: +    aspectratio=GR_ASPECT_8x1; +    l=lod[8-logw]; +    s=256.0f; +    t=32.0f; +    is=INT_TRICK(8);it=INT_TRICK(5); +    ws=1; +    hs=1; +    break; +  case 4: +    aspectratio=GR_ASPECT_8x1; +    l=lod[8-logw]; +    s=256.0f; +    t=32.0f; +    is=INT_TRICK(8);it=INT_TRICK(5); +    ws=1; +    hs=2; +    break; +  case 5: +    aspectratio=GR_ASPECT_8x1; +    l=lod[8-logw]; +    s=256.0f; +    t=32.0f; +    is=INT_TRICK(8);it=INT_TRICK(5); +    ws=1; +    hs=4; +    break; +  case 6: +    aspectratio=GR_ASPECT_8x1; +    l=lod[8-logw]; +    s=256.0f; +    t=32.0f; +    is=INT_TRICK(8);it=INT_TRICK(5); +    ws=1; +    hs=8; +    break; +  case 7: +    aspectratio=GR_ASPECT_8x1; +    l=lod[8-logw]; +    s=256.0f; +    t=32.0f; +    is=INT_TRICK(8);it=INT_TRICK(5); +    ws=1; +    hs=16; +    break; +  case 8: +    aspectratio=GR_ASPECT_8x1; +    l=lod[8-logw]; +    s=256.0f; +    t=32.0f; +    is=INT_TRICK(8);it=INT_TRICK(5); +    ws=1; +    hs=32; +    break; +  case -1: +    aspectratio=GR_ASPECT_1x2; +    l=lod[8-logh]; +    s=128.0f; +    t=256.0f; +    is=INT_TRICK(7);it=INT_TRICK(8); +    ws=1; +    hs=1; +    break; +  case -2: +    aspectratio=GR_ASPECT_1x4; +    l=lod[8-logh]; +    s=64.0f; +    t=256.0f; +    is=INT_TRICK(6);it=INT_TRICK(8); +    ws=1; +    hs=1; +    break; +  case -3: +    aspectratio=GR_ASPECT_1x8; +    l=lod[8-logh]; +    s=32.0f; +    t=256.0f; +    is=INT_TRICK(5);it=INT_TRICK(8); +    ws=1; +    hs=1; +    break; +  case -4: +    aspectratio=GR_ASPECT_1x8; +    l=lod[8-logh]; +    s=32.0f; +    t=256.0f; +    is=INT_TRICK(5);it=INT_TRICK(8); +    ws=2; +    hs=1; +    break; +  case -5: +    aspectratio=GR_ASPECT_1x8; +    l=lod[8-logh]; +    s=32.0f; +    t=256.0f; +    is=INT_TRICK(5);it=INT_TRICK(8); +    ws=4; +    hs=1; +    break; +  case -6: +    aspectratio=GR_ASPECT_1x8; +    l=lod[8-logh]; +    s=32.0f; +    t=256.0f; +    is=INT_TRICK(5);it=INT_TRICK(8); +    ws=8; +    hs=1; +    break; +  case -7: +    aspectratio=GR_ASPECT_1x8; +    l=lod[8-logh]; +    s=32.0f; +    t=256.0f; +    is=INT_TRICK(5);it=INT_TRICK(8); +    ws=16; +    hs=1; +    break; +  case -8: +    aspectratio=GR_ASPECT_1x8; +    l=lod[8-logh]; +    s=32.0f; +    t=256.0f; +    is=INT_TRICK(5);it=INT_TRICK(8); +    ws=32; +    hs=1; +    break; +  default: +    return 0; +    break; +  } + +  if(lodlevel) +    (*lodlevel)=l; + +  if(ar) +    (*ar)=aspectratio; + +  if(sscale) +    (*sscale)=s; + +  if(tscale) +    (*tscale)=t; + +  if(wscale) +    (*wscale)=ws; + +  if(hscale) +    (*hscale)=hs; + +  if (i_sscale) +     *i_sscale = is; + +  if (i_tscale) +     *i_tscale = it; + + +  return 1; +} + +void fxTexGetFormat(GLenum glformat, GrTextureFormat_t *tfmt, GLint *ifmt) +{ +  switch(glformat) { +  case 1: +  case GL_LUMINANCE: +  case GL_LUMINANCE4: +  case GL_LUMINANCE8: +  case GL_LUMINANCE12: +  case GL_LUMINANCE16: +    if(tfmt) +      (*tfmt)=GR_TEXFMT_INTENSITY_8; +    if(ifmt) +      (*ifmt)=GL_LUMINANCE; +    break; +  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: +    if(tfmt) +      (*tfmt)=GR_TEXFMT_ALPHA_INTENSITY_88; +    if(ifmt) +      (*ifmt)=GL_LUMINANCE_ALPHA; +    break; +  case GL_INTENSITY: +  case GL_INTENSITY4: +  case GL_INTENSITY8: +  case GL_INTENSITY12: +  case GL_INTENSITY16: +    if(tfmt) +      (*tfmt)=GR_TEXFMT_ALPHA_8; +    if(ifmt) +      (*ifmt)=GL_INTENSITY; +    break; +  case GL_ALPHA: +  case GL_ALPHA4: +  case GL_ALPHA8: +  case GL_ALPHA12: +  case GL_ALPHA16: +    if(tfmt) +      (*tfmt)=GR_TEXFMT_ALPHA_8; +    if(ifmt) +      (*ifmt)=GL_ALPHA; +    break; +  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: +    if(tfmt) +      (*tfmt)=GR_TEXFMT_RGB_565; +    if(ifmt) +      (*ifmt)=GL_RGB; +    break; +  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: +    if(tfmt) +      (*tfmt)=GR_TEXFMT_ARGB_4444; +    if(ifmt) +      (*ifmt)=GL_RGBA; +    break; +  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: +    if(tfmt) +      (*tfmt)=GR_TEXFMT_P_8; +    if(ifmt) +      (*ifmt)=GL_RGBA; +    break; +  default: +    fprintf(stderr,"fx Driver: unsupported internalFormat in fxTexGetFormat()\n"); +    fxCloseHardware(); +    exit(-1); +    break; +  } +} + +static int fxIsTexSupported(GLenum target, GLint internalFormat, +                            const struct gl_texture_image *image) +{ +  if(target!=GL_TEXTURE_2D) +    return GL_FALSE; + +  switch(internalFormat) { +  case GL_INTENSITY: +  case GL_INTENSITY4: +  case GL_INTENSITY8: +  case GL_INTENSITY12: +  case GL_INTENSITY16: +  case 1: +  case GL_LUMINANCE: +  case GL_LUMINANCE4: +  case GL_LUMINANCE8: +  case GL_LUMINANCE12: +  case GL_LUMINANCE16: +  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: +  case GL_ALPHA: +  case GL_ALPHA4: +  case GL_ALPHA8: +  case GL_ALPHA12: +  case GL_ALPHA16: +  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: +  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: +  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: +    break; +  default: +    return GL_FALSE; +  } + +  if(image->Width>256) +    return GL_FALSE; + +  if(image->Height>256) +    return GL_FALSE; + +  if(!fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL, +		   NULL,NULL)) +    return GL_FALSE; + +  return GL_TRUE; +} + +static void fxTexBuildImageMap(const struct gl_texture_image *image, +                               GLint internalFormat, unsigned short **dest, +                               GLboolean *istranslate) +{ +  unsigned short *src; +  unsigned char *data; +  int x,y,w,h,wscale,hscale,idx; + +  fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL, +	       &wscale,&hscale); +  w=image->Width*wscale; +  h=image->Height*hscale; + +  data=image->Data; +  switch(internalFormat) { +  case GL_INTENSITY: +  case GL_INTENSITY4: +  case GL_INTENSITY8: +  case GL_INTENSITY12: +  case GL_INTENSITY16: +  case 1: +  case GL_LUMINANCE: +  case GL_LUMINANCE4: +  case GL_LUMINANCE8: +  case GL_LUMINANCE12: +  case GL_LUMINANCE16: +  case GL_ALPHA: +  case GL_ALPHA4: +  case GL_ALPHA8: +  case GL_ALPHA12: +  case GL_ALPHA16: +  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: +    /* Optimized for GLQuake */ + +    if(wscale==hscale==1) { +      (*istranslate)=GL_FALSE; + +      (*dest)=(unsigned short *)data; +    } else { +      unsigned char *srcb; + +      (*istranslate)=GL_TRUE; + +      if(!(*dest)) { +        if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned char)*w*h))) { +          fprintf(stderr,"fx Driver: out of memory !\n"); +          fxCloseHardware(); +          exit(-1); +        } +      } else +        src=(*dest); + +      srcb=(unsigned char *)src; + +      for(y=0;y<h;y++) +        for(x=0;x<w;x++) { +          idx=(x/wscale+(y/hscale)*(w/wscale)); +          srcb[x+y*w]=data[idx]; +        } +    } +    break; +  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: +    (*istranslate)=GL_TRUE; + +    if(!(*dest)) { +      if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) { +        fprintf(stderr,"fx Driver: out of memory !\n"); +        fxCloseHardware(); +        exit(-1); +      } +    } else +      src=(*dest); + +    if(wscale==hscale==1) { +      int i=0; +      int lenght=h*w; +      unsigned short a,l; + +      while(i++<lenght) { +        l=*data++; +        a=*data++; + +        *src++=(a << 8) | l; +      } +    } else { +      unsigned short a,l; + +      for(y=0;y<h;y++) +        for(x=0;x<w;x++) { +          idx=(x/wscale+(y/hscale)*(w/wscale))*2; +          l=data[idx]; +          a=data[idx+1]; + +          src[x+y*w]=(a << 8) | l; +        } +    } +    break; +  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: +    (*istranslate)=GL_TRUE; + +    if(!(*dest)) { +      if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) { +        fprintf(stderr,"fx Driver: out of memory !\n"); +        fxCloseHardware(); +        exit(-1); +      } +    } else +      src=(*dest); + +    if(wscale==hscale==1) { +      int i=0; +      int lenght=h*w; +      unsigned short r,g,b; + +      while(i++<lenght) { +        r=*data++; +        g=*data++; +        b=*data++; + +        *src++=((0xf8 & r) << (11-3))  | +          ((0xfc & g) << (5-3+1))      | +          ((0xf8 & b) >> 3);  +      } +    } else { +      unsigned short r,g,b; + +      for(y=0;y<h;y++) +        for(x=0;x<w;x++) { +          idx=(x/wscale+(y/hscale)*(w/wscale))*3; +          r=data[idx]; +          g=data[idx+1]; +          b=data[idx+2]; + +          src[x+y*w]=((0xf8 & r) << (11-3))  | +            ((0xfc & g) << (5-3+1))      | +            ((0xf8 & b) >> 3);  +        } +    } +    break; +  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: +    (*istranslate)=GL_TRUE; + +    if(!(*dest)) { +      if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) { +        fprintf(stderr,"fx Driver: out of memory !\n"); +        fxCloseHardware(); +        exit(-1); +      } +    } else +      src=(*dest); + +    if(wscale==hscale==1) { +      int i=0; +      int lenght=h*w; +      unsigned short r,g,b,a; + +      while(i++<lenght) { +        r=*data++; +        g=*data++; +        b=*data++; +        a=*data++; + +        *src++=((0xf0 & a) << 8) | +          ((0xf0 & r) << 4)      | +          (0xf0 & g)             | +          ((0xf0 & b) >> 4); +      } +    } else { +      unsigned short r,g,b,a; + +      for(y=0;y<h;y++) +        for(x=0;x<w;x++) { +          idx=(x/wscale+(y/hscale)*(w/wscale))*4; +          r=data[idx]; +          g=data[idx+1]; +          b=data[idx+2]; +          a=data[idx+3]; + +          src[x+y*w]=((0xf0 & a) << 8) | +            ((0xf0 & r) << 4)      | +            (0xf0 & g)             | +            ((0xf0 & b) >> 4); +        } +    } +    break; +  default: +    fprintf(stderr,"fx Driver: wrong internalFormat in texbuildimagemap()\n"); +    fxCloseHardware(); +    exit(-1); +    break; +  } +} + +void fxDDTexImg(GLcontext *ctx, GLenum target, +                struct gl_texture_object *tObj, GLint level, GLint internalFormat, +                const struct gl_texture_image *image) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxTexInfo *ti; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: (%d) fxDDTexImg(...,%d,%x,%d,%d...)\n",tObj->Name, +	     target,internalFormat,image->Width,image->Height); +  } + +  if(target!=GL_TEXTURE_2D) +    return; + +  if(!tObj->DriverData) +    tObj->DriverData=fxAllocTexObjData(fxMesa); + +  ti=(tfxTexInfo *)tObj->DriverData; + +  if(fxIsTexSupported(target,internalFormat,image)) { +    GrTextureFormat_t gldformat; +    tfxMipMapLevel *mml=&ti->tmi.mipmapLevel[level]; + +    fxTexGetFormat(internalFormat,&gldformat,NULL); +     +    if(mml->used) { +      if((mml->glideFormat==gldformat) && +         (mml->width==image->Width) && +         (mml->height==image->Height)) { +        fxTexBuildImageMap(image,internalFormat,&(mml->data), +                           &(mml->translated)); + +        if(ti->validated && ti->tmi.isInTM) +          fxTMReloadMipMapLevel(fxMesa,tObj,level); +        else +          fxTexInvalidate(ctx,tObj); + +        return; +      } else { +        if(mml->translated) +          free(mml->data); +        mml->data=NULL; +      } +    } + +    mml->glideFormat=gldformat; +    mml->width=image->Width; +    mml->height=image->Height; +    mml->used=GL_TRUE; + +    fxTexBuildImageMap(image,internalFormat,&(mml->data), +                       &(mml->translated)); + +    fxTexInvalidate(ctx,tObj); +  } +#ifndef FX_SILENT +  else +    fprintf(stderr,"fx Driver: unsupported texture in fxDDTexImg()\n"); +#endif +} + +static void fxTexBuildSubImageMap(const struct gl_texture_image *image, +                                  GLint internalFormat, +                                  GLint xoffset, GLint yoffset, GLint width, GLint height, +                                  unsigned short *destimg) +{ +  fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL, +	       NULL,NULL); + +  switch(internalFormat) { +  case GL_INTENSITY: +  case GL_INTENSITY4: +  case GL_INTENSITY8: +  case GL_INTENSITY12: +  case GL_INTENSITY16: +  case 1: +  case GL_LUMINANCE: +  case GL_LUMINANCE4: +  case GL_LUMINANCE8: +  case GL_LUMINANCE12: +  case GL_LUMINANCE16: +  case GL_ALPHA: +  case GL_ALPHA4: +  case GL_ALPHA8: +  case GL_ALPHA12: +  case GL_ALPHA16: +  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: +    { + +      int y; +      unsigned char *bsrc,*bdst; + +      bsrc=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)); +      bdst=((unsigned char *)destimg)+(yoffset*image->Width+xoffset); +     +      for(y=0;y<height;y++) { +        MEMCPY(bdst,bsrc,width); +        bsrc += image->Width; +        bdst += image->Width; +      } +    } +    break; +  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: +    { +      int x,y; +      unsigned char *src; +      unsigned short *dst,a,l; +      int simgw,dimgw; + +      src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*2); +      dst=destimg+(yoffset*image->Width+xoffset); +     +      simgw=(image->Width-width)*2; +      dimgw=image->Width-width; +      for(y=0;y<height;y++) { +        for(x=0;x<width;x++) { +          l=*src++; +          a=*src++; +          *dst++=(a << 8) | l; +        } + +        src += simgw; +        dst += dimgw; +      } +    } +    break; +  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: +    { +      int x,y; +      unsigned char *src; +      unsigned short *dst,r,g,b; +      int simgw,dimgw; + +      src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*3); +      dst=destimg+(yoffset*image->Width+xoffset); +     +      simgw=(image->Width-width)*3; +      dimgw=image->Width-width; +      for(y=0;y<height;y++) { +        for(x=0;x<width;x++) { +          r=*src++; +          g=*src++; +          b=*src++; +          *dst++=((0xf8 & r) << (11-3))  | +            ((0xfc & g) << (5-3+1))      | +            ((0xf8 & b) >> 3);  +        } + +        src += simgw; +        dst += dimgw; +      } +    } +    break; +  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: +    { +      int x,y; +      unsigned char *src; +      unsigned short *dst,r,g,b,a; +      int simgw,dimgw; + +      src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*4); +      dst=destimg+(yoffset*image->Width+xoffset); +     +      simgw=(image->Width-width)*4; +      dimgw=image->Width-width; +      for(y=0;y<height;y++) { +        for(x=0;x<width;x++) { +          r=*src++; +          g=*src++; +          b=*src++; +          a=*src++; +          *dst++=((0xf0 & a) << 8) | +            ((0xf0 & r) << 4)      | +            (0xf0 & g)             | +            ((0xf0 & b) >> 4); +        } + +        src += simgw; +        dst += dimgw; +      } +    } +    break; +  default: +    fprintf(stderr,"fx Driver: wrong internalFormat in fxTexBuildSubImageMap()\n"); +    fxCloseHardware(); +    exit(-1); +    break; +  } +} +  + +void fxDDTexSubImg(GLcontext *ctx, GLenum target, +                   struct gl_texture_object *tObj, GLint level, +                   GLint xoffset, GLint yoffset, GLint width, GLint height, +                   GLint internalFormat, const struct gl_texture_image *image) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxTexInfo *ti; +  GrTextureFormat_t gldformat; +  int wscale,hscale; +  tfxMipMapLevel *mml; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: (%d) fxDDTexSubImg(...,%d,%x,%d,%d...)\n",tObj->Name, +	     target,internalFormat,image->Width,image->Height); +  } + +  if(target!=GL_TEXTURE_2D) +    return; + +  if(!tObj->DriverData) +    return; + +  ti=(tfxTexInfo *)tObj->DriverData; +  mml=&ti->tmi.mipmapLevel[level]; + +  fxTexGetFormat(internalFormat,&gldformat,NULL); + +  if(mml->glideFormat!=gldformat) { +     if (MESA_VERBOSE&VERBOSE_DRIVER) { +	fprintf(stderr,"fxmesa:  ti->info.format!=format in fxDDTexSubImg()\n"); +     } +    fxDDTexImg(ctx,target,tObj,level,internalFormat,image); + +    return; +  } + +  fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,&wscale,&hscale); + +  if((wscale!=1) || (hscale!=1)) { +     if (MESA_VERBOSE&VERBOSE_DRIVER) { +	fprintf(stderr,"fxmesa:  (wscale!=1) || (hscale!=1) in fxDDTexSubImg()\n"); +     } +    fxDDTexImg(ctx,target,tObj,level,internalFormat,image); + +    return; +  } + +  if(mml->translated) +    fxTexBuildSubImageMap(image,internalFormat,xoffset,yoffset, +                          width,height,mml->data); + +  if(ti->validated && ti->tmi.isInTM) +    fxTMReloadSubMipMapLevel(fxMesa,tObj,level,yoffset,height); +  else +    fxTexInvalidate(ctx,tObj); +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_ddtex(void) +{ +  return 0; +} + +#endif  /* FX */ diff --git a/src/mesa/drivers/glide/fxdrv.h b/src/mesa/drivers/glide/fxdrv.h new file mode 100644 index 0000000000..bb8f5b8761 --- /dev/null +++ b/src/mesa/drivers/glide/fxdrv.h @@ -0,0 +1,576 @@ +/* -*- mode: C; tab-width:8;  -*- + +             fxdrv.h - 3Dfx VooDoo driver types +*/ + +/* + * 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. + * + * See the file fxapi.c for more informations about authors + * + */ + +#ifndef FXDRV_H +#define FXDRV_H + +/* If you comment out this define, a variable takes its place, letting + * you turn debugging on/off from the debugger. + */ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <assert.h> + +#if defined(__linux__) +#include <signal.h> +#endif + +#include "context.h" +#include "macros.h" +#include "matrix.h" +#include "texture.h" +#include "types.h" +#include "vb.h" +#include "xform.h" +#include "clip.h" +#include "vbrender.h" + +#include "GL/fxmesa.h" +#include "fxglidew.h" +/* use gl/gl.h GLAPI/GLAPIENTRY/GLCALLBACK in place of WINGDIAPI/APIENTRY/CALLBACK, */ +/* these are defined in mesa gl/gl.h - tjump@spgs.com */ + + + +#if defined(MESA_DEBUG) && 0 +extern void fx_sanity_triangle( GrVertex *, GrVertex *, GrVertex * ); +#define grDrawTriangle fx_sanity_triangle +#endif + + +/* Define some shorter names for these things. + */ +#define XCOORD   GR_VERTEX_X_OFFSET +#define YCOORD   GR_VERTEX_Y_OFFSET +#define ZCOORD   GR_VERTEX_OOZ_OFFSET +#define OOWCOORD GR_VERTEX_OOW_OFFSET + +#define RCOORD   GR_VERTEX_R_OFFSET +#define GCOORD   GR_VERTEX_G_OFFSET +#define BCOORD   GR_VERTEX_B_OFFSET +#define ACOORD   GR_VERTEX_A_OFFSET + +#define S0COORD  GR_VERTEX_SOW_TMU0_OFFSET +#define T0COORD  GR_VERTEX_TOW_TMU0_OFFSET +#define S1COORD  GR_VERTEX_SOW_TMU1_OFFSET +#define T1COORD  GR_VERTEX_TOW_TMU1_OFFSET + +#define CLIP_XCOORD 0		/* normal place */ +#define CLIP_YCOROD 1		/* normal place */ +#define CLIP_ZCOORD 2		/* GR_VERTEX_Z_OFFSET */ +#define CLIP_WCOORD 3		/* GR_VERTEX_R_OFFSET */ +#define CLIP_GCOORD 4		/* normal place */ +#define CLIP_BCOORD 5		/* normal place */ +#define CLIP_RCOORD 6		/* GR_VERTEX_OOZ_OFFSET */ +#define CLIP_ACOORD 7		/* normal place */ + + + + +/* Should have size == 16 * sizeof(float). + */ +typedef struct { +   GLfloat f[15];		/* Same layout as GrVertex */ +   GLubyte mask;		/* Unsued  */ +   GLubyte usermask;		/* Unused */ +} fxVertex; + + + + +#if defined(FXMESA_USE_ARGB) +#define FXCOLOR4( c ) (      \ +  ( ((unsigned int)(c[3]))<<24 ) | \ +  ( ((unsigned int)(c[0]))<<16 ) | \ +  ( ((unsigned int)(c[1]))<<8 )  | \ +  (  (unsigned int)(c[2])) ) +   +#else +#ifdef __i386__ +#define FXCOLOR4( c )  (* (int *)c) +#else +#define FXCOLOR4( c ) (      \ +  ( ((unsigned int)(c[3]))<<24 ) | \ +  ( ((unsigned int)(c[2]))<<16 ) | \ +  ( ((unsigned int)(c[1]))<<8 )  | \ +  (  (unsigned int)(c[0])) ) +#endif +#endif + +#define FX_VB_COLOR(fxm, color)			\ +do {						\ +  if (sizeof(GLint) == 4*sizeof(GLubyte)) {	\ +     if (fxm->constColor != *(GLuint*)color) {	\ +	fxm->constColor = *(GLuint*)color;	\ +	grConstantColorValue(FXCOLOR4(color));	\ +     }						\ +  } else {					\ +     grConstantColorValue(FXCOLOR4(color));	\ +  }						\ +} while (0) + +#define GOURAUD(x) {					\ +  GLubyte *col = VB->ColorPtr->data[(x)];		\ +  gWin[(x)].v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]);	\ +  gWin[(x)].v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]);	\ +  gWin[(x)].v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]);	\ +  gWin[(x)].v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]);	\ +} + +#define GOURAUD2(v, c) {			\ +  GLubyte *col = c;  				\ +  v->r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]);	\ +  v->g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]);	\ +  v->b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]);	\ +  v->a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]);	\ +} + + +/* Mergable items first + */ +#define SETUP_RGBA 0x1 +#define SETUP_TMU0 0x2 +#define SETUP_TMU1 0x4 +#define SETUP_XY   0x8 +#define SETUP_Z    0x10 +#define SETUP_W    0x20 + +#define MAX_MERGABLE 0x8 + + +#define FX_NUM_TMU 2 + +#define FX_TMU0      GR_TMU0 +#define FX_TMU1      GR_TMU1 +#define FX_TMU_SPLIT 98 +#define FX_TMU_BOTH  99 +#define FX_TMU_NONE  100 + +/* Used for fxMesa->lastUnitsMode */ + +#define FX_UM_NONE                  0x00000000 + +#define FX_UM_E0_REPLACE            0x00000001 +#define FX_UM_E0_MODULATE           0x00000002 +#define FX_UM_E0_DECAL              0x00000004 +#define FX_UM_E0_BLEND              0x00000008 + +#define FX_UM_E1_REPLACE            0x00000010 +#define FX_UM_E1_MODULATE           0x00000020 +#define FX_UM_E1_DECAL              0x00000040 +#define FX_UM_E1_BLEND              0x00000080 + +#define FX_UM_E_ENVMODE             0x000000ff + +#define FX_UM_E0_ALPHA              0x00000100 +#define FX_UM_E0_LUMINANCE          0x00000200 +#define FX_UM_E0_LUMINANCE_ALPHA    0x00000400 +#define FX_UM_E0_INTENSITY          0x00000800 +#define FX_UM_E0_RGB                0x00001000 +#define FX_UM_E0_RGBA               0x00002000 + +#define FX_UM_E1_ALPHA              0x00004000 +#define FX_UM_E1_LUMINANCE          0x00008000 +#define FX_UM_E1_LUMINANCE_ALPHA    0x00010000 +#define FX_UM_E1_INTENSITY          0x00020000 +#define FX_UM_E1_RGB                0x00040000 +#define FX_UM_E1_RGBA               0x00080000 + +#define FX_UM_E_IFMT                0x000fff00 + +#define FX_UM_COLOR_ITERATED        0x00100000 +#define FX_UM_COLOR_CONSTANT        0x00200000 +#define FX_UM_ALPHA_ITERATED        0x00400000 +#define FX_UM_ALPHA_CONSTANT        0x00800000 + +typedef void (*tfxRenderVBFunc)(GLcontext *); + +typedef struct tfxTMFreeListNode { +  struct tfxTMFreeListNode *next; +  FxU32 startAddress, endAddress; +} tfxTMFreeNode; + +typedef struct tfxTMAllocListNode { +  struct tfxTMAllocListNode *next; +  FxU32 startAddress, endAddress; +  struct gl_texture_object *tObj; +} tfxTMAllocNode; + +typedef struct { +  GLsizei width, height; +  GLint glideFormat; + +  unsigned short *data; +  GLboolean translated, used; +} tfxMipMapLevel; + +typedef struct { +  GLuint lastTimeUsed; + +  FxU32 whichTMU; + +  tfxTMAllocNode *tm[FX_NUM_TMU]; + +  tfxMipMapLevel mipmapLevel[MAX_TEXTURE_LEVELS]; +  GLboolean isInTM; +} tfxTMInfo; + +typedef struct { +  tfxTMInfo tmi; + +  GLint minLevel, maxLevel; +  GLint baseLevelInternalFormat; + +  GrTexInfo info; + +  GrTextureFilterMode_t minFilt; +  GrTextureFilterMode_t maxFilt; +  FxBool LODblend; + +  GrTextureClampMode_t sClamp; +  GrTextureClampMode_t tClamp; + +  GrMipMapMode_t mmMode; + +  GLfloat sScale, tScale; +  GLint int_sScale, int_tScale;	/* x86 floating point trick for +				 * multiplication by powers of 2.   +				 * Used in fxfasttmp.h +				 */ + +  GuTexPalette palette; + +  GLboolean fixedPalette; +  GLboolean validated; +} tfxTexInfo; + +typedef struct { +  GLuint swapBuffer; +  GLuint reqTexUpload; +  GLuint texUpload; +  GLuint memTexUpload; +} tfxStats; + + +typedef void (*tfxTriViewClipFunc)( struct vertex_buffer *VB,  +				    GLuint v[], +				    GLubyte mask ); + +typedef void (*tfxTriClipFunc)( struct vertex_buffer *VB,  +				GLuint v[], +				GLuint mask ); + + +typedef void (*tfxLineClipFunc)( struct vertex_buffer *VB,  +				 GLuint v1, GLuint v2, +				 GLubyte mask ); + + +extern tfxTriViewClipFunc fxTriViewClipTab[0x8]; +extern tfxTriClipFunc fxTriClipStrideTab[0x8]; +extern tfxLineClipFunc fxLineClipTab[0x8]; + +typedef struct { +  /* Alpha test */ + +  GLboolean alphaTestEnabled; +  GrCmpFnc_t alphaTestFunc; +  GrAlpha_t alphaTestRefValue; + +  /* Blend function */ + +  GLboolean blendEnabled; +  GrAlphaBlendFnc_t blendSrcFuncRGB; +  GrAlphaBlendFnc_t blendDstFuncRGB; +  GrAlphaBlendFnc_t blendSrcFuncAlpha; +  GrAlphaBlendFnc_t blendDstFuncAlpha; + +  /* Depth test */ + +  GLboolean depthTestEnabled; +  GLboolean depthMask; +  GrCmpFnc_t depthTestFunc; +} tfxUnitsState; + + +/* Flags for render_index. + */ +#define FX_OFFSET             0x1 +#define FX_TWOSIDE            0x2 +#define FX_FRONT_BACK         0x4  +#define FX_FLAT               0x8 +#define FX_ANTIALIAS          0x10  +#define FX_FALLBACK           0x20  + + +/* Flags for fxMesa->new_state + */ +#define FX_NEW_TEXTURING      0x1 +#define FX_NEW_BLEND          0x2 +#define FX_NEW_ALPHA          0x4 +#define FX_NEW_DEPTH          0x8 +#define FX_NEW_FOG            0x10 +#define FX_NEW_SCISSOR        0x20 +#define FX_NEW_COLOR_MASK     0x40 +#define FX_NEW_CULL           0x80 + +/* FX struct stored in VB->driver_data. + */ +struct tfxMesaVertexBuffer { +   GLvector1ui clipped_elements; + +   fxVertex *verts; +   fxVertex *last_vert; +   void *vert_store; +#if defined(FX_GLIDE3) +   GrVertex **triangle_b;	/* Triangle buffer */ +   GrVertex **strips_b;		/* Strips buffer */ +#endif + +   GLuint size; +}; + +#define FX_DRIVER_DATA(vb) ((struct tfxMesaVertexBuffer *)((vb)->driver_data)) +#define FX_CONTEXT(ctx) ((struct tfxMesaContext *)((ctx)->DriverCtx)) +#define FX_TEXTURE_DATA(t) ((tfxTexInfo *) ((t)->Current->DriverData)) + +struct tfxMesaContext { +  GuTexPalette glbPalette; + +  GLcontext *glCtx;              /* the core Mesa context */ +  GLvisual *glVis;               /* describes the color buffer */ +  GLframebuffer *glBuffer;       /* the ancillary buffers */ + +  GLint board;                   /* the board used for this context */ +  GLint width, height;           /* size of color buffer */ + +  GrBuffer_t currentFB; + +  GrColor_t color; +  GrColor_t clearC; +  GrAlpha_t clearA; +  GLuint constColor; + +  tfxUnitsState unitsState; +  tfxUnitsState restoreUnitsState; /* saved during multipass */ + + +  GLuint tmu_source[FX_NUM_TMU]; +  GLuint tex_dest[MAX_TEXTURE_UNITS]; +  GLuint setupindex; +  GLuint partial_setup_index; +  GLuint setupdone; +  GLuint mergeindex; +  GLuint mergeinputs; +  GLuint render_index; +  GLuint last_tri_caps; +  GLuint stw_hint_state;		/* for grHints */ +  GLuint is_in_hardware; +  GLuint new_state;    +  GLuint using_fast_path, passes, multipass; + +  tfxLineClipFunc clip_line; +  tfxTriClipFunc clip_tri_stride; +  tfxTriViewClipFunc view_clip_tri; + + +  /* Texture Memory Manager Data */ + +  GLuint texBindNumber; +  GLint tmuSrc; +  GLuint lastUnitsMode; +  GLuint freeTexMem[FX_NUM_TMU]; +  tfxTMFreeNode *tmFree[FX_NUM_TMU]; +  tfxTMAllocNode *tmAlloc[FX_NUM_TMU]; + +  GLenum fogTableMode; +  GLfloat fogDensity; +  GrFog_t *fogTable; + +  /* Acc. functions */ + +  points_func PointsFunc; +  line_func LineFunc; +  triangle_func TriangleFunc; +  quad_func QuadFunc; + +  render_func **RenderVBTables; + +  tfxStats stats; + +  void *state; + +  /* Options */ + +  GLboolean verbose; +  GLboolean haveTwoTMUs;	/* True if we really have 2 tmu's  */ +  GLboolean emulateTwoTMUs;	/* True if we present 2 tmu's to mesa.  */ +  GLboolean haveAlphaBuffer; +  GLboolean haveDoubleBuffer; +  GLboolean haveGlobalPaletteTexture; +  GLint swapInterval; +  GLint maxPendingSwapBuffers; +   +  FX_GrContext_t glideContext; +}; + +typedef void (*tfxSetupFunc)(struct vertex_buffer *, GLuint, GLuint); + +extern GrHwConfiguration glbHWConfig; +extern int glbCurrentBoard; + +extern void fxSetupFXUnits(GLcontext *); +extern void fxSetupDDPointers(GLcontext *); +extern void fxDDSetNearFar(GLcontext *, GLfloat, GLfloat); + +extern void fxDDSetupInit(); +extern void fxDDCvaInit(); +extern void fxDDTrifuncInit(); +extern void fxDDFastPathInit(); + +extern void fxDDChooseRenderState( GLcontext *ctx ); + +extern void fxRenderClippedLine( struct vertex_buffer *VB,  +				 GLuint v1, GLuint v2 ); + +extern void fxRenderClippedTriangle( struct vertex_buffer *VB, +				     GLuint n, GLuint vlist[] ); + + +extern tfxSetupFunc fxDDChooseSetupFunction(GLcontext *); + +extern points_func fxDDChoosePointsFunction(GLcontext *); +extern line_func fxDDChooseLineFunction(GLcontext *); +extern triangle_func fxDDChooseTriangleFunction(GLcontext *); +extern quad_func fxDDChooseQuadFunction(GLcontext *); +extern render_func **fxDDChooseRenderVBTables(GLcontext *); + +extern void fxDDRenderInit(GLcontext *); +extern void fxDDClipInit(); + +extern void fxUpdateDDSpanPointers(GLcontext *); +extern void fxSetupDDSpanPointers(GLcontext *); + +extern void fxDDBufferSize(GLcontext *, GLuint *, GLuint *); + +extern void fxDDTexEnv(GLcontext *, GLenum, const GLfloat *); +extern void fxDDTexImg(GLcontext *, GLenum, struct gl_texture_object *, +		       GLint, GLint, const struct gl_texture_image *); +extern void fxDDTexParam(GLcontext *, GLenum, struct gl_texture_object *, +			 GLenum, const GLfloat *); +extern void fxDDTexBind(GLcontext *, GLenum, struct gl_texture_object *); +extern void fxDDTexDel(GLcontext *, struct gl_texture_object *); +extern void fxDDTexPalette(GLcontext *, struct gl_texture_object *); +extern void fxDDTexuseGlbPalette(GLcontext *, GLboolean); +extern void fxDDTexSubImg(GLcontext *, GLenum, struct gl_texture_object *, GLint, +			  GLint, GLint, GLint, GLint, GLint, const struct gl_texture_image *); +extern void fxDDTexUseGlbPalette(GLcontext *, GLboolean); + +extern void fxDDEnable(GLcontext *, GLenum, GLboolean); +extern void fxDDAlphaFunc(GLcontext *, GLenum, GLclampf); +extern void fxDDBlendFunc(GLcontext *, GLenum, GLenum); +extern void fxDDDepthMask(GLcontext *, GLboolean); +extern void fxDDDepthFunc(GLcontext *, GLenum); + +extern void fxDDRegisterVB( struct vertex_buffer *VB ); +extern void fxDDUnregisterVB( struct vertex_buffer *VB ); +extern void fxDDResizeVB( struct tfxMesaVertexBuffer *fvb, GLuint size ); + +extern void fxDDCheckMergeAndRender( GLcontext *ctx,  +				     struct gl_pipeline_stage *d ); + +extern void fxDDMergeAndRender( struct vertex_buffer *VB ); + +extern void fxDDCheckPartialRasterSetup( GLcontext *ctx,  +					 struct gl_pipeline_stage *d ); + +extern void fxDDPartialRasterSetup( struct vertex_buffer *VB ); + +extern void fxDDDoRasterSetup( struct vertex_buffer *VB ); + +extern GLuint fxDDRegisterPipelineStages( struct gl_pipeline_stage *out, +					  const struct gl_pipeline_stage *in, +					  GLuint nr ); + +extern GLboolean fxDDBuildPrecalcPipeline( GLcontext *ctx ); + +extern void fxDDOptimizePrecalcPipeline( GLcontext *ctx,  +					 struct gl_pipeline *pipe ); + +extern void fxDDRenderElementsDirect( struct vertex_buffer *VB ); +extern void fxDDRenderVBIndirectDirect( struct vertex_buffer *VB ); + +extern void fxDDInitExtensions( GLcontext *ctx ); + +extern void fxTMInit(fxMesaContext); +extern void fxTMClose(fxMesaContext); +extern void fxTMMoveInTM(fxMesaContext, struct gl_texture_object *, GLint); +extern void fxTMMoveOutTM(fxMesaContext, struct gl_texture_object *); +extern void fxTMFreeTexture(fxMesaContext, struct gl_texture_object *); +extern void fxTMReloadMipMapLevel(fxMesaContext, struct gl_texture_object *, GLint); +extern void fxTMReloadSubMipMapLevel(fxMesaContext, struct gl_texture_object *, +				     GLint, GLint, GLint); + +extern void fxTexGetFormat(GLenum, GrTextureFormat_t *, GLint *); +extern int fxTexGetInfo(int, int, GrLOD_t *, GrAspectRatio_t *, +			float *, float *, int *, int *, int *, int *); + +extern void fxDDScissor( GLcontext *ctx, +			      GLint x, GLint y, GLsizei w, GLsizei h ); +extern void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params ); +extern GLboolean fxDDColorMask(GLcontext *ctx,  +			       GLboolean r, GLboolean g,  +			       GLboolean b, GLboolean a ); + +extern GLuint fxDDDepthTestSpanGeneric(GLcontext *ctx, +                                       GLuint n, GLint x, GLint y,  +				       const GLdepth z[], +                                       GLubyte mask[]); + +extern void fxDDDepthTestPixelsGeneric(GLcontext* ctx, +                                       GLuint n,  +				       const GLint x[], const GLint y[], +                                       const GLdepth z[], GLubyte mask[]); + +extern void fxDDReadDepthSpanFloat(GLcontext *ctx, +				   GLuint n, GLint x, GLint y, GLfloat depth[]); + +extern void fxDDReadDepthSpanInt(GLcontext *ctx, +				 GLuint n, GLint x, GLint y, GLdepth depth[]); + + +extern void fxDDFastPath( struct vertex_buffer *VB ); + +extern void fxDDShadeModel(GLcontext *ctx, GLenum mode); + +extern void fxDDCullFace(GLcontext *ctx, GLenum mode); +extern void fxDDFrontFace(GLcontext *ctx, GLenum mode); + + + + +#endif diff --git a/src/mesa/drivers/glide/fxglidew.c b/src/mesa/drivers/glide/fxglidew.c new file mode 100644 index 0000000000..3ced928f49 --- /dev/null +++ b/src/mesa/drivers/glide/fxglidew.c @@ -0,0 +1,247 @@ +/* $Id: fxglidew.c,v 1.1 1999/08/19 00:55:42 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 HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) +#include "glide.h" +#include "fxglidew.h" +#include "fxdrv.h" + +#include <stdlib.h> +#include <string.h> + + +FxI32 FX_grGetInteger(FxU32 pname) +{ +#if !defined(FX_GLIDE3) +  switch (pname)  +  { +    case FX_FOG_TABLE_ENTRIES: +       return GR_FOG_TABLE_SIZE; +    case FX_GLIDE_STATE_SIZE: +       return sizeof(GrState); +    case FX_LFB_PIXEL_PIPE: +       return FXFALSE; +    case FX_PENDING_BUFFERSWAPS: +       return grBufferNumPending(); +    default: +       if (MESA_VERBOSE&VERBOSE_DRIVER) { +          fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n"); +          return -1; +       } +  } +#else +  FxU32 grname; +  FxI32 result; +   +  switch (pname) +  { +     case FX_FOG_TABLE_ENTRIES: +     case FX_GLIDE_STATE_SIZE: +     case FX_LFB_PIXEL_PIPE: +     case FX_PENDING_BUFFERSWAPS: +       grname = pname; +       break; +     default: +       if (MESA_VERBOSE&VERBOSE_DRIVER) { +          fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n"); +          return -1; +       } +  } +   +  grGet(grname,4,&result); +  return result; +#endif +} + + + +#if defined(FX_GLIDE3) + +void FX_grGammaCorrectionValue(float val) +{ +  (void)val; +/* ToDo */ +} + +void FX_grSstControl(int par) +{ +  (void)par; +  /* ToDo */ +} +int FX_getFogTableSize(void) +{ +   int result; +   grGet(GR_FOG_TABLE_ENTRIES,sizeof(int),(void*)&result); +   return result;  +} + +int FX_getGrStateSize(void) +{ +   int result; +   grGet(GR_GLIDE_STATE_SIZE,sizeof(int),(void*)&result); +    +   return result; +    +} +int FX_grBufferNumPending() +{ +   int result; +   grGet(GR_PENDING_BUFFERSWAPS,sizeof(int),(void*)&result); +    +   return result; +} + +int FX_grSstScreenWidth() +{ +   FxI32 result[4]; +    +   grGet(GR_VIEWPORT,sizeof(FxI32)*4,result); +    +   return result[2]; +} + +int FX_grSstScreenHeight() +{ +   FxI32 result[4]; +    +   grGet(GR_VIEWPORT,sizeof(FxI32)*4,result); +    +   return result[3]; +} + +void FX_grGlideGetVersion(char *buf) +{ +   strcpy(buf,grGetString(GR_VERSION)); +} + +void FX_grSstPerfStats(GrSstPerfStats_t *st) +{ +  /* ToDo */ +  st->pixelsIn = 0; +  st->chromaFail = 0; +  st->zFuncFail = 0; +  st->aFuncFail = 0; +  st->pixelsOut = 0; +} + +void FX_grAADrawLine(GrVertex *a,GrVertex *b) +{ +   /* ToDo */ +   grDrawLine(a,b); +} +void FX_grAADrawPoint(GrVertex *a) +{ +  grDrawPoint(a); +} + +void FX_setupGrVertexLayout(void) +{ +   grReset(GR_VERTEX_PARAMETER); +    +   grCoordinateSpace(GR_WINDOW_COORDS); +   grVertexLayout(GR_PARAM_XY,  	GR_VERTEX_X_OFFSET << 2, 	GR_PARAM_ENABLE); +   grVertexLayout(GR_PARAM_RGB, 	GR_VERTEX_R_OFFSET << 2, 	GR_PARAM_ENABLE); + /*  grVertexLayout(GR_PARAM_Z,   	GR_VERTEX_Z_OFFSET << 2, 	GR_PARAM_ENABLE); */ +   grVertexLayout(GR_PARAM_A,   	GR_VERTEX_A_OFFSET << 2, 	GR_PARAM_ENABLE); +   grVertexLayout(GR_PARAM_Q,		GR_VERTEX_OOW_OFFSET << 2,	GR_PARAM_ENABLE); +   grVertexLayout(GR_PARAM_Z,           GR_VERTEX_OOZ_OFFSET << 2, 	GR_PARAM_ENABLE); +   grVertexLayout(GR_PARAM_ST0, 	GR_VERTEX_SOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE);	 +   grVertexLayout(GR_PARAM_Q0,  	GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE);  +   grVertexLayout(GR_PARAM_ST1, 	GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);	 +   grVertexLayout(GR_PARAM_Q1,  	GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);	 +} + +void FX_grHints(GrHint_t hintType, FxU32 hintMask) +{ +   switch(hintType) { +      case GR_HINT_STWHINT: +      { +        if (hintMask & GR_STWHINT_W_DIFF_TMU0) +           grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, 	GR_PARAM_ENABLE); +        else +           grVertexLayout(GR_PARAM_Q0,GR_VERTEX_OOW_TMU0_OFFSET << 2, 	GR_PARAM_DISABLE); +            +        if (hintMask & GR_STWHINT_ST_DIFF_TMU1) +            grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE); +        else +            grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE); +         +        if (hintMask & GR_STWHINT_W_DIFF_TMU1) +            grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2,	GR_PARAM_ENABLE); +        else +            grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2,	GR_PARAM_DISABLE); +      	 +      } +   } +} +int FX_grSstQueryHardware(GrHwConfiguration *config) +{ +   int i,j; +   int numFB; +   grGet(GR_NUM_BOARDS,4,(void*)&(config->num_sst)); +   if (config->num_sst == 0) +   	return 0; +   for (i = 0; i< config->num_sst; i++) +   { +      config->SSTs[i].type = GR_SSTTYPE_VOODOO; +      grSstSelect(i); +      grGet(GR_MEMORY_FB,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.fbRam)); +      config->SSTs[i].sstBoard.VoodooConfig.fbRam/= 1024*1024; +       +      grGet(GR_NUM_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.nTexelfx)); +    +       +      grGet(GR_NUM_FB,4,(void*)&numFB); +      if (numFB > 1) +         config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXTRUE; +      else +         config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXFALSE; +      for (j = 0; j < config->SSTs[i].sstBoard.VoodooConfig.nTexelfx; j++) +      { +      	 grGet(GR_MEMORY_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.tmuConfig[i].tmuRam)); +      } +   } +   return 1; +} + + +#endif  +#else + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_glidew(void) +{ +  return 0; +} + +#endif /* FX */ diff --git a/src/mesa/drivers/glide/fxglidew.h b/src/mesa/drivers/glide/fxglidew.h new file mode 100644 index 0000000000..17f395686c --- /dev/null +++ b/src/mesa/drivers/glide/fxglidew.h @@ -0,0 +1,358 @@ +/* + * 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 __FX_GLIDE_WARPER__ +#define __FX_GLIDE_WARPER__ + +#include <glide.h> + +/*  + * General context:  + */ +#if !defined(FX_GLIDE3) +     typedef FxU32 	 FX_GrContext_t;	/* Not used in Glide2 */ +#else +     typedef GrContext_t FX_GrContext_t; +#endif + +/*  + * Glide3 emulation on Glide2:  + */ +#if !defined(FX_GLIDE3) +	/* Constanst for FX_grGetInteger( ) */ +	#define FX_FOG_TABLE_ENTRIES            0x0004    /* The number of entries in the hardware fog table. */ +	#define FX_GLIDE_STATE_SIZE             0x0006	  /* Size of buffer, in bytes, needed to save Glide state. */ +	#define FX_LFB_PIXEL_PIPE               0x0009	  /* 1 if LFB writes can go through the 3D pixel pipe. */		 +	#define FX_PENDING_BUFFERSWAPS          0x0014    /* The number of buffer swaps pending. */ +#else +        #define FX_FOG_TABLE_ENTRIES            GR_FOG_TABLE_ENTRIES   +	#define FX_GLIDE_STATE_SIZE             GR_GLIDE_STATE_SIZE +	#define FX_LFB_PIXEL_PIPE               GR_LFB_PIXEL_PIPE		 +	#define FX_PENDING_BUFFERSWAPS          GR_PENDING_BUFFERSWAPS   +#endif + +/* + * Genral warper functions for Glide2/Glide3: + */  +extern FxI32 FX_grGetInteger(FxU32 pname); + +/* + * Glide2 emulation on Glide3: + */ +#if defined(FX_GLIDE3) + +#define GR_ASPECT_1x1 GR_ASPECT_LOG2_1x1 +#define GR_ASPECT_2x1 GR_ASPECT_LOG2_2x1 +#define GR_ASPECT_4x1 GR_ASPECT_LOG2_4x1 +#define GR_ASPECT_8x1 GR_ASPECT_LOG2_8x1 +#define GR_ASPECT_1x2 GR_ASPECT_LOG2_1x2 +#define GR_ASPECT_1x4 GR_ASPECT_LOG2_1x4 +#define GR_ASPECT_1x8 GR_ASPECT_LOG2_1x8 + +#define GR_LOD_256	GR_LOD_LOG2_256 +#define GR_LOD_128	GR_LOD_LOG2_128 +#define GR_LOD_64	GR_LOD_LOG2_64 +#define GR_LOD_32	GR_LOD_LOG2_32	 +#define GR_LOD_16	GR_LOD_LOG2_16 +#define GR_LOD_8	GR_LOD_LOG2_8 +#define GR_LOD_4	GR_LOD_LOG2_4 +#define GR_LOD_2	GR_LOD_LOG2_2 +#define GR_LOD_1	GR_LOD_LOG2_1 + +#define GR_FOG_WITH_TABLE GR_FOG_WITH_TABLE_ON_Q + +typedef int GrSstType; + +#define MAX_NUM_SST            4 + +#define GR_SSTTYPE_VOODOO    0 +#define GR_SSTTYPE_SST96     1 +#define GR_SSTTYPE_AT3D      2 +#define GR_SSTTYPE_Voodoo2   3 + +typedef struct GrTMUConfig_St { +  int    tmuRev;                /* Rev of Texelfx chip */ +  int    tmuRam;                /* 1, 2, or 4 MB */ +} GrTMUConfig_t; + +typedef struct GrVoodooConfig_St { +  int    fbRam;                         /* 1, 2, or 4 MB */ +  int    fbiRev;                        /* Rev of Pixelfx chip */ +  int    nTexelfx;                      /* How many texelFX chips are there? */ +  FxBool sliDetect;                     /* Is it a scan-line interleaved board? */ +  GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU];   /* Configuration of the Texelfx chips */ +} GrVoodooConfig_t; + +typedef struct GrSst96Config_St { +  int   fbRam;                  /* How much? */ +  int   nTexelfx; +  GrTMUConfig_t tmuConfig; +} GrSst96Config_t; + +typedef GrVoodooConfig_t GrVoodoo2Config_t; + +typedef struct GrAT3DConfig_St { +  int   rev; +} GrAT3DConfig_t; + +typedef struct { +  int num_sst;                  /* # of HW units in the system */ +  struct { +    GrSstType type;             /* Which hardware is it? */ +    union SstBoard_u { +      GrVoodooConfig_t  VoodooConfig; +      GrSst96Config_t   SST96Config; +      GrAT3DConfig_t    AT3DConfig; +      GrVoodoo2Config_t Voodoo2Config; +    } sstBoard; +  } SSTs[MAX_NUM_SST];          /* configuration for each board */ +} GrHwConfiguration; + +typedef FxU32 GrHint_t; +#define GR_HINTTYPE_MIN                 0 +#define GR_HINT_STWHINT                 0 + +typedef FxU32 GrSTWHint_t; +#define GR_STWHINT_W_DIFF_FBI   FXBIT(0) +#define GR_STWHINT_W_DIFF_TMU0  FXBIT(1) +#define GR_STWHINT_ST_DIFF_TMU0 FXBIT(2) +#define GR_STWHINT_W_DIFF_TMU1  FXBIT(3) +#define GR_STWHINT_ST_DIFF_TMU1 FXBIT(4) +#define GR_STWHINT_W_DIFF_TMU2  FXBIT(5) +#define GR_STWHINT_ST_DIFF_TMU2 FXBIT(6) + +#define GR_CONTROL_ACTIVATE 		1 +#define GR_CONTROL_DEACTIVATE		0 + +#define GrState				void + +/* +** move the vertex layout defintion to application +*/ +typedef struct { +  float  sow;                   /* s texture ordinate (s over w) */ +  float  tow;                   /* t texture ordinate (t over w) */   +  float  oow;                   /* 1/w (used mipmapping - really 0xfff/w) */ +}  GrTmuVertex; + +typedef struct +{ +  float x, y;         /* X and Y in screen space */ +  float ooz;          /* 65535/Z (used for Z-buffering) */ +  float oow;          /* 1/W (used for W-buffering, texturing) */ +  float r, g, b, a;   /* R, G, B, A [0..255.0] */ +  float z;            /* Z is ignored */ +  GrTmuVertex  tmuvtx[GLIDE_NUM_TMU]; +} GrVertex; + +#define GR_VERTEX_X_OFFSET              0 +#define GR_VERTEX_Y_OFFSET              1 +#define GR_VERTEX_OOZ_OFFSET            2 +#define GR_VERTEX_OOW_OFFSET            3 +#define GR_VERTEX_R_OFFSET              4 +#define GR_VERTEX_G_OFFSET              5 +#define GR_VERTEX_B_OFFSET              6 +#define GR_VERTEX_A_OFFSET              7 +#define GR_VERTEX_Z_OFFSET              8 +#define GR_VERTEX_SOW_TMU0_OFFSET       9 +#define GR_VERTEX_TOW_TMU0_OFFSET       10 +#define GR_VERTEX_OOW_TMU0_OFFSET       11 +#define GR_VERTEX_SOW_TMU1_OFFSET       12 +#define GR_VERTEX_TOW_TMU1_OFFSET       13 +#define GR_VERTEX_OOW_TMU1_OFFSET       14 + +#endif + + +/* + * Glide2 functions for Glide3 + */ +#if defined(FX_GLIDE3) +#define FX_grTexDownloadTable(TMU,type,data)		grTexDownloadTable(type,data) +#else +#define FX_grTexDownloadTable(TMU,type,data) 		grTexDownloadTable(TMU,type,data) +#endif + +/* + * Flush + */ +#if defined(FX_GLIDE3) +#define FX_grFlush		grFlush +#else +#define FX_grFlush		grSstIdle +#endif	 +/* + * Write region: ToDo possible exploit the PixelPipe parameter. + */ +#if defined(FX_GLIDE3) +#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)	\ +	grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data) +#else +#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)	\ +	grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) +#endif +/* + * For Lod/LodLog2 conversion. + */ +#if defined(FX_GLIDE3) +	#define FX_largeLodLog2(info)		(info).largeLodLog2 +#else +	#define FX_largeLodLog2(info)		(info).largeLod	 +#endif + +#if defined(FX_GLIDE3) +	#define FX_aspectRatioLog2(info)		(info).aspectRatioLog2 +#else +	#define FX_aspectRatioLog2(info)		(info).aspectRatio +#endif + +#if defined(FX_GLIDE3) +	#define FX_smallLodLog2(info)		(info).smallLodLog2 +#else +	#define FX_smallLodLog2(info)		(info).smallLod +#endif + +#if defined(FX_GLIDE3) +	#define FX_lodToValue(val)		((int)(GR_LOD_256-val)) +#else +	#define FX_lodToValue(val)		((int)(val)) +#endif + +#if defined(FX_GLIDE3) +	#define FX_largeLodValue(info)		((int)(GR_LOD_256-(info).largeLodLog2)) +#else +	#define FX_largeLodValue(info)		((int)(info).largeLod) +#endif + +#if defined(FX_GLIDE3) +	#define FX_smallLodValue(info)		((int)(GR_LOD_256-(info).smallLodLog2)) +#else +	#define FX_smallLodValue(info)		((int)(info).smallLod) +#endif + +#if defined(FX_GLIDE3) +	#define FX_valueToLod(val)		((GrLOD_t)(GR_LOD_256-val)) +#else +	#define FX_valueToLod(val)		((GrLOD_t)(val)) +#endif + +/* + * ScreenWidth/Height stuff. + */ +#if defined(FX_GLIDE3) +	extern int FX_grSstScreenWidth(); +	extern int FX_grSstScreenHeight(); +#else +	#define FX_grSstScreenWidth()		grSstScreenWidth() +	#define FX_grSstScreenHeight()		grSstScreenHeight() +#endif + + +/* + * Version string. + */ +#if defined(FX_GLIDE3) +	extern void FX_grGlideGetVersion(char *buf); +#else +	#define FX_grGlideGetVersion		grGlideGetVersion	 +#endif +/* + * Performance statistics + */ +#if defined(FX_GLIDE3) +        extern void FX_grSstPerfStats(GrSstPerfStats_t *st); +#else +	#define FX_grSstPerfStats		grSstPerfStats +#endif + +/* + * Hardware Query + */ +#if defined(FX_GLIDE3) +       extern int FX_grSstQueryHardware(GrHwConfiguration *config); +#else +       #define FX_grSstQueryHardware		grSstQueryHardware		 +#endif + +/* + * GrHints + */ +#if defined(FX_GLIDE3) +	extern void FX_grHints(GrHint_t hintType, FxU32 hintMask); +#else +	#define FX_grHints			grHints +#endif +/* + * Antialiashed line+point drawing. + */ +#if defined(FX_GLIDE3) +	extern void FX_grAADrawLine(GrVertex *a,GrVertex *b); +#else +	#define FX_grAADrawLine			grAADrawLine +#endif + +#if defined(FX_GLIDE3) +	extern void FX_grAADrawPoint(GrVertex *a); +#else +	#define FX_grAADrawPoint		grAADrawPoint +#endif + +/* + * Needed for Glide3 only, to set up Glide2 compatible vertex layout. + */ +#if defined(FX_GLIDE3) +	extern void FX_setupGrVertexLayout(void); +#else +	#define FX_setupGrVertexLayout()		do {} while (0) +#endif +/* + * grSstControl stuff + */ +#if defined(FX_GLIDE3) +	extern void FX_grSstControl(int par); +#else +	#define FX_grSstControl				grSstControl +#endif +/* + * grGammaCorrectionValue + */ +#if defined(FX_GLIDE3) +      extern void FX_grGammaCorrectionValue(float val); +#else +      #define FX_grGammaCorrectionValue			grGammaCorrectionValue +#endif + +/* + * WinOpen/Close. + */ +#if defined(FX_GLIDE3) +       #define FX_grSstWinOpen(hWnd,screen_resolution,refresh_rate,color_format,origin_location,nColBuffers,nAuxBuffers) \ +      		  grSstWinOpen(-1,screen_resolution,refresh_rate,color_format,origin_location,nColBuffers,nAuxBuffers) +       #define FX_grSstWinClose		grSstWinClose +#else +       #define FX_grSstWinOpen		grSstWinOpen +       #define FX_grSstWinClose(win)	grSstWinClose() +#endif + + +#endif /* __FX_GLIDE_WARPER__ */ diff --git a/src/mesa/drivers/glide/fxopengl.def b/src/mesa/drivers/glide/fxopengl.def new file mode 100644 index 0000000000..af76f4c1b2 --- /dev/null +++ b/src/mesa/drivers/glide/fxopengl.def @@ -0,0 +1,467 @@ +EXPORTS
 + glAccum
 + glAlphaFunc
 + glAreTexturesResident
 + glArrayElement
 + glBegin
 + glBindTexture
 + glBitmap
 + glBlendFunc
 + glCallList
 + glCallLists
 + glClear
 + glClearAccum
 + glClearIndex
 + glClearColor
 + glClearDepth
 + glClearStencil
 + glClipPlane
 + glColor3b
 + glColor3d
 + glColor3f
 + glColor3i
 + glColor3s
 + glColor3ub
 + glColor3ui
 + glColor3us
 + glColor4b
 + glColor4d
 + glColor4f
 + glColor4i
 + glColor4s
 + glColor4ub
 + glColor4ui
 + glColor4us
 + glColor3bv
 + glColor3dv
 + glColor3fv
 + glColor3iv
 + glColor3sv
 + glColor3ubv
 + glColor3uiv
 + glColor3usv
 + glColor4bv
 + glColor4dv
 + glColor4fv
 + glColor4iv
 + glColor4sv
 + glColor4ubv
 + glColor4uiv
 + glColor4usv
 + glColorMask
 + glColorMaterial
 + glColorPointer
 + glColorTableEXT
 + glColorSubTableEXT
 + glCopyPixels
 + glCopyTexImage1D
 + glCopyTexImage2D
 + glCopyTexSubImage1D
 + glCopyTexSubImage2D
 + glCullFace
 + glDepthFunc
 + glDepthMask
 + glDepthRange
 + glDeleteLists
 + glDeleteTextures
 + glDisable
 + glDisableClientState
 + glDrawArrays
 + glDrawBuffer
 + glDrawElements
 + glDrawPixels
 + glEnable
 + glEnableClientState
 + glEnd
 + glEndList
 + glEvalCoord1d
 + glEvalCoord1f
 + glEvalCoord1dv
 + glEvalCoord1fv
 + glEvalCoord2d
 + glEvalCoord2f
 + glEvalCoord2dv
 + glEvalCoord2fv
 + glEvalPoint1
 + glEvalPoint2
 + glEvalMesh1
 + glEdgeFlag
 + glEdgeFlagv
 + glEdgeFlagPointer
 + glEvalMesh2
 + glFeedbackBuffer
 + glFinish
 + glFlush
 + glFogf
 + glFogi
 + glFogfv
 + glFogiv
 + glFrontFace
 + glFrustum
 + glGenLists
 + glGenTextures
 + glGetBooleanv
 + glGetClipPlane
 + glGetColorTableEXT
 + glGetColorTableParameterivEXT
 + glGetColorTableParameterfvEXT
 + glGetDoublev
 + glGetError
 + glGetFloatv
 + glGetIntegerv
 + glGetLightfv
 + glGetLightiv
 + glGetMapdv
 + glGetMapfv
 + glGetMapiv
 + glGetMaterialfv
 + glGetMaterialiv
 + glGetPixelMapfv
 + glGetPixelMapuiv
 + glGetPixelMapusv
 + glGetPointerv
 + glGetPolygonStipple
 + glGetString
 + glGetTexEnvfv
 + glGetTexEnviv
 + glGetTexGeniv
 + glGetTexGendv
 + glGetTexGenfv
 + glGetTexImage
 + glGetTexLevelParameterfv
 + glGetTexLevelParameteriv
 + glGetTexParameterfv
 + glGetTexParameteriv
 + glHint
 + glIndexd
 + glIndexf
 + glIndexi
 + glIndexs
 + glIndexub
 + glIndexdv
 + glIndexfv
 + glIndexiv
 + glIndexsv
 + glIndexubv
 + glIndexMask
 + glIndexPointer
 + glInterleavedArrays
 + glInitNames
 + glIsList
 + glIsTexture
 + glLightf
 + glLighti
 + glLightfv
 + glLightiv
 + glLightModelf
 + glLightModeli
 + glLightModelfv
 + glLightModeliv
 + glLineWidth
 + glLineStipple
 + glListBase
 + glLoadIdentity
 + glLoadMatrixd
 + glLoadMatrixf
 + glLoadName
 + glLogicOp
 + glMap1d
 + glMap1f
 + glMap2d
 + glMap2f
 + glMapGrid1d
 + glMapGrid1f
 + glMapGrid2d
 + glMapGrid2f
 + glMaterialf
 + glMateriali
 + glMaterialfv
 + glMaterialiv
 + glMatrixMode
 + glMultMatrixd
 + glMultMatrixf
 + glNewList
 + glNormal3b
 + glNormal3d
 + glNormal3f
 + glNormal3i
 + glNormal3s
 + glNormal3bv
 + glNormal3dv
 + glNormal3fv
 + glNormal3iv
 + glNormal3sv
 + glNormalPointer
 + glOrtho
 + glPassThrough
 + glPixelMapfv
 + glPixelMapuiv
 + glPixelMapusv
 + glPixelStoref
 + glPixelStorei
 + glPixelTransferf
 + glPixelTransferi
 + glPixelZoom
 + glPointSize
 + glPolygonMode
 + glPolygonOffset
 + glPolygonOffsetEXT
 + glPolygonStipple
 + glPopAttrib
 + glPopClientAttrib
 + glPopMatrix
 + glPopName
 + glPrioritizeTextures
 + glPushMatrix
 + glRasterPos2d
 + glRasterPos2f
 + glRasterPos2i
 + glRasterPos2s
 + glRasterPos3d
 + glRasterPos3f
 + glRasterPos3i
 + glRasterPos3s
 + glRasterPos4d
 + glRasterPos4f
 + glRasterPos4i
 + glRasterPos4s
 + glRasterPos2dv
 + glRasterPos2fv
 + glRasterPos2iv
 + glRasterPos2sv
 + glRasterPos3dv
 + glRasterPos3fv
 + glRasterPos3iv
 + glRasterPos3sv
 + glRasterPos4dv
 + glRasterPos4fv
 + glRasterPos4iv
 + glRasterPos4sv
 + glReadBuffer
 + glReadPixels
 + glRectd
 + glRectf
 + glRecti
 + glRects
 + glRectdv
 + glRectfv
 + glRectiv
 + glRectsv
 + glScissor
 + glIsEnabled
 + glPushAttrib
 + glPushClientAttrib
 + glPushName
 + glRenderMode
 + glRotated
 + glRotatef
 + glSelectBuffer
 + glScaled
 + glScalef
 + glShadeModel
 + glStencilFunc
 + glStencilMask
 + glStencilOp
 + glTexCoord1d
 + glTexCoord1f
 + glTexCoord1i
 + glTexCoord1s
 + glTexCoord2d
 + glTexCoord2f
 + glTexCoord2i
 + glTexCoord2s
 + glTexCoord3d
 + glTexCoord3f
 + glTexCoord3i
 + glTexCoord3s
 + glTexCoord4d
 + glTexCoord4f
 + glTexCoord4i
 + glTexCoord4s
 + glTexCoord1dv
 + glTexCoord1fv
 + glTexCoord1iv
 + glTexCoord1sv
 + glTexCoord2dv
 + glTexCoord2fv
 + glTexCoord2iv
 + glTexCoord2sv
 + glTexCoord3dv
 + glTexCoord3fv
 + glTexCoord3iv
 + glTexCoord3sv
 + glTexCoord4dv
 + glTexCoord4fv
 + glTexCoord4iv
 + glTexCoord4sv
 + glTexCoordPointer
 + glTexGend
 + glTexGenf
 + glTexGeni
 + glTexGendv
 + glTexGeniv
 + glTexGenfv
 + glTexEnvf
 + glTexEnvi
 + glTexEnvfv
 + glTexEnviv
 + glTexImage1D
 + glTexImage2D
 + glTexParameterf
 + glTexParameteri
 + glTexParameterfv
 + glTexParameteriv
 + glTexSubImage1D
 + glTexSubImage2D
 + glTranslated
 + glTranslatef
 + glVertex2d
 + glVertex2f
 + glVertex2i
 + glVertex2s
 + glVertex3d
 + glVertex3f
 + glVertex3i
 + glVertex3s
 + glVertex4d
 + glVertex4f
 + glVertex4i
 + glVertex4s
 + glVertex2dv
 + glVertex2fv
 + glVertex2iv
 + glVertex2sv
 + glVertex3dv
 + glVertex3fv
 + glVertex3iv
 + glVertex3sv
 + glVertex4dv
 + glVertex4fv
 + glVertex4iv
 + glVertex4sv
 + glVertexPointer
 + glViewport
 + glBlendEquationEXT
 + glBlendColorEXT
 + glVertexPointerEXT
 + glNormalPointerEXT
 + glColorPointerEXT
 + glIndexPointerEXT
 + glTexCoordPointerEXT
 + glEdgeFlagPointerEXT
 + glGetPointervEXT
 + glArrayElementEXT
 + glDrawArraysEXT
 + glBindTextureEXT
 + glDeleteTexturesEXT
 + glGenTexturesEXT
 + glPrioritizeTexturesEXT
 + glCopyTexSubImage3DEXT
 + glTexImage3DEXT
 + glTexSubImage3DEXT
 + glWindowPos4fMESA
 + glWindowPos2iMESA
 + glWindowPos2sMESA
 + glWindowPos2fMESA
 + glWindowPos2dMESA
 + glWindowPos2ivMESA
 + glWindowPos2svMESA
 + glWindowPos2fvMESA
 + glWindowPos2dvMESA
 + glWindowPos3iMESA
 + glWindowPos3sMESA
 + glWindowPos3fMESA
 + glWindowPos3dMESA
 + glWindowPos3ivMESA
 + glWindowPos3svMESA
 + glWindowPos3fvMESA
 + glWindowPos3dvMESA
 + glWindowPos4iMESA
 + glWindowPos4sMESA
 + glWindowPos4dMESA
 + glWindowPos4ivMESA
 + glWindowPos4svMESA
 + glWindowPos4fvMESA
 + glWindowPos4dvMESA
 + glResizeBuffersMESA
 + wglCopyContext
 + wglCreateContext
 + wglCreateLayerContext
 + wglDeleteContext
 +;wglDescribeLayerPlane
 + wglGetCurrentContext
 + wglGetCurrentDC
 +;wglGetLayerPaletteEntries
 + wglGetProcAddress
 + wglMakeCurrent
 +;wglRealizeLayerPalette
 +;wglSetLayerPaletteEntries
 + wglShareLists
 + wglSwapLayerBuffers
 + wglUseFontBitmapsA
 + wglUseFontBitmapsW
 + wglUseFontOutlinesA
 + wglUseFontOutlinesW
 + wglChoosePixelFormat
 + ChoosePixelFormat
 + wglDescribePixelFormat
 + DescribePixelFormat
 + wglGetPixelFormat
 + GetPixelFormat
 + wglSetPixelFormat
 + SetPixelFormat
 + wglSwapBuffers
 + SwapBuffers
 + gl3DfxSetPaletteEXT
 + glActiveTextureARB
 + glClientActiveTextureARB
 + glMultiTexCoord1dARB
 + glMultiTexCoord1dvARB
 + glMultiTexCoord1fARB
 + glMultiTexCoord1fvARB
 + glMultiTexCoord1iARB
 + glMultiTexCoord1ivARB
 + glMultiTexCoord1sARB
 + glMultiTexCoord1svARB
 + glMultiTexCoord2dARB
 + glMultiTexCoord2dvARB
 + glMultiTexCoord2fARB
 + glMultiTexCoord2fvARB
 + glMultiTexCoord2iARB
 + glMultiTexCoord2ivARB
 + glMultiTexCoord2sARB
 + glMultiTexCoord2svARB
 + glMultiTexCoord3dARB
 + glMultiTexCoord3dvARB
 + glMultiTexCoord3fARB
 + glMultiTexCoord3fvARB
 + glMultiTexCoord3iARB
 + glMultiTexCoord3ivARB
 + glMultiTexCoord3sARB
 + glMultiTexCoord3svARB
 + glMultiTexCoord4dARB
 + glMultiTexCoord4dvARB
 + glMultiTexCoord4fARB
 + glMultiTexCoord4fvARB
 + glMultiTexCoord4iARB
 + glMultiTexCoord4ivARB
 + glMultiTexCoord4sARB
 + glMultiTexCoord4svARB
 + fxMesaCreateContext
 + fxMesaCreateBestContext
 + fxMesaDestroyContext
 + fxMesaSelectCurrentBoard
 + fxMesaMakeCurrent
 + fxMesaGetCurrentContext
 + fxMesaSwapBuffers
 + fxMesaSetNearFar
 + fxMesaUpdateScreenSize
 + fxQueryHardware
 + fxCloseHardware
 + OSMesaCreateContext
 + OSMesaDestroyContext
 + OSMesaGetCurrentContext
 + OSMesaGetDepthBuffer
 + OSMesaGetIntegerv
 + OSMesaMakeCurrent
 + OSMesaPixelStore
 diff --git a/src/mesa/drivers/glide/fxsetup.c b/src/mesa/drivers/glide/fxsetup.c new file mode 100644 index 0000000000..9996499316 --- /dev/null +++ b/src/mesa/drivers/glide/fxsetup.c @@ -0,0 +1,1552 @@ +/* -*- mode: C; tab-width:8;  -*- + +             fxsetup.c - 3Dfx VooDoo rendering mode setup functions +*/ + +/* + * 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. + * + * See the file fxapi.c for more informations about authors + * + */ + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "enums.h" + +static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj) +{ +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; +  GLint minl,maxl; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxTexValidate(...) Start\n"); +  } + +  if(ti->validated) { +     if (MESA_VERBOSE&VERBOSE_DRIVER) { +	fprintf(stderr,"fxmesa: fxTexValidate(...) End (validated=GL_TRUE)\n"); +     } +    return; +  } + +  minl=ti->minLevel=tObj->BaseLevel; +  maxl=ti->maxLevel=MIN2(tObj->MaxLevel,tObj->Image[0]->MaxLog2); + +  fxTexGetInfo(tObj->Image[minl]->Width,tObj->Image[minl]->Height, +	       &(FX_largeLodLog2(ti->info)),&(FX_aspectRatioLog2(ti->info)), +	       &(ti->sScale),&(ti->tScale), +	       &(ti->int_sScale),&(ti->int_tScale),	        +	       NULL,NULL); + + +  if((tObj->MinFilter!=GL_NEAREST) && (tObj->MinFilter!=GL_LINEAR)) +    fxTexGetInfo(tObj->Image[maxl]->Width,tObj->Image[maxl]->Height, +		 &(FX_smallLodLog2(ti->info)),NULL, +		 NULL,NULL, +		 NULL,NULL, +		 NULL,NULL); +  else +    FX_smallLodLog2(ti->info)=FX_largeLodLog2(ti->info); + +  fxTexGetFormat(tObj->Image[minl]->Format,&(ti->info.format),&(ti->baseLevelInternalFormat)); + +  ti->validated=GL_TRUE; + +  ti->info.data=NULL; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxTexValidate(...) End\n"); +  } +} + +static void fxPrintUnitsMode( const char *msg, GLuint mode ) +{ +   fprintf(stderr,  +	   "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", +	   msg, +	   mode, +	   (mode & FX_UM_E0_REPLACE)         ? "E0_REPLACE, " : "", +	   (mode & FX_UM_E0_MODULATE)        ? "E0_MODULATE, " : "", +	   (mode & FX_UM_E0_DECAL)           ? "E0_DECAL, " : "", +	   (mode & FX_UM_E0_BLEND)           ? "E0_BLEND, " : "", +	   (mode & FX_UM_E1_REPLACE)         ? "E1_REPLACE, " : "", +	   (mode & FX_UM_E1_MODULATE)        ? "E1_MODULATE, " : "", +	   (mode & FX_UM_E1_DECAL)           ? "E1_DECAL, " : "", +	   (mode & FX_UM_E1_BLEND)           ? "E1_BLEND, " : "", +	   (mode & FX_UM_E0_ALPHA)           ? "E0_ALPHA, " : "", +	   (mode & FX_UM_E0_LUMINANCE)       ? "E0_LUMINANCE, " : "", +	   (mode & FX_UM_E0_LUMINANCE_ALPHA) ? "E0_LUMINANCE_ALPHA, " : "", +	   (mode & FX_UM_E0_INTENSITY)       ? "E0_INTENSITY, " : "", +	   (mode & FX_UM_E0_RGB)             ? "E0_RGB, " : "", +	   (mode & FX_UM_E0_RGBA)            ? "E0_RGBA, " : "", +	   (mode & FX_UM_E1_ALPHA)           ? "E1_ALPHA, " : "", +	   (mode & FX_UM_E1_LUMINANCE)       ? "E1_LUMINANCE, " : "", +	   (mode & FX_UM_E1_LUMINANCE_ALPHA) ? "E1_LUMINANCE_ALPHA, " : "", +	   (mode & FX_UM_E1_INTENSITY)       ? "E1_INTENSITY, " : "", +	   (mode & FX_UM_E1_RGB)             ? "E1_RGB, " : "", +	   (mode & FX_UM_E1_RGBA)            ? "E1_RGBA, " : "", +	   (mode & FX_UM_COLOR_ITERATED)     ? "COLOR_ITERATED, " : "", +	   (mode & FX_UM_COLOR_CONSTANT)     ? "COLOR_CONSTANT, " : "", +	   (mode & FX_UM_ALPHA_ITERATED)     ? "ALPHA_ITERATED, " : "", +	   (mode & FX_UM_ALPHA_CONSTANT)     ? "ALPHA_CONSTANT, " : ""); +} + +GLuint fxGetTexSetConfiguration(GLcontext *ctx, +				struct gl_texture_object *tObj0, +				struct gl_texture_object *tObj1) +{ +  GLuint unitsmode=0; +  GLuint envmode=0; +  GLuint ifmt=0; + +  if((ctx->Light.ShadeModel==GL_SMOOTH) || +     (ctx->Point.SmoothFlag) || +     (ctx->Line.SmoothFlag) || +     (ctx->Polygon.SmoothFlag)) +    unitsmode|=FX_UM_ALPHA_ITERATED; +  else +    unitsmode|=FX_UM_ALPHA_CONSTANT; + +  if(ctx->Light.ShadeModel==GL_SMOOTH) +    unitsmode|=FX_UM_COLOR_ITERATED; +  else +    unitsmode|=FX_UM_COLOR_CONSTANT; + +  if(tObj0) { +    tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData; + +    switch(ti0->baseLevelInternalFormat) { +    case GL_ALPHA: +      ifmt|=FX_UM_E0_ALPHA; +      break; +    case GL_LUMINANCE: +      ifmt|=FX_UM_E0_LUMINANCE; +      break; +    case GL_LUMINANCE_ALPHA: +      ifmt|=FX_UM_E0_LUMINANCE_ALPHA; +      break; +    case GL_INTENSITY: +      ifmt|=FX_UM_E0_INTENSITY; +      break; +    case GL_RGB: +      ifmt|=FX_UM_E0_RGB; +      break; +    case GL_RGBA: +      ifmt|=FX_UM_E0_RGBA; +      break; +    } + +    switch(ctx->Texture.Unit[0].EnvMode) { +    case GL_DECAL: +      envmode|=FX_UM_E0_DECAL; +      break; +    case GL_MODULATE: +      envmode|=FX_UM_E0_MODULATE; +      break; +    case GL_REPLACE: +      envmode|=FX_UM_E0_REPLACE; +      break; +    case GL_BLEND: +      envmode|=FX_UM_E0_BLEND; +      break; +    default: +      /* do nothing */ +      break; +    } +  } + +  if(tObj1) { +    tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData; + +    switch(ti1->baseLevelInternalFormat) { +    case GL_ALPHA: +      ifmt|=FX_UM_E1_ALPHA; +      break; +    case GL_LUMINANCE: +      ifmt|=FX_UM_E1_LUMINANCE; +      break; +    case GL_LUMINANCE_ALPHA: +      ifmt|=FX_UM_E1_LUMINANCE_ALPHA; +      break; +    case GL_INTENSITY: +      ifmt|=FX_UM_E1_INTENSITY; +      break; +    case GL_RGB: +      ifmt|=FX_UM_E1_RGB; +      break; +    case GL_RGBA: +      ifmt|=FX_UM_E1_RGBA; +      break; +    default: +      /* do nothing */ +      break; +    } + +    switch(ctx->Texture.Unit[1].EnvMode) { +    case GL_DECAL: +      envmode|=FX_UM_E1_DECAL; +      break; +    case GL_MODULATE: +      envmode|=FX_UM_E1_MODULATE; +      break; +    case GL_REPLACE: +      envmode|=FX_UM_E1_REPLACE; +      break; +    case GL_BLEND: +      envmode|=FX_UM_E1_BLEND; +      break; +    default: +      /* do nothing */ +      break; +    } +  } + +  unitsmode|=(ifmt | envmode); + +  if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) +     fxPrintUnitsMode("unitsmode", unitsmode); + +  return unitsmode; +} + +/************************************************************************/ +/************************* Rendering Mode SetUp *************************/ +/************************************************************************/ + +/************************* Single Texture Set ***************************/ + +static void fxSetupSingleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj) +{ +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; + +  if(!ti->tmi.isInTM) { +    if(ti->LODblend) +      fxTMMoveInTM(fxMesa,tObj,FX_TMU_SPLIT); +    else { +      if(fxMesa->haveTwoTMUs) { +	if(fxMesa->freeTexMem[FX_TMU0]>grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info))) +	  fxTMMoveInTM(fxMesa,tObj,FX_TMU0); +	else +	  fxTMMoveInTM(fxMesa,tObj,FX_TMU1); +      } else +	fxTMMoveInTM(fxMesa,tObj,FX_TMU0); +    } +  } + +  if(ti->LODblend && ti->tmi.whichTMU == FX_TMU_SPLIT) { +    if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) { +       if (MESA_VERBOSE&VERBOSE_DRIVER) { +	  fprintf(stderr,"fxmesa: uploading texture palette\n"); +       } +      FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette)); +      FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(ti->palette)); +    } + +    grTexClampMode(GR_TMU0,ti->sClamp,ti->tClamp); +    grTexClampMode(GR_TMU1,ti->sClamp,ti->tClamp); +    grTexFilterMode(GR_TMU0,ti->minFilt,ti->maxFilt); +    grTexFilterMode(GR_TMU1,ti->minFilt,ti->maxFilt); +    grTexMipMapMode(GR_TMU0,ti->mmMode,ti->LODblend); +    grTexMipMapMode(GR_TMU1,ti->mmMode,ti->LODblend); + +    grTexSource(GR_TMU0,ti->tmi.tm[FX_TMU0]->startAddress, +		GR_MIPMAPLEVELMASK_ODD,&(ti->info)); +    grTexSource(GR_TMU1,ti->tmi.tm[FX_TMU1]->startAddress, +		GR_MIPMAPLEVELMASK_EVEN,&(ti->info)); +  } else { +    if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) { +       if (MESA_VERBOSE&VERBOSE_DRIVER) { +	  fprintf(stderr,"fxmesa: uploading texture palette\n"); +       } +      FX_grTexDownloadTable(ti->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti->palette)); +    } + +    /* KW: The alternative is to do the download to the other tmu.  If +     * we get to this point, I think it means we are thrashing the +     * texture memory, so perhaps it's not a good idea.   +     */ +    if (ti->LODblend && (MESA_VERBOSE&VERBOSE_DRIVER)) +       fprintf(stderr, "fxmesa: not blending texture - only on one tmu\n"); + +    grTexClampMode(ti->tmi.whichTMU,ti->sClamp,ti->tClamp); +    grTexFilterMode(ti->tmi.whichTMU,ti->minFilt,ti->maxFilt); +    grTexMipMapMode(ti->tmi.whichTMU,ti->mmMode,FXFALSE); + +    grTexSource(ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]->startAddress, +		GR_MIPMAPLEVELMASK_BOTH,&(ti->info)); +  } +} + +static void fxSelectSingleTMUSrc(fxMesaContext fxMesa, GLint tmu, FxBool LODblend) +{ +   if (MESA_VERBOSE&VERBOSE_DRIVER) { +      fprintf(stderr,"fxmesa: fxSelectSingleTMUSrc(%d,%d)\n",tmu,LODblend); +   } + +  if(LODblend) { +    grTexCombine(GR_TMU0, +		 GR_COMBINE_FUNCTION_BLEND, +		 GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION, +		 GR_COMBINE_FUNCTION_BLEND, +		 GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION, +		 FXFALSE,FXFALSE); + +    grTexCombine(GR_TMU1, +		 GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		 GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		 FXFALSE,FXFALSE); + +    fxMesa->tmuSrc=FX_TMU_SPLIT; +  } else { +    if(tmu==FX_TMU0) { +      grTexCombine(GR_TMU0, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   FXFALSE,FXFALSE); +       +      fxMesa->tmuSrc=FX_TMU0; +    } else { +      grTexCombine(GR_TMU1, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   FXFALSE,FXFALSE); +     +      /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */ +     +      grTexCombine(GR_TMU0, +		   GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE, +		   GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE, +		   FXFALSE,FXFALSE); +     +      fxMesa->tmuSrc=FX_TMU1; +    } +  } +} + +void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GrCombineLocal_t localc,locala; +  GLuint unitsmode; +  GLint ifmt; +  tfxTexInfo *ti; +  struct gl_texture_object *tObj=ctx->Texture.Unit[textureset].CurrentD[2]; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) Start\n"); +  } + +  ti=(tfxTexInfo *)tObj->DriverData; + +  fxTexValidate(ctx,tObj); + +  fxSetupSingleTMU(fxMesa,tObj); + +  if(fxMesa->tmuSrc!=ti->tmi.whichTMU) +    fxSelectSingleTMUSrc(fxMesa,ti->tmi.whichTMU,ti->LODblend); + +  if(textureset==0 || !fxMesa->haveTwoTMUs) +    unitsmode=fxGetTexSetConfiguration(ctx,tObj,NULL); +  else +    unitsmode=fxGetTexSetConfiguration(ctx,NULL,tObj); + +  if(fxMesa->lastUnitsMode==unitsmode) +    return; + +  fxMesa->lastUnitsMode=unitsmode; + +  fxMesa->stw_hint_state = 0; +  FX_grHints(GR_HINT_STWHINT,0); + +  ifmt=ti->baseLevelInternalFormat; + +  if(unitsmode & FX_UM_ALPHA_ITERATED) +    locala=GR_COMBINE_LOCAL_ITERATED; +  else +    locala=GR_COMBINE_LOCAL_CONSTANT; + +  if(unitsmode & FX_UM_COLOR_ITERATED) +    localc=GR_COMBINE_LOCAL_ITERATED; +  else +    localc=GR_COMBINE_LOCAL_CONSTANT; + +  if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) +     fprintf(stderr, "fxMesa: fxSetupTextureSingleTMU, envmode is %s\n", +	     gl_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode)); + +  switch(ctx->Texture.Unit[textureset].EnvMode) { +  case GL_DECAL: +    grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, +		   GR_COMBINE_FACTOR_NONE, +		   locala, +		   GR_COMBINE_OTHER_NONE, +		   FXFALSE); + +    grColorCombine(GR_COMBINE_FUNCTION_BLEND, +		   GR_COMBINE_FACTOR_TEXTURE_ALPHA, +		   localc, +		   GR_COMBINE_OTHER_TEXTURE, +		   FXFALSE); +    break; +  case GL_MODULATE: +    grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		   GR_COMBINE_FACTOR_LOCAL, +		   locala, +		   GR_COMBINE_OTHER_TEXTURE, +		   FXFALSE); + +    if(ifmt==GL_ALPHA) +      grColorCombine(GR_COMBINE_FUNCTION_LOCAL, +		     GR_COMBINE_FACTOR_NONE, +		     localc, +		     GR_COMBINE_OTHER_NONE, +		     FXFALSE); +    else +      grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		     GR_COMBINE_FACTOR_LOCAL, +		     localc, +		     GR_COMBINE_OTHER_TEXTURE, +		     FXFALSE); +    break; +  case GL_BLEND: +#ifndef FX_SILENT +    fprintf(stderr,"fx Driver: GL_BLEND not yet supported\n"); +#endif +    /* TO DO (I think that the Voodoo Graphics isn't able to support GL_BLEND) */ +    break; +  case GL_REPLACE: +    if((ifmt==GL_RGB) || (ifmt==GL_LUMINANCE)) +      grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, +		     GR_COMBINE_FACTOR_NONE, +		     locala, +		     GR_COMBINE_OTHER_NONE, +		     FXFALSE); +    else +      grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		     GR_COMBINE_FACTOR_ONE, +		     locala, +		     GR_COMBINE_OTHER_TEXTURE, +		     FXFALSE); +     +    if(ifmt==GL_ALPHA) +      grColorCombine(GR_COMBINE_FUNCTION_LOCAL, +		     GR_COMBINE_FACTOR_NONE, +		     localc, +		     GR_COMBINE_OTHER_NONE, +		     FXFALSE); +    else +      grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		     GR_COMBINE_FACTOR_ONE, +		     localc, +		     GR_COMBINE_OTHER_TEXTURE, +		     FXFALSE); +    break; +  default: +#ifndef FX_SILENT +    fprintf(stderr,"fx Driver: %x Texture.EnvMode not yet supported\n",ctx->Texture.Unit[textureset].EnvMode); +#endif +    break; +  } + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) End\n"); +  } +} + +/************************* Double Texture Set ***************************/ + +void fxSetupDoubleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj0, +		      struct gl_texture_object *tObj1) +{ +#define T0_NOT_IN_TMU  0x01 +#define T1_NOT_IN_TMU  0x02 +#define T0_IN_TMU0     0x04 +#define T1_IN_TMU0     0x08 +#define T0_IN_TMU1     0x10 +#define T1_IN_TMU1     0x20 + +  tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData; +  tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData; +  GLuint tstate=0; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxSetupDoubleTMU(...)\n"); +  } + +  if(ti0->tmi.isInTM) { +    if(ti0->tmi.whichTMU==FX_TMU0) +      tstate|=T0_IN_TMU0; +    else if(ti0->tmi.whichTMU==FX_TMU1) +      tstate|=T0_IN_TMU1; +    else { +      fxTMMoveOutTM(fxMesa,tObj0); +      tstate|=T0_NOT_IN_TMU; +    } +  } else +    tstate|=T0_NOT_IN_TMU; + +  if(ti1->tmi.isInTM) { +    if(ti1->tmi.whichTMU==FX_TMU0) +      tstate|=T1_IN_TMU0; +    else if(ti1->tmi.whichTMU==FX_TMU1) +      tstate|=T1_IN_TMU1; +    else { +      fxTMMoveOutTM(fxMesa,tObj1); +      tstate|=T1_NOT_IN_TMU; +    } +  } else +    tstate|=T1_NOT_IN_TMU; + +  ti0->tmi.lastTimeUsed=fxMesa->texBindNumber; +  ti1->tmi.lastTimeUsed=fxMesa->texBindNumber; + +  /* Move texture maps in TMUs */  + +  switch(tstate) { +  case (T0_IN_TMU0 | T1_IN_TMU0): +    fxTMMoveOutTM(fxMesa,tObj1); + +    fxTMMoveInTM(fxMesa,tObj1,FX_TMU1); +    break; + +  case (T0_IN_TMU1 | T1_IN_TMU1): +    fxTMMoveOutTM(fxMesa,tObj0); + +    fxTMMoveInTM(fxMesa,tObj0,FX_TMU0); +    break; + +  case (T0_NOT_IN_TMU | T1_NOT_IN_TMU): +    fxTMMoveInTM(fxMesa,tObj0,FX_TMU0); +    fxTMMoveInTM(fxMesa,tObj1,FX_TMU1); +    break; + +    /*** T0/T1 ***/ + +  case (T0_NOT_IN_TMU | T1_IN_TMU0): +    fxTMMoveInTM(fxMesa,tObj0,FX_TMU1); +    break; + +  case (T0_NOT_IN_TMU | T1_IN_TMU1): +    fxTMMoveInTM(fxMesa,tObj0,FX_TMU0); +    break; + +  case (T0_IN_TMU0 | T1_NOT_IN_TMU): +    fxTMMoveInTM(fxMesa,tObj1,FX_TMU1); +    break; + +  case (T0_IN_TMU1 | T1_NOT_IN_TMU): +    fxTMMoveInTM(fxMesa,tObj1,FX_TMU0); +    break; + +    /*** Best Case ***/ + +  case (T0_IN_TMU1 | T1_IN_TMU0): +  case (T0_IN_TMU0 | T1_IN_TMU1): +    break; + +  default: +    fprintf(stderr,"fx Driver: internal error in fxSetupDoubleTMU()\n"); +    fxCloseHardware(); +    exit(-1); +    break; +  } + +  if(!fxMesa->haveGlobalPaletteTexture) { +    if(ti0->info.format==GR_TEXFMT_P_8) { +       if (MESA_VERBOSE&VERBOSE_DRIVER) { +	  fprintf(stderr,"fxmesa: uploading texture palette TMU0\n"); +       } +      FX_grTexDownloadTable(ti0->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti0->palette)); +    } + +    if(ti1->info.format==GR_TEXFMT_P_8) { +       if (MESA_VERBOSE&VERBOSE_DRIVER) { +	  fprintf(stderr,"fxmesa: uploading texture palette TMU1\n"); +       } +      FX_grTexDownloadTable(ti1->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti1->palette)); +    } +  } + +  grTexClampMode(ti0->tmi.whichTMU,ti0->sClamp,ti0->tClamp); +  grTexFilterMode(ti0->tmi.whichTMU,ti0->minFilt,ti0->maxFilt); +  grTexMipMapMode(ti0->tmi.whichTMU,ti0->mmMode,FXFALSE); +  grTexSource(ti0->tmi.whichTMU,ti0->tmi.tm[ti0->tmi.whichTMU]->startAddress, +	      GR_MIPMAPLEVELMASK_BOTH,&(ti0->info)); + +  grTexClampMode(ti1->tmi.whichTMU,ti1->sClamp,ti1->tClamp); +  grTexFilterMode(ti1->tmi.whichTMU,ti1->minFilt,ti1->maxFilt); +  grTexMipMapMode(ti1->tmi.whichTMU,ti1->mmMode,FXFALSE); +  grTexSource(ti1->tmi.whichTMU,ti1->tmi.tm[ti1->tmi.whichTMU]->startAddress, +	      GR_MIPMAPLEVELMASK_BOTH,&(ti1->info)); + +#undef T0_NOT_IN_TMU +#undef T1_NOT_IN_TMU +#undef T0_IN_TMU0 +#undef T1_IN_TMU0 +#undef T0_IN_TMU1 +#undef T1_IN_TMU1 +} + +static void fxSetupTextureDoubleTMU(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GrCombineLocal_t localc,locala; +  tfxTexInfo *ti0,*ti1; +  struct gl_texture_object *tObj0=ctx->Texture.Unit[0].CurrentD[2]; +  struct gl_texture_object *tObj1=ctx->Texture.Unit[1].CurrentD[2]; +  GLuint envmode,ifmt,unitsmode; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) Start\n"); +  } + +  ti0=(tfxTexInfo *)tObj0->DriverData; +  fxTexValidate(ctx,tObj0); + +  ti1=(tfxTexInfo *)tObj1->DriverData; +  fxTexValidate(ctx,tObj1); + +  fxSetupDoubleTMU(fxMesa,tObj0,tObj1); + +  unitsmode=fxGetTexSetConfiguration(ctx,tObj0,tObj1); + +  if(fxMesa->lastUnitsMode==unitsmode) +    return; + +  fxMesa->lastUnitsMode=unitsmode; + +  fxMesa->stw_hint_state |= GR_STWHINT_ST_DIFF_TMU1; +  FX_grHints(GR_HINT_STWHINT, fxMesa->stw_hint_state); + +  envmode=unitsmode & FX_UM_E_ENVMODE; +  ifmt=unitsmode & FX_UM_E_IFMT; + +  if(unitsmode & FX_UM_ALPHA_ITERATED) +    locala=GR_COMBINE_LOCAL_ITERATED; +  else +    locala=GR_COMBINE_LOCAL_CONSTANT; + +  if(unitsmode & FX_UM_COLOR_ITERATED) +    localc=GR_COMBINE_LOCAL_ITERATED; +  else +    localc=GR_COMBINE_LOCAL_CONSTANT; + + +  if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) +     fprintf(stderr, "fxMesa: fxSetupTextureDoubleTMU, envmode is %s/%s\n", +	     gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode), +	     gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode)); + + +  fxMesa->tmuSrc=FX_TMU_BOTH; +  switch(envmode) { +  case (FX_UM_E0_MODULATE | FX_UM_E1_MODULATE): +    { +      GLboolean isalpha[FX_NUM_TMU]; + +      if(ti0->baseLevelInternalFormat==GL_ALPHA) +	isalpha[ti0->tmi.whichTMU]=GL_TRUE; +      else +	isalpha[ti0->tmi.whichTMU]=GL_FALSE; + +      if(ti1->baseLevelInternalFormat==GL_ALPHA) +	isalpha[ti1->tmi.whichTMU]=GL_TRUE; +      else +	isalpha[ti1->tmi.whichTMU]=GL_FALSE; +	 +      if(isalpha[FX_TMU1]) +	grTexCombine(GR_TMU1, +		     GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE, +		     GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		     FXTRUE,FXFALSE); +      else +	grTexCombine(GR_TMU1, +		     GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		     GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		     FXFALSE,FXFALSE); + +      if(isalpha[FX_TMU0]) +	grTexCombine(GR_TMU0, +		     GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE, +		     GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		     FXFALSE,FXFALSE); +      else +	grTexCombine(GR_TMU0, +		     GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		     GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		     FXFALSE,FXFALSE); + +      grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		     GR_COMBINE_FACTOR_LOCAL, +		     localc, +		     GR_COMBINE_OTHER_TEXTURE, +		     FXFALSE); + +      grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		     GR_COMBINE_FACTOR_LOCAL, +		     locala, +		     GR_COMBINE_OTHER_TEXTURE, +		     FXFALSE); +      break; +    } +  case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */ +    if(ti1->tmi.whichTMU==FX_TMU1) { +      grTexCombine(GR_TMU1, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   FXTRUE,FXFALSE); +		   +      grTexCombine(GR_TMU0, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		   FXFALSE,FXFALSE); +    } else { +      grTexCombine(GR_TMU1, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   FXFALSE,FXFALSE); +		   +      grTexCombine(GR_TMU0, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, +		   FXFALSE,FXFALSE); +    } +	   +    grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, +		   GR_COMBINE_FACTOR_NONE, +		   locala, +		   GR_COMBINE_OTHER_NONE, +		   FXFALSE); + +    grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		   GR_COMBINE_FACTOR_ONE, +		   localc, +		   GR_COMBINE_OTHER_TEXTURE, +		   FXFALSE); +    break; +  case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */ +    if(ti1->tmi.whichTMU==FX_TMU1) { +      grTexCombine(GR_TMU1, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE, +		   FXFALSE,FXTRUE); +		   +      grTexCombine(GR_TMU0, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		   FXFALSE,FXFALSE); + +    } else { +      grTexCombine(GR_TMU1, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, +		   FXFALSE,FXFALSE); +		   +      grTexCombine(GR_TMU0, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, +		   GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE, +		   FXFALSE,FXFALSE); +    } +	   +    if(ti0->baseLevelInternalFormat==GL_RGB) +      grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, +		     GR_COMBINE_FACTOR_NONE, +		     locala, +		     GR_COMBINE_OTHER_NONE, +		     FXFALSE); +    else +      grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		     GR_COMBINE_FACTOR_ONE, +		     locala, +		     GR_COMBINE_OTHER_NONE, +		     FXFALSE); + + +    grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, +		   GR_COMBINE_FACTOR_ONE, +		   localc, +		   GR_COMBINE_OTHER_TEXTURE, +		   FXFALSE); +    break; +  } + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) End\n"); +  } +} + +/************************* No Texture ***************************/ + +static void fxSetupTextureNone(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GrCombineLocal_t localc,locala; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxSetupTextureNone(...)\n"); +  } + +  if((ctx->Light.ShadeModel==GL_SMOOTH) || +     (ctx->Point.SmoothFlag) || +     (ctx->Line.SmoothFlag) || +     (ctx->Polygon.SmoothFlag)) +    locala=GR_COMBINE_LOCAL_ITERATED; +  else +    locala=GR_COMBINE_LOCAL_CONSTANT; +   +  if(ctx->Light.ShadeModel==GL_SMOOTH) +    localc=GR_COMBINE_LOCAL_ITERATED; +  else +    localc=GR_COMBINE_LOCAL_CONSTANT; +   +  grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, +		 GR_COMBINE_FACTOR_NONE, +		 locala, +		 GR_COMBINE_OTHER_NONE, +		 FXFALSE); + +  grColorCombine(GR_COMBINE_FUNCTION_LOCAL, +		 GR_COMBINE_FACTOR_NONE, +		 localc, +		 GR_COMBINE_OTHER_NONE, +		 FXFALSE); + +  fxMesa->lastUnitsMode=FX_UM_NONE; +} + +/* See below. + */ +static GLboolean fxMultipassTexture( struct vertex_buffer *, GLuint ); + + + +/************************************************************************/ +/************************** Texture Mode SetUp **************************/ +/************************************************************************/ + +void fxSetupTexture(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint tex2Denabled; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxSetupTexture(...)\n"); +  } + +  /* Disable multipass texturing. +   */ +  ctx->Driver.MultipassFunc = 0; + +  /* Texture Combine, Color Combine and Alpha Combine. +   */   +  tex2Denabled = (ctx->Texture.ReallyEnabled & TEXTURE0_2D); + +  if (fxMesa->emulateTwoTMUs) +     tex2Denabled |= (ctx->Texture.ReallyEnabled & TEXTURE1_2D); +   +  switch(tex2Denabled) { +  case TEXTURE0_2D: +    fxSetupTextureSingleTMU(ctx,0);     +    break; +  case TEXTURE1_2D: +    fxSetupTextureSingleTMU(ctx,1); +    break; +  case (TEXTURE0_2D|TEXTURE1_2D): +     if (fxMesa->haveTwoTMUs) +	fxSetupTextureDoubleTMU(ctx); +     else { +	if (MESA_VERBOSE&VERBOSE_DRIVER) +	   fprintf(stderr, "fxmesa: enabling fake multitexture\n"); + +	fxSetupTextureSingleTMU(ctx,0); +	ctx->Driver.MultipassFunc = fxMultipassTexture; +     } +    break; +  default: +    fxSetupTextureNone(ctx); +    break; +  } +} + +/************************************************************************/ +/**************************** Blend SetUp *******************************/ +/************************************************************************/ + +/* XXX consider supporting GL_INGR_blend_func_separate */ +void fxDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; +  GrAlphaBlendFnc_t sfact,dfact,asfact,adfact; + +  /* From the Glide documentation: +     For alpha source and destination blend function factor +     parameters, Voodoo Graphics supports only +     GR_BLEND_ZERO and GR_BLEND_ONE. +  */ + +  switch(sfactor) { +  case GL_ZERO: +    asfact=sfact=GR_BLEND_ZERO; +    break; +  case GL_ONE: +    asfact=sfact=GR_BLEND_ONE; +    break; +  case GL_DST_COLOR: +    sfact=GR_BLEND_DST_COLOR; +    asfact=GR_BLEND_ONE; +    break; +  case GL_ONE_MINUS_DST_COLOR: +    sfact=GR_BLEND_ONE_MINUS_DST_COLOR; +    asfact=GR_BLEND_ONE; +    break; +  case GL_SRC_ALPHA: +    sfact=GR_BLEND_SRC_ALPHA; +    asfact=GR_BLEND_ONE; +    break; +  case GL_ONE_MINUS_SRC_ALPHA: +    sfact=GR_BLEND_ONE_MINUS_SRC_ALPHA; +    asfact=GR_BLEND_ONE; +    break; +  case GL_DST_ALPHA: +    sfact=GR_BLEND_DST_ALPHA; +    asfact=GR_BLEND_ONE; +    break; +  case GL_ONE_MINUS_DST_ALPHA: +    sfact=GR_BLEND_ONE_MINUS_DST_ALPHA; +    asfact=GR_BLEND_ONE; +    break; +  case GL_SRC_ALPHA_SATURATE: +    sfact=GR_BLEND_ALPHA_SATURATE; +    asfact=GR_BLEND_ONE; +    break; +  case GL_SRC_COLOR: +  case GL_ONE_MINUS_SRC_COLOR: +    /* USELESS */ +    asfact=sfact=GR_BLEND_ONE; +    break; +  default: +    asfact=sfact=GR_BLEND_ONE; +    break; +  } + +  if((sfact!=us->blendSrcFuncRGB) || +     (asfact!=us->blendSrcFuncAlpha)) { +    us->blendSrcFuncRGB=sfact; +    us->blendSrcFuncAlpha=asfact; +    fxMesa->new_state |= FX_NEW_BLEND; +    ctx->Driver.RenderStart = fxSetupFXUnits; +  } + +  switch(dfactor) { +  case GL_ZERO: +    adfact=dfact=GR_BLEND_ZERO; +    break; +  case GL_ONE: +    adfact=dfact=GR_BLEND_ONE; +    break; +  case GL_SRC_COLOR: +    dfact=GR_BLEND_SRC_COLOR; +    adfact=GR_BLEND_ZERO; +    break; +  case GL_ONE_MINUS_SRC_COLOR: +    dfact=GR_BLEND_ONE_MINUS_SRC_COLOR; +    adfact=GR_BLEND_ZERO; +    break; +  case GL_SRC_ALPHA: +    dfact=GR_BLEND_SRC_ALPHA; +    adfact=GR_BLEND_ZERO; +    break; +  case GL_ONE_MINUS_SRC_ALPHA: +    dfact=GR_BLEND_ONE_MINUS_SRC_ALPHA; +    adfact=GR_BLEND_ZERO; +    break; +  case GL_DST_ALPHA: +    dfact=GR_BLEND_DST_ALPHA; +    adfact=GR_BLEND_ZERO; +    break; +  case GL_ONE_MINUS_DST_ALPHA: +    dfact=GR_BLEND_ONE_MINUS_DST_ALPHA; +    adfact=GR_BLEND_ZERO; +    break; +  case GL_SRC_ALPHA_SATURATE: +  case GL_DST_COLOR: +  case GL_ONE_MINUS_DST_COLOR: +    /* USELESS */ +    adfact=dfact=GR_BLEND_ZERO; +    break; +  default: +    adfact=dfact=GR_BLEND_ZERO; +    break; +  } + +  if((dfact!=us->blendDstFuncRGB) || +     (adfact!=us->blendDstFuncAlpha)) { +    us->blendDstFuncRGB=dfact; +    us->blendDstFuncAlpha=adfact; +    fxMesa->new_state |= FX_NEW_BLEND; +    ctx->Driver.RenderStart = fxSetupFXUnits; +  } +} + +void fxSetupBlend(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; + +  if(us->blendEnabled) +     grAlphaBlendFunction(us->blendSrcFuncRGB,us->blendDstFuncRGB, +			  us->blendSrcFuncAlpha,us->blendDstFuncAlpha); +  else +     grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO); +} +   +/************************************************************************/ +/************************** Alpha Test SetUp ****************************/ +/************************************************************************/ + +void fxDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; +  GrCmpFnc_t newfunc; + +  switch(func) { +  case GL_NEVER: +    newfunc=GR_CMP_NEVER; +    break; +  case GL_LESS: +    newfunc=GR_CMP_LESS; +    break; +  case GL_EQUAL: +    newfunc=GR_CMP_EQUAL; +    break; +  case GL_LEQUAL: +    newfunc=GR_CMP_LEQUAL; +    break; +  case GL_GREATER: +    newfunc=GR_CMP_GREATER; +    break; +  case GL_NOTEQUAL: +    newfunc=GR_CMP_NOTEQUAL; +    break; +  case GL_GEQUAL: +    newfunc=GR_CMP_GEQUAL; +    break; +  case GL_ALWAYS: +    newfunc=GR_CMP_ALWAYS; +    break; +  default: +    fprintf(stderr,"fx Driver: internal error in fxDDAlphaFunc()\n"); +    fxCloseHardware(); +    exit(-1); +    break; +  } + +  if(newfunc!=us->alphaTestFunc) { +    us->alphaTestFunc=newfunc; +    fxMesa->new_state |= FX_NEW_ALPHA; +    ctx->Driver.RenderStart = fxSetupFXUnits; +  } + +  if(ctx->Color.AlphaRef!=us->alphaTestRefValue) { +    us->alphaTestRefValue=ctx->Color.AlphaRef; +    fxMesa->new_state |= FX_NEW_ALPHA; +    ctx->Driver.RenderStart = fxSetupFXUnits; +  } +} + +static void fxSetupAlphaTest(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; + +  if(us->alphaTestEnabled) { +     grAlphaTestFunction(us->alphaTestFunc); +     grAlphaTestReferenceValue(us->alphaTestRefValue); +  } else +     grAlphaTestFunction(GR_CMP_ALWAYS); +} + +/************************************************************************/ +/************************** Depth Test SetUp ****************************/ +/************************************************************************/ + +void fxDDDepthFunc(GLcontext *ctx, GLenum func) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; +  GrCmpFnc_t dfunc; + +  switch(func) { +  case GL_NEVER: +    dfunc=GR_CMP_NEVER; +    break; +  case GL_LESS: +    dfunc=GR_CMP_LESS; +    break; +  case GL_GEQUAL: +    dfunc=GR_CMP_GEQUAL; +    break; +  case GL_LEQUAL: +    dfunc=GR_CMP_LEQUAL; +    break; +  case GL_GREATER: +    dfunc=GR_CMP_GREATER; +    break; +  case GL_NOTEQUAL: +    dfunc=GR_CMP_NOTEQUAL; +    break; +  case GL_EQUAL: +    dfunc=GR_CMP_EQUAL; +    break; +  case GL_ALWAYS: +    dfunc=GR_CMP_ALWAYS; +    break; +  default: +    fprintf(stderr,"fx Driver: internal error in fxDDDepthFunc()\n"); +    fxCloseHardware(); +    exit(-1); +    break; +  } + +  if(dfunc!=us->depthTestFunc) { +    us->depthTestFunc=dfunc; +    fxMesa->new_state |= FX_NEW_DEPTH; +    ctx->Driver.RenderStart = fxSetupFXUnits; +  } + +} + +void fxDDDepthMask(GLcontext *ctx, GLboolean flag) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; + +  if(flag!=us->depthMask) { +    us->depthMask=flag; +    fxMesa->new_state |= FX_NEW_DEPTH; +    ctx->Driver.RenderStart = fxSetupFXUnits; +  } +} + +void fxSetupDepthTest(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; + +  if(us->depthTestEnabled) +     grDepthBufferFunction(us->depthTestFunc); +  else +     grDepthBufferFunction(GR_CMP_ALWAYS); + +  grDepthMask(us->depthMask); +} + +/************************************************************************/ +/**************************** Color Mask SetUp **************************/ +/************************************************************************/ + +GLboolean fxDDColorMask(GLcontext *ctx,  +			GLboolean r, GLboolean g,  +			GLboolean b, GLboolean a ) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  fxMesa->new_state |= FX_NEW_COLOR_MASK; +  ctx->Driver.RenderStart = fxSetupFXUnits; +  (void) r; (void) g; (void) b; (void) a; +  return 1; +} + +static void fxSetupColorMask(GLcontext *ctx) +{ +  fxMesaContext fxMesa = FX_CONTEXT(ctx); + +  grColorMask(ctx->Color.ColorMask[RCOMP] || +	      ctx->Color.ColorMask[GCOMP] || +	      ctx->Color.ColorMask[BCOMP], +	      ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); +} + + + +/************************************************************************/ +/**************************** Fog Mode SetUp ****************************/ +/************************************************************************/ + +void fxFogTableGenerate(GLcontext *ctx) +{ +  int i; +  float f,eyez; +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +  for(i=0;i<FX_grGetInteger(FX_FOG_TABLE_ENTRIES);i++) { +    eyez=guFogTableIndexToW(i); + +    switch(ctx->Fog.Mode) { +    case GL_LINEAR: +      f=(ctx->Fog.End-eyez)/(ctx->Fog.End-ctx->Fog.Start); +      break; +    case GL_EXP: +      f=exp(-ctx->Fog.Density*eyez);   +      break; +    case GL_EXP2: +      f=exp(-ctx->Fog.Density*ctx->Fog.Density*eyez*eyez); +      break; +    default: /* That should never happen */ +      f=0.0f; +      break;  +    } + +    fxMesa->fogTable[i]=(GrFog_t)((1.0f-CLAMP(f,0.0f,1.0f))*255.0f); +  } +} + +void fxSetupFog(GLcontext *ctx, GLboolean forceTableRebuild) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +  if(ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) { +    GLubyte col[4]; +    grFogMode(GR_FOG_WITH_TABLE); + +    col[0]=(unsigned int)(255*ctx->Fog.Color[0]); +    col[1]=(unsigned int)(255*ctx->Fog.Color[1]); +    col[2]=(unsigned int)(255*ctx->Fog.Color[2]);  +    col[3]=(unsigned int)(255*ctx->Fog.Color[3]); + +    grFogColorValue(FXCOLOR4(col)); + +    if(forceTableRebuild || +       (fxMesa->fogTableMode!=ctx->Fog.Mode) || +       (fxMesa->fogDensity!=ctx->Fog.Density)) { +      fxFogTableGenerate(ctx); +          +      fxMesa->fogTableMode=ctx->Fog.Mode; +      fxMesa->fogDensity=ctx->Fog.Density; +    } +       +    grFogTable(fxMesa->fogTable); +  } else +    grFogMode(GR_FOG_DISABLE); +} + +void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params ) +{ +   FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG; +   ctx->Driver.RenderStart = fxSetupFXUnits; +} + +/************************************************************************/ +/************************** Scissor Test SetUp **************************/ +/************************************************************************/ + +static void fxSetupScissor(GLcontext *ctx) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + +  if (ctx->Scissor.Enabled) { +    int ymin, ymax; + +    ymin=ctx->Scissor.Y; +    ymax=ctx->Scissor.Y+ctx->Scissor.Height; + +    if (ymin<0) ymin=0; + +    if (ymax>fxMesa->height) ymax=fxMesa->height; + +    grClipWindow(ctx->Scissor.X,  + 		 ymin, + 		 ctx->Scissor.X+ctx->Scissor.Width,  + 		 ymax); +  } else +    grClipWindow(0,0,fxMesa->width,fxMesa->height); +} + +void fxDDScissor( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h ) +{ +   FX_CONTEXT(ctx)->new_state |= FX_NEW_SCISSOR; +   ctx->Driver.RenderStart = fxSetupFXUnits; +} + +/************************************************************************/ +/*************************** Cull mode setup ****************************/ +/************************************************************************/ + + +void fxDDCullFace(GLcontext *ctx, GLenum mode) +{ +   (void) mode; +   FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL; +   ctx->Driver.RenderStart = fxSetupFXUnits;    +} + +void fxDDFrontFace(GLcontext *ctx, GLenum mode) +{ +   (void) mode; +   FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL; +   ctx->Driver.RenderStart = fxSetupFXUnits;    +} + + +void fxSetupCull(GLcontext *ctx) +{ +   if(ctx->Polygon.CullFlag) { +      switch(ctx->Polygon.CullFaceMode) { +      case GL_BACK: +	 if(ctx->Polygon.FrontFace==GL_CCW) +	    grCullMode(GR_CULL_NEGATIVE); +	 else +	    grCullMode(GR_CULL_POSITIVE); +	 break; +      case GL_FRONT: +	 if(ctx->Polygon.FrontFace==GL_CCW) +	    grCullMode(GR_CULL_POSITIVE); +	 else +	    grCullMode(GR_CULL_NEGATIVE); +	 break; +      case GL_FRONT_AND_BACK: +	 grCullMode(GR_CULL_DISABLE); +	 break; +      default: +	 break; +      } +   } else +      grCullMode(GR_CULL_DISABLE); +} + + +/************************************************************************/ +/****************************** DD Enable ******************************/ +/************************************************************************/ + +void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  tfxUnitsState *us=&fxMesa->unitsState; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxDDEnable(...)\n"); +  } + +  switch(cap) { +  case GL_ALPHA_TEST: +    if(state!=us->alphaTestEnabled) { +      us->alphaTestEnabled=state; +      fxMesa->new_state |= FX_NEW_ALPHA; +      ctx->Driver.RenderStart = fxSetupFXUnits; +    } +    break; +  case GL_BLEND: +    if(state!=us->blendEnabled) { +      us->blendEnabled=state; +      fxMesa->new_state |= FX_NEW_BLEND; +      ctx->Driver.RenderStart = fxSetupFXUnits; +    } +    break; +  case GL_DEPTH_TEST: +    if(state!=us->depthTestEnabled) { +      us->depthTestEnabled=state; +      fxMesa->new_state |= FX_NEW_DEPTH; +      ctx->Driver.RenderStart = fxSetupFXUnits; +    } +    break; +  case GL_SCISSOR_TEST: +     fxMesa->new_state |= FX_NEW_SCISSOR; +     ctx->Driver.RenderStart = fxSetupFXUnits; +     break; +  case GL_FOG: +     fxMesa->new_state |= FX_NEW_FOG; +     ctx->Driver.RenderStart = fxSetupFXUnits; +     break; +  case GL_CULL_FACE: +     fxMesa->new_state |= FX_NEW_CULL; +     ctx->Driver.RenderStart = fxSetupFXUnits; +     break; +  case GL_LINE_SMOOTH: +  case GL_POINT_SMOOTH: +  case GL_POLYGON_SMOOTH: +  case GL_TEXTURE_2D: +      fxMesa->new_state |= FX_NEW_TEXTURING; +      ctx->Driver.RenderStart = fxSetupFXUnits; +      break; +  default: +    ;  /* XXX no-op??? */ +  }     +} + +/************************************************************************/ +/******************** Fake Multitexture Support *************************/ +/************************************************************************/ + +/* Its considered cheeky to try to fake ARB multitexture by doing + * multipass rendering, because it is not possible to emulate the full + * spec in this way.  The fact is that the voodoo 2 supports only a + * subset of the possible multitexturing modes, and it is possible to + * support almost the same subset using multipass blending on the + * voodoo 1.  In all other cases for both voodoo 1 and 2, we fall back + * to software rendering, satisfying the spec if not the user.   + */ +static GLboolean fxMultipassTexture( struct vertex_buffer *VB, GLuint pass ) +{ +   GLcontext *ctx = VB->ctx; +   fxVertex *v = FX_DRIVER_DATA(VB)->verts; +   fxVertex *last = FX_DRIVER_DATA(VB)->last_vert; +   fxMesaContext fxMesa = FX_CONTEXT(ctx); + +   switch (pass) { +   case 1: +      if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_PIPELINE|VERBOSE_TEXTURE)) +	 fprintf(stderr, "fxmesa: Second texture pass\n"); + +      for ( ; v != last ; v++) { +	 v->f[S0COORD] = v->f[S1COORD]; +	 v->f[T0COORD] = v->f[T1COORD]; +      } + +      fxMesa->restoreUnitsState = fxMesa->unitsState;  +      fxMesa->tmu_source[0] = 1; + +      if (ctx->Depth.Mask) { +	 switch (ctx->Depth.Func) { +	 case GL_NEVER: +	 case GL_ALWAYS: +	    break; +	 default: +	    fxDDDepthFunc( ctx, GL_EQUAL ); +	    break; +	 } + +	 fxDDDepthMask( ctx, GL_FALSE );  +      } +       +      if (ctx->Texture.Unit[1].EnvMode == GL_MODULATE) { +	 fxDDEnable( ctx, GL_BLEND, GL_TRUE ); +	 fxDDBlendFunc( ctx, GL_DST_COLOR, GL_ZERO ); +      } + +      fxSetupTextureSingleTMU( ctx, 1 );  +      fxSetupBlend( ctx ); +      fxSetupDepthTest( ctx ); +      break; + +   case 2: +      /* Restore original state.   +       */ +      fxMesa->tmu_source[0] = 0; +      fxMesa->unitsState = fxMesa->restoreUnitsState; +      fxMesa->setupdone &= ~SETUP_TMU0; +      fxSetupTextureSingleTMU( ctx, 0 );  +      fxSetupBlend( ctx ); +      fxSetupDepthTest( ctx ); +      break; +   } + +   return pass == 1;       +} + + +/************************************************************************/ +/************************** Changes to units state **********************/ +/************************************************************************/ + + +/* All units setup is handled under texture setup. + */ +void fxDDShadeModel(GLcontext *ctx, GLenum mode) +{ +   FX_CONTEXT(ctx)->new_state |= FX_NEW_TEXTURING; +   ctx->Driver.RenderStart = fxSetupFXUnits; +} + + + +/************************************************************************/ +/****************************** Units SetUp *****************************/ +/************************************************************************/ +void gl_print_fx_state_flags( const char *msg, GLuint flags ) +{ +   fprintf(stderr,  +	   "%s: (0x%x) %s%s%s%s%s%s%s\n", +	   msg, +	   flags, +	   (flags & FX_NEW_TEXTURING)   ? "texture, " : "", +	   (flags & FX_NEW_BLEND)       ? "blend, " : "", +	   (flags & FX_NEW_ALPHA)       ? "alpha, " : "", +	   (flags & FX_NEW_FOG)         ? "fog, " : "", +	   (flags & FX_NEW_SCISSOR)     ? "scissor, " : "", +	   (flags & FX_NEW_COLOR_MASK)  ? "colormask, " : "", +	   (flags & FX_NEW_CULL)        ? "cull, " : ""); +} + +void fxSetupFXUnits( GLcontext *ctx ) +{ +  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; +  GLuint newstate = fxMesa->new_state; + +  if (MESA_VERBOSE&VERBOSE_DRIVER)  +     gl_print_fx_state_flags("fxmesa: fxSetupFXUnits", newstate); + +  if (newstate) { +     if (newstate & FX_NEW_TEXTURING) +	fxSetupTexture(ctx); + +     if (newstate & FX_NEW_BLEND) +	fxSetupBlend(ctx); + +     if (newstate & FX_NEW_ALPHA) +	fxSetupAlphaTest(ctx); +      +     if (newstate & FX_NEW_DEPTH) +	fxSetupDepthTest(ctx); + +     if (newstate & FX_NEW_FOG) +	fxSetupFog(ctx,GL_FALSE); + +     if (newstate & FX_NEW_SCISSOR) +	fxSetupScissor(ctx); + +     if (newstate & FX_NEW_COLOR_MASK) +	fxSetupColorMask(ctx); + +     if (newstate & FX_NEW_CULL) +	fxSetupCull(ctx);      + +     fxMesa->new_state = 0; +     ctx->Driver.RenderStart = 0; +  } +} + + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_setup(void) +{ +  return 0; +} + +#endif  /* FX */ diff --git a/src/mesa/drivers/glide/fxtexman.c b/src/mesa/drivers/glide/fxtexman.c new file mode 100644 index 0000000000..5ee145e3cb --- /dev/null +++ b/src/mesa/drivers/glide/fxtexman.c @@ -0,0 +1,579 @@ +/* -*- mode: C; tab-width:8;  -*- + +             fxtexman.c - 3Dfx VooDoo texture memory functions +*/ + +/* + * 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. + * + * See the file fxapi.c for more informations about authors + * + */ + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" + +static tfxTMFreeNode *fxTMNewTMFreeNode(FxU32 start, FxU32 end) +{ +  tfxTMFreeNode *tmn; + +  if(!(tmn=malloc(sizeof(tfxTMFreeNode)))) { +    fprintf(stderr,"fx Driver: out of memory !\n"); +    fxCloseHardware(); +    exit(-1); +  } + +  tmn->next=NULL; +  tmn->startAddress=start; +  tmn->endAddress=end; + +  return tmn; +} + +static void fxTMUInit(fxMesaContext fxMesa, int tmu) +{ +  tfxTMFreeNode *tmn,*tmntmp; +  FxU32 start,end,blockstart,blockend; + +  start=grTexMinAddress(tmu); +  end=grTexMaxAddress(tmu); + +  if(fxMesa->verbose) { +    fprintf(stderr,"%s configuration:",(tmu==FX_TMU0) ? "TMU0" : "TMU1"); +    fprintf(stderr,"  Lower texture memory address (%u)\n",(unsigned int)start); +    fprintf(stderr,"  Higher texture memory address (%u)\n",(unsigned int)end); +    fprintf(stderr,"  Splitting Texture memory in 2Mb blocks:\n"); +  } + +  fxMesa->freeTexMem[tmu]=end-start; +  fxMesa->tmFree[tmu]=NULL; +  fxMesa->tmAlloc[tmu]=NULL; + +  blockstart=start; +  while(blockstart<=end) { +    if(blockstart+0x1fffff>end) +      blockend=end; +    else +      blockend=blockstart+0x1fffff; + +    if(fxMesa->verbose) +      fprintf(stderr,"    %07u-%07u\n",(unsigned int)blockstart,(unsigned int)blockend); + +    tmn=fxTMNewTMFreeNode(blockstart,blockend); + +    if(fxMesa->tmFree[tmu]) { +      for(tmntmp=fxMesa->tmFree[tmu];tmntmp->next!=NULL;tmntmp=tmntmp->next){}; +      tmntmp->next=tmn; +    } else +      fxMesa->tmFree[tmu]=tmn; + +    blockstart+=0x1fffff+1; +  } +} + +void fxTMInit(fxMesaContext fxMesa) +{ +  fxTMUInit(fxMesa,FX_TMU0); + +  if(fxMesa->haveTwoTMUs) +    fxTMUInit(fxMesa,FX_TMU1); + +  fxMesa->texBindNumber=0; +} + +static struct gl_texture_object *fxTMFindOldestTMBlock(fxMesaContext fxMesa, +						       tfxTMAllocNode *tmalloc, +						       GLuint texbindnumber) +{ +  GLuint age,oldestage,lasttimeused; +  struct gl_texture_object *oldesttexobj; + +  (void)fxMesa; +  oldesttexobj=tmalloc->tObj; +  oldestage=0; + +  while(tmalloc) { +    lasttimeused=((tfxTexInfo *)(tmalloc->tObj->DriverData))->tmi.lastTimeUsed; + +    if(lasttimeused>texbindnumber) +      age=texbindnumber+(UINT_MAX-lasttimeused+1); /* TO DO: check */ +    else +      age=texbindnumber-lasttimeused; + +    if(age>=oldestage) { +      oldestage=age; +      oldesttexobj=tmalloc->tObj; +    } + +    tmalloc=tmalloc->next; +  } + +  return oldesttexobj; +} + +static GLboolean fxTMFreeOldTMBlock(fxMesaContext fxMesa, GLint tmu) +{ +  struct gl_texture_object *oldesttexobj; + +  if(!fxMesa->tmAlloc[tmu]) +    return GL_FALSE; + +  oldesttexobj=fxTMFindOldestTMBlock(fxMesa,fxMesa->tmAlloc[tmu],fxMesa->texBindNumber); + +  fxTMMoveOutTM(fxMesa,oldesttexobj); + +  return GL_TRUE; +} + +static tfxTMFreeNode *fxTMExtractTMFreeBlock(tfxTMFreeNode *tmfree, int texmemsize, +					     GLboolean *success, FxU32 *startadr) +{ +  int blocksize; + +  /* TO DO: cut recursion */ + +  if(!tmfree) { +    *success=GL_FALSE; +    return NULL; +  } + +  blocksize=(int)tmfree->endAddress-(int)tmfree->startAddress+1; + +  if(blocksize==texmemsize) { +    tfxTMFreeNode *nexttmfree; + +    *success=GL_TRUE; +    *startadr=tmfree->startAddress; + +    nexttmfree=tmfree->next; +    free(tmfree); + +    return nexttmfree; +  } + +  if(blocksize>texmemsize) { +    *success=GL_TRUE; +    *startadr=tmfree->startAddress; + +    tmfree->startAddress+=texmemsize; + +    return tmfree; +  } + +  tmfree->next=fxTMExtractTMFreeBlock(tmfree->next,texmemsize,success,startadr); + +  return tmfree; +} + +static tfxTMAllocNode *fxTMGetTMBlock(fxMesaContext fxMesa, struct gl_texture_object *tObj, +				      GLint tmu, int texmemsize) +{ +  tfxTMFreeNode *newtmfree; +  tfxTMAllocNode *newtmalloc; +  GLboolean success; +  FxU32 startadr; + +  for(;;) { /* TO DO: improve performaces */ +    newtmfree=fxTMExtractTMFreeBlock(fxMesa->tmFree[tmu],texmemsize,&success,&startadr); + +    if(success) { +      fxMesa->tmFree[tmu]=newtmfree; + +      fxMesa->freeTexMem[tmu]-=texmemsize; + +      if(!(newtmalloc=malloc(sizeof(tfxTMAllocNode)))) { +	fprintf(stderr,"fx Driver: out of memory !\n"); +	fxCloseHardware(); +	exit(-1); +      } +       +      newtmalloc->next=fxMesa->tmAlloc[tmu]; +      newtmalloc->startAddress=startadr; +      newtmalloc->endAddress=startadr+texmemsize-1; +      newtmalloc->tObj=tObj; + +      fxMesa->tmAlloc[tmu]=newtmalloc; + +      return newtmalloc; +    } + +    if(!fxTMFreeOldTMBlock(fxMesa,tmu)) { +      fprintf(stderr,"fx Driver: internal error in fxTMGetTMBlock()\n"); +      fprintf(stderr,"           TMU: %d Size: %d\n",tmu,texmemsize); +     +      fxCloseHardware(); +      exit(-1); +    } +  } +} + +void fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint where) +{ +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; +  int i,l; +  int texmemsize; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxTMMoveInTM(%d)\n",tObj->Name); +  } + +  fxMesa->stats.reqTexUpload++; + +  if(!ti->validated) { +    fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> not validated\n"); +    fxCloseHardware(); +    exit(-1); +  } + +  if(ti->tmi.isInTM) +    return; + +  if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_TEXTURE)) { +     fprintf(stderr,"fxmesa: downloading %x (%d) in texture memory in %d\n",(GLuint)tObj,tObj->Name,where); +  } + +  ti->tmi.whichTMU=(FxU32)where; + +  switch(where) { +  case FX_TMU0: +  case FX_TMU1: +    texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info)); +    ti->tmi.tm[where]=fxTMGetTMBlock(fxMesa,tObj,where,texmemsize); +    fxMesa->stats.memTexUpload+=texmemsize; + +    for(i=FX_largeLodValue(ti->info),l=ti->minLevel;i<=FX_smallLodValue(ti->info);i++,l++) +      grTexDownloadMipMapLevel(where, +			       ti->tmi.tm[where]->startAddress,FX_valueToLod(i), +			       FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +			       ti->info.format,GR_MIPMAPLEVELMASK_BOTH, +			       ti->tmi.mipmapLevel[l].data); +    break; +  case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */ +    texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD,&(ti->info)); +    ti->tmi.tm[FX_TMU0]=fxTMGetTMBlock(fxMesa,tObj,FX_TMU0,texmemsize); +    fxMesa->stats.memTexUpload+=texmemsize; + +    texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN,&(ti->info)); +    ti->tmi.tm[FX_TMU1]=fxTMGetTMBlock(fxMesa,tObj,FX_TMU1,texmemsize); +    fxMesa->stats.memTexUpload+=texmemsize; + +    for(i=FX_largeLodValue(ti->info),l=ti->minLevel;i<=FX_smallLodValue(ti->info);i++,l++) { +      grTexDownloadMipMapLevel(GR_TMU0,ti->tmi.tm[FX_TMU0]->startAddress,FX_valueToLod(i), +			       FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +			       ti->info.format,GR_MIPMAPLEVELMASK_ODD, +			       ti->tmi.mipmapLevel[l].data); + +      grTexDownloadMipMapLevel(GR_TMU1,ti->tmi.tm[FX_TMU1]->startAddress,FX_valueToLod(i), +			       FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +			       ti->info.format,GR_MIPMAPLEVELMASK_EVEN, +			       ti->tmi.mipmapLevel[l].data); +    } +    break; +  default: +    fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",where); +    fxCloseHardware(); +    exit(-1); +  } + +  fxMesa->stats.texUpload++; + +  ti->tmi.isInTM=GL_TRUE; +} + +void fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint level) +{ +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; +  GrLOD_t lodlevel; +  GLint tmu; + +  if(!ti->validated) { +    fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> not validated\n"); +    fxCloseHardware(); +    exit(-1); +  } + +  tmu=(int)ti->tmi.whichTMU; +  fxTMMoveInTM(fxMesa,tObj,tmu); + +  fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height, +	       &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + +  switch(tmu) { +  case FX_TMU0: +  case FX_TMU1: +    grTexDownloadMipMapLevel(tmu, +			     ti->tmi.tm[tmu]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level), +			     FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +			     ti->info.format,GR_MIPMAPLEVELMASK_BOTH, +			     ti->tmi.mipmapLevel[level].data); +    break; +  case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */ +    grTexDownloadMipMapLevel(GR_TMU0, +			     ti->tmi.tm[GR_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level), +			     FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +			     ti->info.format,GR_MIPMAPLEVELMASK_ODD, +			     ti->tmi.mipmapLevel[level].data); +     +    grTexDownloadMipMapLevel(GR_TMU1, +			     ti->tmi.tm[GR_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level), +			     FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +			     ti->info.format,GR_MIPMAPLEVELMASK_EVEN, +			     ti->tmi.mipmapLevel[level].data); +    break; +  default: +    fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",tmu); +    fxCloseHardware(); +    exit(-1); +  } +} + +void fxTMReloadSubMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, +			      GLint level, GLint yoffset, GLint height) +{ +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; +  GrLOD_t lodlevel; +  unsigned short *data; +  GLint tmu; + +  if(!ti->validated) { +    fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> not validated\n"); +    fxCloseHardware(); +    exit(-1); +  } + +  tmu=(int)ti->tmi.whichTMU; +  fxTMMoveInTM(fxMesa,tObj,tmu); + +  fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height, +	       &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + +  if((ti->info.format==GR_TEXFMT_INTENSITY_8) || +     (ti->info.format==GR_TEXFMT_P_8) || +     (ti->info.format==GR_TEXFMT_ALPHA_8)) +    data=ti->tmi.mipmapLevel[level].data+((yoffset*ti->tmi.mipmapLevel[level].width)>>1); +  else +    data=ti->tmi.mipmapLevel[level].data+yoffset*ti->tmi.mipmapLevel[level].width; + +  switch(tmu) { +  case FX_TMU0: +  case FX_TMU1: +    grTexDownloadMipMapLevelPartial(tmu, +				    ti->tmi.tm[tmu]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level), +				    FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +				    ti->info.format,GR_MIPMAPLEVELMASK_BOTH, +				    data, +				    yoffset,yoffset+height-1); +    break; +  case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */ +    grTexDownloadMipMapLevelPartial(GR_TMU0, +				    ti->tmi.tm[FX_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level), +				    FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +				    ti->info.format,GR_MIPMAPLEVELMASK_ODD, +				    data, +				    yoffset,yoffset+height-1); + +    grTexDownloadMipMapLevelPartial(GR_TMU1, +				    ti->tmi.tm[FX_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level), +				    FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info), +				    ti->info.format,GR_MIPMAPLEVELMASK_EVEN, +				    data, +				    yoffset,yoffset+height-1); +    break; +  default: +    fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",tmu); +    fxCloseHardware(); +    exit(-1); +  } +} + +static tfxTMAllocNode *fxTMFreeTMAllocBlock(tfxTMAllocNode *tmalloc, +					    tfxTMAllocNode *tmunalloc) +{ +  if(!tmalloc) +    return NULL; + +  if(tmalloc==tmunalloc) { +    tfxTMAllocNode *newtmalloc; + +    newtmalloc=tmalloc->next; +    free(tmalloc); + +    return newtmalloc; +  } + +  tmalloc->next=fxTMFreeTMAllocBlock(tmalloc->next,tmunalloc); + +  return tmalloc; +} + +static tfxTMFreeNode *fxTMAddTMFree(tfxTMFreeNode *tmfree, FxU32 startadr, FxU32 endadr) +{ +  if(!tmfree) +    return fxTMNewTMFreeNode(startadr,endadr); + +  if((endadr+1==tmfree->startAddress) && (tmfree->startAddress & 0x1fffff)) { +    tmfree->startAddress=startadr; + +    return tmfree; +  } + +  if((startadr-1==tmfree->endAddress) && (startadr & 0x1fffff)) { +    tmfree->endAddress=endadr; + +    if((tmfree->next && (endadr+1==tmfree->next->startAddress) && +        (tmfree->next->startAddress & 0x1fffff))) { +      tfxTMFreeNode *nexttmfree; + +      tmfree->endAddress=tmfree->next->endAddress; + +      nexttmfree=tmfree->next->next; +      free(tmfree->next); + +      tmfree->next=nexttmfree; +    } + + +    return tmfree; +  } + +  if(startadr<tmfree->startAddress) { +    tfxTMFreeNode *newtmfree; + +    newtmfree=fxTMNewTMFreeNode(startadr,endadr); +    newtmfree->next=tmfree; + +    return newtmfree; +  } + +  tmfree->next=fxTMAddTMFree(tmfree->next,startadr,endadr); + +  return tmfree; +} + +static void fxTMFreeTMBlock(fxMesaContext fxMesa, GLint tmu, tfxTMAllocNode *tmalloc) +{ +  FxU32 startadr,endadr; + +  startadr=tmalloc->startAddress; +  endadr=tmalloc->endAddress; + +  fxMesa->tmAlloc[tmu]=fxTMFreeTMAllocBlock(fxMesa->tmAlloc[tmu],tmalloc); + +  fxMesa->tmFree[tmu]=fxTMAddTMFree(fxMesa->tmFree[tmu],startadr,endadr); + +  fxMesa->freeTexMem[tmu]+=endadr-startadr+1; +} + +void fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj) +{ +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; + +  if (MESA_VERBOSE&VERBOSE_DRIVER) { +     fprintf(stderr,"fxmesa: fxTMMoveOutTM(%x (%d))\n",(GLuint)tObj,tObj->Name); +  } + +  if(!ti->tmi.isInTM) +    return; + +  switch(ti->tmi.whichTMU) { +  case FX_TMU0: +  case FX_TMU1: +    fxTMFreeTMBlock(fxMesa,(int)ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]); +    break; +  case FX_TMU_SPLIT: +    fxTMFreeTMBlock(fxMesa,FX_TMU0,ti->tmi.tm[FX_TMU0]); +    fxTMFreeTMBlock(fxMesa,FX_TMU1,ti->tmi.tm[FX_TMU1]); +    break; +  default: +    fprintf(stderr,"fx Driver: internal error in fxTMMoveOutTM()\n"); +    fxCloseHardware(); +    exit(-1); +  } + +  ti->tmi.whichTMU=FX_TMU_NONE; +  ti->tmi.isInTM=GL_FALSE; +} + +void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj) +{ +  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; +  int i; + +  fxTMMoveOutTM(fxMesa,tObj); + +  for(i=0;i<MAX_TEXTURE_LEVELS;i++) { +    if(ti->tmi.mipmapLevel[i].used && +       ti->tmi.mipmapLevel[i].translated) +      free(ti->tmi.mipmapLevel[i].data); + +    (void)ti->tmi.mipmapLevel[i].data; +  } +} + +void fxTMFreeAllFreeNode(tfxTMFreeNode *fn) +{ +  if(!fn) +    return; + +  if(fn->next) +    fxTMFreeAllFreeNode(fn->next); + +  free(fn); +} + +void fxTMFreeAllAllocNode(tfxTMAllocNode *an) +{ +  if(!an) +    return; + +  if(an->next) +    fxTMFreeAllAllocNode(an->next); + +  free(an); +} + +void fxTMClose(fxMesaContext fxMesa) +{ +  fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU0]); +  fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU0]); +  fxMesa->tmFree[FX_TMU0] = NULL; +  fxMesa->tmAlloc[FX_TMU0] = NULL; +  if(fxMesa->haveTwoTMUs) { +    fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU1]); +    fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU1]); +    fxMesa->tmFree[FX_TMU1] = NULL; +    fxMesa->tmAlloc[FX_TMU1] = NULL; +  } +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_texman(void) +{ +  return 0; +} + +#endif  /* FX */ diff --git a/src/mesa/drivers/glide/fxwgl.c b/src/mesa/drivers/glide/fxwgl.c new file mode 100644 index 0000000000..cbea79aecd --- /dev/null +++ b/src/mesa/drivers/glide/fxwgl.c @@ -0,0 +1,806 @@ +/* fxwgl.c - Microsoft wgl functions emulation for + *           3Dfx VooDoo/Mesa interface + */ + +/* + * 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. + * + * See the file fxapi.c for more informations about authors + * + */ + +#ifdef __WIN32__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <windows.h> +#include <GL/gl.h> +#include <GL/glu.h> + +#ifdef __cplusplus +           } +#endif + +#include <stdio.h> +#include <GL/fxmesa.h> +#include "fxdrv.h" + +#define MAX_MESA_ATTRS  20 + +struct __extensions__ +{ +  PROC  proc; +  char  *name; +}; + +struct __pixelformat__ +{ +  PIXELFORMATDESCRIPTOR pfd; +  GLint mesaAttr[MAX_MESA_ATTRS]; +}; + +WINGDIAPI void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *); + +static struct __extensions__   ext[] = { + +#ifdef GL_EXT_polygon_offset +   { (PROC)glPolygonOffsetEXT,			"glPolygonOffsetEXT"		}, +#endif +   { (PROC)glBlendEquationEXT,			"glBlendEquationEXT"		}, +   { (PROC)glBlendColorEXT,			"glBlendColorExt"		}, +   { (PROC)glVertexPointerEXT,			"glVertexPointerEXT"		}, +   { (PROC)glNormalPointerEXT,			"glNormalPointerEXT"		}, +   { (PROC)glColorPointerEXT,			"glColorPointerEXT"		}, +   { (PROC)glIndexPointerEXT,			"glIndexPointerEXT"		}, +   { (PROC)glTexCoordPointerEXT,		"glTexCoordPointer"		}, +   { (PROC)glEdgeFlagPointerEXT,		"glEdgeFlagPointerEXT"		}, +   { (PROC)glGetPointervEXT,			"glGetPointervEXT"		}, +   { (PROC)glArrayElementEXT,			"glArrayElementEXT"		}, +   { (PROC)glDrawArraysEXT,			"glDrawArrayEXT"		}, +   { (PROC)glAreTexturesResidentEXT,		"glAreTexturesResidentEXT"	}, +   { (PROC)glBindTextureEXT,			"glBindTextureEXT"		}, +   { (PROC)glDeleteTexturesEXT,			"glDeleteTexturesEXT"		}, +   { (PROC)glGenTexturesEXT,			"glGenTexturesEXT"		}, +   { (PROC)glIsTextureEXT,			"glIsTextureEXT"		}, +   { (PROC)glPrioritizeTexturesEXT,		"glPrioritizeTexturesEXT"	}, +   { (PROC)glCopyTexSubImage3DEXT,		"glCopyTexSubImage3DEXT"	}, +   { (PROC)glTexImage3DEXT,			"glTexImage3DEXT"		}, +   { (PROC)glTexSubImage3DEXT,			"glTexSubImage3DEXT"		}, +   { (PROC)gl3DfxSetPaletteEXT,			"3DFX_set_global_palette"	}, +   { (PROC)glColorTableEXT,			"glColorTableEXT"		}, +   { (PROC)glColorSubTableEXT,			"glColorSubTableEXT"		}, +   { (PROC)glGetColorTableEXT,			"glGetColorTableEXT"		}, +   { (PROC)glGetColorTableParameterfvEXT,	"glGetColorTableParameterfvEXT"	}, +   { (PROC)glGetColorTableParameterivEXT,	"glGetColorTableParameterivEXT"	}, +   { (PROC)glPointParameterfEXT,		"glPointParameterfEXT"		}, +   { (PROC)glPointParameterfvEXT,		"glPointParameterfvEXT"		}, +   { (PROC)glBlendFuncSeparateINGR,		"glBlendFuncSeparateINGR"	}, +   { (PROC)glLockArraysEXT,			"glLockArraysEXT"		}, +   { (PROC)glUnlockArraysEXT,			"glUnlockArraysEXT"		} +}; + +static int qt_ext = sizeof(ext) / sizeof(ext[0]); + +struct __pixelformat__  pix[] = +{ +  /* None */ +  { +    { +      sizeof(PIXELFORMATDESCRIPTOR),  1, +      PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| +      PFD_DOUBLEBUFFER|PFD_SWAP_COPY, +      PFD_TYPE_RGBA, +      32, +      8,0,8,8,8,16,0,24, +      0,0,0,0,0, +      0, +      0, +      0, +      PFD_MAIN_PLANE, +      0,0,0,0 +    }, +    { +      FXMESA_DOUBLEBUFFER, +      FXMESA_ALPHA_SIZE,      0, +      FXMESA_DEPTH_SIZE,      0, +      FXMESA_STENCIL_SIZE,    0, +      FXMESA_ACCUM_SIZE,      0, +      FXMESA_NONE +    } +  }, + +  /* Alpha */ +  { +    { +      sizeof(PIXELFORMATDESCRIPTOR),  1, +      PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| +      PFD_DOUBLEBUFFER|PFD_SWAP_COPY, +      PFD_TYPE_RGBA, +      32, +      8,0,8,8,8,16,8,24, +      0,0,0,0,0, +      0, +      0, +      0, +      PFD_MAIN_PLANE, +      0,0,0,0 +    }, +    { +      FXMESA_DOUBLEBUFFER, +      FXMESA_ALPHA_SIZE,      8, +      FXMESA_DEPTH_SIZE,      0, +      FXMESA_STENCIL_SIZE,    0, +      FXMESA_ACCUM_SIZE,      0, +      FXMESA_NONE +    } +  }, + +  /* Depth */ +  { +    { +      sizeof(PIXELFORMATDESCRIPTOR),  1, +      PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| +      PFD_DOUBLEBUFFER|PFD_SWAP_COPY, +      PFD_TYPE_RGBA, +      32, +      8,0,8,8,8,16,0,24, +      0,0,0,0,0, +      16, +      0, +      0, +      PFD_MAIN_PLANE, +      0,0,0,0 +    }, +    { +      FXMESA_DOUBLEBUFFER, +      FXMESA_ALPHA_SIZE,      0, +      FXMESA_DEPTH_SIZE,      16, +      FXMESA_STENCIL_SIZE,    0, +      FXMESA_ACCUM_SIZE,      0, +      FXMESA_NONE +    } +  } +}; +static int qt_pix = sizeof(pix) / sizeof(pix[0]); + +static fxMesaContext ctx = NULL; +static WNDPROC hWNDOldProc; +static int curPFD = 0; +static HDC hDC; +static HWND hWND; + +static GLboolean haveDualHead; + +/* For the in-window-rendering hack */ + +static GLboolean   gdiWindowHack; +static GLboolean   gdiWindowHackEna; +static void        *dibSurfacePtr; +static BITMAPINFO  *dibBMI; +static HBITMAP     dibHBM; +static HWND        dibWnd; + +LONG GLAPIENTRY __wglMonitor(HWND hwnd,UINT message,UINT wParam,LONG lParam) + +{ +  long ret; /* Now gives the resized window at the end to hWNDOldProc */ + +  if(ctx && hwnd == hWND) { +    switch(message) { +    case WM_PAINT: +    case WM_MOVE: +      break; +    case WM_DISPLAYCHANGE: +    case WM_SIZE: +      if (wParam != SIZE_MINIMIZED) { +        static int moving = 0; +        if (!moving) { +          if(fxQueryHardware()!=GR_SSTTYPE_VOODOO) { +            if(!grSstControl(GR_CONTROL_RESIZE)) { +              moving = 1; +              SetWindowPos(hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER); +              moving = 0; +              if(!grSstControl(GR_CONTROL_RESIZE)) { +                /*MessageBox(0,_T("Error changing windowsize"),_T("fxMESA"),MB_OK);*/ +                PostMessage(hWND,WM_CLOSE,0,0); +              } +            } +          } + +          /* Do the clipping in the glide library */ +          grClipWindow(0,0,grSstScreenWidth(),grSstScreenHeight()); +          /* And let the new size set in the context */ +          fxMesaUpdateScreenSize(ctx); +        } +      } +      break; +    case WM_ACTIVATE: +      if((fxQueryHardware()==GR_SSTTYPE_VOODOO) && +         (!gdiWindowHack) && +         (!haveDualHead)) { +        WORD fActive = LOWORD(wParam); +        BOOL fMinimized = (BOOL) HIWORD(wParam); + +        if((fActive == WA_INACTIVE) || fMinimized) +          grSstControl(GR_CONTROL_DEACTIVATE); +        else +          grSstControl(GR_CONTROL_ACTIVATE); +      } +      break; +    case WM_SHOWWINDOW: +      break; +    case WM_SYSCHAR: +      if(gdiWindowHackEna && (VK_RETURN == wParam)) { +        if(gdiWindowHack) { +          gdiWindowHack = GL_FALSE; +          grSstControl(GR_CONTROL_ACTIVATE); +        } else { +          gdiWindowHack = GL_TRUE; +          grSstControl(GR_CONTROL_DEACTIVATE); +        } +      } +      break; +    } +  } + +  /* Finaly call the hWNDOldProc, which handles the resize witch the +     now changed window sizes */ +  ret = CallWindowProc( hWNDOldProc, hwnd, message, wParam, lParam ); + +  return(ret); +} + +BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask) +{ +  return(FALSE); +} + +HGLRC GLAPIENTRY wglCreateContext(HDC hdc) +{ +  HWND hWnd; +  WNDPROC oldProc; +  int error; + +  if(ctx) { +    SetLastError(0); +    return(NULL); +  } + +  if(!(hWnd = WindowFromDC(hdc))) { +    SetLastError(0); +    return(NULL); +  } + +  if(curPFD == 0) { +    SetLastError(0); +    return(NULL); +  } + +  if((oldProc = (WNDPROC)GetWindowLong(hWnd,GWL_WNDPROC)) != __wglMonitor) { +    hWNDOldProc = oldProc; +    SetWindowLong(hWnd,GWL_WNDPROC,(LONG)__wglMonitor); +  } + +#ifndef FX_SILENT +  freopen("MESA.LOG","w",stderr); +#endif + +  ShowWindow(hWnd, SW_SHOWNORMAL); +  SetForegroundWindow(hWnd); +  Sleep(100); /* an hack for win95 */ + +  if(fxQueryHardware() == GR_SSTTYPE_VOODOO) { +    RECT cliRect; + +    GetClientRect(hWnd,&cliRect); +    error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom, +                                            pix[curPFD - 1].mesaAttr)); + +    if(!error) { +      /* create the DIB section for windowed rendering */ +      DWORD *p; + +      dibWnd = hWnd; + +      hDC = GetDC(dibWnd); + +      dibBMI = (BITMAPINFO*) malloc( sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD))); + +      memset(dibBMI,0,sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD))); + +      dibBMI->bmiHeader.biSize                  = sizeof(BITMAPINFOHEADER); +      dibBMI->bmiHeader.biWidth                 = ctx->width; +      dibBMI->bmiHeader.biHeight                = -ctx->height; +      dibBMI->bmiHeader.biPlanes                = (short)1; +      dibBMI->bmiHeader.biBitCount              = (short)16; +      dibBMI->bmiHeader.biCompression           = BI_BITFIELDS; +      dibBMI->bmiHeader.biSizeImage             = 0; +      dibBMI->bmiHeader.biXPelsPerMeter         = 0; +      dibBMI->bmiHeader.biYPelsPerMeter         = 0; +      dibBMI->bmiHeader.biClrUsed               = 3; +      dibBMI->bmiHeader.biClrImportant          = 3; + +      p = (DWORD*)dibBMI->bmiColors; +      p[0] = 0xF800; +      p[1] = 0x07E0; +      p[2] = 0x001F; + +      dibHBM = CreateDIBSection(hDC, dibBMI, DIB_RGB_COLORS, &dibSurfacePtr, NULL, 0); + +      ReleaseDC(dibWnd, hDC); + +      gdiWindowHackEna = (dibHBM != NULL ? GL_TRUE : GL_FALSE); + +      if (!getenv("MESA_WGL_FX") || !strcmp(getenv("MESA_WGL_FX"),"fullscreen")) +        gdiWindowHack = GL_FALSE; +      else { +        gdiWindowHack = GL_TRUE; +        grSstControl(GR_CONTROL_DEACTIVATE); +      } +    } +  } else { +    /* For the Voodoo Rush */ + +    if(getenv("MESA_WGL_FX") && !strcmp(getenv("MESA_WGL_FX"),"fullscreen")) { +      RECT cliRect; + +      GetClientRect(hWnd,&cliRect); +      error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom, +                                              pix[curPFD - 1].mesaAttr)); +    } else +      error = !(ctx = fxMesaCreateContext((GLuint)hWnd,GR_RESOLUTION_NONE,GR_REFRESH_75Hz, +                                          pix[curPFD - 1].mesaAttr)); +  } + +  if(getenv("SST_DUALHEAD")) +    haveDualHead=((atoi(getenv("SST_DUALHEAD"))==1) ? GL_TRUE:GL_FALSE); +  else +    haveDualHead=GL_FALSE; + +  if(error) { +    SetLastError(0); +    return(NULL); +  } + +  hDC = hdc; +  hWND = hWnd; + +  /* Required by the OpenGL Optimizer 1.1 (is it a Optimizer bug ?) */ +  wglMakeCurrent(hdc,(HGLRC)1); + +  return((HGLRC)1); +} + +HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,int iLayerPlane) +{ +  SetLastError(0); +  return(NULL); +} + +BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc) +{ +  if(ctx && hglrc == (HGLRC)1) { +    if (gdiWindowHackEna) { +      DeleteObject(dibHBM); +      free(dibBMI); + +      dibSurfacePtr = NULL; +      dibBMI = NULL; +      dibHBM = NULL; +      dibWnd = NULL; +    } + +    fxMesaDestroyContext(ctx); + +    SetWindowLong(WindowFromDC(hDC),GWL_WNDPROC,(LONG)hWNDOldProc); + +    ctx = NULL; +    hDC = 0; +    return(TRUE); +  } + +  SetLastError(0); + +  return(FALSE); +} + +HGLRC GLAPIENTRY wglGetCurrentContext(VOID) +{ +  if(ctx) +    return((HGLRC)1); + +  SetLastError(0); +  return(NULL); +} + +HDC GLAPIENTRY wglGetCurrentDC(VOID) +{ +  if(ctx) +    return(hDC); + +  SetLastError(0); +  return(NULL); +} + +PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc) +{ +  int           i; + +  /*fprintf(stderr,"fxMesa: looking for extension %s\n",lpszProc); +    fflush(stderr);*/ + +  for(i = 0;i < qt_ext;i++) +    if(!strcmp(lpszProc,ext[i].name)) { +      /*fprintf(stderr,"fxMesa: found extension %s\n",lpszProc); +        fflush(stderr);*/ + +      return(ext[i].proc); +    } +  SetLastError(0); +  return(NULL); +} + +BOOL GLAPIENTRY wglMakeCurrent(HDC hdc,HGLRC hglrc) +{ +  if((hdc==NULL) && (hglrc==NULL)) +    return(TRUE); + +  if(!ctx || hglrc != (HGLRC)1 || WindowFromDC(hdc) != hWND) { +    SetLastError(0); +    return(FALSE); +  } + +  hDC = hdc; + +  fxMesaMakeCurrent(ctx); + +  return(TRUE); +} + +BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,HGLRC hglrc2) +{ +  if(!ctx || hglrc1 != (HGLRC)1 || hglrc1 != hglrc2) { +    SetLastError(0); +    return(FALSE); +  } + +  return(TRUE); +} + +BOOL GLAPIENTRY wglUseFontBitmaps(HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase) +{ +#define VERIFY(a) a + +  TEXTMETRIC metric; +  BITMAPINFO *dibInfo; +  HDC bitDevice; +  COLORREF tempColor; +  int i; + +  VERIFY(GetTextMetrics(fontDevice, &metric)); + +  dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1); +  dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); +  dibInfo->bmiHeader.biPlanes = 1; +  dibInfo->bmiHeader.biBitCount = 1; +  dibInfo->bmiHeader.biCompression = BI_RGB; + +  bitDevice = CreateCompatibleDC(fontDevice); +  // HDC bitDevice = CreateDC("DISPLAY", NULL, NULL, NULL); +  // VERIFY(bitDevice); + +  // Swap fore and back colors so the bitmap has the right polarity +  tempColor = GetBkColor(bitDevice); +  SetBkColor(bitDevice, GetTextColor(bitDevice)); +  SetTextColor(bitDevice, tempColor); + +  // Place chars based on base line +  VERIFY(SetTextAlign(bitDevice, TA_BASELINE) >= 0); + +  for(i = 0; i < numChars; i++) { +    SIZE size; +    char curChar; +    int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res; +    HBITMAP bitObject; +    HGDIOBJ origBmap; +    unsigned char *bmap; + +    curChar = i + firstChar; + +    // Find how high/wide this character is +    VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size)); + +    // Create the output bitmap +    charWidth = size.cx; +    charHeight = size.cy; +    bmapWidth = ((charWidth + 31) / 32) * 32;   // Round up to the next multiple of 32 bits +    bmapHeight = charHeight; +    bitObject = CreateCompatibleBitmap(bitDevice, +                                       bmapWidth, +                                       bmapHeight); +    //VERIFY(bitObject); + +    // Assign the output bitmap to the device +    origBmap = SelectObject(bitDevice, bitObject); +    VERIFY(origBmap); + +    VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) ); + +    // Use our source font on the device +    VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT))); + +    // Draw the character +    VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1)); + +    // Unselect our bmap object +    VERIFY(SelectObject(bitDevice, origBmap)); + +    // Convert the display dependant representation to a 1 bit deep DIB +    numBytes = (bmapWidth * bmapHeight) / 8; +    bmap = malloc(numBytes); +    dibInfo->bmiHeader.biWidth = bmapWidth; +    dibInfo->bmiHeader.biHeight = bmapHeight; +    res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap, +                    dibInfo, +                    DIB_RGB_COLORS); +    //VERIFY(res); + +    // Create the GL object +    glNewList(i + listBase, GL_COMPILE); +    glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent, +             charWidth, 0.0, +             bmap); +    glEndList(); +    // CheckGL(); + +    // Destroy the bmap object +    DeleteObject(bitObject); + +    // Deallocate the bitmap data +    free(bmap); +  } + +  // Destroy the DC +  VERIFY(DeleteDC(bitDevice)); + +  free(dibInfo); + +  return TRUE; +#undef VERIFY +} + +BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase) +{ +  return(FALSE); +} + +BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count, +                                  DWORD listBase,FLOAT deviation, +                                  FLOAT extrusion,int format, +                                  LPGLYPHMETRICSFLOAT lpgmf) +{ +  SetLastError(0); +  return(FALSE); +} + +BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count, +                                  DWORD listBase,FLOAT deviation, +                                  FLOAT extrusion,int format, +                                  LPGLYPHMETRICSFLOAT lpgmf) +{ +  SetLastError(0); +  return(FALSE); +} + + +BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,UINT fuPlanes) +{ +  if(ctx && WindowFromDC(hdc) == hWND) { +    fxMesaSwapBuffers(); + +    return(TRUE); +  } + +  SetLastError(0); +  return(FALSE); +} + +int GLAPIENTRY wglChoosePixelFormat(HDC hdc, +                                  CONST PIXELFORMATDESCRIPTOR *ppfd) +{ +  int i,best=-1,qt_valid_pix; + +  qt_valid_pix = qt_pix; + +  if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) { +    SetLastError(0); +    return(0); +  } + +  for(i = 0;i < qt_valid_pix;i++) { +    if((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) +      continue; +    if((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) +      continue; +    if((ppfd->dwFlags & PFD_SUPPORT_GDI) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI)) +      continue; +    if((ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) +      continue; +    if(!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && +       ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) +      continue; +    if(!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && +       ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO))) +      continue; + +    if (ppfd->cDepthBits > 0 && pix[i].pfd.cDepthBits == 0) +      continue; /* need depth buffer */ + +    if (ppfd->cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0) +      continue; /* need alpha buffer */ + +    if(ppfd->iPixelType == pix[i].pfd.iPixelType) { +      best = i + 1; +      break; +    } +  } + +  if(best == -1) { +    SetLastError(0); +    return(0); +  } + +  return(best); +} + +int GLAPIENTRY ChoosePixelFormat(HDC hdc, +			       CONST PIXELFORMATDESCRIPTOR *ppfd) +{ +  return wglChoosePixelFormat(hdc,ppfd); +} + +int GLAPIENTRY wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes, +                                    LPPIXELFORMATDESCRIPTOR ppfd) +{ +  int qt_valid_pix; + +  qt_valid_pix = qt_pix; + +  if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || +     ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) { +    SetLastError(0); +    return(0); +  } + +  if(nBytes != 0) +    *ppfd = pix[iPixelFormat - 1].pfd; + +  return(qt_valid_pix); +} + +int GLAPIENTRY DescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes, +				 LPPIXELFORMATDESCRIPTOR ppfd) +{ +  return wglDescribePixelFormat(hdc,iPixelFormat,nBytes,ppfd); +} + +int GLAPIENTRY wglGetPixelFormat(HDC hdc) +{ +  if(curPFD == 0) { +    SetLastError(0); +    return(0); +  } + +  return(curPFD); +} + +int GLAPIENTRY GetPixelFormat(HDC hdc) +{ +  return wglGetPixelFormat(hdc); +} + +BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat, +                                CONST PIXELFORMATDESCRIPTOR *ppfd) +{ +  int qt_valid_pix; + +  qt_valid_pix = qt_pix; + +  if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) { +    SetLastError(0); +    return(FALSE); +  } +  curPFD = iPixelFormat; + +  return(TRUE); +} + +BOOL GLAPIENTRY wglSwapBuffers(HDC hdc) +{ +  if(!ctx) { +    SetLastError(0); +    return(FALSE); +  } + +  fxMesaSwapBuffers(); + +  if(gdiWindowHack) { +    GLuint width=ctx->width; +    GLuint height=ctx->height; + +    HDC hdcScreen      = GetDC(dibWnd); +    HDC hdcDIBSection  = CreateCompatibleDC(hdcScreen); +    HBITMAP holdBitmap = (HBITMAP) SelectObject(hdcDIBSection, dibHBM); + +    grLfbReadRegion(GR_BUFFER_FRONTBUFFER, 0, 0, +                    width, height, +                    width * 2, +                    dibSurfacePtr); + +    /* Since the hardware is configured for GR_COLORFORMAT_ABGR the pixel data is +     * going to come out as BGR 565, which is reverse of what we need for blitting +     * to screen, so we need to convert it here pixel-by-pixel (ick). This loop would NOT +     * be required if the color format was changed to GR_COLORFORMAT_ARGB, but I do +     * not know the ramifications of that, so this will work until that is resolved. +     * +     * This routine CRIES out for MMX implementation, however since that's not +     * guaranteed to be running on MMX enabled hardware so I'm not going to do +     * that. I'm just going to try to make a reasonably efficient C +     * version. -TAJ +     * +     * This routine drops frame rate by <1 fps on a 200Mhz MMX processor with a 640x480 +     * display. Obviously, it's performance hit will be higher on larger displays and +     * less on smaller displays. To support the window-hack display this is probably fine. +     */ +    { +      unsigned long *pixel = dibSurfacePtr; +      unsigned long count = (width * height) / 2; + +      while (count--) +        { +          *pixel++ = (*pixel & 0x07e007e0)                /* greens */ +            | ((*pixel & 0xf800f800) >> 11) /* swap blues */ +            | ((*pixel & 0x001f001f) << 11) /* swap reds */ +            ; +        } +    } + +    BitBlt(hdcScreen, 0, 0, +           width, height, +           hdcDIBSection, +           0, 0, SRCCOPY); + +    ReleaseDC(dibWnd, hdcScreen); +    SelectObject(hdcDIBSection, holdBitmap); +    DeleteDC(hdcDIBSection); +  } + +  return(TRUE); +} + +BOOL GLAPIENTRY SetPixelFormat(HDC hdc, int iPixelFormat, +                             CONST PIXELFORMATDESCRIPTOR *ppfd) +{ +  return wglSetPixelFormat(hdc,iPixelFormat,ppfd); +} + +BOOL GLAPIENTRY SwapBuffers(HDC hdc) +{ +  return wglSwapBuffers(hdc); +} + +#endif /* FX */ diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c new file mode 100644 index 0000000000..25bba5b5e8 --- /dev/null +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -0,0 +1,1594 @@ +/* $Id: osmesa.c,v 1.1 1999/08/19 00:55:42 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. + */ + + +/* + * Off-Screen Mesa rendering / Rendering into client memory space + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <stdlib.h> +#include <string.h> +#include "GL/osmesa.h" +#include "context.h" +#include "depth.h" +#include "macros.h" +#include "matrix.h" +#include "types.h" +#include "vb.h" +#endif + + +struct osmesa_context { +   GLcontext *gl_ctx;		/* The core GL/Mesa context */ +   GLvisual *gl_visual;		/* Describes the buffers */ +   GLframebuffer *gl_buffer;	/* Depth, stencil, accum, etc buffers */ +   GLenum format;		/* either GL_RGBA or GL_COLOR_INDEX */ +   void *buffer;		/* the image buffer */ +   GLint width, height;		/* size of image buffer */ +   GLuint pixel;		/* current color index or RGBA pixel value */ +   GLuint clearpixel;		/* pixel for clearing the color buffer */ +   GLint rowlength;		/* number of pixels per row */ +   GLint userRowLength;		/* user-specified number of pixels per row */ +   GLint rshift, gshift;	/* bit shifts for RGBA formats */ +   GLint bshift, ashift; +   GLint rind, gind, bind;	/* index offsets for RGBA formats */ +   void *rowaddr[MAX_HEIGHT];	/* address of first pixel in each image row */ +   GLboolean yup;		/* TRUE  -> Y increases upward */ +				/* FALSE -> Y increases downward */ +}; + + + +#ifdef THREADS + +#include "mthreads.h" /* Mesa platform independent threads interface */ + +static MesaTSD osmesa_ctx_tsd; + +static void osmesa_ctx_thread_init() { +  MesaInitTSD(&osmesa_ctx_tsd); +} + +static OSMesaContext osmesa_get_thread_context( void ) { +  return (OSMesaContext) MesaGetTSD(&osmesa_ctx_tsd); +} + +static void osmesa_set_thread_context( OSMesaContext ctx ) { +  MesaSetTSD(&osmesa_ctx_tsd, ctx, osmesa_ctx_thread_init); +} + + +#else +   /* One current context for address space, all threads */ +   static OSMesaContext Current = NULL; +#endif + + + +/* A forward declaration: */ +static void osmesa_update_state( GLcontext *ctx ); + + + +/**********************************************************************/ +/*****                    Public Functions                        *****/ +/**********************************************************************/ + + +/* + * Create an Off-Screen Mesa rendering context.  The only attribute needed is + * an RGBA vs Color-Index mode flag. + * + * Input:  format - either GL_RGBA or GL_COLOR_INDEX + *         sharelist - specifies another OSMesaContext with which to share + *                     display lists.  NULL indicates no sharing. + * Return:  an OSMesaContext or 0 if error + */ +OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) +{ +   OSMesaContext osmesa; +   GLint rshift, gshift, bshift, ashift; +   GLint rind, gind, bind; +   GLint indexBits, alphaBits; +   GLboolean rgbmode; +   GLboolean swalpha; +   GLuint i4 = 1; +   GLubyte *i1 = (GLubyte *) &i4; +   GLint little_endian = *i1; + +   swalpha = GL_FALSE; +   rind = gind = bind = 0; +   if (format==OSMESA_COLOR_INDEX) { +      indexBits = 8; +      rshift = gshift = bshift = ashift = 0; +      rgbmode = GL_FALSE; +   } +   else if (format==OSMESA_RGBA) { +      indexBits = 0; +      alphaBits = 8; +      if (little_endian) { +         rshift = 0; +         gshift = 8; +         bshift = 16; +         ashift = 24; +      } +      else { +         rshift = 24; +         gshift = 16; +         bshift = 8; +         ashift = 0; +      } +      rgbmode = GL_TRUE; +   } +   else if (format==OSMESA_BGRA) { +      indexBits = 0; +      alphaBits = 8; +      if (little_endian) { +         ashift = 0; +         rshift = 8; +         gshift = 16; +         bshift = 24; +      } +      else { +         bshift = 24; +         gshift = 16; +         rshift = 8; +         ashift = 0; +      } +      rgbmode = GL_TRUE; +   } +   else if (format==OSMESA_ARGB) { +      indexBits = 0; +      alphaBits = 8; +      if (little_endian) { +         bshift = 0; +         gshift = 8; +         rshift = 16; +         ashift = 24; +      } +      else { +         ashift = 24; +         rshift = 16; +         gshift = 8; +         bshift = 0; +      } +      rgbmode = GL_TRUE; +   } +   else if (format==OSMESA_RGB) { +      indexBits = 0; +      alphaBits = 0; +      bshift = 0; +      gshift = 8; +      rshift = 16; +      ashift = 24; +      bind = 2; +      gind = 1; +      rind = 0; +      rgbmode = GL_TRUE; +      swalpha = GL_TRUE; +   } +   else if (format==OSMESA_BGR) { +      indexBits = 0; +      alphaBits = 0; +      bshift = 0; +      gshift = 8; +      rshift = 16; +      ashift = 24; +      bind = 0; +      gind = 1; +      rind = 2; +      rgbmode = GL_TRUE; +      swalpha = GL_TRUE; +   } +   else { +      return NULL; +   } + + +   osmesa = (OSMesaContext) calloc( 1, sizeof(struct osmesa_context) ); +   if (osmesa) { +      osmesa->gl_visual = gl_create_visual( rgbmode, +                                            swalpha,    /* software alpha */ +                                            GL_FALSE,	/* double buffer */ +                                            GL_FALSE,	/* stereo */ +                                            DEPTH_BITS, +                                            STENCIL_BITS, +                                            ACCUM_BITS, +                                            indexBits, +                                            8, 8, 8, alphaBits ); +      if (!osmesa->gl_visual) { +         return NULL; +      } + +      osmesa->gl_ctx = gl_create_context( osmesa->gl_visual, +                            sharelist ? sharelist->gl_ctx : (GLcontext *) NULL, +                            (void *) osmesa, GL_TRUE ); +      if (!osmesa->gl_ctx) { +         gl_destroy_visual( osmesa->gl_visual ); +         free(osmesa); +         return NULL; +      } +      osmesa->gl_buffer = gl_create_framebuffer( osmesa->gl_visual ); +      if (!osmesa->gl_buffer) { +         gl_destroy_visual( osmesa->gl_visual ); +         gl_destroy_context( osmesa->gl_ctx ); +         free(osmesa); +         return NULL; +      } +      osmesa->format = format; +      osmesa->buffer = NULL; +      osmesa->width = 0; +      osmesa->height = 0; +      osmesa->pixel = 0; +      osmesa->clearpixel = 0; +      osmesa->userRowLength = 0; +      osmesa->rowlength = 0; +      osmesa->yup = GL_TRUE; +      osmesa->rshift = rshift; +      osmesa->gshift = gshift; +      osmesa->bshift = bshift; +      osmesa->ashift = ashift; +      osmesa->rind = rind; +      osmesa->gind = gind; +      osmesa->bind = bind; +   } +   return osmesa; +} + + + +/* + * Destroy an Off-Screen Mesa rendering context. + * + * Input:  ctx - the context to destroy + */ +void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx ) +{ +   if (ctx) { +      gl_destroy_visual( ctx->gl_visual ); +      gl_destroy_framebuffer( ctx->gl_buffer ); +      gl_destroy_context( ctx->gl_ctx ); +      free( ctx ); +   } +} + + + +/* + * Recompute the values of the context's rowaddr array. + */ +static void compute_row_addresses( OSMesaContext ctx ) +{ +   GLint i; + +   if (ctx->yup) { +      /* Y=0 is bottom line of window */ +      if (ctx->format==OSMESA_COLOR_INDEX) { +         /* 1-byte CI mode */ +         GLubyte *origin = (GLubyte *) ctx->buffer; +         for (i=0;i<MAX_HEIGHT;i++) { +            ctx->rowaddr[i] = origin + i * ctx->rowlength; +         } +      } +      else { +         if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) { +            /* 3-byte RGB mode */ +            GLubyte *origin = (GLubyte *) ctx->buffer; +            for (i=0;i<MAX_HEIGHT;i++) { +               ctx->rowaddr[i] = origin + (i * (ctx->rowlength*3)); +            } +         } else { +            /* 4-byte RGBA mode */ +            GLuint *origin = (GLuint *) ctx->buffer; +            for (i=0;i<MAX_HEIGHT;i++) { +               ctx->rowaddr[i] = origin + i * ctx->rowlength; +            } +         } +      } +   } +   else { +      /* Y=0 is top line of window */ +      if (ctx->format==OSMESA_COLOR_INDEX) { +         /* 1-byte CI mode */ +         GLubyte *origin = (GLubyte *) ctx->buffer; +         for (i=0;i<MAX_HEIGHT;i++) { +            ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength; +         } +      } +      else { +         if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) { +            /* 3-byte RGB mode */ +            GLubyte *origin = (GLubyte *) ctx->buffer; +            for (i=0;i<MAX_HEIGHT;i++) { +               ctx->rowaddr[i] = origin + ((ctx->height-i-1) * (ctx->rowlength*3)); +            } +         } else { +            /* 4-byte RGBA mode */ +            GLuint *origin = (GLuint *) ctx->buffer; +            for (i=0;i<MAX_HEIGHT;i++) { +               ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength; +            } +         } +      } +   } +} + + +/* + * Bind an OSMesaContext to an image buffer.  The image buffer is just a + * block of memory which the client provides.  Its size must be at least + * as large as width*height*sizeof(type).  Its address should be a multiple + * of 4 if using RGBA mode. + * + * Image data is stored in the order of glDrawPixels:  row-major order + * with the lower-left image pixel stored in the first array position + * (ie. bottom-to-top). + * + * Since the only type initially supported is GL_UNSIGNED_BYTE, if the + * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA + * value.  If the context is in color indexed mode, each pixel will be + * stored as a 1-byte value. + * + * If the context's viewport hasn't been initialized yet, it will now be + * initialized to (0,0,width,height). + * + * Input:  ctx - the rendering context + *         buffer - the image buffer memory + *         type - data type for pixel components, only GL_UNSIGNED_BYTE + *                supported now + *         width, height - size of image buffer in pixels, at least 1 + * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx, + *          invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1, + *          width>internal limit or height>internal limit. + */ +GLboolean GLAPIENTRY OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, +                             GLsizei width, GLsizei height ) +{ +   if (!ctx || !buffer || type!=GL_UNSIGNED_BYTE +       || width<1 || height<1 || width>MAX_WIDTH || height>MAX_HEIGHT) { +      return GL_FALSE; +   } + +   osmesa_update_state( ctx->gl_ctx ); +   gl_make_current( ctx->gl_ctx, ctx->gl_buffer ); + +   ctx->buffer = buffer; +   ctx->width = width; +   ctx->height = height; +   if (ctx->userRowLength) +      ctx->rowlength = ctx->userRowLength; +   else +      ctx->rowlength = width; + +#ifdef THREADS +   /* Set current context for the calling thread */ +   osmesa_set_thread_context(ctx); +#else +   /* Set current context for the address space, all threads */ +   Current = ctx; +#endif + +   compute_row_addresses( ctx ); + +   /* init viewport */ +   if (ctx->gl_ctx->Viewport.Width==0) { +      /* initialize viewport and scissor box to buffer size */ +      gl_Viewport( ctx->gl_ctx, 0, 0, width, height ); +      ctx->gl_ctx->Scissor.Width = width; +      ctx->gl_ctx->Scissor.Height = height; +   } + +   return GL_TRUE; +} + + + + +OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) +{ +#ifdef THREADS +   /* Return current handle for the calling thread */ +   return osmesa_get_thread_context(); +#else +   /* Return current handle for the address space, all threads */ +   return Current; +#endif +} + + + +void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) +{ +   OSMesaContext ctx = OSMesaGetCurrentContext(); + +   switch (pname) { +      case OSMESA_ROW_LENGTH: +         if (value<0) { +            gl_error( ctx->gl_ctx, GL_INVALID_VALUE, +                      "OSMesaPixelStore(value)" ); +            return; +         } +         ctx->userRowLength = value; +         ctx->rowlength = value; +         break; +      case OSMESA_Y_UP: +         ctx->yup = value ? GL_TRUE : GL_FALSE; +         break; +      default: +         gl_error( ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); +         return; +   } + +   compute_row_addresses( ctx ); +} + + +void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) +{ +   OSMesaContext ctx = OSMesaGetCurrentContext(); + +   switch (pname) { +      case OSMESA_WIDTH: +         *value = ctx->width; +         return; +      case OSMESA_HEIGHT: +         *value = ctx->height; +         return; +      case OSMESA_FORMAT: +         *value = ctx->format; +         return; +      case OSMESA_TYPE: +         *value = GL_UNSIGNED_BYTE; +         return; +      case OSMESA_ROW_LENGTH: +         *value = ctx->rowlength; +         return; +      case OSMESA_Y_UP: +         *value = ctx->yup; +         return; +      default: +         gl_error( ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)" ); +         return; +   } +} + + + +/* + * Return the depth buffer associated with an OSMesa context. + * Input:  c - the OSMesa context + * Output:  width, height - size of buffer in pixels + *          bytesPerValue - bytes per depth value (2 or 4) + *          buffer - pointer to depth buffer values + * Return:  GL_TRUE or GL_FALSE to indicate success or failure. + */ +GLboolean GLAPIENTRY OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, +                                GLint *bytesPerValue, void **buffer ) +{ +   if ((!c->gl_buffer) || (!c->gl_buffer->Depth)) { +      *width = 0; +      *height = 0; +      *bytesPerValue = 0; +      *buffer = 0; +      return GL_FALSE; +   } +   else { +      *width = c->gl_buffer->Width; +      *height = c->gl_buffer->Height; +      *bytesPerValue = sizeof(GLdepth); +      *buffer = c->gl_buffer->Depth; +      return GL_TRUE; +   } +} + + + + +/**********************************************************************/ +/*** Device Driver Functions                                        ***/ +/**********************************************************************/ + + +/* + * Useful macros: + */ +#define PACK_RGBA(R,G,B,A)  (  ((R) << osmesa->rshift) \ +                             | ((G) << osmesa->gshift) \ +                             | ((B) << osmesa->bshift) \ +                             | ((A) << osmesa->ashift) ) + +#define PACK_RGBA2(R,G,B,A)  (  ((R) << rshift) \ +                              | ((G) << gshift) \ +                              | ((B) << bshift) \ +                              | ((A) << ashift) ) + +#define UNPACK_RED(P)      (((P) >> osmesa->rshift) & 0xff) +#define UNPACK_GREEN(P)    (((P) >> osmesa->gshift) & 0xff) +#define UNPACK_BLUE(P)     (((P) >> osmesa->bshift) & 0xff) +#define UNPACK_ALPHA(P)    (((P) >> osmesa->ashift) & 0xff) + +#define PIXELADDR1(X,Y)  ((GLubyte *) osmesa->rowaddr[Y] + (X)) +#define PIXELADDR3(X,Y)  ((GLubyte *) osmesa->rowaddr[Y] + ((X)*3)) +#define PIXELADDR4(X,Y)  ((GLuint *)  osmesa->rowaddr[Y] + (X)) + + + + +static GLboolean set_buffer( GLcontext *ctx, GLenum mode ) +{ +   (void) ctx; +   if (mode==GL_FRONT_LEFT) { +      return GL_TRUE; +   } +   else { +      return GL_FALSE; +   } +} + + +static void clear_index( GLcontext *ctx, GLuint index ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   osmesa->clearpixel = index; +} + + + +static void clear_color( GLcontext *ctx, +                         GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   osmesa->clearpixel = PACK_RGBA( r, g, b, a ); +} + + + +static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all, +                         GLint x, GLint y, GLint width, GLint height ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   if (mask & GL_COLOR_BUFFER_BIT) { +      if (osmesa->format==OSMESA_COLOR_INDEX) { +         if (all) { +            /* Clear whole CI buffer */ +            MEMSET(osmesa->buffer, osmesa->clearpixel, +                   osmesa->rowlength * osmesa->height); +         } +         else { +            /* Clear part of CI buffer */ +            GLint i, j; +            for (i=0;i<height;i++) { +               GLubyte *ptr1 = PIXELADDR1( x, (y+i) ); +               for (j=0;j<width;j++) { +                  *ptr1++ = osmesa->clearpixel; +               } +            } +         } +      } +      else if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) { +         GLubyte rval = UNPACK_RED(osmesa->clearpixel); +         GLubyte gval = UNPACK_GREEN(osmesa->clearpixel); +         GLubyte bval = UNPACK_BLUE(osmesa->clearpixel); +         GLint   rind = osmesa->rind; +         GLint   gind = osmesa->gind; +         GLint   bind = osmesa->bind; +         if (all) { +            GLuint  i, n; +            GLubyte *ptr3 = (GLubyte *) osmesa->buffer; +            /* Clear whole RGB buffer */ +            n = osmesa->rowlength * osmesa->height; +            for (i=0;i<n;i++) { +               ptr3[rind] = rval; +               ptr3[gind] = gval; +               ptr3[bind] = bval; +               ptr3 += 3; +            } +         } +         else { +            /* Clear part of RGB buffer */ +            GLint i, j; +            for (i=0;i<height;i++) { +               GLubyte *ptr3 = PIXELADDR3( x, (y+i) ); +               for (j=0;j<width;j++) { +                  ptr3[rind] = rval; +                  ptr3[gind] = gval; +                  ptr3[bind] = bval; +                  ptr3 += 3; +               } +            } +         } +      } +      else { +         if (all) { +            /* Clear whole RGBA buffer */ +            GLuint i, n, *ptr4; +            n = osmesa->rowlength * osmesa->height; +            ptr4 = (GLuint *) osmesa->buffer; +            for (i=0;i<n;i++) { +               *ptr4++ = osmesa->clearpixel; +            } +         } +         else { +            /* Clear part of RGBA buffer */ +            GLint i, j; +            for (i=0;i<height;i++) { +               GLuint *ptr4 = PIXELADDR4( x, (y+i) ); +               for (j=0;j<width;j++) { +                  *ptr4++ = osmesa->clearpixel; +               } +            } +         } +      } +   } +   return mask & (~GL_COLOR_BUFFER_BIT); +} + + + +static void set_index( GLcontext *ctx, GLuint index ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   osmesa->pixel = index; +} + + + +static void set_color( GLcontext *ctx, +                       GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   osmesa->pixel = PACK_RGBA( r, g, b, a ); +} + + + +static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   *width = osmesa->width; +   *height = osmesa->height; +} + + +/**********************************************************************/ +/*****        Read/write spans/arrays of RGBA pixels              *****/ +/**********************************************************************/ + +/* Write RGBA pixels to an RGBA (or permuted) buffer. */ +static void write_rgba_span( const GLcontext *ctx, +                             GLuint n, GLint x, GLint y, +                             CONST GLubyte rgba[][4], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint *ptr4 = PIXELADDR4( x, y ); +   GLuint i; +   GLint rshift = osmesa->rshift; +   GLint gshift = osmesa->gshift; +   GLint bshift = osmesa->bshift; +   GLint ashift = osmesa->ashift; +   if (mask) { +      for (i=0;i<n;i++,ptr4++) { +         if (mask[i]) { +            *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); +         } +      } +   } +   else { +      for (i=0;i<n;i++,ptr4++) { +         *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); +      } +   } +} + + +/* Write RGBA pixels to an RGBA buffer.  This is the fastest span-writer. */ +static void write_rgba_span_rgba( const GLcontext *ctx, +                                  GLuint n, GLint x, GLint y, +                                  CONST GLubyte rgba[][4], +                                  const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint *ptr4 = PIXELADDR4( x, y ); +   const GLuint *rgba4 = (const GLuint *) rgba; +   GLuint i; +   if (mask) { +      for (i=0;i<n;i++) { +         if (mask[i]) { +            ptr4[i] = rgba4[i]; +         } +      } +   } +   else { +      MEMCPY( ptr4, rgba4, n * 4 ); +   } +} + + +/* Write RGB pixels to an RGBA (or permuted) buffer. */ +static void write_rgb_span( const GLcontext *ctx, +                            GLuint n, GLint x, GLint y, +                            CONST GLubyte rgb[][3], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint *ptr4 = PIXELADDR4( x, y ); +   GLuint i; +   GLint rshift = osmesa->rshift; +   GLint gshift = osmesa->gshift; +   GLint bshift = osmesa->bshift; +   GLint ashift = osmesa->ashift; +   if (mask) { +      for (i=0;i<n;i++,ptr4++) { +         if (mask[i]) { +            *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 ); +         } +      } +   } +   else { +      for (i=0;i<n;i++,ptr4++) { +         *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255); +      } +   } +} + + + +static void write_monocolor_span( const GLcontext *ctx, +                                  GLuint n, GLint x, GLint y, +				  const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint *ptr4 = PIXELADDR4(x,y); +   GLuint i; +   for (i=0;i<n;i++,ptr4++) { +      if (mask[i]) { +         *ptr4 = osmesa->pixel; +      } +   } +} + + + +static void write_rgba_pixels( const GLcontext *ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               CONST GLubyte rgba[][4], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   GLint rshift = osmesa->rshift; +   GLint gshift = osmesa->gshift; +   GLint bshift = osmesa->bshift; +   GLint ashift = osmesa->ashift; +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLuint *ptr4 = PIXELADDR4(x[i],y[i]); +         *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); +      } +   } +} + + + +static void write_monocolor_pixels( const GLcontext *ctx, +                                    GLuint n, const GLint x[], const GLint y[], +				    const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLuint *ptr4 = PIXELADDR4(x[i],y[i]); +         *ptr4 = osmesa->pixel; +      } +   } +} + + +static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, +                             GLubyte rgba[][4] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   GLuint *ptr4 = PIXELADDR4(x,y); +   for (i=0;i<n;i++) { +      GLuint pixel = *ptr4++; +      rgba[i][RCOMP] = UNPACK_RED(pixel); +      rgba[i][GCOMP] = UNPACK_GREEN(pixel); +      rgba[i][BCOMP] = UNPACK_BLUE(pixel); +      rgba[i][ACOMP] = UNPACK_ALPHA(pixel); +   } +} + + +/* Read RGBA pixels from an RGBA buffer */ +static void read_rgba_span_rgba( const GLcontext *ctx, +                                 GLuint n, GLint x, GLint y, +                                 GLubyte rgba[][4] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint *ptr4 = PIXELADDR4(x,y); +   MEMCPY( rgba, ptr4, n * 4 * sizeof(GLubyte) ); +} + + +static void read_rgba_pixels( const GLcontext *ctx, +                               GLuint n, const GLint x[], const GLint y[], +			       GLubyte rgba[][4], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLuint *ptr4 = PIXELADDR4(x[i],y[i]); +         GLuint pixel = *ptr4; +         rgba[i][RCOMP] = UNPACK_RED(pixel); +         rgba[i][GCOMP] = UNPACK_GREEN(pixel); +         rgba[i][BCOMP] = UNPACK_BLUE(pixel); +         rgba[i][ACOMP] = UNPACK_ALPHA(pixel); +      } +   } +} + +/**********************************************************************/ +/*****                3 byte RGB pixel support funcs              *****/ +/**********************************************************************/ + +/* Write RGBA pixels to an RGB or BGR buffer. */ +static void write_rgba_span3( const GLcontext *ctx, +                              GLuint n, GLint x, GLint y, +                              CONST GLubyte rgba[][4], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLubyte *ptr3 = PIXELADDR3( x, y); +   GLuint i; +   GLint rind = osmesa->rind; +   GLint gind = osmesa->gind; +   GLint bind = osmesa->bind; +   if (mask) { +      for (i=0;i<n;i++,ptr3+=3) { +         if (mask[i]) { +            ptr3[rind] = rgba[i][RCOMP]; +            ptr3[gind] = rgba[i][GCOMP]; +            ptr3[bind] = rgba[i][BCOMP]; +         } +      } +   } +   else { +      for (i=0;i<n;i++,ptr3+=3) { +         ptr3[rind] = rgba[i][RCOMP]; +         ptr3[gind] = rgba[i][GCOMP]; +         ptr3[bind] = rgba[i][BCOMP]; +      } +   } +} + +/* Write RGB pixels to an RGB or BGR buffer. */ +static void write_rgb_span3( const GLcontext *ctx, +                             GLuint n, GLint x, GLint y, +                             CONST GLubyte rgb[][3], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLubyte *ptr3 = PIXELADDR3( x, y); +   GLuint i; +   GLint rind = osmesa->rind; +   GLint gind = osmesa->gind; +   GLint bind = osmesa->bind; +   if (mask) { +      for (i=0;i<n;i++,ptr3+=3) { +         if (mask[i]) { +            ptr3[rind] = rgb[i][RCOMP]; +            ptr3[gind] = rgb[i][GCOMP]; +            ptr3[bind] = rgb[i][BCOMP]; +         } +      } +   } +   else { +      for (i=0;i<n;i++,ptr3+=3) { +         ptr3[rind] = rgb[i][RCOMP]; +         ptr3[gind] = rgb[i][GCOMP]; +         ptr3[bind] = rgb[i][BCOMP]; +      } +   } +} + + +static void write_monocolor_span3( const GLcontext *ctx, +                                  GLuint n, GLint x, GLint y, +				  const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + +   GLubyte rval = UNPACK_RED(osmesa->pixel); +   GLubyte gval = UNPACK_GREEN(osmesa->pixel); +   GLubyte bval = UNPACK_BLUE(osmesa->pixel); +   GLint   rind = osmesa->rind; +   GLint   gind = osmesa->gind; +   GLint   bind = osmesa->bind; + + +   GLubyte *ptr3 = PIXELADDR3( x, y); +   GLuint i; +   for (i=0;i<n;i++,ptr3+=3) { +      if (mask[i]) { +         ptr3[rind] = rval; +         ptr3[gind] = gval; +         ptr3[bind] = bval; +      } +   } +} + +static void write_rgba_pixels3( const GLcontext *ctx, +                                GLuint n, const GLint x[], const GLint y[], +                                CONST GLubyte rgba[][4], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   GLint rind = osmesa->rind; +   GLint gind = osmesa->gind; +   GLint bind = osmesa->bind; + +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLubyte *ptr3 = PIXELADDR3(x[i],y[i]); +         ptr3[rind] = rgba[i][RCOMP]; +         ptr3[gind] = rgba[i][GCOMP]; +         ptr3[bind] = rgba[i][BCOMP]; +      } +   } +} + +static void write_monocolor_pixels3( const GLcontext *ctx, +                                    GLuint n, const GLint x[], const GLint y[], +				    const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   GLint rind = osmesa->rind; +   GLint gind = osmesa->gind; +   GLint bind = osmesa->bind; +   GLubyte rval = UNPACK_RED(osmesa->pixel); +   GLubyte gval = UNPACK_GREEN(osmesa->pixel); +   GLubyte bval = UNPACK_BLUE(osmesa->pixel); +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLubyte *ptr3 = PIXELADDR3(x[i],y[i]); +         ptr3[rind] = rval; +         ptr3[gind] = gval; +         ptr3[bind] = bval; +      } +   } +} + +static void read_rgba_span3( const GLcontext *ctx, +                             GLuint n, GLint x, GLint y, +                             GLubyte rgba[][4] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   GLint rind = osmesa->rind; +   GLint gind = osmesa->gind; +   GLint bind = osmesa->bind; +   GLubyte *ptr3 = PIXELADDR3( x, y); +   for (i=0;i<n;i++,ptr3+=3) { +      rgba[i][RCOMP] = ptr3[rind]; +      rgba[i][GCOMP] = ptr3[gind]; +      rgba[i][BCOMP] = ptr3[bind]; +      rgba[i][ACOMP] = 0; +   } +} + +static void read_rgba_pixels3( const GLcontext *ctx, +                               GLuint n, const GLint x[], const GLint y[], +			       GLubyte rgba[][4], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   GLint rind = osmesa->rind; +   GLint gind = osmesa->gind; +   GLint bind = osmesa->bind; +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLubyte *ptr3 = PIXELADDR3(x[i],y[i]); +         rgba[i][RCOMP] = ptr3[rind]; +         rgba[i][GCOMP] = ptr3[gind]; +         rgba[i][BCOMP] = ptr3[bind]; +         rgba[i][ACOMP] = 0; +      } +   } +} + + +/**********************************************************************/ +/*****        Read/write spans/arrays of CI pixels                *****/ +/**********************************************************************/ + +/* Write 32-bit color index to buffer */ +static void write_index32_span( const GLcontext *ctx, +                                GLuint n, GLint x, GLint y, +                                const GLuint index[], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLubyte *ptr1 = PIXELADDR1(x,y); +   GLuint i; +   if (mask) { +      for (i=0;i<n;i++,ptr1++) { +         if (mask[i]) { +            *ptr1 = (GLubyte) index[i]; +         } +      } +   } +   else { +      for (i=0;i<n;i++,ptr1++) { +         *ptr1 = (GLubyte) index[i]; +      } +   } +} + + +/* Write 8-bit color index to buffer */ +static void write_index8_span( const GLcontext *ctx, +                               GLuint n, GLint x, GLint y, +                               const GLubyte index[], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLubyte *ptr1 = PIXELADDR1(x,y); +   GLuint i; +   if (mask) { +      for (i=0;i<n;i++,ptr1++) { +         if (mask[i]) { +            *ptr1 = (GLubyte) index[i]; +         } +      } +   } +   else { +      MEMCPY( ptr1, index, n ); +   } +} + + +static void write_monoindex_span( const GLcontext *ctx, +                                  GLuint n, GLint x, GLint y, +				  const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLubyte *ptr1 = PIXELADDR1(x,y); +   GLuint i; +   for (i=0;i<n;i++,ptr1++) { +      if (mask[i]) { +         *ptr1 = (GLubyte) osmesa->pixel; +      } +   } +} + + +static void write_index_pixels( const GLcontext *ctx, +                                GLuint n, const GLint x[], const GLint y[], +			        const GLuint index[], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLubyte *ptr1 = PIXELADDR1(x[i],y[i]); +         *ptr1 = (GLubyte) index[i]; +      } +   } +} + + +static void write_monoindex_pixels( const GLcontext *ctx, +                                    GLuint n, const GLint x[], const GLint y[], +				    const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   for (i=0;i<n;i++) { +      if (mask[i]) { +         GLubyte *ptr1 = PIXELADDR1(x[i],y[i]); +         *ptr1 = (GLubyte) osmesa->pixel; +      } +   } +} + + +static void read_index_span( const GLcontext *ctx, +                             GLuint n, GLint x, GLint y, GLuint index[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   GLubyte *ptr1 = PIXELADDR1(x,y); +   for (i=0;i<n;i++,ptr1++) { +      index[i] = (GLuint) *ptr1; +   } +} + + +static void read_index_pixels( const GLcontext *ctx, +                               GLuint n, const GLint x[], const GLint y[], +			       GLuint index[], const GLubyte mask[] ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLuint i; +   for (i=0;i<n;i++) { +      if (mask[i] ) { +         GLubyte *ptr1 = PIXELADDR1(x[i],y[i]); +         index[i] = (GLuint) *ptr1; +      } +   } +} + + + +/**********************************************************************/ +/*****                   Optimized line rendering                 *****/ +/**********************************************************************/ + + +/* + * Draw a flat-shaded, RGB line into an osmesa buffer. + */ +static void flat_rgba_line( GLcontext *ctx, +                            GLuint vert0, GLuint vert1, GLuint pvert ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLubyte *color = ctx->VB->ColorPtr->data[pvert]; +   unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] ); + +#define INTERP_XY 1 +#define CLIP_HACK 1 +#define PLOT(X,Y) { GLuint *ptr4 = PIXELADDR4(X,Y); *ptr4 = pixel; } + +#ifdef WIN32 +#include "..\linetemp.h" +#else +#include "linetemp.h" +#endif +} + + +/* + * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. + */ +static void flat_rgba_z_line( GLcontext *ctx, +                              GLuint vert0, GLuint vert1, GLuint pvert ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLubyte *color = ctx->VB->ColorPtr->data[pvert]; +   unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] ); + +#define INTERP_XY 1 +#define INTERP_Z 1 +#define CLIP_HACK 1 +#define PLOT(X,Y)				\ +	if (Z < *zPtr) {			\ +	   GLuint *ptr4 = PIXELADDR4(X,Y);	\ +	   *ptr4 = pixel;			\ +	   *zPtr = Z;				\ +	} + +#ifdef WIN32 +#include "..\linetemp.h" +#else +#include "linetemp.h" +#endif +} + + +/* + * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer. + */ +static void flat_blend_rgba_line( GLcontext *ctx, +                                  GLuint vert0, GLuint vert1, GLuint pvert ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   struct vertex_buffer *VB = ctx->VB; +   GLint rshift = osmesa->rshift; +   GLint gshift = osmesa->gshift; +   GLint bshift = osmesa->bshift; +   GLint avalue = VB->ColorPtr->data[pvert][3]; +   GLint msavalue = 255 - avalue; +   GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; +   GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; +   GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; + +#define INTERP_XY 1 +#define CLIP_HACK 1 +#define PLOT(X,Y)					\ +   { GLuint *ptr4 = PIXELADDR4(X,Y); \ +     GLuint  pixel = 0; \ +     pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\ +     pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\ +     pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\ +     *ptr4 = pixel; \ +   } + +#ifdef WIN32 +#include "..\linetemp.h" +#else +#include "linetemp.h" +#endif +} + +/* + * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. + */ +static void flat_blend_rgba_z_line( GLcontext *ctx, +                                   GLuint vert0, GLuint vert1, GLuint pvert ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   struct vertex_buffer *VB = ctx->VB; +   GLint rshift = osmesa->rshift; +   GLint gshift = osmesa->gshift; +   GLint bshift = osmesa->bshift; +   GLint avalue = VB->ColorPtr->data[pvert][3]; +   GLint msavalue = 256 - avalue; +   GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; +   GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; +   GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; + +#define INTERP_XY 1 +#define INTERP_Z 1 +#define CLIP_HACK 1 +#define PLOT(X,Y)				\ +	if (Z < *zPtr) {			\ +   { GLuint *ptr4 = PIXELADDR4(X,Y); \ +     GLuint  pixel = 0; \ +     pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\ +     pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\ +     pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\ +     *ptr4 = pixel; \ +   } \ +	} + +#ifdef WIN32 +#include "..\linetemp.h" +#else +#include "linetemp.h" +#endif +} + +/* + * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. + */ +static void flat_blend_rgba_z_line_write( GLcontext *ctx, +                                   GLuint vert0, GLuint vert1, GLuint pvert ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   struct vertex_buffer *VB = ctx->VB; +   GLint rshift = osmesa->rshift; +   GLint gshift = osmesa->gshift; +   GLint bshift = osmesa->bshift; +   GLint avalue = VB->ColorPtr->data[pvert][3]; +   GLint msavalue = 256 - avalue; +   GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; +   GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; +   GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; + +#define INTERP_XY 1 +#define INTERP_Z 1 +#define CLIP_HACK 1 +#define PLOT(X,Y)				\ +	if (Z < *zPtr) {			\ +   { GLuint *ptr4 = PIXELADDR4(X,Y); \ +     GLuint  pixel = 0; \ +     pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\ +     pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\ +     pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\ +     *ptr4 = pixel; \ +   } \ +	   *zPtr = Z;				\ +	} + +#ifdef WIN32 +#include "..\linetemp.h" +#else +#include "linetemp.h" +#endif +} + + +/* + * Analyze context state to see if we can provide a fast line drawing + * function, like those in lines.c.  Otherwise, return NULL. + */ +static line_func choose_line_function( GLcontext *ctx ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + +   if (ctx->Line.SmoothFlag)              return NULL; +   if (ctx->Texture.Enabled)              return NULL; +   if (ctx->Light.ShadeModel!=GL_FLAT)    return NULL; + +   if (ctx->Line.Width==1.0F +       && ctx->Line.StippleFlag==GL_FALSE) { + +       if (ctx->RasterMask==DEPTH_BIT +           && ctx->Depth.Func==GL_LESS +           && ctx->Depth.Mask==GL_TRUE) { +           switch(osmesa->format) { +       		case OSMESA_RGBA: +       		case OSMESA_BGRA: +       		case OSMESA_ARGB: +       			return flat_rgba_z_line; +       		default: +       			return NULL; +           } +       } + +       if (ctx->RasterMask==0) { +           switch(osmesa->format) { +       		case OSMESA_RGBA: +       		case OSMESA_BGRA: +       		case OSMESA_ARGB: +       			return flat_rgba_line; +       		default: +       			return NULL; +           } +       } + +       if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT) +           && ctx->Depth.Func==GL_LESS +           && ctx->Depth.Mask==GL_TRUE +           && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA +           && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA +           && ctx->Color.BlendSrcA==GL_SRC_ALPHA +           && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA +           && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { +           switch(osmesa->format) { +       		case OSMESA_RGBA: +       		case OSMESA_BGRA: +       		case OSMESA_ARGB: +       			return flat_blend_rgba_z_line_write; +       		default: +       			return NULL; +           } +       } + +       if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT) +           && ctx->Depth.Func==GL_LESS +           && ctx->Depth.Mask==GL_FALSE +           && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA +           && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA +           && ctx->Color.BlendSrcA==GL_SRC_ALPHA +           && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA +           && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { +           switch(osmesa->format) { +       		case OSMESA_RGBA: +       		case OSMESA_BGRA: +       		case OSMESA_ARGB: +       			return flat_blend_rgba_z_line; +       		default: +       			return NULL; +           } +       } + +       if (ctx->RasterMask==BLEND_BIT +           && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA +           && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA +           && ctx->Color.BlendSrcA==GL_SRC_ALPHA +           && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA +           && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { +           switch(osmesa->format) { +       		case OSMESA_RGBA: +       		case OSMESA_BGRA: +       		case OSMESA_ARGB: +       			return flat_blend_rgba_line; +       		default: +       			return NULL; +           } +       } + +   } +   return NULL; +} + + +/**********************************************************************/ +/*****                 Optimized triangle rendering               *****/ +/**********************************************************************/ + + +/* + * Smooth-shaded, z-less triangle, RGBA color. + */ +static void smooth_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                    GLuint v2, GLuint pv ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +   GLint rshift = osmesa->rshift; +   GLint gshift = osmesa->gshift; +   GLint bshift = osmesa->bshift; +   GLint ashift = osmesa->ashift; +   (void) pv; +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define INTERP_ALPHA 1 +#define INNER_LOOP( LEFT, RIGHT, Y )				\ +{								\ +   GLint i, len = RIGHT-LEFT;					\ +   GLuint *img = PIXELADDR4(LEFT,Y);   				\ +   for (i=0;i<len;i++,img++) {					\ +      GLdepth z = FixedToDepth(ffz);				\ +      if (z < zRow[i]) {					\ +         *img = PACK_RGBA2( FixedToInt(ffr), FixedToInt(ffg),	\ +		            FixedToInt(ffb), FixedToInt(ffa) );	\ +         zRow[i] = z;						\ +      }								\ +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;  ffa += fdadx;\ +      ffz += fdzdx;						\ +   }								\ +} +#ifdef WIN32 +#include "..\tritemp.h" +#else +#include "tritemp.h" +#endif +} + + + + +/* + * Flat-shaded, z-less triangle, RGBA color. + */ +static void flat_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define SETUP_CODE			\ +   GLubyte r = VB->ColorPtr->data[pv][0];	\ +   GLubyte g = VB->ColorPtr->data[pv][1];	\ +   GLubyte b = VB->ColorPtr->data[pv][2];	\ +   GLubyte a = VB->ColorPtr->data[pv][3];	\ +   GLuint pixel = PACK_RGBA(r,g,b,a); + +#define INNER_LOOP( LEFT, RIGHT, Y )	\ +{					\ +   GLint i, len = RIGHT-LEFT;		\ +   GLuint *img = PIXELADDR4(LEFT,Y);   	\ +   for (i=0;i<len;i++,img++) {		\ +      GLdepth z = FixedToDepth(ffz);	\ +      if (z < zRow[i]) {		\ +         *img = pixel;			\ +         zRow[i] = z;			\ +      }					\ +      ffz += fdzdx;			\ +   }					\ +} +#ifdef WIN32 +#include "..\tritemp.h" +#else +#include "tritemp.h" +#endif +} + + + +/* + * Return pointer to an accelerated triangle function if possible. + */ +static triangle_func choose_triangle_function( GLcontext *ctx ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + +   if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) return NULL; + +   if (ctx->Polygon.SmoothFlag)     return NULL; +   if (ctx->Polygon.StippleFlag)    return NULL; +   if (ctx->Texture.Enabled)        return NULL; + +   if (ctx->RasterMask==DEPTH_BIT +       && ctx->Depth.Func==GL_LESS +       && ctx->Depth.Mask==GL_TRUE +       && osmesa->format!=OSMESA_COLOR_INDEX) { +      if (ctx->Light.ShadeModel==GL_SMOOTH) { +         return smooth_rgba_z_triangle; +      } +      else { +         return flat_rgba_z_triangle; +      } +   } +   return NULL; +} + + + +static const GLubyte *get_string( GLcontext *ctx, GLenum name ) +{ +   (void) ctx; +   switch (name) { +      case GL_RENDERER: +         return (const GLubyte *) "Mesa OffScreen"; +      default: +         return NULL; +   } +} + + +static void osmesa_update_state( GLcontext *ctx ) +{ +   OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx; + +   ctx->Driver.GetString = get_string; +   ctx->Driver.UpdateState = osmesa_update_state; + +   ctx->Driver.SetBuffer = set_buffer; +   ctx->Driver.Color = set_color; +   ctx->Driver.Index = set_index; +   ctx->Driver.ClearIndex = clear_index; +   ctx->Driver.ClearColor = clear_color; +   ctx->Driver.Clear = clear; + +   ctx->Driver.GetBufferSize = buffer_size; + +   ctx->Driver.PointsFunc = NULL; +   ctx->Driver.LineFunc = choose_line_function( ctx ); +   ctx->Driver.TriangleFunc = choose_triangle_function( ctx ); + + +   /* RGB(A) span/pixel functions */ +   if ((osmesa->format==OSMESA_RGB) || (osmesa->format==OSMESA_BGR)) { +      /* 3 bytes / pixel in frame buffer */ +      ctx->Driver.WriteRGBASpan = write_rgba_span3; +      ctx->Driver.WriteRGBSpan = write_rgb_span3; +      ctx->Driver.WriteRGBAPixels = write_rgba_pixels3; +      ctx->Driver.WriteMonoRGBASpan = write_monocolor_span3; +      ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels3; +      ctx->Driver.ReadRGBASpan = read_rgba_span3; +      ctx->Driver.ReadRGBAPixels = read_rgba_pixels3; +   } +   else { +      /* 4 bytes / pixel in frame buffer */ +      if (osmesa->format==OSMESA_RGBA +          && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) +         ctx->Driver.WriteRGBASpan = write_rgba_span_rgba; +      else +         ctx->Driver.WriteRGBASpan = write_rgba_span; +      ctx->Driver.WriteRGBSpan = write_rgb_span; +      ctx->Driver.WriteRGBAPixels = write_rgba_pixels; +      ctx->Driver.WriteMonoRGBASpan = write_monocolor_span; +      ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels; +      if (osmesa->format==OSMESA_RGBA +          && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) +         ctx->Driver.ReadRGBASpan = read_rgba_span_rgba; +      else +         ctx->Driver.ReadRGBASpan = read_rgba_span; +      ctx->Driver.ReadRGBAPixels = read_rgba_pixels; +   } + +   /* CI span/pixel functions */ +   ctx->Driver.WriteCI32Span = write_index32_span; +   ctx->Driver.WriteCI8Span = write_index8_span; +   ctx->Driver.WriteMonoCISpan = write_monoindex_span; +   ctx->Driver.WriteCI32Pixels = write_index_pixels; +   ctx->Driver.WriteMonoCIPixels = write_monoindex_pixels; +   ctx->Driver.ReadCI32Span = read_index_span; +   ctx->Driver.ReadCI32Pixels = read_index_pixels; +} diff --git a/src/mesa/drivers/svga/svgamesa.c b/src/mesa/drivers/svga/svgamesa.c new file mode 100644 index 0000000000..4c4d9f793e --- /dev/null +++ b/src/mesa/drivers/svga/svgamesa.c @@ -0,0 +1,540 @@ +/* $Id: svgamesa.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version:  3.0 + * 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. + */ + + + +/* + * Linux SVGA/Mesa interface. + * + * This interface is not finished!  Still have to implement pixel + * reading functions and double buffering.  Then, look into accelerated + * line and polygon rendering.  And, clean up a bunch of other stuff. + * Any volunteers? + */ + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#ifdef SVGA + + +#ifdef PC_HEADER +#include "all.h" +#else +#include <stdio.h> +#include <stdlib.h> +#include <vga.h> +#include "GL/svgamesa.h" +#include "context.h" +#include "matrix.h" +#include "types.h" +#endif + + +struct svgamesa_context { +   GLcontext *gl_ctx;		/* the core Mesa context */ +   GLvisual *gl_vis;		/* describes the color buffer */ +   GLframebuffer *gl_buffer;	/* the ancillary buffers */ +   GLuint index;		/* current color index */ +   GLint red, green, blue;	/* current rgb color */ +   GLint width, height;		/* size of color buffer */ +   GLint depth;			/* bits per pixel (8,16,24 or 32) */ +}; + + +static SVGAMesaContext SVGAMesa = NULL;    /* the current context */ + + + +/* + * Convert Mesa window Y coordinate to VGA screen Y coordinate: + */ +#define FLIP(Y)  (SVGAMesa->height-(Y)-1) + + + +/**********************************************************************/ +/*****                 Miscellaneous functions                    *****/ +/**********************************************************************/ + + +static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height ) +{ +   *width = SVGAMesa->width = vga_getxdim(); +   *height = SVGAMesa->height = vga_getydim(); +} + + +/* Set current color index */ +static void set_index( GLcontext *ctx, GLuint index ) +{ +   SVGAMesa->index = index; +   vga_setcolor( index ); +} + + +/* Set current drawing color */ +static void set_color( GLcontext *ctx, +                       GLubyte red, GLubyte green, +                       GLubyte blue, GLubyte alpha ) +{ +   SVGAMesa->red = red; +   SVGAMesa->green = green; +   SVGAMesa->blue = blue; +   vga_setrgbcolor( red, green, blue ); +} + + +static void clear_index( GLcontext *ctx, GLuint index ) +{ +   /* TODO: Implements glClearIndex() */ +} + + +static void clear_color( GLcontext *ctx, +                         GLubyte red, GLubyte green, +                         GLubyte blue, GLubyte alpha ) +{ +   /* TODO: Implements glClearColor() */ +} + + +static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all, +                         GLint x, GLint y, GLint width, GLint height ) +{ +   if (mask & GL_COLOR_BUFFER_BIT) { +      vga_clear(); +   } +   return mask & (~GL_COLOR_BUFFER_BIT); +} + + +static GLboolean set_buffer( GLcontext *ctx, GLenum buffer ) +{ +   /* TODO: implement double buffering and use this function to select */ +   /* between front and back buffers. */ +   if (buffer == GL_FRONT_LEFT) +      return GL_TRUE; +   else if (buffer == GL_BACK_LEFT) +      return GL_TRUE; +   else +      return GL_FALSE; +} + + + + +/**********************************************************************/ +/*****            Write spans of pixels                           *****/ +/**********************************************************************/ + + +static void write_ci32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, +                             const GLuint index[], const GLubyte mask[] ) +{ +   int i; +   y = FLIP(y); +   for (i=0;i<n;i++,x++) { +      if (mask[i]) { +         vga_setcolor( index[i] ); +         vga_drawpixel( x, y ); +      } +   } +} + +static void write_ci8_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, +                            const GLubyte index[], const GLubyte mask[] ) +{ +   int i; +   y = FLIP(y); +   for (i=0;i<n;i++,x++) { +      if (mask[i]) { +         vga_setcolor( index[i] ); +         vga_drawpixel( x, y ); +      } +   } +} + + + +static void write_mono_ci_span( const GLcontext *ctx, GLuint n, +                                GLint x, GLint y, const GLubyte mask[] ) +{ +   int i; +   y = FLIP(y); +   /* use current color index */ +   vga_setcolor( SVGAMesa->index ); +   for (i=0;i<n;i++,x++) { +      if (mask[i]) { +         vga_drawpixel( x, y ); +      } +   } +} + + + +static void write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, +                             const GLubyte rgba[][4], const GLubyte mask[] ) +{ +   int i; +   y=FLIP(y); +   if (mask) { +      /* draw some pixels */ +      for (i=0; i<n; i++, x++) { +         if (mask[i]) { +            vga_setrgbcolor( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); +            vga_drawpixel( x, y ); +         } +      } +   } +   else { +      /* draw all pixels */ +      for (i=0; i<n; i++, x++) { +         vga_setrgbcolor( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); +         vga_drawpixel( x, y ); +      } +   } +} + + + +static void write_mono_rgba_span( const GLcontext *ctx, +                                  GLuint n, GLint x, GLint y, +                                  const GLubyte mask[]) +{ +   int i; +   y=FLIP(y); +   /* use current rgb color */ +   vga_setrgbcolor( SVGAMesa->red, SVGAMesa->green, SVGAMesa->blue ); +   for (i=0; i<n; i++, x++) { +      if (mask[i]) { +         vga_drawpixel( x, y ); +      } +   } +} + + + +/**********************************************************************/ +/*****                 Read spans of pixels                       *****/ +/**********************************************************************/ + + +static void read_ci32_span( const GLcontext *ctx, +                            GLuint n, GLint x, GLint y, GLuint index[]) +{ +   int i; +   y = FLIP(y); +   for (i=0; i<n; i++,x++) { +      index[i] = vga_getpixel( x, y ); +   } +} + + + +static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, +                            GLubyte rgba[][4] ) +{ +   int i; +   for (i=0; i<n; i++, x++) { +      /* TODO */ +   } +} + + + +/**********************************************************************/ +/*****                  Write arrays of pixels                    *****/ +/**********************************************************************/ + + +static void write_ci32_pixels( const GLcontext *ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               const GLuint index[], const GLubyte mask[] ) +{ +   int i; +   for (i=0; i<n; i++) { +      if (mask[i]) { +         vga_setcolor( index[i] ); +         vga_drawpixel( x[i], FLIP(y[i]) ); +      } +   } +} + + +static void write_mono_ci_pixels( const GLcontext *ctx, GLuint n, +                                  const GLint x[], const GLint y[], +                                  const GLubyte mask[] ) +{ +   int i; +   /* use current color index */ +   vga_setcolor( SVGAMesa->index ); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         vga_drawpixel( x[i], FLIP(y[i]) ); +      } +   } +} + + + +static void write_rgba_pixels( const GLcontext *ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               const GLubyte rgba[][4], const GLubyte mask[] ) +{ +   int i; +   for (i=0; i<n; i++) { +      if (mask[i]) { +         vga_setrgbcolor( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); +         vga_drawpixel( x[i], FLIP(y[i]) ); +      } +   } +} + + + +static void write_mono_rgba_pixels( const GLcontext *ctx, +                                    GLuint n, +                                    const GLint x[], const GLint y[], +                                    const GLubyte mask[] ) +{ +   int i; +   /* use current rgb color */ +   vga_setrgbcolor( SVGAMesa->red, SVGAMesa->green, SVGAMesa->blue ); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         vga_drawpixel( x[i], FLIP(y[i]) ); +      } +   } +} + + + + +/**********************************************************************/ +/*****                   Read arrays of pixels                    *****/ +/**********************************************************************/ + +/* Read an array of color index pixels. */ +static void read_ci32_pixels( const GLcontext *ctx, +                              GLuint n, const GLint x[], const GLint y[], +                              GLuint index[], const GLubyte mask[] ) +{ +   int i; +   for (i=0; i<n; i++,x++) { +      index[i] = vga_getpixel( x[i], FLIP(y[i]) ); +   } +} + + + +static void read_rgba_pixels( const GLcontext *ctx, +                              GLuint n, const GLint x[], const GLint y[], +                              GLubyte rgba[][4], const GLubyte mask[] ) +{ +   /* TODO */ +} + + + +static void svgamesa_update_state( GLcontext *ctx ) +{ +   /* Initialize all the pointers in the DD struct.  Do this whenever */ +   /* a new context is made current or we change buffers via set_buffer! */ + +   ctx->Driver.UpdateState = svgamesa_update_state; + +   ctx->Driver.ClearIndex = clear_index; +   ctx->Driver.ClearColor = clear_color; +   ctx->Driver.Clear = clear; + +   ctx->Driver.Index = set_index; +   ctx->Driver.Color = set_color; + +   ctx->Driver.SetBuffer = set_buffer; +   ctx->Driver.GetBufferSize = get_buffer_size; + +   ctx->Driver.PointsFunc = NULL; +   ctx->Driver.LineFunc = NULL; +   ctx->Driver.TriangleFunc = NULL; + +   /* Pixel/span writing functions: */ +   /* TODO: use different funcs for 8, 16, 32-bit depths */ +   ctx->Driver.WriteRGBASpan        = write_rgba_span; +   ctx->Driver.WriteMonoRGBASpan    = write_mono_rgba_span; +   ctx->Driver.WriteRGBAPixels      = write_rgba_pixels; +   ctx->Driver.WriteMonoRGBAPixels  = write_mono_rgba_pixels; +   ctx->Driver.WriteCI32Span        = write_ci32_span; +   ctx->Driver.WriteCI8Span         = write_ci8_span; +   ctx->Driver.WriteMonoCISpan      = write_mono_ci_span; +   ctx->Driver.WriteCI32Pixels      = write_ci32_pixels; +   ctx->Driver.WriteMonoCIPixels    = write_mono_ci_pixels; + +   /* Pixel/span reading functions: */ +   /* TODO: use different funcs for 8, 16, 32-bit depths */ +   ctx->Driver.ReadCI32Span   = read_ci32_span; +   ctx->Driver.ReadRGBASpan   = read_rgba_span; +   ctx->Driver.ReadCI32Pixels = read_ci32_pixels; +   ctx->Driver.ReadRGBAPixels = read_rgba_pixels; +} + + + +/* + * Create a new VGA/Mesa context and return a handle to it. + */ +SVGAMesaContext SVGAMesaCreateContext( GLboolean doubleBuffer ) +{ +   SVGAMesaContext ctx; +   GLboolean rgb_flag; +   GLfloat redscale, greenscale, bluescale, alphascale; +   GLboolean alpha_flag = GL_FALSE; +   int colors; +   GLint index_bits; +   GLint redbits, greenbits, bluebits, alphabits; + +   /* determine if we're in RGB or color index mode */ +   colors = vga_getcolors(); +   if (colors==32768) { +      rgb_flag = GL_TRUE; +      redscale = greenscale = bluescale = alphascale = 255.0; +      redbits = greenbits = bluebits = 8; +      alphabits = 0; +      index_bits = 0; +   } +   else if (colors==256) { +      rgb_flag = GL_FALSE; +      redscale = greenscale = bluescale = alphascale = 0.0; +      redbits = greenbits = bluebits = alphabits = 0; +      index_bits = 8; +   } +   else { +      printf(">16 bit color not implemented yet!\n"); +      return NULL; +   } + +   ctx = (SVGAMesaContext) calloc( 1, sizeof(struct svgamesa_context) ); +   if (!ctx) { +      return NULL; +   } + +   ctx->gl_vis = gl_create_visual( rgb_flag, +                                   alpha_flag, +                                   doubleBuffer, +                                   GL_FALSE,  /* stereo */ +                                   16,   /* depth_size */ +                                   8,    /* stencil_size */ +                                   16,   /* accum_size */ +                                   index_bits, +                                   redbits, greenbits, +                                   bluebits, alphabits ); + +   ctx->gl_ctx = gl_create_context( ctx->gl_vis, +                                    NULL,  /* share list context */ +                                    (void *) ctx, GL_TRUE ); + +   ctx->gl_buffer = gl_create_framebuffer( ctx->gl_vis ); + +   ctx->index = 1; +   ctx->red = ctx->green = ctx->blue = 255; + +   ctx->width = ctx->height = 0;  /* temporary until first "make-current" */ + +   return ctx; +} + + + + +/* + * Destroy the given VGA/Mesa context. + */ +void SVGAMesaDestroyContext( SVGAMesaContext ctx ) +{ +   if (ctx) { +      gl_destroy_visual( ctx->gl_vis ); +      gl_destroy_context( ctx->gl_ctx ); +      gl_destroy_framebuffer( ctx->gl_buffer ); +      free( ctx ); +      if (ctx==SVGAMesa) { +         SVGAMesa = NULL; +      } +   } +} + + + +/* + * Make the specified VGA/Mesa context the current one. + */ +void SVGAMesaMakeCurrent( SVGAMesaContext ctx ) +{ +   SVGAMesa = ctx; +   svgamesa_update_state( ctx->gl_ctx ); +   gl_make_current( ctx->gl_ctx, ctx->gl_buffer ); + +   if (ctx->width==0 || ctx->height==0) { +      /* setup initial viewport */ +      ctx->width = vga_getxdim(); +      ctx->height = vga_getydim(); +      gl_Viewport( ctx->gl_ctx, 0, 0, ctx->width, ctx->height ); +   } +} + + + +/* + * Return a handle to the current VGA/Mesa context. + */ +SVGAMesaContext SVGAMesaGetCurrentContext( void ) +{ +   return SVGAMesa; +} + + +/* + * Swap front/back buffers for current context if double buffered. + */ +void SVGAMesaSwapBuffers( void ) +{ +   FLUSH_VB( SVGAMesa->gl_ctx, "swap buffers" ); +   if (SVGAMesa->gl_vis->DBflag) { +      vga_flip(); +   } +} + + +#else + +/* + * Need this to provide at least one external definition when SVGA is + * not defined on the compiler command line. + */ + +int gl_svga_dummy_function(void) +{ +   return 0; +} + +#endif  /*SVGA*/ + diff --git a/src/mesa/drivers/windows/colors.h b/src/mesa/drivers/windows/colors.h new file mode 100644 index 0000000000..40ead3040f --- /dev/null +++ b/src/mesa/drivers/windows/colors.h @@ -0,0 +1,499 @@ +/*	File name	:	colors.h
 + *  Version		:	2.3
 + *
 + *  Header file for display driver for Mesa 2.3  under 
 + *	Windows95 and WindowsNT 
 + *	This file defines macros and global variables  needed
 + *	for converting color format
 + *
 + *	Copyright (C) 1996-  Li Wei
 + *  Address		:		Institute of Artificial Intelligence
 + *				:			& Robotics
 + *				:		Xi'an Jiaotong University
 + *  Email		:		liwei@aiar.xjtu.edu.cn
 + *  Web page	:		http://sun.aiar.xjtu.edu.cn
 + *
 + *  This file and its associations are partially based on the 
 + *  Windows NT driver for Mesa, written by Mark Leaming
 + *  (mark@rsinc.com).
 + */
 +
 +/* $Log: ddcolors.h 1997/6/14 by Li Wei(liwei@aiar.xjtu.edu.cn)
 + * Macros for pixel format defined
 + */
 +
 +/*
 + * $Log: colors.h,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.2  1999/01/03 03:08:57  brianp + * Ted Jump's changes + * + * Revision 1.1  1999/01/03 03:08:12  brianp + * Initial revision + *
 + * Revision 2.0.2  1997/4/30 15:58:00  CST by Li Wei(liwei@aiar.xjtu.edu.cn)
 + * Add LUTs need for dithering
 + */
 +
 +/*
 + * $Log: colors.h,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.2  1999/01/03 03:08:57  brianp + * Ted Jump's changes + * + * Revision 1.1  1999/01/03 03:08:12  brianp + * Initial revision + *
 + * Revision 2.0.1  1997/4/29 15:52:00  CST by Li Wei(liwei@aiar.xjtu.edu.cn)
 + * Add BGR8 Macro
 + */
 + 
 +/*
 + * $Log: colors.h,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.2  1999/01/03 03:08:57  brianp + * Ted Jump's changes + * + * Revision 1.1  1999/01/03 03:08:12  brianp + * Initial revision + *
 + * Revision 2.0  1996/11/15 10:55:00  CST by Li Wei(liwei@aiar.xjtu.edu.cn)
 + * Initial revision
 + */
 +/* Values for wmesa->pixelformat: */
 +
 +#define PF_8A8B8G8R	3	/* 32-bit TrueColor:  8-A, 8-B, 8-G, 8-R */
 +#define PF_8R8G8B	4	/* 32-bit TrueColor:  8-R, 8-G, 8-B */
 +#define PF_5R6G5B	5	/* 16-bit TrueColor:  5-R, 6-G, 5-B bits */
 +#define PF_DITHER8	6	/* Dithered RGB using a lookup table */
 +#define PF_LOOKUP	7	/* Undithered RGB using a lookup table */
 +#define PF_GRAYSCALE	10	/* Grayscale or StaticGray */
 +#define PF_BADFORMAT	11
 +#define PF_INDEX8		12
 +
 +char ColorMap16[] = {
 +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
 +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
 +0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
 +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
 +0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
 +0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
 +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
 +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
 +0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
 +0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,
 +0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,
 +0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,
 +0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
 +0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,
 +0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
 +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
 +0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
 +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
 +0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
 +0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
 +0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
 +0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
 +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
 +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
 +0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
 +0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,
 +0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,
 +0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,
 +0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,
 +0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,
 +0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
 +
 +#define BGR8(r,g,b)		(unsigned)(((BYTE)(b & 0xc0 | (g & 0xe0)>>2 | (r & 0xe0)>>5)))
 +#ifdef DDRAW
 +#define BGR16(r,g,b)	((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(g&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[r])) << 11)))
 +#else
 +#define BGR16(r,g,b)	((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(ColorMap16[g]) << 5)) | (((WORD)(BYTE)(ColorMap16[r])) << 10)))
 +#endif
 +#define BGR24(r,g,b)	(unsigned long)(((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) << 8)
 +#define BGR32(r,g,b)	(unsigned long)((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16)))
 +
 +
 +
 +/*
 + * If pixelformat==PF_8A8B8G8R:
 + */
 +#define PACK_8A8B8G8R( R, G, B, A )	\
 +	( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
 +
 +
 +/*
 + * If pixelformat==PF_8R8G8B:
 + */
 +#define PACK_8R8G8B( R, G, B)	 ( ((R) << 16) | ((G) << 8) | (B) )
 +
 +
 +/*
 + * If pixelformat==PF_5R6G5B:
 + */
 +
 +
 +#ifdef DDRAW
 +#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(G&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[R])) << 11)))
 +#else
 +#define PACK_5R6G5B( R, G, B)	((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(ColorMap16[G]) << 5)) | (((WORD)(BYTE)(ColorMap16[R])) << 10)))
 +#endif
 +/*----------------------------------------------------------------------------
 +
 +Division lookup tables.  These tables compute 0-255 divided by 51 and
 +modulo 51.  These tables could approximate gamma correction.
 +
 +*/
 +
 +char unsigned const aDividedBy51Rounded[256] =
 +{
 +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 +  0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 +  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 +  1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 +  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 +  2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 +  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 +  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 +  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 +  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 +  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 +};
 +
 +char unsigned const aDividedBy51[256] =
 +{
 +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 +  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 +  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 +  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 +  1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 +  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 +  2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 +  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 +  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 +  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 +  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 
 +};
 +
 +char unsigned const aModulo51[256] =
 +{
 +  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
 +  20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
 +  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6,
 +  7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
 +  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
 +  44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
 +  13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
 +  31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
 +  49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
 +  18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
 +  36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3,
 +  4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
 +  23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
 +  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 
 +};
 +
 +/*----------------------------------------------------------------------------
 +
 +Multiplication LUTs.  These compute 0-5 times 6 and 36.
 +
 +*/
 +
 +char unsigned const aTimes6[6] =
 +{
 +  0, 6, 12, 18, 24, 30
 +};
 +
 +char unsigned const aTimes36[6] =
 +{
 +  0, 36, 72, 108, 144, 180
 +};
 +
 +
 +/*----------------------------------------------------------------------------
 +
 +Dither matrices for 8 bit to 2.6 bit halftones.
 +
 +*/
 +
 +char unsigned const aHalftone16x16[256] =
 +{
 +  0, 44, 9, 41, 3, 46, 12, 43, 1, 44, 10, 41, 3, 46, 12, 43,
 +  34, 16, 25, 19, 37, 18, 28, 21, 35, 16, 26, 19, 37, 18, 28, 21,
 +  38, 6, 47, 3, 40, 9, 50, 6, 38, 7, 47, 4, 40, 9, 49, 6,
 +  22, 28, 13, 31, 25, 31, 15, 34, 22, 29, 13, 32, 24, 31, 15, 34,
 +  2, 46, 12, 43, 1, 45, 10, 42, 2, 45, 11, 42, 1, 45, 11, 42,
 +  37, 18, 27, 21, 35, 17, 26, 20, 36, 17, 27, 20, 36, 17, 26, 20,
 +  40, 8, 49, 5, 38, 7, 48, 4, 39, 8, 48, 5, 39, 7, 48, 4,
 +  24, 30, 15, 33, 23, 29, 13, 32, 23, 30, 14, 33, 23, 29, 14, 32,
 +  2, 46, 12, 43, 0, 44, 10, 41, 3, 47, 12, 44, 0, 44, 10, 41,
 +  37, 18, 27, 21, 35, 16, 25, 19, 37, 19, 28, 22, 35, 16, 25, 19,
 +  40, 9, 49, 5, 38, 7, 47, 4, 40, 9, 50, 6, 38, 6, 47, 3,
 +  24, 30, 15, 34, 22, 29, 13, 32, 25, 31, 15, 34, 22, 28, 13, 31,
 +  1, 45, 11, 42, 2, 46, 11, 42, 1, 45, 10, 41, 2, 46, 11, 43,
 +  36, 17, 26, 20, 36, 17, 27, 21, 35, 16, 26, 20, 36, 18, 27, 21,
 +  39, 8, 48, 4, 39, 8, 49, 5, 38, 7, 48, 4, 39, 8, 49, 5,
 +  23, 29, 14, 33, 24, 30, 14, 33, 23, 29, 13, 32, 24, 30, 14, 33,
 +};
 +
 +char unsigned const aHalftone8x8[64] =
 +{
 +   0, 38,  9, 47,  2, 40, 11, 50,
 +  25, 12, 35, 22, 27, 15, 37, 24,
 +   6, 44,  3, 41,  8, 47,  5, 43,
 +  31, 19, 28, 15, 34, 21, 31, 18,
 +   1, 39, 11, 49,  0, 39, 10, 48,
 +  27, 14, 36, 23, 26, 13, 35, 23,
 +   7, 46,  4, 43,  7, 45,  3, 42,
 +  33, 20, 30, 17, 32, 19, 29, 16,
 +};
 +
 +char unsigned const aHalftone4x4_1[16] =
 +{
 +  0, 25, 6, 31,
 +  38, 12, 44, 19,
 +  9, 35, 3, 28,
 +  47, 22, 41, 15
 +};
 +
 +char unsigned const aHalftone4x4_2[16] =
 +{
 +  41, 3, 9, 28,
 +  35, 15, 22, 47,
 +  6, 25, 38, 0,
 +  19, 44, 31, 12
 +};
 +
 +/***************************************************************************
 +  aWinGHalftoneTranslation
 +
 +  Translates a 2.6 bit-per-pixel halftoned representation into the
 +  slightly rearranged WinG Halftone Palette.
 +*/
 +
 +char unsigned const aWinGHalftoneTranslation[216] =
 +{
 +  0,
 +  29,
 +  30,
 +  31,
 +  32,
 +  249,
 +  33,
 +  34,
 +  35,
 +  36,
 +  37,
 +  38,
 +  39,
 +  40,
 +  41,
 +  42,
 +  43,
 +  44,
 +  45,
 +  46,
 +  47,
 +  48,
 +  49,
 +  50,
 +  51,
 +  52,
 +  53,
 +  54,
 +  55,
 +  56,
 +  250,
 +  250,
 +  57,
 +  58,
 +  59,
 +  251,
 +  60,
 +  61,
 +  62,
 +  63,
 +  64,
 +  65,
 +  66,
 +  67,
 +  68,
 +  69,
 +  70,
 +  71,
 +  72,
 +  73,
 +  74,
 +  75,
 +  76,
 +  77,
 +  78,
 +  79,
 +  80,
 +  81,
 +  82,
 +  83,
 +  84,
 +  85,
 +  86,
 +  87,
 +  88,
 +  89,
 +  250,
 +  90,
 +  91,
 +  92,
 +  93,
 +  94,
 +  95,
 +  96,
 +  97,
 +  98,
 +  99,
 +  100,
 +  101,
 +  102,
 +  103,
 +  104,
 +  105,
 +  106,
 +  107,
 +  108,
 +  109,
 +  110,
 +  111,
 +  227,
 +  112,
 +  113,
 +  114,
 +  115,
 +  116,
 +  117,
 +  118,
 +  119,
 +  151,
 +  120,
 +  121,
 +  122,
 +  123,
 +  124,
 +  228,
 +  125,
 +  126,
 +  229,
 +  133,
 +  162,
 +  135,
 +  131,
 +  132,
 +  137,
 +  166,
 +  134,
 +  140,
 +  130,
 +  136,
 +  143,
 +  138,
 +  139,
 +  174,
 +  141,
 +  142,
 +  177,
 +  129,
 +  144,
 +  145,
 +  146,
 +  147,
 +  148,
 +  149,
 +  150,
 +  157,
 +  152,
 +  153,
 +  154,
 +  155,
 +  156,
 +  192,
 +  158,
 +  159,
 +  160,
 +  161,
 +  196,
 +  163,
 +  164,
 +  165,
 +  127,
 +  199,
 +  167,
 +  168,
 +  169,
 +  170,
 +  171,
 +  172,
 +  173,
 +  207,
 +  175,
 +  176,
 +  210,
 +  178,
 +  179,
 +  180,
 +  181,
 +  182,
 +  183,
 +  184,
 +  185,
 +  186,
 +  187,
 +  188,
 +  189,
 +  190,
 +  191,
 +  224,
 +  193,
 +  194,
 +  195,
 +  252,
 +  252,
 +  197,
 +  198,
 +  128,
 +  253,
 +  252,
 +  200,
 +  201,
 +  202,
 +  203,
 +  204,
 +  205,
 +  206,
 +  230,
 +  208,
 +  209,
 +  231,
 +  211,
 +  212,
 +  213,
 +  214,
 +  215,
 +  216,
 +  217,
 +  218,
 +  219,
 +  220,
 +  221,
 +  222,
 +  254,
 +  223,
 +  232,
 +  225,
 +  226,
 +  255,
 +};
\ No newline at end of file diff --git a/src/mesa/drivers/windows/mesa_extend.c b/src/mesa/drivers/windows/mesa_extend.c new file mode 100644 index 0000000000..933e3badd3 --- /dev/null +++ b/src/mesa/drivers/windows/mesa_extend.c @@ -0,0 +1,211 @@ +/* File: mesa_extend.c for wmesa-2.3
 +   Written by Li Wei (liwei@aiar.xjtu.edu.cn)
 +*/
 +
 +/*******************************************************************
 + Users can use the following keys to control the view
 +
 + The following four key combinations can shift the view correspondingly,
 + function in both stereo and normal mode.
 + Ctrl+left arrow
 + Ctrl+right arrow
 + Ctrl+up arrow
 + Ctrl+down arrow
 +
 + F (captital letter) shift the camera far from objects
 + N (captital letter) shift the camera near from objects
 + S (captital letter) toggle between normal and stereo mode
 + I (captital letter) increase the distance between two views
 + D (captital letter) decrease the distance between two views
 +
 + if the Key function defined by user maps any key appearing above, it will be
 + masked by the program. Hence, user should either modify his own code or
 + modify function defaultKeyProc at the end of this file 
 +*******************************************************************/
 +
 +/* Log 6/14, 1997
 + * revision 1.01
 + * struct DisplayOptions defined for tk_ddmesa.c to read the initial file
 + */
 +
 +#include "mesa_extend.h"
 +#include "gltk.h"
 +#include <stdio.h>
 +#ifndef NO_STEREO
 +	#include "stereo.h"
 +#endif
 +#ifndef NO_PARALLEL
 +//	#include "parallel.h"
 +#endif
 +
 +GLenum (*userKeyProc) (int, GLenum) = NULL;
 +
 +GLfloat viewDistance = 1.0;
 +GLfloat deltaView = 0.1;
 +GLfloat deltaShift = 0.1;
 +
 +GLuint viewShift = SHIFT_NONE;
 +GLuint viewTag = 0 ;
 +
 +GLenum imageRendered = GL_FALSE;
 +
 +GLenum glImageRendered()
 +{
 +	return imageRendered; 
 +}
 +
 +//Code added by Li Wei to enable stereo display
 +GLenum defaultKeyProc(int key, GLenum mask )
 +{
 +	GLenum flag = GL_FALSE ;
 +	if(mask & TK_CONTROL){
 +	flag = GL_TRUE ;
 +	switch(key){
 +		case TK_LEFT:
 +		viewShift = SHIFT_LEFT;
 +		break;
 +		case TK_RIGHT:
 +		viewShift = SHIFT_RIGHT;
 +		break;
 +		case TK_UP:
 +		viewShift = SHIFT_UP;
 +		break;
 +		case TK_DOWN:
 +		viewShift = SHIFT_DOWN;
 +		break;
 +		default:
 +			flag = GL_FALSE ;
 +		}
 +	}
 +	if(flag == GL_FALSE){
 +	flag = GL_TRUE ;
 +	switch(key){
 +		case TK_F:
 +		viewShift = SHIFT_FAR;
 +		break;
 +		case TK_N:
 +		viewShift = SHIFT_NEAR;
 +		break;
 +
 +#if !defined(NO_STEREO)
 +		case TK_D:
 +		viewDistance-= deltaView;
 +		break;
 +		case TK_I:
 +		viewDistance+= deltaView;
 +		break;
 +		case TK_S:
 +		toggleStereoMode();
 +		break;
 +#endif
 +
 +#if !defined(NO_PARALLEL)
 +		case TK_P:
 +		if(machineType == MASTER)
 +			toggleParallelMode();
 +		break;
 +#endif
 +		default:
 +			flag = GL_FALSE;
 +		}
 +		}
 +
 +	if(userKeyProc)
 +		flag=flag||(*userKeyProc)(key, mask);
 +
 +#if !defined(NO_PARALLEL)
 +	if(parallelFlag&&key!=TK_P&&machineType == MASTER){
 +		PRKeyDown(key,mask);
 +	}
 +#endif
 +
 +	return flag;
 +}
 +
 +/* The following function implemented key board control of the display,
 +	availabe even in normal mode so long the driver is linked into exe file.
 +*/
 +void shiftView()
 +{
 +	GLfloat cm[16];
 +	if(viewShift != SHIFT_NONE){
 +/*	glGetFloatv(GL_MODELVIEW_MATRIX,cm);
 +	glMatrixMode(GL_MODELVIEW);
 +*/
 +    GLint matrix_mode;
 +    glGetIntegerv(GL_MATRIX_MODE,&matrix_mode);
 +/*	if(matrix_mode!=GL_PROJECTION)
 +        glMatrixMode(GL_PROJECTION);
 +    glGetFloatv(GL_PROJECTION_MATRIX,cm);
 +    glLoadIdentity();
 +	switch(viewShift){
 +		case SHIFT_LEFT:
 +			glTranslatef(-deltaShift,0,0);
 +			break;
 +		case SHIFT_RIGHT:
 +			glTranslatef(deltaShift,0,0);
 +			break;
 +		case SHIFT_UP:
 +			glTranslatef(0,deltaShift,0);
 +			break;
 +		case SHIFT_DOWN:
 +			glTranslatef(0,-deltaShift,0);
 +			break;
 +		case SHIFT_FAR:
 +			glTranslatef(0,0,-deltaShift);
 +			break;
 +		case SHIFT_NEAR:
 +			glTranslatef(0,0,deltaShift);
 +			break;
 +		}
 +
 +		viewShift = SHIFT_NONE;
 +		glMultMatrixf( cm );
 +        if(matrix_mode!=GL_PROJECTION)
 +            glMatrixMode(matrix_mode);
 +
 +	}
 +*/
 +	if(matrix_mode!=GL_MODELVIEW)
 +        glMatrixMode(GL_MODELVIEW);
 +    glGetFloatv(GL_MODELVIEW_MATRIX,cm);
 +    glLoadIdentity();
 +	switch(viewShift){
 +		case SHIFT_LEFT:
 +			glTranslatef(-deltaShift,0,0);
 +			break;
 +		case SHIFT_RIGHT:
 +			glTranslatef(deltaShift,0,0);
 +			break;
 +		case SHIFT_UP:
 +			glTranslatef(0,deltaShift,0);
 +			break;
 +		case SHIFT_DOWN:
 +			glTranslatef(0,-deltaShift,0);
 +			break;
 +		case SHIFT_FAR:
 +			glTranslatef(0,0,-deltaShift);
 +			break;
 +		case SHIFT_NEAR:
 +			glTranslatef(0,0,deltaShift);
 +			break;
 +		}
 +
 +		viewShift = SHIFT_NONE;
 +		glMultMatrixf( cm );
 +        if(matrix_mode!=GL_MODELVIEW)
 +            glMatrixMode(matrix_mode);
 +
 +	}
 +}
 +
 +
 +void getDisplayOptions( void)
 +{
 +	displayOptions.stereo = GetPrivateProfileInt("DISPLAY", "STEREO",1,"ddmesa.ini" );
 +	displayOptions.fullScreen = GetPrivateProfileInt("DISPLAY", "FULLSCREEN",0,"ddmesa.ini" );
 +	displayOptions.mode = GetPrivateProfileInt("DISPLAY", "MODE",1, "ddmesa.ini");
 +	displayOptions.bpp = GetPrivateProfileInt("DISPLAY", "BPP", 32, "ddmesa.ini");
 +
 +}
 +//end modification
 diff --git a/src/mesa/drivers/windows/mesa_extend.h b/src/mesa/drivers/windows/mesa_extend.h new file mode 100644 index 0000000000..66a8a77d65 --- /dev/null +++ b/src/mesa/drivers/windows/mesa_extend.h @@ -0,0 +1,43 @@ +/* mesa_extend.h
 + * for wmesa-2.3
 + *  Written by Li Wei (liwei@aiar.xjtu.edu.cn)
 + */
 +
 +/* Log 6/14, 1997
 + * revision 1.01
 + * struct DisplayOptions defined for tk_ddmesa.c to read the initial file
 + */
 +
 +#include <GL/gl.h>
 +#include <stdlib.h>
 +#include <windows.h>
 +#include <winbase.h>
 +
 +typedef enum SHIFT{ SHIFT_NONE, SHIFT_LEFT,SHIFT_RIGHT,SHIFT_UP,SHIFT_DOWN,SHIFT_FAR,SHIFT_NEAR};
 +
 +extern GLfloat deltaView ;
 +
 +extern GLuint viewShift;
 +
 +extern GLenum glImageRendered();
 +
 +extern GLenum imageRendered ;
 +
 +extern GLfloat deltaView ;
 +
 +extern GLfloat deltaShift;
 +
 +void shiftView( void );
 +
 +struct DISPLAY_OPTIONS {
 +	int  stereo;
 +	int  fullScreen;
 +	int	 mode;
 +	int	 bpp;
 +};
 +
 +extern struct DISPLAY_OPTIONS displayOptions;
 +extern void getDisplayOptions( void);
 +
 +GLenum defaultKeyProc(int, GLenum);
 +extern GLenum (*userKeyProc) (int, GLenum);
 diff --git a/src/mesa/drivers/windows/stereo.h b/src/mesa/drivers/windows/stereo.h new file mode 100644 index 0000000000..544af54235 --- /dev/null +++ b/src/mesa/drivers/windows/stereo.h @@ -0,0 +1,47 @@ +/* File name stereov.h
 +   header file for stereo display driver 
 +***************************************************************
 +*                     WMesa                                   *
 +*                     version 2.3                             *	
 +*                                                             *
 +*                        By                                   *
 +*                      Li Wei                                 *
 +*       Institute of Artificial Intelligence & Robotics       *
 +*       Xi'an Jiaotong University                             *
 +*       Email: liwei@aiar.xjtu.edu.cn                         * 
 +*       Web page: http://sun.aiar.xjtu.edu.cn                 *
 +*                                                             *
 +*	       July 7th, 1997				                      *	
 +***************************************************************
 +
 +*/
 +#if defined( __WIN32__) || defined (WIN32)
 +   #include <windows.h>
 +#endif
 +
 +typedef enum VIEW_INDICATOR { FIRST, SECOND};
 +
 +#define MAXIMUM_DISPLAY_LIST 99
 +
 +extern GLenum stereoBuffer;
 +
 +extern GLint displayList;
 +
 +extern GLint stereo_flag ;
 +
 +extern GLfloat viewDistance;
 +
 +extern GLuint viewTag;
 +
 +extern GLuint displayListBase;
 +
 +extern GLuint numOfLists;
 +
 +extern GLenum stereoCompile;
 +
 +extern GLenum stereoShowing;
 +
 +extern void glShowStereo(GLuint list);
 +
 +extern void toggleStereoMode();
 +
 diff --git a/src/mesa/drivers/windows/wgl.c b/src/mesa/drivers/windows/wgl.c new file mode 100644 index 0000000000..d5f577dd81 --- /dev/null +++ b/src/mesa/drivers/windows/wgl.c @@ -0,0 +1,518 @@ +/* $Id: wgl.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
 +
 +/*
 +* 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.
 +*
 +*/
 +
 +/*
 +* File name 	: wgl.c
 +* WGL stuff. Added by Oleg Letsinsky, ajl@ultersys.ru
 +* Some things originated from the 3Dfx WGL functions
 +*/
 +
 +#ifdef WIN32
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +#include <windows.h>
 +
 +#include <GL/gl.h>
 +#include <GL/glu.h>
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#include <stdio.h>
 +#include <tchar.h>
 +#include "wmesadef.h"
 +#include "GL/wmesa.h"
 +#include "types.h"
 +
 +#define MAX_MESA_ATTRS	20
 +
 +struct __extensions__
 +{
 +    PROC	proc;
 +    char	*name;
 +};
 +
 +struct __pixelformat__
 +{
 +    PIXELFORMATDESCRIPTOR	pfd;
 +    GLboolean doubleBuffered;
 +};
 +
 +struct __extensions__	ext[] = {
 +
 +#ifdef GL_EXT_polygon_offset
 +   { (PROC)glPolygonOffsetEXT,			"glPolygonOffsetEXT"		},
 +#endif
 +   { (PROC)glBlendEquationEXT,			"glBlendEquationEXT"		},
 +   { (PROC)glBlendColorEXT,			"glBlendColorExt"		},
 +   { (PROC)glVertexPointerEXT,			"glVertexPointerEXT"		},
 +   { (PROC)glNormalPointerEXT,			"glNormalPointerEXT"		},
 +   { (PROC)glColorPointerEXT,			"glColorPointerEXT"		},
 +   { (PROC)glIndexPointerEXT,			"glIndexPointerEXT"		},
 +   { (PROC)glTexCoordPointerEXT,		"glTexCoordPointer"		},
 +   { (PROC)glEdgeFlagPointerEXT,		"glEdgeFlagPointerEXT"		},
 +   { (PROC)glGetPointervEXT,			"glGetPointervEXT"		},
 +   { (PROC)glArrayElementEXT,			"glArrayElementEXT"		},
 +   { (PROC)glDrawArraysEXT,			"glDrawArrayEXT"		},
 +   { (PROC)glAreTexturesResidentEXT,		"glAreTexturesResidentEXT"	},
 +   { (PROC)glBindTextureEXT,			"glBindTextureEXT"		},
 +   { (PROC)glDeleteTexturesEXT,			"glDeleteTexturesEXT"		},
 +   { (PROC)glGenTexturesEXT,			"glGenTexturesEXT"		},
 +   { (PROC)glIsTextureEXT,			"glIsTextureEXT"		},
 +   { (PROC)glPrioritizeTexturesEXT,		"glPrioritizeTexturesEXT"	},
 +   { (PROC)glCopyTexSubImage3DEXT,		"glCopyTexSubImage3DEXT"	},
 +   { (PROC)glTexImage3DEXT,			"glTexImage3DEXT"		},
 +   { (PROC)glTexSubImage3DEXT,			"glTexSubImage3DEXT"		},
 +   { (PROC)glColorTableEXT,			"glColorTableEXT"		},
 +   { (PROC)glColorSubTableEXT,			"glColorSubTableEXT"		},
 +   { (PROC)glGetColorTableEXT,			"glGetColorTableEXT"		},
 +   { (PROC)glGetColorTableParameterfvEXT,	"glGetColorTableParameterfvEXT"	},
 +   { (PROC)glGetColorTableParameterivEXT,	"glGetColorTableParameterivEXT"	},
 +   { (PROC)glPointParameterfEXT,		"glPointParameterfEXT"		},
 +   { (PROC)glPointParameterfvEXT,		"glPointParameterfvEXT"		},
 +   { (PROC)glBlendFuncSeparateINGR,		"glBlendFuncSeparateINGR"	},
 +   { (PROC)glLockArraysEXT,			"glLockArraysEXT"		},
 +   { (PROC)glUnlockArraysEXT,			"glUnlockArraysEXT"		}
 +};
 +
 +int qt_ext = sizeof(ext) / sizeof(ext[0]);
 +
 +struct __pixelformat__	pix[] =
 +{
 +    {	{	sizeof(PIXELFORMATDESCRIPTOR),	1,
 +        PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
 +        PFD_TYPE_RGBA,
 +        24,	8,	0,	8,	8,	8,	16,	8,	24,
 +        0,	0,	0,	0,	0,	16,	8,	0,	0,	0,	0,	0,	0 },
 +        GL_TRUE
 +    },
 +    {	{	sizeof(PIXELFORMATDESCRIPTOR),	1,
 +        PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT,
 +        PFD_TYPE_RGBA,
 +        24,	8,	0,	8,	8,	8,	16,	8,	24,
 +        0,	0,	0,	0,	0,	16,	8,	0,	0,	0,	0,	0,	0 },
 +        GL_FALSE
 +    },
 +};
 +
 +int				qt_pix = sizeof(pix) / sizeof(pix[0]);
 +
 +typedef struct {
 +    WMesaContext ctx;
 +    HDC hdc;
 +} MesaWglCtx;
 +
 +#define MESAWGL_CTX_MAX_COUNT 20
 +
 +static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT];
 +
 +static unsigned ctx_count = 0;
 +static unsigned ctx_current = -1;
 +static unsigned curPFD = 0;
 +
 +GLAPI BOOL GLWINAPI wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
 +{
 +    return(FALSE);
 +}
 +
 +GLAPI HGLRC GLWINAPI wglCreateContext(HDC hdc)
 +{
 +    HWND		hWnd;
 +    int i = 0;
 +    if(!(hWnd = WindowFromDC(hdc)))
 +    {
 +        SetLastError(0);
 +        return(NULL);
 +    }
 +    if (!ctx_count)
 +    {
 +    	for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++)
 +    	{
 +    		wgl_ctx[i].ctx = NULL;
 +    		wgl_ctx[i].hdc = NULL;
 +    	}
 +    }
 +    for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
 +    {
 +        if ( wgl_ctx[i].ctx == NULL )
 +        {
 +            wgl_ctx[i].ctx = WMesaCreateContext( hWnd, NULL, GL_TRUE,
 +                pix[curPFD-1].doubleBuffered );
 +            if (wgl_ctx[i].ctx == NULL)
 +                break;
 +            wgl_ctx[i].hdc = hdc;
 +            ctx_count++;
 +            return ((HGLRC)wgl_ctx[i].ctx);
 +        }
 +    }
 +    SetLastError(0);
 +    return(NULL);
 +}
 +
 +GLAPI BOOL GLWINAPI wglDeleteContext(HGLRC hglrc)
 +{
 +    int i;
 +    for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
 +    {
 +    	if ( wgl_ctx[i].ctx == (PWMC) hglrc )
 +    	{
 +            WMesaMakeCurrent((PWMC) hglrc);
 +            WMesaDestroyContext();
 +            wgl_ctx[i].ctx = NULL;
 +            wgl_ctx[i].hdc = NULL;
 +            ctx_count--;
 +            return(TRUE);
 +    	}
 +    }
 +    SetLastError(0);
 +    return(FALSE);
 +}
 +
 +GLAPI HGLRC GLWINAPI wglCreateLayerContext(HDC hdc,int iLayerPlane)
 +{
 +    SetLastError(0);
 +    return(NULL);
 +}
 +
 +GLAPI HGLRC GLWINAPI wglGetCurrentContext(VOID)
 +{
 +   if (ctx_current < 0)
 +      return 0;
 +   else
 +      return (HGLRC) wgl_ctx[ctx_current].ctx;
 +}
 +
 +GLAPI HDC GLWINAPI wglGetCurrentDC(VOID)
 +{
 +   if (ctx_current < 0)
 +      return 0;
 +   else
 +      return wgl_ctx[ctx_current].hdc;
 +}
 +
 +GLAPI BOOL GLWINAPI wglMakeCurrent(HDC hdc,HGLRC hglrc)
 +{
 +    int i;
 +
 +    /* new code suggested by Andy Sy */
 +    if (!hdc || !hglrc) {
 +       WMesaMakeCurrent(NULL);
 +       ctx_current = -1;
 +       return TRUE;
 +    }
 +
 +    for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
 +    {
 +        if ( wgl_ctx[i].ctx == (PWMC) hglrc )
 +        {
 +            wgl_ctx[i].hdc = hdc;
 +            WMesaMakeCurrent( (WMesaContext) hglrc );
 +            ctx_current = i;
 +            return TRUE;
 +        }
 +    }
 +    return FALSE;
 +}
 +
 +GLAPI BOOL GLWINAPI wglShareLists(HGLRC hglrc1,HGLRC hglrc2)
 +{
 +    return(TRUE);
 +}
 +
 + +static FIXED FixedFromDouble(double d) +{ +   long l = (long) (d * 65536L); +   return *(FIXED *)&l; +} + + +GLAPI BOOL GLWINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, +                                       DWORD count, DWORD listBase) +{ +   int i; +   GLuint font_list; +   DWORD size; +   GLYPHMETRICS gm; +   HANDLE hBits; +   LPSTR lpBits; +   MAT2 mat; + +   if (first<0) +      return FALSE; +   if (count<0) +      return FALSE; +   if (listBase<0) +      return FALSE; + +   font_list = glGenLists( count ); +   if(font_list == 0) +      return FALSE; + +   mat.eM11 = FixedFromDouble(1); +   mat.eM12 = FixedFromDouble(0); +   mat.eM21 = FixedFromDouble(0); +   mat.eM22 = FixedFromDouble(1); + +   memset(&gm,0,sizeof(gm)); + +   for (i = 0; i < count; i++) +   { +      glNewList( font_list+i, GL_COMPILE ); + +      /* allocate space for the bitmap/outline */ +      size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0, NULL, &mat); +      if (size == GDI_ERROR) +      { +         DWORD err; +         err = GetLastError(); +         return(FALSE); +      } + +      hBits  = GlobalAlloc(GHND, size); +      lpBits = GlobalLock(hBits); + +      GetGlyphOutline(hdc,    /* handle to device context */ +                      first + i,          /* character to query */ +                      GGO_BITMAP,         /* format of data to return */ +                      &gm,                /* pointer to structure for metrics */ +                      size,               /* size of buffer for data */ +                      lpBits,             /* pointer to buffer for data */ +                      &mat                /* pointer to transformation */ +                                          /* matrix structure */ +                  ); + +      if (*lpBits == GDI_ERROR) +      { +         DWORD err; +         err = GetLastError(); + +         GlobalUnlock(hBits); +         GlobalFree(hBits); + +         return(FALSE); +      } + +      glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY, +               gm.gmptGlyphOrigin.x, +               gm.gmptGlyphOrigin.y, +               gm.gmCellIncX,gm.gmCellIncY, +               (const GLubyte * )lpBits); + +      GlobalUnlock(hBits); +      GlobalFree(hBits); + +      glEndList( ); +   } + +    return TRUE; +} +
 +GLAPI BOOL GLWINAPI wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase)
 +{
 +    return FALSE;
 +}
 +
 +GLAPI BOOL GLWINAPI wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count,
 +                                  DWORD listBase,FLOAT deviation,
 +                                  FLOAT extrusion,int format,
 +                                  LPGLYPHMETRICSFLOAT lpgmf)
 +{
 +    SetLastError(0);
 +    return(FALSE);
 +}
 +
 +GLAPI BOOL GLWINAPI wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count,
 +                                  DWORD listBase,FLOAT deviation,
 +                                  FLOAT extrusion,int format,
 +                                  LPGLYPHMETRICSFLOAT lpgmf)
 +{
 +    SetLastError(0);
 +    return(FALSE);
 +}
 +
 +GLAPI BOOL GLWINAPI wglDescribeLayerPlane(HDC hdc,int iPixelFormat,
 +                                    int iLayerPlane,UINT nBytes,
 +                                    LPLAYERPLANEDESCRIPTOR plpd)
 +{
 +    SetLastError(0);
 +    return(FALSE);
 +}
 +
 +GLAPI int GLWINAPI wglSetLayerPaletteEntries(HDC hdc,int iLayerPlane,
 +                                       int iStart,int cEntries,
 +                                       CONST COLORREF *pcr)
 +{
 +    SetLastError(0);
 +    return(0);
 +}
 +
 +GLAPI int GLWINAPI wglGetLayerPaletteEntries(HDC hdc,int iLayerPlane,
 +                                       int iStart,int cEntries,
 +                                       COLORREF *pcr)
 +{
 +    SetLastError(0);
 +    return(0);
 +}
 +
 +GLAPI BOOL GLWINAPI wglRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)
 +{
 +    SetLastError(0);
 +    return(FALSE);
 +}
 +
 +GLAPI BOOL GLWINAPI wglSwapLayerBuffers(HDC hdc,UINT fuPlanes)
 +{
 +    if( !hdc )
 +    {
 +        WMesaSwapBuffers();
 +        return(TRUE);
 +    }
 +    SetLastError(0);
 +    return(FALSE);
 +}
 +
 +GLAPI int GLWINAPI wglChoosePixelFormat(HDC hdc,
 +                                  CONST PIXELFORMATDESCRIPTOR *ppfd)
 +{
 +    int		i,best = -1,bestdelta = 0x7FFFFFFF,delta,qt_valid_pix;
 +
 +    qt_valid_pix = qt_pix;
 +    if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1)
 +    {
 +        SetLastError(0);
 +        return(0);
 +    }
 +    for(i = 0;i < qt_valid_pix;i++)
 +    {
 +        delta = 0;
 +        if(
 +            (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) &&
 +            !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
 +            continue;
 +        if(
 +            (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) &&
 +            !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
 +            continue;
 +        if(
 +            (ppfd->dwFlags & PFD_SUPPORT_GDI) &&
 +            !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI))
 +            continue;
 +        if(
 +            (ppfd->dwFlags & PFD_SUPPORT_OPENGL) &&
 +            !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
 +            continue;
 +        if(
 +            !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
 +            ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
 +            continue;
 +        if(
 +            !(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
 +            ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO)))
 +            continue;
 +        if(ppfd->iPixelType != pix[i].pfd.iPixelType)
 +            delta++;
 +        if(delta < bestdelta)
 +        {
 +            best = i + 1;
 +            bestdelta = delta;
 +            if(bestdelta == 0)
 +                break;
 +        }
 +    }
 +    if(best == -1)
 +    {
 +        SetLastError(0);
 +        return(0);
 +    }
 +    return(best);
 +}
 +
 +GLAPI int GLWINAPI wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
 +                                    LPPIXELFORMATDESCRIPTOR ppfd)
 +{
 +    int		qt_valid_pix;
 +
 +    qt_valid_pix = qt_pix;
 +    if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || nBytes != sizeof(PIXELFORMATDESCRIPTOR))
 +    {
 +        SetLastError(0);
 +        return(0);
 +    }
 +    *ppfd = pix[iPixelFormat - 1].pfd;
 +    return(qt_valid_pix);
 +}
 +
 +/*
 +* GetProcAddress - return the address of an appropriate extension
 +*/
 +GLAPI PROC GLWINAPI wglGetProcAddress(LPCSTR lpszProc)
 +{
 +    int		i;
 +    for(i = 0;i < qt_ext;i++)
 +        if(!strcmp(lpszProc,ext[i].name))
 +            return(ext[i].proc);
 +
 +        SetLastError(0);
 +        return(NULL);
 +}
 +
 +GLAPI int GLWINAPI wglGetPixelFormat(HDC hdc)
 +{
 +    if(curPFD == 0)
 +    {
 +        SetLastError(0);
 +        return(0);
 +    }
 +    return(curPFD);
 +}
 +
 +GLAPI BOOL GLWINAPI wglSetPixelFormat(HDC hdc,int iPixelFormat,
 +                                PIXELFORMATDESCRIPTOR *ppfd)
 +{
 +    int		qt_valid_pix;
 +
 +    qt_valid_pix = qt_pix;
 +    if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR))
 +    {
 +        SetLastError(0);
 +        return(FALSE);
 +    }
 +    curPFD = iPixelFormat;
 +    return(TRUE);
 +}
 +
 +GLAPI BOOL GLWINAPI wglSwapBuffers(HDC hdc)
 +{
 +   if (ctx_current < 0)
 +      return FALSE;
 +
 +   if(wgl_ctx[ctx_current].ctx == NULL) {
 +      SetLastError(0);
 +      return(FALSE);
 +   }
 +   WMesaSwapBuffers();
 +   return(TRUE);
 +}
 +
 +#endif /* WIN32 */
 diff --git a/src/mesa/drivers/windows/wing32.def b/src/mesa/drivers/windows/wing32.def new file mode 100644 index 0000000000..ac8fc1dfb6 --- /dev/null +++ b/src/mesa/drivers/windows/wing32.def @@ -0,0 +1,12 @@ +EXPORTS +        WinGBitBlt@32 +        WinGCreateBitmap@12 +        WinGCreateDC@0 +        WinGCreateHalftoneBrush@12 +        WinGCreateHalftonePalette@0 +        WinGGetDIBColorTable@16 +        WinGGetDIBPointer@8 +        WinGRecommendDIBFormat@4 +        WinGSetDIBColorTable@16 +        WinGStretchBlt@40 + diff --git a/src/mesa/drivers/windows/wmesa.c b/src/mesa/drivers/windows/wmesa.c new file mode 100644 index 0000000000..d2c0a56b26 --- /dev/null +++ b/src/mesa/drivers/windows/wmesa.c @@ -0,0 +1,3021 @@ +/* $Id: wmesa.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ + +/* +*   File name   :   wmesa.c +*  Version      :   2.3 +* +*  Display driver for Mesa 2.3  under +*   Windows95 and WindowsNT +* +*   Copyright (C) 1996-  Li Wei +*  Address      :       Institute of Artificial Intelligence +*               :           & Robotics +*               :       Xi'an Jiaotong University +*  Email        :       liwei@aiar.xjtu.edu.cn +*  Web page :       http://sun.aiar.xjtu.edu.cn +* +*  This file and its associations are partially borrowed from the +*  Windows NT driver for Mesa 1.8 , written by Mark Leaming +*  (mark@rsinc.com). +*/ + + +/* + * $Log: wmesa.c,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 3.10  1999/06/15 01:35:06  brianp + * small change to wmSetPixel() from TWILMOT@cpr.fr + * + * Revision 3.9  1999/05/11 19:06:01  brianp + * fixed a few VB->Index bugs (mikec@ensoniq.com) + * + * Revision 3.8  1999/05/08 15:15:23  brianp + * various updates from mikec@ensoniq.com + * + * Revision 3.7  1999/04/01 01:27:34  brianp + * always flip Y coord in read_rgba_span() + * + * Revision 3.6  1999/03/28 21:17:27  brianp + * updated SetBuffer driver function + * + * Revision 3.5  1999/03/16 01:36:42  brianp + * patched dither() to check if Current is NULL, per xzhou@nyx.net + * + * Revision 3.4  1999/02/25 14:12:33  keithw + * Merged in kw3 patch + * + * Revision 3.3  1999/01/03 03:08:57  brianp + * Ted Jump's changes + * + * Revision 3.2  1998/08/29 00:26:01 + * updated for Mesa 3.0 to accomodate EGCS-Mingw32 build + * + * Revision 3.1  1998/06/11 01:42:08  brianp + * updated for Mesa 3.0 device driver interface (but not tested) + * + * Revision 3.0  1998/06/11 01:18:25  brianp + * initial revision + * + */ + + +#define WMESA_STEREO_C + +#include <windows.h> +#include <stdio.h> +#include <stdlib.h> +#include <GL/wmesa.h> +#include "mesa_extend.h" +#include "colors.h" +#include "macros.h" +#include "context.h" +#include "dd.h" +#include "xform.h" +#include "vb.h" +#include "matrix.h" +#include "depth.h" +#include "wmesadef.h" + +#pragma warning ( disable : 4133 4761 ) + +#ifdef PROFILE +//  #include "profile.h" +#endif + +#ifdef DITHER +#include <wing.h> +#endif + +#ifdef __CYGWIN32__ +#include "macros.h" +#include <string.h> +#define CopyMemory memcpy +#endif + +#if !defined(NO_STEREO) + +#include "gl\glu.h" +#include "stereo.h" + +#endif +#if !defined(NO_PARALLEL) +//  #include "parallel.h" +#endif + +struct DISPLAY_OPTIONS displayOptions; + +GLenum stereoCompile = GL_FALSE ; +GLenum stereoShowing  = GL_FALSE ; +GLenum stereoBuffer = GL_FALSE; +#if !defined(NO_STEREO) +GLint displayList = MAXIMUM_DISPLAY_LIST ; +#endif +GLint stereo_flag = 0 ; + +/* end of added code*/ + +static PWMC Current = NULL; +WMesaContext WC = NULL; + +#ifdef NDEBUG +#define assert(ignore)  ((void) 0) +#else +void Mesa_Assert(void *Cond,void *File,unsigned Line) +{ +    char Msg[512]; +    sprintf(Msg,"%s %s %d",Cond,File,Line); +    MessageBox(NULL,Msg,"Assertion failed.",MB_OK); +    exit(1); +} +#define assert(e)   if (!e) Mesa_Assert(#e,__FILE__,__LINE__); +#endif + +//#define DD_GETDC (Current->hDC ) +#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC ) +//#define DD_GETDC ((Current->db_flag) ? Current->hDCPrimary : Current->hDCBack ) +#define DD_RELEASEDC + +//#define BEGINGDICALL  if(Current->rgb_flag)wmFlushBits(Current); +#define BEGINGDICALL +//#define ENDGDICALL        if(Current->rgb_flag)wmGetBits(Current); +#define ENDGDICALL + +//#define FLIP(Y)  (Current->dither_flag? Y : Current->height-(Y)-1) +//#define FLIP(Y)  (Current->height-(Y)-1) +//#define FLIP(Y) Y +/* + * XXX Why only flip Y coord if single buffered??? + */ +#define FLIP(Y)  (Current->db_flag? Y: Current->height-(Y)-1) +#define STARTPROFILE +#define ENDPROFILE(PARA) + +#define DITHER_RGB_TO_8BIT_SETUP            \ +GLubyte pixelDithered; + +#define DITHER_RGB_TO_8BIT(red, green, blue, pixel, scanline)               \ +{                                                                           \ +    char unsigned redtemp, greentemp, bluetemp, paletteindex;               \ +    redtemp = aDividedBy51[red]                                             \ +    + (aModulo51[red] > aHalftone8x8[(pixel%8)*8                        \ +    + scanline%8]);                                                 \ +    greentemp = aDividedBy51[(char unsigned)green]                          \ +    + (aModulo51[green] > aHalftone8x8[                             \ +    (pixel%8)*8 + scanline%8]);                                     \ +    bluetemp = aDividedBy51[(char unsigned)blue]                            \ +    + (aModulo51[blue] > aHalftone8x8[                              \ +    (pixel%8)*8 +scanline%8]);                                      \ +    paletteindex = redtemp + aTimes6[greentemp] + aTimes36[bluetemp];       \ +    pixelDithered = aWinGHalftoneTranslation[paletteindex];                 \ +} + + +#ifdef DDRAW +static BOOL DDInit( WMesaContext wc, HWND hwnd); +static void DDFree( WMesaContext wc); +static HRESULT DDRestoreAll( WMesaContext wc ); +static void DDDeleteOffScreen(WMesaContext wc); +static BOOL DDCreateOffScreen(WMesaContext wc); +#endif + +static void FlushToFile(PWMC pwc, PSTR  szFile); + +BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize); +BOOL wmDeleteBackingStore(PWMC pwc); +void wmCreatePalette( PWMC pwdc ); +BOOL wmSetDibColors(PWMC pwc); +void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b); + +void wmCreateDIBSection( +                        HDC  hDC, +                        PWMC pwc,   // handle of device context +                        CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data +                        UINT iUsage // color data type indicator: RGB values or palette indices +                        ); + + +void WMesaViewport( GLcontext *ctx, +                    GLint x, GLint y, GLsizei width, GLsizei height ); + + +static triangle_func choose_triangle_function( GLcontext *ctx ); + + +static void wmSetPixelFormat( PWMC wc, HDC hDC) +{ +    if(wc->rgb_flag) +        wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL); +    else +        wc->cColorBits = 8; +    switch(wc->cColorBits){ +    case 8: +        if(wc->dither_flag != GL_TRUE) +            wc->pixelformat = PF_INDEX8; +        else +            wc->pixelformat = PF_DITHER8; +        break; +    case 16: +        wc->pixelformat = PF_5R6G5B; +        break; +    case 32: +        wc->pixelformat = PF_8R8G8B; +        break; +    default: +        wc->pixelformat = PF_BADFORMAT; +    } +} + +// +// This function sets the color table of a DIB section +// to match that of the destination DC +// +BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc) +{ +    RGBQUAD         *pColTab, *pRGB; +    PALETTEENTRY    *pPal, *pPE; +    int             i, nColors; +    BOOL            bRet=TRUE; +    DWORD           dwErr=0; + +    /* Build a color table in the DIB that maps to the +    selected palette in the DC. +    */ +    nColors = 1 << pwc->cColorBits; +    pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY)); +    memset( pPal, 0, nColors * sizeof(PALETTEENTRY) ); +    GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal ); +    pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD)); +    for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) { +        pRGB->rgbRed = pPE->peRed; +        pRGB->rgbGreen = pPE->peGreen; +        pRGB->rgbBlue = pPE->peBlue; +    } +    if(pwc->db_flag) +        bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab ); + +    if(!bRet) +        dwErr = GetLastError(); + +    free( pColTab ); +    free( pPal ); + +    return(bRet); +} + + +// +// Free up the dib section that was created +// +BOOL wmDeleteBackingStore(PWMC pwc) +{ +    SelectObject(pwc->dib.hDC, pwc->hOldBitmap); +    DeleteDC(pwc->dib.hDC); +    DeleteObject(pwc->hbmDIB); +    UnmapViewOfFile(pwc->dib.base); +    CloseHandle(pwc->dib.hFileMap); +    return TRUE; +} + + +// +// This function creates the DIB section that is used for combined +// GL and GDI calls +// +BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize) +{ +    HDC hdc = pwc->hDC; +    LPBITMAPINFO pbmi = &(pwc->bmi); +    int     iUsage; + +    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); +    pbmi->bmiHeader.biWidth = lxSize; +    pbmi->bmiHeader.biHeight= -lySize; +    pbmi->bmiHeader.biPlanes = 1; +    if(pwc->rgb_flag) +        pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL); +    else +        pbmi->bmiHeader.biBitCount = 8; +    pbmi->bmiHeader.biCompression = BI_RGB; +    pbmi->bmiHeader.biSizeImage = 0; +    pbmi->bmiHeader.biXPelsPerMeter = 0; +    pbmi->bmiHeader.biYPelsPerMeter = 0; +    pbmi->bmiHeader.biClrUsed = 0; +    pbmi->bmiHeader.biClrImportant = 0; + +    iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS; + +    pwc->cColorBits = pbmi->bmiHeader.biBitCount; +    pwc->ScanWidth = pwc->pitch = lxSize; + +    wmCreateDIBSection(hdc, pwc, pbmi, iUsage); + +    if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) { +        wmCreatePalette( pwc ); +        wmSetDibColors( pwc ); +    } +    wmSetPixelFormat(pwc, pwc->hDC); +    return(TRUE); + +} + + +// +// This function copies one scan line in a DIB section to another +// +BOOL WINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits) +{ +    UINT uiScans = 0; +    LPBYTE  pDest = pwc->pbPixels; +    DWORD   dwNextScan = uiScanWidth; +    DWORD   dwNewScan = uiNewWidth; +    DWORD   dwScanWidth = (uiScanWidth * nBypp); + +    // +    // We need to round up to the nearest DWORD +    // and multiply by the number of bytes per +    // pixel +    // +    dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3); +    dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3); + +    for(uiScans = 0; uiScans < uiNumScans; uiScans++){ +        CopyMemory(pDest, pBits, dwScanWidth); +        pBits += dwNextScan; +        pDest += dwNewScan; +    } + +    return(TRUE); + +} + + +BOOL wmFlush(PWMC pwc); + +/* +* Useful macros: +Modified from file osmesa.c +*/ + + +#define PIXELADDR(X,Y)  ((GLubyte *)Current->pbPixels + (Current->height-Y-1)* Current->ScanWidth + (X)*nBypp) +#define PIXELADDR1( X, Y )  \ +((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)) +#define PIXELADDR2( X, Y )  \ +((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*2) +#define PIXELADDR4( X, Y )  \ +((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*4) + + +BYTE DITHER_RGB_2_8BIT( int r, int g, int b, int x, int y); + +/* Finish all pending operations and synchronize. */ +static void finish(GLcontext* ctx) +{ +    /* No op */ +} + + +// +// We cache all gl draw routines until a flush is made +// +static void flush(GLcontext* ctx) +{ +    STARTPROFILE +        if((Current->rgb_flag /*&& !(Current->dib.fFlushed)*/&&!(Current->db_flag)) +            ||(!Current->rgb_flag)) +        { +            wmFlush(Current); +        } +        ENDPROFILE(flush) + +} + + + +/* +* Set the color index used to clear the color buffer. +*/ +static void clear_index(GLcontext* ctx, GLuint index) +{ +    STARTPROFILE +        Current->clearpixel = index; +    ENDPROFILE(clear_index) +} + + + +/* +* Set the color used to clear the color buffer. +*/ +static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ +    STARTPROFILE +        Current->clearpixel=RGB(r, g, b ); +    ENDPROFILE(clear_color) +} + + + +/* +* Clear the specified region of the color buffer using the clear color +* or index as specified by one of the two functions above. +*/ +//static void clear(GLcontext* ctx, +//                  GLboolean all,GLint x, GLint y, GLint width, GLint height ) +// TODO: I modified this function to match the prototype in dd.h. (swansma@geocities.com) +//       dd.h does not explain what the return type is so I could not set this to the proper +//       value. +static GLbitfield clear(GLcontext* ctx, GLbitfield mask, +                  GLboolean all, GLint x, GLint y, GLint width, GLint height) +{ +    DWORD   dwColor; +    WORD    wColor; +    BYTE    bColor; +    LPDWORD lpdw = (LPDWORD)Current->pbPixels; +    LPWORD  lpw = (LPWORD)Current->pbPixels; +    LPBYTE  lpb = Current->pbPixels; +    int     lines; + +    STARTPROFILE + +        if (all){ +            x=y=0; +            width=Current->width; +            height=Current->height; +        } +        if(Current->db_flag==GL_TRUE){ +            UINT    nBypp = Current->cColorBits / 8; +            int     i = 0; +            int     iSize = 0; + +            if(nBypp ==1 ){ +                /* Need rectification */ +                iSize = Current->width/4; +                bColor  = BGR8(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +                wColor  = MAKEWORD(bColor,bColor); +                dwColor = MAKELONG(wColor, wColor); +            } +            if(nBypp == 2){ +                iSize = Current->width / 2; +                wColor = BGR16(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +                dwColor = MAKELONG(wColor, wColor); +            } +            else if(nBypp == 4){ +                iSize = Current->width; +                dwColor = BGR32(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +            } + +            while(i < iSize){ +                *lpdw = dwColor; +                lpdw++; +                i++; +            } + +            // +            // This is the 24bit case +            // +            if (nBypp == 3) { +                iSize = Current->width *3/4; +                dwColor = BGR24(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +                while(i < iSize){ +                    *lpdw = dwColor; +                    lpb += nBypp; +                    lpdw = (LPDWORD)lpb; +                    i++; +                } +            } + +            i = 0; +            if (stereo_flag) +               lines = height /2; +            else +               lines = height; +            do { +                memcpy(lpb, Current->pbPixels, iSize*4); +                lpb += Current->ScanWidth; +                i++; +            } +            while (i<lines-1); +        } +        else { // For single buffer +            HDC DC=DD_GETDC; +            HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel); +            HBRUSH Brush=CreateSolidBrush(Current->clearpixel); +            HPEN Old_Pen=SelectObject(DC,Pen); +            HBRUSH Old_Brush=SelectObject(DC,Brush); +            Rectangle(DC,x,y,x+width,y+height); +            SelectObject(DC,Old_Pen); +            SelectObject(DC,Old_Brush); +            DeleteObject(Pen); +            DeleteObject(Brush); +            DD_RELEASEDC; +        } + + + +        ENDPROFILE(clear) + +		return mask;	// TODO: I doubt this is correct. dd.h doesn't explain what this should +		                //       be... +} + + + +/* Set the current color index. */ +static void set_index(GLcontext* ctx, GLuint index) +{ +    STARTPROFILE +        Current->pixel=index; +    ENDPROFILE(set_index) +} + + + +/* Set the current RGBA color. */ +static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ +    STARTPROFILE +        Current->pixel = RGB( r, g, b ); +    ENDPROFILE(set_color) +} + + + +/* Set the index mode bitplane mask. */ +static GLboolean index_mask(GLcontext* ctx, GLuint mask) +{ +    /* can't implement */ +    return GL_FALSE; +} + + + +/* Set the RGBA drawing mask. */ +static GLboolean color_mask( GLcontext* ctx, +                            GLboolean rmask, GLboolean gmask, +                            GLboolean bmask, GLboolean amask) +{ +    /* can't implement */ +    return GL_FALSE; +} + + + +/* +* Set the pixel logic operation.  Return GL_TRUE if the device driver +* can perform the operation, otherwise return GL_FALSE.  If GL_FALSE +* is returned, the logic op will be done in software by Mesa. +*/ +GLboolean logicop( GLcontext* ctx, GLenum op ) +{ +    /* can't implement */ +    return GL_FALSE; +} + + +static void dither( GLcontext* ctx, GLboolean enable ) +{ +   if (!Current) +      return; + +    if(enable == GL_FALSE){ +        Current->dither_flag = GL_FALSE; +        if(Current->cColorBits == 8) +            Current->pixelformat = PF_INDEX8; +    } +    else{ +        if (Current->rgb_flag && Current->cColorBits == 8){ +            Current->pixelformat = PF_DITHER8; +            Current->dither_flag = GL_TRUE; +        } +        else +            Current->dither_flag = GL_FALSE; +    } +} + + + +static GLboolean set_buffer( GLcontext* ctx, GLenum mode ) +{ +   STARTPROFILE +   /* TODO: this could be better */ +   if (mode==GL_FRONT_LEFT || mode==GL_BACK_LEFT) { +      return GL_TRUE; +   } +   else { +      return GL_FALSE; +   } +   ENDPROFILE(set_buffer) +} + + + +/* Return characteristics of the output buffer. */ +static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height ) +{ +   int New_Size; +   RECT CR; + +   STARTPROFILE +   GetClientRect(Current->Window,&CR); + +   *width=CR.right; +   *height=CR.bottom; + +   New_Size=((*width)!=Current->width) || ((*height)!=Current->height); + +   if (New_Size){ +      Current->width=*width; +      Current->height=*height; +      Current->ScanWidth=Current->width; +      if ((Current->ScanWidth%sizeof(long))!=0) +         Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long))); + +      if (Current->db_flag){ +#ifdef DDRAW +         DDDeleteOffScreen(Current); +         DDCreateOffScreen(Current); +#else +         if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){ +            wmDeleteBackingStore(Current); +            wmCreateBackingStore(Current, Current->width, Current->height); +         } +#endif +      } + +      //  Resize OsmesaBuffer if in Parallel mode +#if !defined(NO_PARALLEL) +      if(parallelFlag) +         PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth, +                            Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem); +#endif +   } +   ENDPROFILE(buffer_size) +} + + + +/**********************************************************************/ +/*****           Accelerated point, line, polygon rendering       *****/ +/**********************************************************************/ + + +static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last ) +{ +    GLuint i; +    //  HDC DC=DD_GETDC; +    PWMC    pwc = Current; + +    STARTPROFILE + +        if (0 /*Current->gl_ctx->VB->MonoColor*/) { +            /* all drawn with current color */ +            for (i=first;i<=last;i++) { +                if (!Current->gl_ctx->VB->ClipMask[i]) { +                    int x, y; +                    x =       (GLint) Current->gl_ctx->VB->Win.data[i][0]; +                    y = FLIP( (GLint) Current->gl_ctx->VB->Win.data[i][1] ); +                    wmSetPixel(pwc, y,x,GetRValue(Current->pixel), +                        GetGValue(Current->pixel), GetBValue(Current->pixel)); +                } +            } +        } +        else { +            /* draw points of different colors */ +            for (i=first;i<=last;i++) { +                if (!Current->gl_ctx->VB->ClipMask[i]) { +                    int x, y; +                    unsigned long pixel=RGB(Current->gl_ctx->VB->ColorPtr->data[i][0]*255.0, +                        Current->gl_ctx->VB->ColorPtr->data[i][1]*255.0, +                        Current->gl_ctx->VB->ColorPtr->data[i][2]*255.0); +                    x =       (GLint) Current->gl_ctx->VB->Win.data[i][0]; +                    y = FLIP( (GLint) Current->gl_ctx->VB->Win.data[i][1] ); +                    wmSetPixel(pwc, y,x,Current->gl_ctx->VB->ColorPtr->data[i][0]*255.0, +                        Current->gl_ctx->VB->ColorPtr->data[i][1]*255.0, +                        Current->gl_ctx->VB->ColorPtr->data[i][2]*255.0); +                } +            } +        } +        //   DD_RELEASEDC; +        ENDPROFILE(fast_rgb_points) +} + + + +/* Return pointer to accerated points function */ +extern points_func choose_points_function( GLcontext* ctx ) +{ +    STARTPROFILE +        if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0 +            && !ctx->Texture.Enabled  && ctx->Visual->RGBAflag) { +            ENDPROFILE(choose_points_function) +                return fast_rgb_points; +        } +        else { +            ENDPROFILE(choose_points_function) +                return NULL; +        } +} + + + +/* Draw a line using the color specified by Current->gl_ctx->VB->ColorPtr->data[pv] */ +static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv ) +{ +    STARTPROFILE +        int x0, y0, x1, y1; +    unsigned long pixel; +    HDC DC=DD_GETDC; +    HPEN Pen; +    HPEN Old_Pen; + +    if (0 /*Current->gl_ctx->VB->MonoColor*/) { +        pixel = Current->pixel;  /* use current color */ +    } +    else { +        pixel = RGB(Current->gl_ctx->VB->ColorPtr->data[pv][0]*255.0, Current->gl_ctx->VB->ColorPtr->data[pv][1]*255.0, Current->gl_ctx->VB->ColorPtr->data[pv][2]*255.0); +    } + +    x0 =       (int) Current->gl_ctx->VB->Win.data[v0][0]; +    y0 = FLIP( (int) Current->gl_ctx->VB->Win.data[v0][1] ); +    x1 =       (int) Current->gl_ctx->VB->Win.data[v1][0]; +    y1 = FLIP( (int) Current->gl_ctx->VB->Win.data[v1][1] ); + + +    BEGINGDICALL + +    Pen=CreatePen(PS_SOLID,1,pixel); +    Old_Pen=SelectObject(DC,Pen); +    MoveToEx(DC,x0,y0,NULL); +    LineTo(DC,x1,y1); +    SelectObject(DC,Old_Pen); +    DeleteObject(Pen); +    DD_RELEASEDC; + +    ENDGDICALL + +    ENDPROFILE(fast_flat_rgb_line) +} + + + +/* Return pointer to accerated line function */ +static line_func choose_line_function( GLcontext* ctx ) +{ +    STARTPROFILE +    if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag +        && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0 +        && !ctx->Texture.Enabled && Current->rgb_flag) { +       ENDPROFILE(choose_line_function) +       return fast_flat_rgb_line; +    } +    else { +       ENDPROFILE(choose_line_function) +       return NULL; +    } +} + + +/**********************************************************************/ +/*****                 Span-based pixel drawing                   *****/ +/**********************************************************************/ + + +/* Write a horizontal span of 32-bit color-index pixels with a boolean mask. */ +static void write_ci32_span( const GLcontext* ctx, +                             GLuint n, GLint x, GLint y, +                             const GLuint index[], +                             const GLubyte mask[] ) +{ +    STARTPROFILE +    GLuint i; +    PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +    assert(Current->rgb_flag==GL_FALSE); +    for (i=0; i<n; i++) +        if (mask[i]) +            Mem[i]=index[i]; +    ENDPROFILE(write_ci32_span) +} + + +/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */ +static void write_ci8_span( const GLcontext* ctx, +                            GLuint n, GLint x, GLint y, +                            const GLubyte index[], +                            const GLubyte mask[] ) +{ +    STARTPROFILE +    GLuint i; +    PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +    assert(Current->rgb_flag==GL_FALSE); +    for (i=0; i<n; i++) +        if (mask[i]) +            Mem[i]=index[i]; +    ENDPROFILE(write_ci8_span) +} + + + +/* +* Write a horizontal span of pixels with a boolean mask.  The current +* color index is used for all pixels. +*/ +static void write_mono_ci_span(const GLcontext* ctx, +                               GLuint n,GLint x,GLint y, +                               const GLubyte mask[]) +{ +   STARTPROFILE +   GLuint i; +   BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) +      if (mask[i]) +         Mem[i]=Current->pixel; +   ENDPROFILE(write_mono_ci_span) +} + +/* + * To improve the performance of this routine, frob the data into an actual + * scanline and call bitblt on the complete scan line instead of SetPixel. + */ + +/* Write a horizontal span of RGBA color pixels with a boolean mask. */ +static void write_rgba_span( const GLcontext* ctx, GLuint n, GLint x, GLint y, +                             const GLubyte rgba[][4], const GLubyte mask[] ) +{ +    STARTPROFILE +    PWMC    pwc = Current; + +    if (pwc->rgb_flag==GL_TRUE) +    { +        GLuint i; +        HDC DC=DD_GETDC; +        y=FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); +        } +        else { +            for (i=0; i<n; i++) +                wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); +        } +        DD_RELEASEDC; +    } +    else +    { +        GLuint i; +        BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x; +        y = FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); +        } +        else { +            for (i=0; i<n; i++) +                Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); +        } +    } +    ENDPROFILE(write_rgba_span) + +} + +/* Write a horizontal span of RGB color pixels with a boolean mask. */ +static void write_rgb_span( const GLcontext* ctx, +                            GLuint n, GLint x, GLint y, +                            const GLubyte rgb[][3], const GLubyte mask[] ) +{ +    STARTPROFILE +    PWMC    pwc = Current; + +    if (pwc->rgb_flag==GL_TRUE) +    { +        GLuint i; +        HDC DC=DD_GETDC; +        y=FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); +        } +        else { +            for (i=0; i<n; i++) +                wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ); +        } +        DD_RELEASEDC; +    } +    else +    { +        GLuint i; +        BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x; +        y = FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP])); +        } +        else { +            for (i=0; i<n; i++) +                Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP])); +        } +    } +    ENDPROFILE(write_rgb_span) + +} + +/* +* Write a horizontal span of pixels with a boolean mask.  The current color +* is used for all pixels. +*/ +static void write_mono_rgba_span( const GLcontext* ctx, +                                  GLuint n, GLint x, GLint y, +                                  const GLubyte mask[]) +{ +    STARTPROFILE +    GLuint i; +    HDC DC=DD_GETDC; +    PWMC pwc = Current; +    assert(Current->rgb_flag==GL_TRUE); +    y=FLIP(y); +    if(Current->rgb_flag==GL_TRUE){ +        for (i=0; i<n; i++) +            if (mask[i]) +                // Trying +                wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel)); +    } +    else { +        for (i=0; i<n; i++) +            if (mask[i]) +                SetPixel(DC, y, x+i, Current->pixel); +    } +    DD_RELEASEDC; +    ENDPROFILE(write_mono_rgba_span) +} + + + +/**********************************************************************/ +/*****                   Array-based pixel drawing                *****/ +/**********************************************************************/ + + +/* Write an array of 32-bit index pixels with a boolean mask. */ +static void write_ci32_pixels( const GLcontext* ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               const GLuint index[], const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]; +         *Mem = index[i]; +      } +   } +   ENDPROFILE(write_ci32_pixels) +} + + + +/* +* Write an array of pixels with a boolean mask.  The current color +* index is used for all pixels. +*/ +static void write_mono_ci_pixels( const GLcontext* ctx, +                                  GLuint n, +                                  const GLint x[], const GLint y[], +                                  const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]; +         *Mem = Current->pixel; +      } +   } +   ENDPROFILE(write_mono_ci_pixels) +} + + + +/* Write an array of RGBA pixels with a boolean mask. */ +static void write_rgba_pixels( const GLcontext* ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               const GLubyte rgba[][4], const GLubyte mask[] ) +{ +    STARTPROFILE +        GLuint i; +    PWMC    pwc = Current; +    HDC DC=DD_GETDC; +    assert(Current->rgb_flag==GL_TRUE); +    for (i=0; i<n; i++) +       if (mask[i]) +          wmSetPixel(pwc, FLIP(y[i]),x[i],rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]); +    DD_RELEASEDC; +    ENDPROFILE(write_rgba_pixels) +} + + + +/* +* Write an array of pixels with a boolean mask.  The current color +* is used for all pixels. +*/ +static void write_mono_rgba_pixels( const GLcontext* ctx, +                                    GLuint n, +                                    const GLint x[], const GLint y[], +                                    const GLubyte mask[] ) +{ +    STARTPROFILE +    GLuint i; +    PWMC    pwc = Current; +    HDC DC=DD_GETDC; +    assert(Current->rgb_flag==GL_TRUE); +    for (i=0; i<n; i++) +        if (mask[i]) +            wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel), +                       GetGValue(Current->pixel), GetBValue(Current->pixel)); +    DD_RELEASEDC; +    ENDPROFILE(write_mono_rgba_pixels) +} + + + +/**********************************************************************/ +/*****            Read spans/arrays of pixels                     *****/ +/**********************************************************************/ + + +/* Read a horizontal span of color-index pixels. */ +static void read_ci32_span( const GLcontext* ctx, GLuint n, GLint x, GLint y, +                            GLuint index[]) +{ +   STARTPROFILE +   GLuint i; +   BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) +      index[i]=Mem[i]; +   ENDPROFILE(read_ci32_span) +} + + + + +/* Read an array of color index pixels. */ +static void read_ci32_pixels( const GLcontext* ctx, +                              GLuint n, const GLint x[], const GLint y[], +                              GLuint indx[], const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]); +      } +   } +   ENDPROFILE(read_ci32_pixels) +} + + + +/* Read a horizontal span of color pixels. */ +static void read_rgba_span( const GLcontext* ctx, +                            GLuint n, GLint x, GLint y, +                            GLubyte rgba[][4] ) +{ +   STARTPROFILE +   UINT i; +   COLORREF Color; +   HDC DC=DD_GETDC; +   assert(Current->rgb_flag==GL_TRUE); +   /*   y=FLIP(y);*/ +   y = Current->height - y - 1; +   for (i=0; i<n; i++) { +      Color=GetPixel(DC,x+i,y); +      rgba[i][RCOMP] = GetRValue(Color); +      rgba[i][GCOMP] = GetGValue(Color); +      rgba[i][BCOMP] = GetBValue(Color); +      rgba[i][ACOMP] = 255; +   } +   DD_RELEASEDC; +// Brian P. Has mentioned to comment this out. +//   memset(alpha,0,n*sizeof(GLubyte)); +   ENDPROFILE(read_rgba_span) +} + + +/* Read an array of color pixels. */ +static void read_rgba_pixels( const GLcontext* ctx, +                              GLuint n, const GLint x[], const GLint y[], +                              GLubyte rgba[][4], const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   COLORREF Color; +   HDC DC=DD_GETDC; +   assert(Current->rgb_flag==GL_TRUE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         Color=GetPixel(DC,x[i],FLIP(y[i])); +         rgba[i][RCOMP] = GetRValue(Color); +         rgba[i][GCOMP] = GetGValue(Color); +         rgba[i][BCOMP] = GetBValue(Color); +         rgba[i][ACOMP] = 255; +      } +   } +   DD_RELEASEDC; +// Brian P. has mentioned to comment this out. +//   memset(alpha,0,n*sizeof(GLint)); +   ENDPROFILE(read_rgba_pixels) +} + + + +/**********************************************************************/ +/**********************************************************************/ + + +static const char *renderer_string(void) +{ +   return "Windows"; +} + + + +void setup_DD_pointers( GLcontext* ctx ) +{ +    ctx->Driver.RendererString = renderer_string; +    ctx->Driver.UpdateState = setup_DD_pointers; +    ctx->Driver.GetBufferSize = buffer_size; +    ctx->Driver.Finish = finish; +    ctx->Driver.Flush = flush; + +    ctx->Driver.ClearIndex = clear_index; +    ctx->Driver.ClearColor = clear_color; +    ctx->Driver.Clear = clear; + +    ctx->Driver.Index = set_index; +    ctx->Driver.Color = set_color; +    ctx->Driver.IndexMask = index_mask; +    ctx->Driver.ColorMask = color_mask; + +    ctx->Driver.LogicOp = logicop; +    ctx->Driver.Dither = dither; + +    ctx->Driver.SetBuffer = set_buffer; +    ctx->Driver.GetBufferSize = buffer_size; + +    ctx->Driver.PointsFunc = choose_points_function(ctx); +    ctx->Driver.LineFunc = choose_line_function(ctx); +    ctx->Driver.TriangleFunc = choose_triangle_function( ctx ); + +    /* Pixel/span writing functions: */ +	ctx->Driver.WriteRGBASpan        = write_rgba_span; +    ctx->Driver.WriteRGBSpan         = write_rgb_span; +    ctx->Driver.WriteMonoRGBASpan    = write_mono_rgba_span; +    ctx->Driver.WriteRGBAPixels      = write_rgba_pixels; +    ctx->Driver.WriteMonoRGBAPixels  = write_mono_rgba_pixels; +    ctx->Driver.WriteCI32Span        = write_ci32_span; +    ctx->Driver.WriteCI8Span         = write_ci8_span; +    ctx->Driver.WriteMonoCISpan      = write_mono_ci_span; +    ctx->Driver.WriteCI32Pixels      = write_ci32_pixels; +    ctx->Driver.WriteMonoCIPixels    = write_mono_ci_pixels; + +    ctx->Driver.ReadCI32Span        = read_ci32_span; +    ctx->Driver.ReadRGBASpan        = read_rgba_span; +    ctx->Driver.ReadCI32Pixels      = read_ci32_pixels; +    ctx->Driver.ReadRGBAPixels      = read_rgba_pixels; +} + + +/**********************************************************************/ +/*****                  WMesa API Functions                       *****/ +/**********************************************************************/ + + + +#define PAL_SIZE 256 +static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB) +{ +    STARTPROFILE +        int i; +    HDC hdc; +    struct +    { +        WORD Version; +        WORD NumberOfEntries; +        PALETTEENTRY aEntries[PAL_SIZE]; +    } Palette = +    { +        0x300, +            PAL_SIZE +    }; +    hdc=GetDC(NULL); +    if (Pal!=NULL) +        GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries); +    else +        GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries); +    if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) +    { +        for(i = 0; i <PAL_SIZE; i++) +            Palette.aEntries[i].peFlags = PC_RESERVED; +        Palette.aEntries[255].peRed = 255; +        Palette.aEntries[255].peGreen = 255; +        Palette.aEntries[255].peBlue = 255; +        Palette.aEntries[255].peFlags = 0; +        Palette.aEntries[0].peRed = 0; +        Palette.aEntries[0].peGreen = 0; +        Palette.aEntries[0].peBlue = 0; +        Palette.aEntries[0].peFlags = 0; +    } +    else +    { +        int nStaticColors; +        int nUsableColors; +        nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2; +        for (i=0; i<nStaticColors; i++) +            Palette.aEntries[i].peFlags = 0; +        nUsableColors = PAL_SIZE-nStaticColors; +        for (; i<nUsableColors; i++) +            Palette.aEntries[i].peFlags = PC_RESERVED; +        for (; i<PAL_SIZE-nStaticColors; i++) +            Palette.aEntries[i].peFlags = PC_RESERVED; +        for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++) +            Palette.aEntries[i].peFlags = 0; +    } +    ReleaseDC(NULL,hdc); +    for (i=0; i<PAL_SIZE; i++) +    { +        aRGB[i].rgbRed=Palette.aEntries[i].peRed; +        aRGB[i].rgbGreen=Palette.aEntries[i].peGreen; +        aRGB[i].rgbBlue=Palette.aEntries[i].peBlue; +        aRGB[i].rgbReserved=Palette.aEntries[i].peFlags; +    } +    ENDPROFILE(GetPalette) +} + + +WMesaContext WMesaCreateContext( HWND hWnd, HPALETTE* Pal, +                                GLboolean rgb_flag, +                                GLboolean db_flag ) +{ +    RECT CR; +    WMesaContext c; +    GLboolean true_color_flag; +    c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context)); +    if (!c) +        return NULL; + +    c->Window=hWnd; +    c->hDC = GetDC(hWnd); +    true_color_flag = GetDeviceCaps(c->hDC, BITSPIXEL) > 8; +#ifdef DDRAW +    if(true_color_flag) c->rgb_flag = rgb_flag = GL_TRUE; +#endif + + +#ifdef DITHER +    if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){ +        c->dither_flag = GL_TRUE; +        c->hPalHalfTone = WinGCreateHalftonePalette(); +    } +    else +        c->dither_flag = GL_FALSE; +#else +    c->dither_flag = GL_FALSE; +#endif + + +    if (rgb_flag==GL_FALSE) +    { +        c->rgb_flag = GL_FALSE; +        //    c->pixel = 1; +        c->db_flag = db_flag =GL_TRUE; // WinG requires double buffering +        printf("Single buffer is not supported in color index mode, setting to double buffer.\n"); +    } +    else +    { +        c->rgb_flag = GL_TRUE; +        //    c->pixel = 0; +    } +    GetClientRect(c->Window,&CR); +    c->width=CR.right; +    c->height=CR.bottom; +    if (db_flag) +    { +        c->db_flag = 1; +        /* Double buffered */ +#ifndef DDRAW +        //  if (c->rgb_flag==GL_TRUE && c->dither_flag != GL_TRUE ) +        { +            wmCreateBackingStore(c, c->width, c->height); + +        } +#endif +    } +    else +    { +        /* Single Buffered */ +        if (c->rgb_flag) +            c->db_flag = 0; +    } +#ifdef DDRAW +    if (DDInit(c,hWnd) == GL_FALSE) { +        free( (void *) c ); +        exit(1); +    } +#endif + + +    c->gl_visual = gl_create_visual(rgb_flag, +                                    GL_FALSE,   /* software alpha */ +                                    db_flag,    /* db_flag */ +                                    GL_FALSE,   /* stereo */ +                                    16,         /* depth_bits */ +                                    8,          /* stencil_bits */ +                                    8,          /* accum_bits */ +                                    0,          /* index bits */ +                                    8,8,8,8 );  /* r, g, b, a bits */ + +    if (!c->gl_visual) { +        return NULL; +    } + +    /* allocate a new Mesa context */ +    c->gl_ctx = gl_create_context( c->gl_visual, NULL, c, GL_TRUE); + +    if (!c->gl_ctx) { +        gl_destroy_visual( c->gl_visual ); +        free(c); +        return NULL; +    } + +    c->gl_buffer = gl_create_framebuffer( c->gl_visual ); +    if (!c->gl_buffer) { +        gl_destroy_visual( c->gl_visual ); +        gl_destroy_context( c->gl_ctx ); +        free(c); +        return NULL; +    } + +	c->gl_ctx->Driver.UpdateState = setup_DD_pointers; + +    //  setup_DD_pointers(c->gl_ctx); + +    return c; +} + +void WMesaDestroyContext( void ) +{ +    WMesaContext c = Current; +    ReleaseDC(c->Window,c->hDC); +    WC = c; +    if(c->hPalHalfTone != NULL) +        DeleteObject(c->hPalHalfTone); +    gl_destroy_visual( c->gl_visual ); +    gl_destroy_framebuffer( c->gl_buffer ); +    gl_destroy_context( c->gl_ctx ); + +    if (c->db_flag) +#ifdef DDRAW +        DDFree(c); +#else +    wmDeleteBackingStore(c); +#endif +    free( (void *) c ); +    //Following code is added to enable parallel render +    // Parallel render only work in double buffer mode +#if !defined(NO_PARALLEL) +    if(parallelMachine) +        PRDestroyRenderBuffer(); +#endif +    // End modification +} + + + +void /*APIENTRY*/ WMesaMakeCurrent( WMesaContext c ) +{ +    if(!c){ +        Current = c; +        return; +    } + +    // +    // A little optimization +    // If it already is current, +    // don't set it again +    // +    if(Current == c) +        return; + +    //gl_set_context( c->gl_ctx ); +    gl_make_current(c->gl_ctx, c->gl_buffer); +    setup_DD_pointers(c->gl_ctx); +    Current = c; +    if (Current->gl_ctx->Viewport.Width==0) { +        /* initialize viewport to window size */ +        gl_Viewport( Current->gl_ctx, +            0, 0, Current->width, Current->height ); +    } +    if ((c->cColorBits <= 8 ) && (c->rgb_flag == GL_TRUE)){ +        WMesaPaletteChange(c->hPalHalfTone); +    } +} + + + +void /*APIENTRY*/ WMesaSwapBuffers( void ) +{ +    HDC DC = Current->hDC; +    if (Current->db_flag) +        wmFlush(Current); +} + + + +void /*APIENTRY*/ WMesaPaletteChange(HPALETTE Pal) +{ +    int vRet; +    LPPALETTEENTRY pPal; +    if (Current && (Current->rgb_flag==GL_FALSE || Current->dither_flag == GL_TRUE)) +    { +        pPal = (PALETTEENTRY *)malloc( 256 * sizeof(PALETTEENTRY)); +        Current->hPal=Pal; +        //  GetPaletteEntries( Pal, 0, 256, pPal ); +        GetPalette( Pal, pPal ); +#ifdef DDRAW +        Current->lpDD->lpVtbl->CreatePalette(Current->lpDD,DDPCAPS_8BIT, +            pPal, &(Current->lpDDPal), NULL); +        if (Current->lpDDPal) +            Current->lpDDSPrimary->lpVtbl->SetPalette(Current->lpDDSPrimary,Current->lpDDPal); +#else +        vRet = SetDIBColorTable(Current->dib.hDC,0,256,pPal); +#endif +        free( pPal ); +    } + +} + + + + +static unsigned char threeto8[8] = { +    0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377 +}; + +static unsigned char twoto8[4] = { +    0, 0x55, 0xaa, 0xff +}; + +static unsigned char oneto8[2] = { +    0, 255 +}; + +static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift) +{ +    unsigned char val; + +    val = i >> shift; +    switch (nbits) { + +    case 1: +        val &= 0x1; +        return oneto8[val]; + +    case 2: +        val &= 0x3; +        return twoto8[val]; + +    case 3: +        val &= 0x7; +        return threeto8[val]; + +    default: +        return 0; +    } +} + +void /*WINAPI*/ wmCreatePalette( PWMC pwdc ) +{ +    /* Create a compressed and re-expanded 3:3:2 palette */ +    int            i; +    LOGPALETTE     *pPal; +    BYTE           rb, rs, gb, gs, bb, bs; + +    pwdc->nColors = 0x100; + +    pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY)); +    memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) ); + +    pPal->palVersion = 0x300; + +    rb = REDBITS; +    rs = REDSHIFT; +    gb = GREENBITS; +    gs = GREENSHIFT; +    bb = BLUEBITS; +    bs = BLUESHIFT; + +    if (pwdc->db_flag) { + +        /* Need to make two palettes: one for the screen DC and one for the DIB. */ +        pPal->palNumEntries = pwdc->nColors; +        for (i = 0; i < pwdc->nColors; i++) { +            pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs ); +            pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs ); +            pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs ); +            pPal->palPalEntry[i].peFlags = 0; +        } +        pwdc->hGLPalette = CreatePalette( pPal ); +        pwdc->hPalette = CreatePalette( pPal ); +    } + +    else { +        pPal->palNumEntries = pwdc->nColors; +        for (i = 0; i < pwdc->nColors; i++) { +            pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs ); +            pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs ); +            pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs ); +            pPal->palPalEntry[i].peFlags = 0; +        } +        pwdc->hGLPalette = CreatePalette( pPal ); +    } + +    free(pPal); + +} + +void /*WINAPI*/ wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b) +{ +    if (Current->db_flag) { +        LPBYTE  lpb = pwc->pbPixels; +        LPDWORD lpdw; +        LPWORD  lpw; +        UINT    nBypp = pwc->cColorBits >> 3; +        UINT    nOffset = iPixel % nBypp; + +        // Move the pixel buffer pointer to the scanline that we +        // want to access + +        //      pwc->dib.fFlushed = FALSE; + +        lpb += pwc->ScanWidth * iScanLine; +        // Now move to the desired pixel +        lpb += iPixel * nBypp; +        lpb = PIXELADDR(iPixel, iScanLine); +        lpdw = (LPDWORD)lpb; +        lpw = (LPWORD)lpb; + +        if(nBypp == 1){ +            if(pwc->dither_flag) +                *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel); +            else +                *lpb = BGR8(r,g,b); +        } +        else if(nBypp == 2) +            *lpw = BGR16(r,g,b); +        else if (nBypp == 3){ +            *lpdw = BGR24(r,g,b); +        } +        else if (nBypp == 4) +            *lpdw = BGR32(r,g,b); +    } +    else{ +        SetPixel(Current->hDC, iPixel, iScanLine, RGB(r,g,b)); +        DD_RELEASEDC; +    } +} + +void /*WINAPI*/ wmCreateDIBSection( +                                   HDC   hDC, +                                   PWMC pwc,    // handle of device context +                                   CONST BITMAPINFO *pbmi,  // address of structure containing bitmap size, format, and color data +                                   UINT iUsage  // color data type indicator: RGB values or palette indices +                                   ) +{ +    DWORD   dwSize = 0; +    DWORD   dwScanWidth; +    UINT    nBypp = pwc->cColorBits / 8; +    HDC     hic; + +    dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3); + +    pwc->ScanWidth =pwc->pitch = dwScanWidth; + +    if (stereo_flag) +        pwc->ScanWidth = 2* pwc->pitch; + +    dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height); + +    pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE, +        NULL, +        PAGE_READWRITE | SEC_COMMIT, +        0, +        dwSize, +        NULL); + +    if (!pwc->dib.hFileMap) +        return; + +    pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap, +        FILE_MAP_ALL_ACCESS, +        0, +        0, +        0); + +    if(!pwc->dib.base){ +        CloseHandle(pwc->dib.hFileMap); +        return; +    } + +    //  pwc->pbPixels = pwc->addrOffScreen = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO); + +    //  pwc->dib.hDC = CreateCompatibleDC(hDC); + +    CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO)); + +    hic = CreateIC("display", NULL, NULL, NULL); +    pwc->dib.hDC = CreateCompatibleDC(hic); + + +    /*  pwc->hbmDIB = CreateDIBitmap(hic, +    &(pwc->bmi.bmiHeader), +    CBM_INIT, +    pwc->pbPixels, +    &(pwc->bmi), +    DIB_RGB_COLORS); +    */ +    pwc->hbmDIB = CreateDIBSection(hic, +        &(pwc->bmi), +        (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS), +        &(pwc->pbPixels), +        pwc->dib.hFileMap, +        0); +        /* +        pwc->hbmDIB = CreateDIBSection(hic, +        &(pwc->bmi), +        DIB_RGB_COLORS, +        &(pwc->pbPixels), +        pwc->dib.hFileMap, +        0); +    */ +    pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels; +    pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB); + +    DeleteDC(hic); + +    return; + +} + +// +// Blit memory DC to screen DC +// +BOOL /*WINAPI*/ wmFlush(PWMC pwc) +{ +    BOOL    bRet = 0; +    DWORD   dwErr = 0; +#ifdef DDRAW +    HRESULT             ddrval; +#endif + +    // Now search through the torus frames and mark used colors +    if(pwc->db_flag){ +#ifdef DDRAW +        if (pwc->lpDDSOffScreen == NULL) +            if(DDCreateOffScreen(pwc) == GL_FALSE) +                return; + +            pwc->lpDDSOffScreen->lpVtbl->Unlock(pwc->lpDDSOffScreen, NULL); + +            while( 1 ) +            { +                ddrval = pwc->lpDDSPrimary->lpVtbl->Blt( pwc->lpDDSPrimary, +                    &(pwc->rectSurface), pwc->lpDDSOffScreen, &(pwc->rectOffScreen), 0, NULL ); + +                if( ddrval == DD_OK ) +                { +                    break; +                } +                if( ddrval == DDERR_SURFACELOST ) +                { +                    if(!DDRestoreAll(pwc)) +                    { +                        break; +                    } +                } +                if( ddrval != DDERR_WASSTILLDRAWING ) +                { +                    break; +                } +            } + +            while (pwc->lpDDSOffScreen->lpVtbl->Lock(pwc->lpDDSOffScreen, +                NULL, &(pwc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING) +                ; + +            if(ddrval != DD_OK) +                dwErr = GetLastError(); +#else +            bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height, +                pwc->dib.hDC, 0, 0, SRCCOPY); +#endif +    } + +    return(TRUE); + +} + + +// The following code is added by Li Wei to enable stereo display + +#if !defined(NO_STEREO) + +void WMesaShowStereo(GLuint list) +{ + +    GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; +    GLfloat cm[16]; +    GLint matrix_mode; +    // Must use double Buffer +    if( ! Current-> db_flag ) +        return; + + +    glGetIntegerv(GL_MATRIX_MODE,&matrix_mode); + +    //  glPushMatrix();  //**** +    WMesaViewport(Current->gl_ctx,0,Current->height/2,Current->width,Current->height/2); +    //  Current->gl_ctx->NewState = 0; + +    //  glViewport(0,0,Current->width,Current->height/2); +    if(matrix_mode!=GL_MODELVIEW) +        glMatrixMode(GL_MODELVIEW); + +    glGetFloatv(GL_MODELVIEW_MATRIX,cm); +    glLoadIdentity(); +    gluLookAt(viewDistance/2,0.0,0.0 , +        viewDistance/2,0.0,-1.0, +        0.0,1.0,0.0 ); +    //  glTranslatef(viewDistance/2.0,0.,0.); +    glMultMatrixf( cm ); + +    Current->ScreenMem = Current->pbPixels = Current->addrOffScreen; +    //glPushMatrix(); +    glCallList( list ); +    //glPopMatrix(); + +    glGetFloatv(GL_MODELVIEW_MATRIX,cm); +    glLoadIdentity(); +    gluLookAt(-viewDistance/2,0.0,0.0 , +        -viewDistance/2,0.0,-1.0, +        0.0,1.0,0.0 ); +    //  glTranslatef(-viewDistance/2.0,0.,0.); +    glMultMatrixf(cm); + +    Current->ScreenMem = Current->pbPixels = Current->addrOffScreen + Current->pitch; +    glCallList(list); +    if(matrix_mode!=GL_MODELVIEW) +        glMatrixMode(matrix_mode); + +    //  glPopMatrix(); +    glFlush(); + +    WMesaViewport(Current->gl_ctx,0,0,Current->width,Current->height); +    //  Current->gl_ctx->NewState = 0; +    WMesaSwapBuffers(); + +} + +void toggleStereoMode() +{ +    if(!Current->db_flag) +        return; +    if(!stereo_flag){ +        stereo_flag = 1; +        if(stereoBuffer==GL_FALSE) +#if !defined(NO_PARALLEL) +            if(!parallelFlag) +#endif +            { +                Current->ScanWidth = Current->pitch*2; +            } +    } +    else { +        stereo_flag = 0; +#if !defined(NO_PARALLEL) +        if(!parallelFlag) +#endif +            Current->ScanWidth = Current->pitch; +        Current->pbPixels = Current->addrOffScreen; +    } +} + +/* if in stereo mode, the following function is called */ +void glShowStereo(GLuint list) +{ +    WMesaShowStereo(list); +} + +#endif // End if NO_STEREO not defined + +#if !defined(NO_PARALLEL) + +void toggleParallelMode(void) +{ +    if(!parallelFlag){ +        parallelFlag = GL_TRUE; +        if(parallelMachine==GL_FALSE){ +            PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX, +                Current->cColorBits/8, +                Current->width ,Current->height, +                Current->ScanWidth, +                Current->rgb_flag? Current->pbPixels: Current->ScreenMem); +            parallelMachine = GL_TRUE; +        } +    } +    else { +        parallelFlag = GL_FALSE; +        if(parallelMachine==GL_TRUE){ +            PRDestroyRenderBuffer(); +            parallelMachine=GL_FALSE; +            ReadyForNextFrame = GL_TRUE; +        } + +        /*********************************************** +        // Seems something wrong!!!! +        ************************************************/ + +        WMesaMakeCurrent(Current); +#if !defined(NO_STEREO) +        stereo_flag = GL_FALSE ; +#endif +    } +} + +void PRShowRenderResult(void) +{ +    int flag = 0; +    if(!glImageRendered()) +        return; + +    if (parallelFlag) +    { +        WMesaSwapBuffers(); +    } + +} +#endif //End if NO_PARALLEL not defined + +//end modification + +BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline) +{ +    char unsigned redtemp, greentemp, bluetemp, paletteindex; + +    //*** now, look up each value in the halftone matrix +    //*** using an 8x8 ordered dither. +    redtemp = aDividedBy51[red] +        + (aModulo51[red] > aHalftone8x8[(pixel%8)*8 +        + scanline%8]); +    greentemp = aDividedBy51[(char unsigned)green] +        + (aModulo51[green] > aHalftone8x8[ +        (pixel%8)*8 + scanline%8]); +    bluetemp = aDividedBy51[(char unsigned)blue] +        + (aModulo51[blue] > aHalftone8x8[ +        (pixel%8)*8 +scanline%8]); + +    //*** recombine the halftoned rgb values into a palette index +    paletteindex = +        redtemp + aTimes6[greentemp] + aTimes36[bluetemp]; + +    //*** and translate through the wing halftone palette +    //*** translation vector to give the correct value. +    return aWinGHalftoneTranslation[paletteindex]; +} + +#ifdef DDRAW +/* +* restoreAll +* +* restore all lost objects +*/ +HRESULT DDRestoreAll( WMesaContext wc ) +{ +    HRESULT     ddrval; + +    ddrval = wc->lpDDSPrimary->lpVtbl->Restore(wc->lpDDSPrimary); +    if( ddrval == DD_OK ) +    { +        ddrval = wc->lpDDSOffScreen->lpVtbl->Restore(wc->lpDDSOffScreen); +    } +    return ddrval; + +} /* restoreAll */ + + +  /* +  * This function is called if the initialization function fails +*/ +BOOL initFail( HWND hwnd, WMesaContext wc ) +{ +    DDFree(wc); +    MessageBox( hwnd, "DirectDraw Init FAILED", "", MB_OK ); +    return FALSE; + +} /* initFail */ + + +static void DDDeleteOffScreen(WMesaContext wc) +{ +    if( wc->lpDDSOffScreen != NULL ) +    { +        wc->lpDDSOffScreen->lpVtbl->Unlock(wc->lpDDSOffScreen,NULL); +        wc->lpDDSOffScreen->lpVtbl->Release(wc->lpDDSOffScreen); +        wc->lpDDSOffScreen = NULL; +    } + +} + +static void DDFreePrimarySurface(WMesaContext wc) +{ +    if( wc->lpDDSPrimary != NULL ) +    { +        if(wc->db_flag == GL_FALSE) +            wc->lpDDSPrimary->lpVtbl->ReleaseDC(wc->lpDDSPrimary, wc->hDC); +        wc->lpDDSPrimary->lpVtbl->Release(wc->lpDDSPrimary); +        wc->lpDDSPrimary = NULL; +    } +} + +static BOOL DDCreatePrimarySurface(WMesaContext wc) +{ +    HRESULT ddrval; +    DDSCAPS             ddscaps; +    wc->ddsd.dwSize = sizeof( wc->ddsd ); +    wc->ddsd.dwFlags = DDSD_CAPS; +    wc->ddsd.ddsCaps.dwCaps =   DDSCAPS_PRIMARYSURFACE; + +    ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD,&(wc->ddsd), &(wc->lpDDSPrimary), NULL ); +    if( ddrval != DD_OK ) +    { +        return initFail(wc->hwnd , wc); +    } +    if(wc->db_flag == GL_FALSE) +        wc->lpDDSPrimary->lpVtbl->GetDC(wc->lpDDSPrimary, wc->hDC); +    return TRUE; +} + +static BOOL DDCreateOffScreen(WMesaContext wc) +{ +    POINT   pt; +    HRESULT     ddrval; +    if(wc->lpDD == NULL) +        return FALSE; +    GetClientRect( wc->hwnd, &(wc->rectOffScreen) ); +    wc->ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; +    wc->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; +    wc->ddsd.dwHeight = wc->rectOffScreen.bottom - wc->rectOffScreen.top; +    wc->ddsd.dwWidth = wc->rectOffScreen.right - wc->rectOffScreen.left; + +    ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD, &(wc->ddsd), &(wc->lpDDSOffScreen), NULL ); +    if( ddrval != DD_OK ) +    { +        return FALSE; +    } + +    while (wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING) +        ; +    //  while ((ddrval = wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), DDLOCK_SURFACEMEMORYPTR , NULL)) != DD_OK) +    ; +    if(wc->ddsd.lpSurface==NULL) +        return initFail(wc->hwnd, wc); + +    wc->ScreenMem = wc->pbPixels = wc->addrOffScreen = (PBYTE)(wc->ddsd.lpSurface); +    wc->ScanWidth = wc->pitch = wc->ddsd.lPitch; +    if (stereo_flag) +        wc->ScanWidth = wc->ddsd.lPitch*2; + +    GetClientRect( wc->hwnd, &(wc->rectSurface) ); +    pt.x = pt.y = 0; +    ClientToScreen( wc->hwnd, &pt ); +    OffsetRect(&(wc->rectSurface), pt.x, pt.y); +    wmSetPixelFormat(wc, wc->hDC); +    return TRUE; +} + +/* +* doInit - do work required for every instance of the application: +*                create the window, initialize data +*/ +static BOOL DDInit( WMesaContext wc, HWND hwnd) +{ +    HRESULT             ddrval; +    DWORD dwFrequency; + +    LPDIRECTDRAW            lpDD;           // DirectDraw object +    LPDIRECTDRAW2            lpDD2; + + +    wc->fullScreen = displayOptions.fullScreen; +    wc->gMode = displayOptions.mode; +    wc->hwnd = hwnd; +    stereo_flag = displayOptions.stereo; +    if(wc->db_flag!= GL_TRUE) +        stereo_flag = GL_FALSE; +        /* +        * create the main DirectDraw object +    */ +    ddrval = DirectDrawCreate( NULL, &(wc->lpDD), NULL ); +    if( ddrval != DD_OK ) +    { +        return initFail(hwnd,wc); +    } + +    // Get exclusive mode if requested +    if(wc->fullScreen) +    { +        ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ); +    } +    else +    { +        ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_NORMAL ); +    } +    if( ddrval != DD_OK ) +    { +        return initFail(hwnd , wc); +    } + + +    /*  ddrval = wc->lpDD->lpVtbl->QueryInterface(wc->lpDD, IID_IDirectDraw2, +    (LPVOID *)((wc->lpDD2))); + +    */ +    if(ddrval != DD_OK) +        return initFail(hwnd , wc); + + +    //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd)); +    //  wc->lpDD2->lpVtbl->GetMonitorFrequency(wc->lpDD, &dwFrequency); +    switch( wc->gMode ) +    { +    case 1:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 640, 480, displayOptions.bpp); break; +    case 2:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 800, 600, displayOptions.bpp); break; +    case 3:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1024, 768, displayOptions.bpp); break; +    case 4:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1152, 864, displayOptions.bpp); break; +    case 5:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1280, 1024, displayOptions.bpp); break; +    } + +    if( ddrval != DD_OK ) +    { +        printf("Can't modify display mode, current mode used\n"); +        //        return initFail(hwnd , wc); +    } +    //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd)); +    switch(ddrval){ +    case DDERR_INVALIDOBJECT: +        break; +    case DDERR_INVALIDPARAMS: +        break; +    case DDERR_UNSUPPORTEDMODE: +        ; +    } + +    if(DDCreatePrimarySurface(wc) == GL_FALSE) +        return initFail(hwnd, wc); + +    if(wc->db_flag) +        return DDCreateOffScreen(wc); +} /* DDInit */ + +static void DDFree( WMesaContext wc) +{ +    if( wc->lpDD != NULL ) +    { +        DDFreePrimarySurface(wc); +        DDDeleteOffScreen(wc); +        wc->lpDD->lpVtbl->Release(wc->lpDD); +        wc->lpDD = NULL; +    } +    // Clean up the screen on exit +    RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | +        RDW_ALLCHILDREN ); + +} +#endif + +void WMesaMove(void) +{ +    WMesaContext wc = Current; +    POINT   pt; +    if (Current != NULL){ +        GetClientRect( wc->hwnd, &(wc->rectSurface) ); +        pt.x = pt.y = 0; +        ClientToScreen( wc->hwnd, &pt ); +        OffsetRect(&(wc->rectSurface), pt.x, pt.y); +    } +} + + + +/* +* Like PACK_8A8B8G8R() but don't use alpha.  This is usually an acceptable +* shortcut. +*/ +#define PACK_8B8G8R( R, G, B )   ( ((B) << 16) | ((G) << 8) | (R) ) + + +/**********************************************************************/ +/***                   Triangle rendering                            ***/ +/**********************************************************************/ + +/* + * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle. + */ +static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx, +                                       GLuint v0, GLuint v1, GLuint v2, +                                       GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),    \ +    FixedToInt(ffb) );          \ +    zRow[i] = z;                            \ +    }                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    ffz += fdzdx;                           \ +    }                                   \ +    } + +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, smooth, depth-buffered, PF_8R8G8B triangle. +*/ +static void smooth_8R8G8B_z_triangle( GLcontext *ctx, +                                     GLuint v0, GLuint v1, GLuint v2, +                                     GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),    \ +    FixedToInt(ffb) );          \ +    zRow[i] = z;                            \ +    }                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    ffz += fdzdx;                           \ +    }                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + + +/* +* XImage, smooth, depth-buffered, PF_5R6G5B triangle. +*/ +static void smooth_5R6G5B_z_triangle( GLcontext *ctx, +                                     GLuint v0, GLuint v1, GLuint v2, +                                     GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg),    \ +    FixedToInt(ffb) );          \ +    zRow[i] = z;                            \ +    }                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    ffz += fdzdx;                           \ +    }                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + +/* +* XImage, flat, depth-buffered, PF_8A8B8G8R triangle. +*/ +static void flat_8A8B8G8R_z_triangle( GLcontext *ctx, GLuint v0, +                                     GLuint v1, GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8B8G8R( VB->ColorPtr->data[pv][0],    \ +    VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = p;                            \ +    zRow[i] = z;                            \ +    }                                   \ +    ffz += fdzdx;                           \ +    }                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, flat, depth-buffered, PF_8R8G8B triangle. +*/ +static void flat_8R8G8B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8R8G8B( VB->ColorPtr->data[pv][0],    \ +    VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint i, len = RIGHT-LEFT;              \ +    for (i=0;i<len;i++) {               \ +    GLdepth z = FixedToDepth(ffz);          \ +    if (z < zRow[i]) {              \ +    pRow[i] = p;                    \ +    zRow[i] = z;                    \ +    }                           \ +    ffz += fdzdx;                   \ +    }                           \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, flat, depth-buffered, PF_5R6G5B triangle. +*/ +static void flat_5R6G5B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_5R6G5B( VB->ColorPtr->data[pv][0],    \ +    VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint i, len = RIGHT-LEFT;              \ +    for (i=0;i<len;i++) {               \ +    GLdepth z = FixedToDepth(ffz);          \ +    if (z < zRow[i]) {              \ +    pRow[i] = p;                    \ +    zRow[i] = z;                    \ +    }                           \ +    ffz += fdzdx;                   \ +    }                           \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle. +*/ +static void smooth_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                     GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),     \ +                FixedToInt(ffb) );          \ +                ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    }                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle. +*/ +static void smooth_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),     \ +                FixedToInt(ffb) );          \ +                ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    }                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle. +*/ +static void smooth_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg),     \ +                FixedToInt(ffb) );          \ +                ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    }                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + + +/* +* XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle. +*/ +static void flat_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, +                                   GLuint v1, GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8B8G8R( VB->ColorPtr->data[pv][0],    \ +    VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint xx;                       \ +    PIXEL_TYPE *pixel = pRow;               \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \ +    *pixel = p;                 \ +    }                           \ +    } + +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, flat, NON-depth-buffered, PF_8R8G8B triangle. +*/ +static void flat_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                 GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8R8G8B( VB->ColorPtr->data[pv][0],    \ +    VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint xx;                       \ +    PIXEL_TYPE *pixel = pRow;               \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \ +    *pixel = p;                 \ +    }                           \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, flat, NON-depth-buffered, PF_5R6G5B triangle. +*/ +static void flat_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                 GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_5R6G5B( VB->ColorPtr->data[pv][0],    \ +    VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint xx;                       \ +    PIXEL_TYPE *pixel = pRow;               \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \ +    *pixel = p;                 \ +    }                           \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle. +*/ + +static void smooth_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                 GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_INDEX 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                                \ +    {                                                                   \ +    GLint i, len = RIGHT-LEFT;                                      \ +    for (i=0;i<len;i++) {                                           \ +    GLdepth z = FixedToDepth(ffz);                              \ +    if (z < zRow[i]) {                                          \ +    pRow[i] = FixedToInt(ffi);                                  \ +    zRow[i] = z;                                                \ +    }                                                               \ +    ffi += fdidx;                                                   \ +    ffz += fdzdx;                                                   \ +    }                                                               \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle. +*/ + +static void flat_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                               GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE			\ +   GLuint index = VB->IndexPtr->data[pv];	\ +   (*ctx->Driver.Index)( ctx, index ); +#define INNER_LOOP( LEFT, RIGHT, Y )	\ +   {					\ +      GLint i, len = RIGHT-LEFT;	\ +      for (i=0;i<len;i++) {		\ +         GLdepth z = FixedToDepth(ffz);	\ +         if (z < zRow[i]) {		\ +            pRow[i] = index;		\ +            zRow[i] = z;		\ +         }				\ +         ffz += fdzdx;			\ +      }					\ +   } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + + +/* +* XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle. +*/ + +static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                               GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_INDEX 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = FixedToInt(ffi);           \ +    ffi += fdidx;           \ +    }                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + +/* +* XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle. +*/ +static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                             GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE			\ +   GLuint index = VB->IndexPtr->data[pv];	\ +   (*ctx->Driver.Index)( ctx, index ); +#define INNER_LOOP( LEFT, RIGHT, Y )		\ +   {						\ +      GLint xx;					\ +      PIXEL_TYPE *pixel = pRow;			\ +      for (xx=LEFT;xx<RIGHT;xx++,pixel++) {	\ +         *pixel = index;			\ +      }						\ +   } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + +/* +* XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle. +*/ +static void smooth_DITHER8_z_triangle( GLcontext *ctx, +                                      GLuint v0, GLuint v1, GLuint v2, +                                      GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT;                 \ +    for (i=0;i<len;i++,xx++) {                                          \ +    GLdepth z = FixedToDepth(ffz);                                  \ +    if (z < zRow[i]) {                                              \ +    DITHER_RGB_TO_8BIT( FixedToInt(ffr), FixedToInt(ffg),           \ +    FixedToInt(ffb), xx, yy);               \ +    pRow[i] = pixelDithered;                                        \ +    zRow[i] = z;                                                    \ +    }                                                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                     \ +    ffz += fdzdx;                                                       \ +    }                                                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + +/* +* XImage, flat, depth-buffered, 8-bit PF_DITHER triangle. +*/ +static void flat_DITHER8_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                    GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) + +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT;                 \ +    for (i=0;i<len;i++,xx++) {                                          \ +    GLdepth z = FixedToDepth(ffz);                                  \ +    if (z < zRow[i]) {                                              \ +    DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0],                           \ +             VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy);               \ +             pRow[i] = pixelDithered;                                       \ +             zRow[i] = z;                                                   \ +    }                                                                   \ +    ffz += fdzdx;                                                       \ +    }                                                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + +/* +* XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle. +*/ +static void smooth_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                    GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint xx, yy = FLIP(Y);                                             \ +    PIXEL_TYPE *pixel = pRow;                                           \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \ +    DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0],   VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy);\ +    *pixel = pixelDithered;                                         \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                     \ +    }                                                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + +/* +* XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle. +*/ + +static void flat_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                  GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) + +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint xx, yy = FLIP(Y);                                             \ +    PIXEL_TYPE *pixel = pRow;                                           \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \ +    DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0],                               \ +             VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy);               \ +             *pixel = pixelDithered;                                            \ +    }                                                                   \ +    } +#ifdef __MINGW32__ +	#include "tritemp.h" +#else + +	#ifdef WIN32 +		#include "..\tritemp.h" +	#else +		#include "tritemp.h" +	#endif +#endif +} + + + + +static triangle_func choose_triangle_function( GLcontext *ctx ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    int depth = wmesa->cColorBits; + +    if (ctx->Polygon.SmoothFlag)     return NULL; +    if (ctx->Texture.Enabled)        return NULL; +    if (!wmesa->db_flag) return NULL; +    /*if (wmesa->xm_buffer->buffer==XIMAGE)*/ { +    if (   ctx->Light.ShadeModel==GL_SMOOTH +        && ctx->RasterMask==DEPTH_BIT +        && ctx->Depth.Func==GL_LESS +        && ctx->Depth.Mask==GL_TRUE +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return smooth_8A8B8G8R_z_triangle; +        case PF_8R8G8B: +            return smooth_8R8G8B_z_triangle; +        case PF_5R6G5B: +            return smooth_5R6G5B_z_triangle; +        case PF_DITHER8: +            return  smooth_DITHER8_z_triangle; +        case PF_INDEX8: +            return smooth_ci_z_triangle; +        default: +            return NULL; +        } +    } +    if (   ctx->Light.ShadeModel==GL_FLAT +        && ctx->RasterMask==DEPTH_BIT +        && ctx->Depth.Func==GL_LESS +        && ctx->Depth.Mask==GL_TRUE +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return flat_8A8B8G8R_z_triangle; +        case PF_8R8G8B: +            return flat_8R8G8B_z_triangle; +        case PF_5R6G5B: +            return flat_5R6G5B_z_triangle; +        case PF_DITHER8: +            return flat_DITHER8_z_triangle; +        case PF_INDEX8: +            return flat_ci_z_triangle; +        default: +            return NULL; +        } +    } +    if (   ctx->RasterMask==0   /* no depth test */ +        && ctx->Light.ShadeModel==GL_SMOOTH +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return smooth_8A8B8G8R_triangle; +        case PF_8R8G8B: +            return smooth_8R8G8B_triangle; +        case PF_5R6G5B: +            return smooth_5R6G5B_triangle; +        case PF_DITHER8: +            return smooth_DITHER8_triangle; +        case PF_INDEX8: +            return smooth_ci_triangle; +        default: +            return NULL; +        } +    } + +    if (   ctx->RasterMask==0   /* no depth test */ +        && ctx->Light.ShadeModel==GL_FLAT +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return flat_8A8B8G8R_triangle; +        case PF_8R8G8B: +            return flat_8R8G8B_triangle; +        case PF_5R6G5B: +            return flat_5R6G5B_triangle; +        case PF_DITHER8: +            return flat_DITHER8_triangle; +        case PF_INDEX8: +            return flat_ci_triangle; +        default: +            return NULL; +        } +    } + +    return NULL; +    } +} + +/* +* Define a new viewport and reallocate auxillary buffers if the size of +* the window (color buffer) has changed. +*/ +void WMesaViewport( GLcontext *ctx, +                   GLint x, GLint y, GLsizei width, GLsizei height ) +{ +    /* Save viewport */ +    ctx->Viewport.X = x; +    ctx->Viewport.Width = width; +    ctx->Viewport.Y = y; +    ctx->Viewport.Height = height; + +    /* compute scale and bias values */ +/* Pre-Keith 3.1 changes +    ctx->Viewport.Map.m[Sx] = (GLfloat) width / 2.0F; +    ctx->Viewport.Map.m[Tx] = ctx->Viewport.Sx + x; +    ctx->Viewport.Map.m[Sy] = (GLfloat) height / 2.0F; +    ctx->Viewport.Map.m[Ty] = ctx->Viewport.Sy + y; +*/ +	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; +} diff --git a/src/mesa/drivers/windows/wmesaBackup.c b/src/mesa/drivers/windows/wmesaBackup.c new file mode 100644 index 0000000000..57269fbadb --- /dev/null +++ b/src/mesa/drivers/windows/wmesaBackup.c @@ -0,0 +1,2879 @@ +/* $Id: wmesaBackup.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ + +/* +*   File name   :   wmesa.c +*  Version      :   2.3 +* +*  Display driver for Mesa 2.3  under +*   Windows95 and WindowsNT +* +*   Copyright (C) 1996-  Li Wei +*  Address      :       Institute of Artificial Intelligence +*               :           & Robotics +*               :       Xi'an Jiaotong University +*  Email        :       liwei@aiar.xjtu.edu.cn +*  Web page :       http://sun.aiar.xjtu.edu.cn +* +*  This file and its associations are partially borrowed from the +*  Windows NT driver for Mesa 1.8 , written by Mark Leaming +*  (mark@rsinc.com). +*/ + + +/* + * $Log: wmesaBackup.c,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.1  1999/01/03 03:08:57  brianp + * Initial revision + * + * Revision 3.1  1998/06/11 01:42:08  brianp + * updated for Mesa 3.0 device driver interface (but not tested) + * + * Revision 3.0  1998/06/11 01:18:25  brianp + * initial revision + * + */ + + +#define WMESA_STEREO_C + +#include <stdio.h> +#include <stdlib.h> +#include <GL/wmesa.h> +#include "mesa_extend.h" +#include "colors.h" +#include "macros.h" +#include "context.h" +#include "dd.h" +#include "xform.h" +#include "vb.h" +#include "matrix.h" +#include "depth.h" +#include "wmesadef.h" + +#pragma warning ( disable : 4133 4761 ) + +#ifdef PROFILE +//  #include "profile.h" +#endif + +#ifdef DITHER +#include <wing.h> +#endif + +#ifdef __CYGWIN32__ +#include "macros.h" +#include <string.h> +#define CopyMemory memcpy +#endif + +#if !defined(NO_STEREO) + +#include "gl\glu.h" +#include "stereo.h" + +#endif +#if !defined(NO_PARALLEL) +//  #include "parallel.h" +#endif + +struct DISPLAY_OPTIONS displayOptions; + +GLenum stereoCompile = GL_FALSE ; +GLenum stereoShowing  = GL_FALSE ; +GLenum stereoBuffer = GL_FALSE; +#if !defined(NO_STEREO) +GLint displayList = MAXIMUM_DISPLAY_LIST ; +#endif +GLint stereo_flag = 0 ; + +/* end of added code*/ + +static PWMC Current = NULL; +WMesaContext WC = NULL; + +#ifdef NDEBUG +#define assert(ignore)  ((void) 0) +#else +void Mesa_Assert(void *Cond,void *File,unsigned Line) +{ +    char Msg[512]; +    sprintf(Msg,"%s %s %d",Cond,File,Line); +    MessageBox(NULL,Msg,"Assertion failed.",MB_OK); +    exit(1); +} +#define assert(e)   if (!e) Mesa_Assert(#e,__FILE__,__LINE__); +#endif + +//#define DD_GETDC (Current->hDC ) +#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC ) +//#define DD_GETDC ((Current->db_flag) ? Current->hDCPrimary : Current->hDCBack ) +#define DD_RELEASEDC + +//#define BEGINGDICALL  if(Current->rgb_flag)wmFlushBits(Current); +#define BEGINGDICALL +//#define ENDGDICALL        if(Current->rgb_flag)wmGetBits(Current); +#define ENDGDICALL + +//#define FLIP(Y)  (Current->dither_flag? Y : Current->height-(Y)-1) +//#define FLIP(Y)  (Current->height-(Y)-1) +//#define FLIP(Y) Y +#define FLIP(Y)  (Current->db_flag? Y: Current->height-(Y)-1) +#define STARTPROFILE +#define ENDPROFILE(PARA) + +#define DITHER_RGB_TO_8BIT_SETUP            \ +GLubyte pixelDithered; + +#define DITHER_RGB_TO_8BIT(red, green, blue, pixel, scanline)               \ +{                                                                           \ +    char unsigned redtemp, greentemp, bluetemp, paletteindex;               \ +    redtemp = aDividedBy51[red]                                             \ +    + (aModulo51[red] > aHalftone8x8[(pixel%8)*8                        \ +    + scanline%8]);                                                 \ +    greentemp = aDividedBy51[(char unsigned)green]                          \ +    + (aModulo51[green] > aHalftone8x8[                             \ +    (pixel%8)*8 + scanline%8]);                                     \ +    bluetemp = aDividedBy51[(char unsigned)blue]                            \ +    + (aModulo51[blue] > aHalftone8x8[                              \ +    (pixel%8)*8 +scanline%8]);                                      \ +    paletteindex = redtemp + aTimes6[greentemp] + aTimes36[bluetemp];       \ +    pixelDithered = aWinGHalftoneTranslation[paletteindex];                 \ +} + + +#ifdef DDRAW +static BOOL DDInit( WMesaContext wc, HWND hwnd); +static void DDFree( WMesaContext wc); +static HRESULT DDRestoreAll( WMesaContext wc ); +static void DDDeleteOffScreen(WMesaContext wc); +static BOOL DDCreateOffScreen(WMesaContext wc); +#endif + +static void FlushToFile(PWMC pwc, PSTR  szFile); + +BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize); +BOOL wmDeleteBackingStore(PWMC pwc); +void wmCreatePalette( PWMC pwdc ); +BOOL wmSetDibColors(PWMC pwc); +void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b); + +void wmCreateDIBSection( +                        HDC  hDC, +                        PWMC pwc,   // handle of device context +                        CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data +                        UINT iUsage // color data type indicator: RGB values or palette indices +                        ); + + +void WMesaViewport( GLcontext *ctx, +                    GLint x, GLint y, GLsizei width, GLsizei height ); + + +static triangle_func choose_triangle_function( GLcontext *ctx ); + + +static void wmSetPixelFormat( PWMC wc, HDC hDC) +{ +    if(wc->rgb_flag) +        wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL); +    else +        wc->cColorBits = 8; +    switch(wc->cColorBits){ +    case 8: +        if(wc->dither_flag != GL_TRUE) +            wc->pixelformat = PF_INDEX8; +        else +            wc->pixelformat = PF_DITHER8; +        break; +    case 16: +        wc->pixelformat = PF_5R6G5B; +        break; +    case 32: +        wc->pixelformat = PF_8R8G8B; +        break; +    default: +        wc->pixelformat = PF_BADFORMAT; +    } +} + +// +// This function sets the color table of a DIB section +// to match that of the destination DC +// +BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc) +{ +    RGBQUAD         *pColTab, *pRGB; +    PALETTEENTRY    *pPal, *pPE; +    int             i, nColors; +    BOOL            bRet=TRUE; +    DWORD           dwErr=0; + +    /* Build a color table in the DIB that maps to the +    selected palette in the DC. +    */ +    nColors = 1 << pwc->cColorBits; +    pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY)); +    memset( pPal, 0, nColors * sizeof(PALETTEENTRY) ); +    GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal ); +    pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD)); +    for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) { +        pRGB->rgbRed = pPE->peRed; +        pRGB->rgbGreen = pPE->peGreen; +        pRGB->rgbBlue = pPE->peBlue; +    } +    if(pwc->db_flag) +        bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab ); + +    if(!bRet) +        dwErr = GetLastError(); + +    free( pColTab ); +    free( pPal ); + +    return(bRet); +} + + +// +// Free up the dib section that was created +// +BOOL wmDeleteBackingStore(PWMC pwc) +{ +    SelectObject(pwc->dib.hDC, pwc->hOldBitmap); +    DeleteDC(pwc->dib.hDC); +    DeleteObject(pwc->hbmDIB); +    UnmapViewOfFile(pwc->dib.base); +    CloseHandle(pwc->dib.hFileMap); +    return TRUE; +} + + +// +// This function creates the DIB section that is used for combined +// GL and GDI calls +// +BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize) +{ +    HDC hdc = pwc->hDC; +    LPBITMAPINFO pbmi = &(pwc->bmi); +    int     iUsage; + +    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); +    pbmi->bmiHeader.biWidth = lxSize; +    pbmi->bmiHeader.biHeight= -lySize; +    pbmi->bmiHeader.biPlanes = 1; +    if(pwc->rgb_flag) +        pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL); +    else +        pbmi->bmiHeader.biBitCount = 8; +    pbmi->bmiHeader.biCompression = BI_RGB; +    pbmi->bmiHeader.biSizeImage = 0; +    pbmi->bmiHeader.biXPelsPerMeter = 0; +    pbmi->bmiHeader.biYPelsPerMeter = 0; +    pbmi->bmiHeader.biClrUsed = 0; +    pbmi->bmiHeader.biClrImportant = 0; + +    iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS; + +    pwc->cColorBits = pbmi->bmiHeader.biBitCount; +    pwc->ScanWidth = pwc->pitch = lxSize; + +    wmCreateDIBSection(hdc, pwc, pbmi, iUsage); + +    if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) { +        wmCreatePalette( pwc ); +        wmSetDibColors( pwc ); +    } +    wmSetPixelFormat(pwc, pwc->hDC); +    return(TRUE); + +} + + +// +// This function copies one scan line in a DIB section to another +// +BOOL GLWINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits) +{ +    UINT uiScans = 0; +    LPBYTE  pDest = pwc->pbPixels; +    DWORD   dwNextScan = uiScanWidth; +    DWORD   dwNewScan = uiNewWidth; +    DWORD   dwScanWidth = (uiScanWidth * nBypp); + +    // +    // We need to round up to the nearest DWORD +    // and multiply by the number of bytes per +    // pixel +    // +    dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3); +    dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3); + +    for(uiScans = 0; uiScans < uiNumScans; uiScans++){ +        CopyMemory(pDest, pBits, dwScanWidth); +        pBits += dwNextScan; +        pDest += dwNewScan; +    } + +    return(TRUE); + +} + + +BOOL wmFlush(PWMC pwc); + +/* +* Useful macros: +Modified from file osmesa.c +*/ + + +#define PIXELADDR(X,Y)  ((GLubyte *)Current->pbPixels + (Current->height-Y-1)* Current->ScanWidth + (X)*nBypp) +#define PIXELADDR1( X, Y )  \ +((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)) +#define PIXELADDR2( X, Y )  \ +((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*2) +#define PIXELADDR4( X, Y )  \ +((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*4) + + +BYTE DITHER_RGB_2_8BIT( int r, int g, int b, int x, int y); + +/* Finish all pending operations and synchronize. */ +static void finish(GLcontext* ctx) +{ +    /* No op */ +} + + +// +// We cache all gl draw routines until a flush is made +// +static void flush(GLcontext* ctx) +{ +    STARTPROFILE +        if((Current->rgb_flag /*&& !(Current->dib.fFlushed)*/&&!(Current->db_flag)) +            ||(!Current->rgb_flag)) +        { +            wmFlush(Current); +        } +        ENDPROFILE(flush) + +} + + + +/* +* Set the color index used to clear the color buffer. +*/ +static void clear_index(GLcontext* ctx, GLuint index) +{ +    STARTPROFILE +        Current->clearpixel = index; +    ENDPROFILE(clear_index) +} + + + +/* +* Set the color used to clear the color buffer. +*/ +static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ +    STARTPROFILE +        Current->clearpixel=RGB(r, g, b ); +    ENDPROFILE(clear_color) +} + + + +/* +* Clear the specified region of the color buffer using the clear color +* or index as specified by one of the two functions above. +*/ +//static void clear(GLcontext* ctx, +//                  GLboolean all,GLint x, GLint y, GLint width, GLint height ) +// TODO: I modified this function to match the prototype in dd.h. (swansma@geocities.com) +//       dd.h does not explain what the return type is so I could not set this to the proper +//       value. +static GLbitfield clear(GLcontext* ctx, GLbitfield mask, +                  GLboolean all, GLint x, GLint y, GLint width, GLint height) +{ +    DWORD   dwColor; +    WORD    wColor; +    BYTE    bColor; +    LPDWORD lpdw = (LPDWORD)Current->pbPixels; +    LPWORD  lpw = (LPWORD)Current->pbPixels; +    LPBYTE  lpb = Current->pbPixels; +    int     lines; + +    STARTPROFILE + +        if (all){ +            x=y=0; +            width=Current->width; +            height=Current->height; +        } +        if(Current->db_flag==GL_TRUE){ +            UINT    nBypp = Current->cColorBits / 8; +            int     i = 0; +            int     iSize = 0; + +            if(nBypp ==1 ){ +                /* Need rectification */ +                iSize = Current->width/4; +                bColor  = BGR8(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +                wColor  = MAKEWORD(bColor,bColor); +                dwColor = MAKELONG(wColor, wColor); +            } +            if(nBypp == 2){ +                iSize = Current->width / 2; +                wColor = BGR16(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +                dwColor = MAKELONG(wColor, wColor); +            } +            else if(nBypp == 4){ +                iSize = Current->width; +                dwColor = BGR32(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +            } + +            while(i < iSize){ +                *lpdw = dwColor; +                lpdw++; +                i++; +            } + +            // +            // This is the 24bit case +            // +            if (nBypp == 3) { +                iSize = Current->width *3/4; +                dwColor = BGR24(GetRValue(Current->clearpixel), +                    GetGValue(Current->clearpixel), +                    GetBValue(Current->clearpixel)); +                while(i < iSize){ +                    *lpdw = dwColor; +                    lpb += nBypp; +                    lpdw = (LPDWORD)lpb; +                    i++; +                } +            } + +            i = 0; +            if (stereo_flag) +               lines = height /2; +            else +               lines = height; +            do { +                memcpy(lpb, Current->pbPixels, iSize*4); +                lpb += Current->ScanWidth; +                i++; +            } +            while (i<lines-1); +        } +        else { // For single buffer +            HDC DC=DD_GETDC; +            HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel); +            HBRUSH Brush=CreateSolidBrush(Current->clearpixel); +            HPEN Old_Pen=SelectObject(DC,Pen); +            HBRUSH Old_Brush=SelectObject(DC,Brush); +            Rectangle(DC,x,y,x+width,y+height); +            SelectObject(DC,Old_Pen); +            SelectObject(DC,Old_Brush); +            DeleteObject(Pen); +            DeleteObject(Brush); +            DD_RELEASEDC; +        } + + + +        ENDPROFILE(clear) + +		return mask;	// TODO: I doubt this is correct. dd.h doesn't explain what this should +		                //       be... +} + + + +/* Set the current color index. */ +static void set_index(GLcontext* ctx, GLuint index) +{ +    STARTPROFILE +        Current->pixel=index; +    ENDPROFILE(set_index) +} + + + +/* Set the current RGBA color. */ +static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ +    STARTPROFILE +        Current->pixel = RGB( r, g, b ); +    ENDPROFILE(set_color) +} + + + +/* Set the index mode bitplane mask. */ +static GLboolean index_mask(GLcontext* ctx, GLuint mask) +{ +    /* can't implement */ +    return GL_FALSE; +} + + + +/* Set the RGBA drawing mask. */ +static GLboolean color_mask( GLcontext* ctx, +                            GLboolean rmask, GLboolean gmask, +                            GLboolean bmask, GLboolean amask) +{ +    /* can't implement */ +    return GL_FALSE; +} + + + +/* +* Set the pixel logic operation.  Return GL_TRUE if the device driver +* can perform the operation, otherwise return GL_FALSE.  If GL_FALSE +* is returned, the logic op will be done in software by Mesa. +*/ +GLboolean logicop( GLcontext* ctx, GLenum op ) +{ +    /* can't implement */ +    return GL_FALSE; +} + + +static void dither( GLcontext* ctx, GLboolean enable ) +{ +    if(enable == GL_FALSE){ +        Current->dither_flag = GL_FALSE; +        if(Current->cColorBits == 8) +            Current->pixelformat = PF_INDEX8; +    } +    else{ +        if (Current->rgb_flag && Current->cColorBits == 8){ +            Current->pixelformat = PF_DITHER8; +            Current->dither_flag = GL_TRUE; +        } +        else +            Current->dither_flag = GL_FALSE; +    } +} + + + +static GLboolean set_buffer( GLcontext* ctx, GLenum mode ) +{ +   STARTPROFILE +   /* TODO: this could be better */ +   if (mode==GL_FRONT || mode==GL_BACK) { +      return GL_TRUE; +   } +   else { +      return GL_FALSE; +   } +   ENDPROFILE(set_buffer) +} + + + +/* Return characteristics of the output buffer. */ +static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height ) +{ +   int New_Size; +   RECT CR; + +   STARTPROFILE +   GetClientRect(Current->Window,&CR); + +   *width=CR.right; +   *height=CR.bottom; + +   New_Size=((*width)!=Current->width) || ((*height)!=Current->height); + +   if (New_Size){ +      Current->width=*width; +      Current->height=*height; +      Current->ScanWidth=Current->width; +      if ((Current->ScanWidth%sizeof(long))!=0) +         Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long))); + +      if (Current->db_flag){ +#ifdef DDRAW +         DDDeleteOffScreen(Current); +         DDCreateOffScreen(Current); +#else +         if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){ +            wmDeleteBackingStore(Current); +            wmCreateBackingStore(Current, Current->width, Current->height); +         } +#endif +      } + +      //  Resize OsmesaBuffer if in Parallel mode +#if !defined(NO_PARALLEL) +      if(parallelFlag) +         PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth, +                            Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem); +#endif +   } +   ENDPROFILE(buffer_size) +} + + + +/**********************************************************************/ +/*****           Accelerated point, line, polygon rendering       *****/ +/**********************************************************************/ + + +static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last ) +{ +    GLuint i; +    //  HDC DC=DD_GETDC; +    PWMC    pwc = Current; + +    STARTPROFILE + +        if (Current->gl_ctx->VB->MonoColor) { +            /* all drawn with current color */ +            for (i=first;i<=last;i++) { +                if (!Current->gl_ctx->VB->ClipMask[i]) { +                    int x, y; +                    x =       (GLint) Current->gl_ctx->VB->Win[i][0]; +                    y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] ); +                    wmSetPixel(pwc, y,x,GetRValue(Current->pixel), +                        GetGValue(Current->pixel), GetBValue(Current->pixel)); +                } +            } +        } +        else { +            /* draw points of different colors */ +            for (i=first;i<=last;i++) { +                if (!Current->gl_ctx->VB->ClipMask[i]) { +                    int x, y; +                    unsigned long pixel=RGB(Current->gl_ctx->VB->Color[i][0]*255.0, +                        Current->gl_ctx->VB->Color[i][1]*255.0, +                        Current->gl_ctx->VB->Color[i][2]*255.0); +                    x =       (GLint) Current->gl_ctx->VB->Win[i][0]; +                    y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] ); +                    wmSetPixel(pwc, y,x,Current->gl_ctx->VB->Color[i][0]*255.0, +                        Current->gl_ctx->VB->Color[i][1]*255.0, +                        Current->gl_ctx->VB->Color[i][2]*255.0); +                } +            } +        } +        //   DD_RELEASEDC; +        ENDPROFILE(fast_rgb_points) +} + + + +/* Return pointer to accerated points function */ +extern points_func choose_points_function( GLcontext* ctx ) +{ +    STARTPROFILE +        if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0 +            && !ctx->Texture.Enabled  && ctx->Visual->RGBAflag) { +            ENDPROFILE(choose_points_function) +                return fast_rgb_points; +        } +        else { +            ENDPROFILE(choose_points_function) +                return NULL; +        } +} + + + +/* Draw a line using the color specified by Current->gl_ctx->VB->Color[pv] */ +static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv ) +{ +    STARTPROFILE +        int x0, y0, x1, y1; +    unsigned long pixel; +    HDC DC=DD_GETDC; +    HPEN Pen; +    HPEN Old_Pen; + +    if (Current->gl_ctx->VB->MonoColor) { +        pixel = Current->pixel;  /* use current color */ +    } +    else { +        pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0); +    } + +    x0 =       (int) Current->gl_ctx->VB->Win[v0][0]; +    y0 = FLIP( (int) Current->gl_ctx->VB->Win[v0][1] ); +    x1 =       (int) Current->gl_ctx->VB->Win[v1][0]; +    y1 = FLIP( (int) Current->gl_ctx->VB->Win[v1][1] ); + + +    BEGINGDICALL + +    Pen=CreatePen(PS_SOLID,1,pixel); +    Old_Pen=SelectObject(DC,Pen); +    MoveToEx(DC,x0,y0,NULL); +    LineTo(DC,x1,y1); +    SelectObject(DC,Old_Pen); +    DeleteObject(Pen); +    DD_RELEASEDC; + +    ENDGDICALL + +    ENDPROFILE(fast_flat_rgb_line) +} + + + +/* Return pointer to accerated line function */ +static line_func choose_line_function( GLcontext* ctx ) +{ +    STARTPROFILE +    if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag +        && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0 +        && !ctx->Texture.Enabled && Current->rgb_flag) { +       ENDPROFILE(choose_line_function) +       return fast_flat_rgb_line; +    } +    else { +       ENDPROFILE(choose_line_function) +       return NULL; +    } +} + + +/**********************************************************************/ +/*****                 Span-based pixel drawing                   *****/ +/**********************************************************************/ + + +/* Write a horizontal span of 32-bit color-index pixels with a boolean mask. */ +static void write_ci32_span( const GLcontext* ctx, +                             GLuint n, GLint x, GLint y, +                             const GLuint index[], +                             const GLubyte mask[] ) +{ +    STARTPROFILE +    GLuint i; +    PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +    assert(Current->rgb_flag==GL_FALSE); +    for (i=0; i<n; i++) +        if (mask[i]) +            Mem[i]=index[i]; +    ENDPROFILE(write_ci32_span) +} + + +/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */ +static void write_ci8_span( const GLcontext* ctx, +                            GLuint n, GLint x, GLint y, +                            const GLubyte index[], +                            const GLubyte mask[] ) +{ +    STARTPROFILE +    GLuint i; +    PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +    assert(Current->rgb_flag==GL_FALSE); +    for (i=0; i<n; i++) +        if (mask[i]) +            Mem[i]=index[i]; +    ENDPROFILE(write_ci8_span) +} + + + +/* +* Write a horizontal span of pixels with a boolean mask.  The current +* color index is used for all pixels. +*/ +static void write_mono_ci_span(const GLcontext* ctx, +                               GLuint n,GLint x,GLint y, +                               const GLubyte mask[]) +{ +   STARTPROFILE +   GLuint i; +   BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) +      if (mask[i]) +         Mem[i]=Current->pixel; +   ENDPROFILE(write_mono_ci_span) +} + +/* + * To improve the performance of this routine, frob the data into an actual + * scanline and call bitblt on the complete scan line instead of SetPixel. + */ + +/* Write a horizontal span of RGBA color pixels with a boolean mask. */ +static void write_rgba_span( const GLcontext* ctx, GLuint n, GLint x, GLint y, +                             const GLubyte rgba[][4], const GLubyte mask[] ) +{ +    STARTPROFILE +    PWMC    pwc = Current; + +    if (pwc->rgb_flag==GL_TRUE) +    { +        GLuint i; +        HDC DC=DD_GETDC; +        y=FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); +        } +        else { +            for (i=0; i<n; i++) +                wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); +        } +        DD_RELEASEDC; +    } +    else +    { +        GLuint i; +        BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x; +        y = FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); +        } +        else { +            for (i=0; i<n; i++) +                Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); +        } +    } +    ENDPROFILE(write_rgba_span) + +} + +/* Write a horizontal span of RGB color pixels with a boolean mask. */ +static void write_rgb_span( const GLcontext* ctx, +                            GLuint n, GLint x, GLint y, +                            const GLubyte rgb[][3], const GLubyte mask[] ) +{ +    STARTPROFILE +    PWMC    pwc = Current; + +    if (pwc->rgb_flag==GL_TRUE) +    { +        GLuint i; +        HDC DC=DD_GETDC; +        y=FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); +        } +        else { +            for (i=0; i<n; i++) +                wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ); +        } +        DD_RELEASEDC; +    } +    else +    { +        GLuint i; +        BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x; +        y = FLIP(y); +        if (mask) { +            for (i=0; i<n; i++) +                if (mask[i]) +                    Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP])); +        } +        else { +            for (i=0; i<n; i++) +                Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP])); +        } +    } +    ENDPROFILE(write_rgb_span) + +} + +/* +* Write a horizontal span of pixels with a boolean mask.  The current color +* is used for all pixels. +*/ +static void write_mono_rgba_span( const GLcontext* ctx, +                                  GLuint n, GLint x, GLint y, +                                  const GLubyte mask[]) +{ +    STARTPROFILE +    GLuint i; +    HDC DC=DD_GETDC; +    PWMC pwc = Current; +    assert(Current->rgb_flag==GL_TRUE); +    y=FLIP(y); +    if(Current->rgb_flag==GL_TRUE){ +        for (i=0; i<n; i++) +            if (mask[i]) +                // Trying +                wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel)); +    } +    else { +        for (i=0; i<n; i++) +            if (mask[i]) +                SetPixel(DC, y, x+i, Current->pixel); +    } +    DD_RELEASEDC; +    ENDPROFILE(write_mono_rgba_span) +} + + + +/**********************************************************************/ +/*****                   Array-based pixel drawing                *****/ +/**********************************************************************/ + + +/* Write an array of 32-bit index pixels with a boolean mask. */ +static void write_ci32_pixels( const GLcontext* ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               const GLuint index[], const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]; +         *Mem = index[i]; +      } +   } +   ENDPROFILE(write_ci32_pixels) +} + + + +/* +* Write an array of pixels with a boolean mask.  The current color +* index is used for all pixels. +*/ +static void write_mono_ci_pixels( const GLcontext* ctx, +                                  GLuint n, +                                  const GLint x[], const GLint y[], +                                  const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]; +         *Mem = Current->pixel; +      } +   } +   ENDPROFILE(write_mono_ci_pixels) +} + + + +/* Write an array of RGBA pixels with a boolean mask. */ +static void write_rgba_pixels( const GLcontext* ctx, +                               GLuint n, const GLint x[], const GLint y[], +                               const GLubyte rgba[][4], const GLubyte mask[] ) +{ +    STARTPROFILE +        GLuint i; +    PWMC    pwc = Current; +    HDC DC=DD_GETDC; +    assert(Current->rgb_flag==GL_TRUE); +    for (i=0; i<n; i++) +       if (mask[i]) +          wmSetPixel(pwc, FLIP(y[i]),x[i],rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]); +    DD_RELEASEDC; +    ENDPROFILE(write_rgba_pixels) +} + + + +/* +* Write an array of pixels with a boolean mask.  The current color +* is used for all pixels. +*/ +static void write_mono_rgba_pixels( const GLcontext* ctx, +                                    GLuint n, +                                    const GLint x[], const GLint y[], +                                    const GLubyte mask[] ) +{ +    STARTPROFILE +    GLuint i; +    PWMC    pwc = Current; +    HDC DC=DD_GETDC; +    assert(Current->rgb_flag==GL_TRUE); +    for (i=0; i<n; i++) +        if (mask[i]) +            wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel), +                       GetGValue(Current->pixel), GetBValue(Current->pixel)); +    DD_RELEASEDC; +    ENDPROFILE(write_mono_rgba_pixels) +} + + + +/**********************************************************************/ +/*****            Read spans/arrays of pixels                     *****/ +/**********************************************************************/ + + +/* Read a horizontal span of color-index pixels. */ +static void read_ci32_span( const GLcontext* ctx, GLuint n, GLint x, GLint y, +                            GLuint index[]) +{ +   STARTPROFILE +   GLuint i; +   BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) +      index[i]=Mem[i]; +   ENDPROFILE(read_ci32_span) +} + + + + +/* Read an array of color index pixels. */ +static void read_ci32_pixels( const GLcontext* ctx, +                              GLuint n, const GLint x[], const GLint y[], +                              GLuint indx[], const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   assert(Current->rgb_flag==GL_FALSE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]); +      } +   } +   ENDPROFILE(read_ci32_pixels) +} + + + +/* Read a horizontal span of color pixels. */ +static void read_rgba_span( const GLcontext* ctx, +                            GLuint n, GLint x, GLint y, +                            GLubyte rgba[][4] ) +{ +   STARTPROFILE +   UINT i; +   COLORREF Color; +   HDC DC=DD_GETDC; +   assert(Current->rgb_flag==GL_TRUE); +   y=FLIP(y); +   for (i=0; i<n; i++) { +      Color=GetPixel(DC,x+i,y); +      rgba[i][RCOMP] = GetRValue(Color); +      rgba[i][GCOMP] = GetGValue(Color); +      rgba[i][BCOMP] = GetBValue(Color); +      rgba[i][ACOMP] = 255; +   } +   DD_RELEASEDC; +// Brian P. Has mentioned to comment this out. +//   memset(alpha,0,n*sizeof(GLubyte)); +   ENDPROFILE(read_rgba_span) +} + + +/* Read an array of color pixels. */ +static void read_rgba_pixels( const GLcontext* ctx, +                              GLuint n, const GLint x[], const GLint y[], +                              GLubyte rgba[][4], const GLubyte mask[] ) +{ +   STARTPROFILE +   GLuint i; +   COLORREF Color; +   HDC DC=DD_GETDC; +   assert(Current->rgb_flag==GL_TRUE); +   for (i=0; i<n; i++) { +      if (mask[i]) { +         Color=GetPixel(DC,x[i],FLIP(y[i])); +         rgba[i][RCOMP] = GetRValue(Color); +         rgba[i][GCOMP] = GetGValue(Color); +         rgba[i][BCOMP] = GetBValue(Color); +         rgba[i][ACOMP] = 255; +      } +   } +   DD_RELEASEDC; +// Brian P. has mentioned to comment this out. +//   memset(alpha,0,n*sizeof(GLint)); +   ENDPROFILE(read_rgba_pixels) +} + + + +/**********************************************************************/ +/**********************************************************************/ + + +static const char *renderer_string(void) +{ +   return "Windows"; +} + + + +void setup_DD_pointers( GLcontext* ctx ) +{ +    ctx->Driver.RendererString = renderer_string; +    ctx->Driver.UpdateState = setup_DD_pointers; +    ctx->Driver.GetBufferSize = buffer_size; +    ctx->Driver.Finish = finish; +    ctx->Driver.Flush = flush; + +    ctx->Driver.ClearIndex = clear_index; +    ctx->Driver.ClearColor = clear_color; +    ctx->Driver.Clear = clear; + +    ctx->Driver.Index = set_index; +    ctx->Driver.Color = set_color; +    ctx->Driver.IndexMask = index_mask; +    ctx->Driver.ColorMask = color_mask; + +    ctx->Driver.LogicOp = logicop; +    ctx->Driver.Dither = dither; + +    ctx->Driver.SetBuffer = set_buffer; +    ctx->Driver.GetBufferSize = buffer_size; + +    ctx->Driver.PointsFunc = choose_points_function(ctx); +    ctx->Driver.LineFunc = choose_line_function(ctx); +    ctx->Driver.TriangleFunc = choose_triangle_function( ctx ); + +    /* Pixel/span writing functions: */ +	ctx->Driver.WriteRGBASpan        = write_rgba_span; +    ctx->Driver.WriteRGBSpan         = write_rgb_span; +    ctx->Driver.WriteMonoRGBASpan    = write_mono_rgba_span; +    ctx->Driver.WriteRGBAPixels      = write_rgba_pixels; +    ctx->Driver.WriteMonoRGBAPixels  = write_mono_rgba_pixels; +    ctx->Driver.WriteCI32Span        = write_ci32_span; +    ctx->Driver.WriteCI8Span         = write_ci8_span; +    ctx->Driver.WriteMonoCISpan      = write_mono_ci_span; +    ctx->Driver.WriteCI32Pixels      = write_ci32_pixels; +    ctx->Driver.WriteMonoCIPixels    = write_mono_ci_pixels; + +    ctx->Driver.ReadCI32Span        = read_ci32_span; +    ctx->Driver.ReadRGBASpan        = read_rgba_span; +    ctx->Driver.ReadCI32Pixels      = read_ci32_pixels; +    ctx->Driver.ReadRGBAPixels      = read_rgba_pixels; +} + + +/**********************************************************************/ +/*****                  WMesa API Functions                       *****/ +/**********************************************************************/ + + + +#define PAL_SIZE 256 +static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB) +{ +    STARTPROFILE +        int i; +    HDC hdc; +    struct +    { +        WORD Version; +        WORD NumberOfEntries; +        PALETTEENTRY aEntries[PAL_SIZE]; +    } Palette = +    { +        0x300, +            PAL_SIZE +    }; +    hdc=GetDC(NULL); +    if (Pal!=NULL) +        GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries); +    else +        GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries); +    if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) +    { +        for(i = 0; i <PAL_SIZE; i++) +            Palette.aEntries[i].peFlags = PC_RESERVED; +        Palette.aEntries[255].peRed = 255; +        Palette.aEntries[255].peGreen = 255; +        Palette.aEntries[255].peBlue = 255; +        Palette.aEntries[255].peFlags = 0; +        Palette.aEntries[0].peRed = 0; +        Palette.aEntries[0].peGreen = 0; +        Palette.aEntries[0].peBlue = 0; +        Palette.aEntries[0].peFlags = 0; +    } +    else +    { +        int nStaticColors; +        int nUsableColors; +        nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2; +        for (i=0; i<nStaticColors; i++) +            Palette.aEntries[i].peFlags = 0; +        nUsableColors = PAL_SIZE-nStaticColors; +        for (; i<nUsableColors; i++) +            Palette.aEntries[i].peFlags = PC_RESERVED; +        for (; i<PAL_SIZE-nStaticColors; i++) +            Palette.aEntries[i].peFlags = PC_RESERVED; +        for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++) +            Palette.aEntries[i].peFlags = 0; +    } +    ReleaseDC(NULL,hdc); +    for (i=0; i<PAL_SIZE; i++) +    { +        aRGB[i].rgbRed=Palette.aEntries[i].peRed; +        aRGB[i].rgbGreen=Palette.aEntries[i].peGreen; +        aRGB[i].rgbBlue=Palette.aEntries[i].peBlue; +        aRGB[i].rgbReserved=Palette.aEntries[i].peFlags; +    } +    ENDPROFILE(GetPalette) +} + + +WMesaContext WMesaCreateContext( HWND hWnd, +											HPALETTE* Pal, +											GLboolean rgb_flag, +											GLboolean db_flag ) +{ +    RECT CR; +    WMesaContext c; +    GLboolean true_color_flag; +    c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context)); +    if (!c) +        return NULL; + +    c->Window=hWnd; +    c->hDC = GetDC(hWnd); +    true_color_flag = GetDeviceCaps(c->hDC, BITSPIXEL) > 8; +#ifdef DDRAW +    if(true_color_flag) c->rgb_flag = rgb_flag = GL_TRUE; +#endif + + +#ifdef DITHER +    if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){ +        c->dither_flag = GL_TRUE; +        c->hPalHalfTone = WinGCreateHalftonePalette(); +    } +    else +        c->dither_flag = GL_FALSE; +#else +    c->dither_flag = GL_FALSE; +#endif + + +    if (rgb_flag==GL_FALSE) +    { +        c->rgb_flag = GL_FALSE; +        //    c->pixel = 1; +        c->db_flag = db_flag =GL_TRUE; // WinG requires double buffering +        printf("Single buffer is not supported in color index mode, setting to double buffer.\n"); +    } +    else +    { +        c->rgb_flag = GL_TRUE; +        //    c->pixel = 0; +    } +    GetClientRect(c->Window,&CR); +    c->width=CR.right; +    c->height=CR.bottom; +    if (db_flag) +    { +        c->db_flag = 1; +        /* Double buffered */ +#ifndef DDRAW +        //  if (c->rgb_flag==GL_TRUE && c->dither_flag != GL_TRUE ) +        { +            wmCreateBackingStore(c, c->width, c->height); + +        } +#endif +    } +    else +    { +        /* Single Buffered */ +        if (c->rgb_flag) +            c->db_flag = 0; +    } +#ifdef DDRAW +    if (DDInit(c,hWnd) == GL_FALSE) { +        free( (void *) c ); +        exit(1); +    } +#endif + + +    c->gl_visual = gl_create_visual(rgb_flag, +                                    GL_FALSE,   /* software alpha */ +                                    db_flag,    /* db_flag */ +                                    GL_FALSE,   /* stereo */ +                                    16,         /* depth_bits */ +                                    8,          /* stencil_bits */ +                                    8,          /* accum_bits */ +                                    0,          /* index bits */ +                                    8,8,8,8 );  /* r, g, b, a bits */ + +    if (!c->gl_visual) { +        return NULL; +    } + +    /* allocate a new Mesa context */ +    c->gl_ctx = gl_create_context( c->gl_visual, NULL, c, GL_TRUE); + +    if (!c->gl_ctx) { +        gl_destroy_visual( c->gl_visual ); +        free(c); +        return NULL; +    } + +    c->gl_buffer = gl_create_framebuffer( c->gl_visual ); +    if (!c->gl_buffer) { +        gl_destroy_visual( c->gl_visual ); +        gl_destroy_context( c->gl_ctx ); +        free(c); +        return NULL; +    }
 +
 +	c->gl_ctx->Driver.UpdateState = setup_DD_pointers;
 + +    //  setup_DD_pointers(c->gl_ctx); + +    return c; +} + +void WMesaDestroyContext( void ) +{ +    WMesaContext c = Current; +    ReleaseDC(c->Window,c->hDC); +    WC = c; +    if(c->hPalHalfTone != NULL) +        DeleteObject(c->hPalHalfTone); +    gl_destroy_visual( c->gl_visual ); +    gl_destroy_framebuffer( c->gl_buffer ); +    gl_destroy_context( c->gl_ctx ); + +    if (c->db_flag) +#ifdef DDRAW +        DDFree(c); +#else +    wmDeleteBackingStore(c); +#endif +    free( (void *) c ); +    //Following code is added to enable parallel render +    // Parallel render only work in double buffer mode +#if !defined(NO_PARALLEL) +    if(parallelMachine) +        PRDestroyRenderBuffer(); +#endif +    // End modification +} + +void WMesaMakeCurrent( WMesaContext c ) +{ +    if(!c){ +        Current = c; +        return; +    } + +    // +    // A little optimization +    // If it already is current, +    // don't set it again +    // +    if(Current == c) +        return; + +    //gl_set_context( c->gl_ctx ); +    gl_make_current(c->gl_ctx, c->gl_buffer); +    setup_DD_pointers(c->gl_ctx);
 +    Current = c; +    if (Current->gl_ctx->Viewport.Width==0) { +        /* initialize viewport to window size */ +        gl_Viewport( Current->gl_ctx, +            0, 0, Current->width, Current->height ); +    } +    if ((c->cColorBits <= 8 ) && (c->rgb_flag == GL_TRUE)){ +        WMesaPaletteChange(c->hPalHalfTone); +    } +} + +void  WMesaSwapBuffers( void ) +{ +    HDC DC = Current->hDC; +    if (Current->db_flag) +        wmFlush(Current); +} + +void  WMesaPaletteChange(HPALETTE Pal) +{ +    int vRet; +    LPPALETTEENTRY pPal; +    if (Current && (Current->rgb_flag==GL_FALSE || Current->dither_flag == GL_TRUE)) +    { +        pPal = (PALETTEENTRY *)malloc( 256 * sizeof(PALETTEENTRY)); +        Current->hPal=Pal; +        //  GetPaletteEntries( Pal, 0, 256, pPal ); +        GetPalette( Pal, pPal ); +#ifdef DDRAW +        Current->lpDD->lpVtbl->CreatePalette(Current->lpDD,DDPCAPS_8BIT, +            pPal, &(Current->lpDDPal), NULL); +        if (Current->lpDDPal) +            Current->lpDDSPrimary->lpVtbl->SetPalette(Current->lpDDSPrimary,Current->lpDDPal); +#else +        vRet = SetDIBColorTable(Current->dib.hDC,0,256,pPal); +#endif +        free( pPal ); +    } + +} + +static unsigned char threeto8[8] = { +    0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377 +}; + +static unsigned char twoto8[4] = { +    0, 0x55, 0xaa, 0xff +}; + +static unsigned char oneto8[2] = { +    0, 255 +}; + +static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift) +{ +    unsigned char val; + +    val = i >> shift; +    switch (nbits) { + +    case 1: +        val &= 0x1; +        return oneto8[val]; + +    case 2: +        val &= 0x3; +        return twoto8[val]; + +    case 3: +        val &= 0x7; +        return threeto8[val]; + +    default: +        return 0; +    } +} + +void wmCreatePalette( PWMC pwdc ) +{ +    /* Create a compressed and re-expanded 3:3:2 palette */ +    int            i; +    LOGPALETTE     *pPal; +    BYTE           rb, rs, gb, gs, bb, bs; + +    pwdc->nColors = 0x100; + +    pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY)); +    memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) ); + +    pPal->palVersion = 0x300; + +    rb = REDBITS; +    rs = REDSHIFT; +    gb = GREENBITS; +    gs = GREENSHIFT; +    bb = BLUEBITS; +    bs = BLUESHIFT; + +    if (pwdc->db_flag) { + +        /* Need to make two palettes: one for the screen DC and one for the DIB. */ +        pPal->palNumEntries = pwdc->nColors; +        for (i = 0; i < pwdc->nColors; i++) { +            pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs ); +            pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs ); +            pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs ); +            pPal->palPalEntry[i].peFlags = 0; +        } +        pwdc->hGLPalette = CreatePalette( pPal ); +        pwdc->hPalette = CreatePalette( pPal ); +    } + +    else { +        pPal->palNumEntries = pwdc->nColors; +        for (i = 0; i < pwdc->nColors; i++) { +            pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs ); +            pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs ); +            pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs ); +            pPal->palPalEntry[i].peFlags = 0; +        } +        pwdc->hGLPalette = CreatePalette( pPal ); +    } + +    free(pPal); + +} + +void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b) +{ +    if(Current->db_flag){ +        LPBYTE  lpb = pwc->pbPixels; +        LPDWORD lpdw; +        LPWORD  lpw; +        UINT    nBypp = pwc->cColorBits / 8; +        UINT    nOffset = iPixel % nBypp; + +        // Move the pixel buffer pointer to the scanline that we +        // want to access + +        //      pwc->dib.fFlushed = FALSE; + +        lpb += pwc->ScanWidth * iScanLine; +        // Now move to the desired pixel +        lpb += iPixel * nBypp; +        lpb = PIXELADDR(iPixel, iScanLine); +        lpdw = (LPDWORD)lpb; +        lpw = (LPWORD)lpb; + +        if(nBypp == 1){ +            if(pwc->dither_flag) +                *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel); +            else +                *lpb = BGR8(r,g,b); +        } +        else if(nBypp == 2) +            *lpw = BGR16(r,g,b); +        else if (nBypp == 3){ +            *lpdw = BGR24(r,g,b); +        } +        else if (nBypp == 4) +            *lpdw = BGR32(r,g,b); +    } +    else{ +        HDC DC = DD_GETDC; +        SetPixel(DC, iPixel, iScanLine, RGB(r,g,b)); +        DD_RELEASEDC; +    } +} + +void wmCreateDIBSection( HDC   hDC, +						 PWMC pwc,    // handle of device context +						 CONST BITMAPINFO *pbmi,  // address of structure containing bitmap size, format, and color data +						 UINT iUsage  // color data type indicator: RGB values or palette indices +                       ) +{ +    DWORD   dwSize = 0; +    DWORD   dwScanWidth; +    UINT    nBypp = pwc->cColorBits / 8; +    HDC     hic; + +    dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3); + +    pwc->ScanWidth =pwc->pitch = dwScanWidth; + +    if (stereo_flag) +        pwc->ScanWidth = 2* pwc->pitch; + +    dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height); + +    pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE, +        NULL, +        PAGE_READWRITE | SEC_COMMIT, +        0, +        dwSize, +        NULL); + +    if (!pwc->dib.hFileMap) +        return; + +    pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap, +        FILE_MAP_ALL_ACCESS, +        0, +        0, +        0); + +    if(!pwc->dib.base){ +        CloseHandle(pwc->dib.hFileMap); +        return; +    } + +    //  pwc->pbPixels = pwc->addrOffScreen = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO); + +    //  pwc->dib.hDC = CreateCompatibleDC(hDC); + +    CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO)); + +    hic = CreateIC("display", NULL, NULL, NULL); +    pwc->dib.hDC = CreateCompatibleDC(hic); + + +    /*  pwc->hbmDIB = CreateDIBitmap(hic, +    &(pwc->bmi.bmiHeader), +    CBM_INIT, +    pwc->pbPixels, +    &(pwc->bmi), +    DIB_RGB_COLORS); +    */ +    pwc->hbmDIB = CreateDIBSection(hic, +        &(pwc->bmi), +        (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS), +        &(pwc->pbPixels), +        pwc->dib.hFileMap, +        0); +        /* +        pwc->hbmDIB = CreateDIBSection(hic, +        &(pwc->bmi), +        DIB_RGB_COLORS, +        &(pwc->pbPixels), +        pwc->dib.hFileMap, +        0); +    */ +    pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels; +    pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB); + +    DeleteDC(hic); + +    return; + +} + +// +// Blit memory DC to screen DC +// +BOOL wmFlush(PWMC pwc) +{ +    BOOL    bRet = 0; +    DWORD   dwErr = 0; +#ifdef DDRAW +    HRESULT             ddrval; +#endif + +    // Now search through the torus frames and mark used colors +    if(pwc->db_flag){ +#ifdef DDRAW +        if (pwc->lpDDSOffScreen == NULL) +            if(DDCreateOffScreen(pwc) == GL_FALSE) +                return; + +            pwc->lpDDSOffScreen->lpVtbl->Unlock(pwc->lpDDSOffScreen, NULL); + +            while( 1 ) +            { +                ddrval = pwc->lpDDSPrimary->lpVtbl->Blt( pwc->lpDDSPrimary, +                    &(pwc->rectSurface), pwc->lpDDSOffScreen, &(pwc->rectOffScreen), 0, NULL ); + +                if( ddrval == DD_OK ) +                { +                    break; +                } +                if( ddrval == DDERR_SURFACELOST ) +                { +                    if(!DDRestoreAll(pwc)) +                    { +                        break; +                    } +                } +                if( ddrval != DDERR_WASSTILLDRAWING ) +                { +                    break; +                } +            } + +            while (pwc->lpDDSOffScreen->lpVtbl->Lock(pwc->lpDDSOffScreen, +                NULL, &(pwc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING) +                ; + +            if(ddrval != DD_OK) +                dwErr = GetLastError(); +#else +            bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height, +                pwc->dib.hDC, 0, 0, SRCCOPY); +#endif +    } + +    return(TRUE); + +} + +// The following code is added by Li Wei to enable stereo display + +#if !defined(NO_STEREO) + +void WMesaShowStereo(GLuint list) +{ + +    GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; +    GLfloat cm[16]; +    GLint matrix_mode; +    // Must use double Buffer +    if( ! Current-> db_flag ) +        return; + + +    glGetIntegerv(GL_MATRIX_MODE,&matrix_mode); + +    //  glPushMatrix();  //**** +    WMesaViewport(Current->gl_ctx,0,Current->height/2,Current->width,Current->height/2); +    //  Current->gl_ctx->NewState = 0; + +    //  glViewport(0,0,Current->width,Current->height/2); +    if(matrix_mode!=GL_MODELVIEW) +        glMatrixMode(GL_MODELVIEW); + +    glGetFloatv(GL_MODELVIEW_MATRIX,cm); +    glLoadIdentity(); +    gluLookAt(viewDistance/2,0.0,0.0 , +        viewDistance/2,0.0,-1.0, +        0.0,1.0,0.0 ); +    //  glTranslatef(viewDistance/2.0,0.,0.); +    glMultMatrixf( cm ); + +    Current->ScreenMem = Current->pbPixels = Current->addrOffScreen; +    //glPushMatrix(); +    glCallList( list ); +    //glPopMatrix(); + +    glGetFloatv(GL_MODELVIEW_MATRIX,cm); +    glLoadIdentity(); +    gluLookAt(-viewDistance/2,0.0,0.0 , +        -viewDistance/2,0.0,-1.0, +        0.0,1.0,0.0 ); +    //  glTranslatef(-viewDistance/2.0,0.,0.); +    glMultMatrixf(cm); + +    Current->ScreenMem = Current->pbPixels = Current->addrOffScreen + Current->pitch; +    glCallList(list); +    if(matrix_mode!=GL_MODELVIEW) +        glMatrixMode(matrix_mode); + +    //  glPopMatrix(); +    glFlush(); + +    WMesaViewport(Current->gl_ctx,0,0,Current->width,Current->height); +    //  Current->gl_ctx->NewState = 0; +    WMesaSwapBuffers(); + +} + +void toggleStereoMode() +{ +    if(!Current->db_flag) +        return; +    if(!stereo_flag){ +        stereo_flag = 1; +        if(stereoBuffer==GL_FALSE) +#if !defined(NO_PARALLEL) +            if(!parallelFlag) +#endif +            { +                Current->ScanWidth = Current->pitch*2; +            } +    } +    else { +        stereo_flag = 0; +#if !defined(NO_PARALLEL) +        if(!parallelFlag) +#endif +            Current->ScanWidth = Current->pitch; +        Current->pbPixels = Current->addrOffScreen; +    } +} + +/* if in stereo mode, the following function is called */ +void glShowStereo(GLuint list) +{ +    WMesaShowStereo(list); +} + +#endif // End if NO_STEREO not defined + +#if !defined(NO_PARALLEL) + +void toggleParallelMode(void) +{ +    if(!parallelFlag){ +        parallelFlag = GL_TRUE; +        if(parallelMachine==GL_FALSE){ +            PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX, +                Current->cColorBits/8, +                Current->width ,Current->height, +                Current->ScanWidth, +                Current->rgb_flag? Current->pbPixels: Current->ScreenMem); +            parallelMachine = GL_TRUE; +        } +    } +    else { +        parallelFlag = GL_FALSE; +        if(parallelMachine==GL_TRUE){ +            PRDestroyRenderBuffer(); +            parallelMachine=GL_FALSE; +            ReadyForNextFrame = GL_TRUE; +        } + +        /*********************************************** +        // Seems something wrong!!!! +        ************************************************/ + +        WMesaMakeCurrent(Current); +#if !defined(NO_STEREO) +        stereo_flag = GL_FALSE ; +#endif +    } +} + +void PRShowRenderResult(void) +{ +    int flag = 0; +    if(!glImageRendered()) +        return; + +    if (parallelFlag) +    { +        WMesaSwapBuffers(); +    } + +} +#endif //End if NO_PARALLEL not defined + +//end modification + +BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline) +{ +    char unsigned redtemp, greentemp, bluetemp, paletteindex; + +    //*** now, look up each value in the halftone matrix +    //*** using an 8x8 ordered dither. +    redtemp = aDividedBy51[red] +        + (aModulo51[red] > aHalftone8x8[(pixel%8)*8 +        + scanline%8]); +    greentemp = aDividedBy51[(char unsigned)green] +        + (aModulo51[green] > aHalftone8x8[ +        (pixel%8)*8 + scanline%8]); +    bluetemp = aDividedBy51[(char unsigned)blue] +        + (aModulo51[blue] > aHalftone8x8[ +        (pixel%8)*8 +scanline%8]); + +    //*** recombine the halftoned rgb values into a palette index +    paletteindex = +        redtemp + aTimes6[greentemp] + aTimes36[bluetemp]; + +    //*** and translate through the wing halftone palette +    //*** translation vector to give the correct value. +    return aWinGHalftoneTranslation[paletteindex]; +} + +#ifdef DDRAW +/* +* restoreAll +* +* restore all lost objects +*/ +static HRESULT DDRestoreAll( WMesaContext wc ) +{ +    HRESULT     ddrval; + +    ddrval = wc->lpDDSPrimary->lpVtbl->Restore(wc->lpDDSPrimary); +    if( ddrval == DD_OK ) +    { +        ddrval = wc->lpDDSOffScreen->lpVtbl->Restore(wc->lpDDSOffScreen); +    } +    return ddrval; + +} /* restoreAll */ + + +  /* +  * This function is called if the initialization function fails +*/ +static BOOL initFail( HWND hwnd, WMesaContext wc ) +{ +    DDFree(wc); +    MessageBox( hwnd, "DirectDraw Init FAILED", "", MB_OK ); +    return FALSE; + +} /* initFail */ + + +static void DDDeleteOffScreen(WMesaContext wc) +{ +    if( wc->lpDDSOffScreen != NULL ) +    { +        wc->lpDDSOffScreen->lpVtbl->Unlock(wc->lpDDSOffScreen,NULL); +        wc->lpDDSOffScreen->lpVtbl->Release(wc->lpDDSOffScreen); +        wc->lpDDSOffScreen = NULL; +    } + +} + +static void DDFreePrimarySurface(WMesaContext wc) +{ +    if( wc->lpDDSPrimary != NULL ) +    { +        if(wc->db_flag == GL_FALSE) +            wc->lpDDSPrimary->lpVtbl->ReleaseDC(wc->lpDDSPrimary, wc->hDC); +        wc->lpDDSPrimary->lpVtbl->Release(wc->lpDDSPrimary); +        wc->lpDDSPrimary = NULL; +    } +} + +static BOOL DDCreatePrimarySurface(WMesaContext wc) +{ +    HRESULT ddrval; +    DDSCAPS             ddscaps; +    wc->ddsd.dwSize = sizeof( wc->ddsd ); +    wc->ddsd.dwFlags = DDSD_CAPS; +    wc->ddsd.ddsCaps.dwCaps =   DDSCAPS_PRIMARYSURFACE; + +    ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD,&(wc->ddsd), &(wc->lpDDSPrimary), NULL ); +    if( ddrval != DD_OK ) +    { +        return initFail(wc->hwnd , wc); +    } +    if(wc->db_flag == GL_FALSE) +        wc->lpDDSPrimary->lpVtbl->GetDC(wc->lpDDSPrimary, wc->hDC); +    return TRUE; +} + +static BOOL DDCreateOffScreen(WMesaContext wc) +{ +    POINT   pt; +    HRESULT     ddrval; +    if(wc->lpDD == NULL) +        return FALSE; +    GetClientRect( wc->hwnd, &(wc->rectOffScreen) ); +    wc->ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; +    wc->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; +    wc->ddsd.dwHeight = wc->rectOffScreen.bottom - wc->rectOffScreen.top; +    wc->ddsd.dwWidth = wc->rectOffScreen.right - wc->rectOffScreen.left; + +    ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD, &(wc->ddsd), &(wc->lpDDSOffScreen), NULL ); +    if( ddrval != DD_OK ) +    { +        return FALSE; +    } + +    while (wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING) +        ; +    //  while ((ddrval = wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), DDLOCK_SURFACEMEMORYPTR , NULL)) != DD_OK) +    ; +    if(wc->ddsd.lpSurface==NULL) +        return initFail(wc->hwnd, wc); + +    wc->ScreenMem = wc->pbPixels = wc->addrOffScreen = (PBYTE)(wc->ddsd.lpSurface); +    wc->ScanWidth = wc->pitch = wc->ddsd.lPitch; +    if (stereo_flag) +        wc->ScanWidth = wc->ddsd.lPitch*2; + +    GetClientRect( wc->hwnd, &(wc->rectSurface) ); +    pt.x = pt.y = 0; +    ClientToScreen( wc->hwnd, &pt ); +    OffsetRect(&(wc->rectSurface), pt.x, pt.y); +    wmSetPixelFormat(wc, wc->hDC); +    return TRUE; +} + +/* +* doInit - do work required for every instance of the application: +*                create the window, initialize data +*/ +static BOOL DDInit( WMesaContext wc, HWND hwnd) +{ +    HRESULT             ddrval; +    DWORD dwFrequency; + +    LPDIRECTDRAW            lpDD;           // DirectDraw object +    LPDIRECTDRAW2            lpDD2; + + +    wc->fullScreen = displayOptions.fullScreen; +    wc->gMode = displayOptions.mode; +    wc->hwnd = hwnd; +    stereo_flag = displayOptions.stereo; +    if(wc->db_flag!= GL_TRUE) +        stereo_flag = GL_FALSE; +        /* +        * create the main DirectDraw object +    */ +    ddrval = DirectDrawCreate( NULL, &(wc->lpDD), NULL ); +    if( ddrval != DD_OK ) +    { +        return initFail(hwnd,wc); +    } + +    // Get exclusive mode if requested +    if(wc->fullScreen) +    { +        ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ); +    } +    else +    { +        ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_NORMAL ); +    } +    if( ddrval != DD_OK ) +    { +        return initFail(hwnd , wc); +    } + + +    /*  ddrval = wc->lpDD->lpVtbl->QueryInterface(wc->lpDD, IID_IDirectDraw2, +    (LPVOID *)((wc->lpDD2))); + +    */ +    if(ddrval != DD_OK) +        return initFail(hwnd , wc); + + +    //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd)); +    //  wc->lpDD2->lpVtbl->GetMonitorFrequency(wc->lpDD, &dwFrequency); +    switch( wc->gMode ) +    { +    case 1:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 640, 480, displayOptions.bpp); break; +    case 2:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 800, 600, displayOptions.bpp); break; +    case 3:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1024, 768, displayOptions.bpp); break; +    case 4:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1152, 864, displayOptions.bpp); break; +    case 5:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1280, 1024, displayOptions.bpp); break; +    } + +    if( ddrval != DD_OK ) +    { +        printf("Can't modify display mode, current mode used\n"); +        //        return initFail(hwnd , wc); +    } +    //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd)); +    switch(ddrval){ +    case DDERR_INVALIDOBJECT: +        break; +    case DDERR_INVALIDPARAMS: +        break; +    case DDERR_UNSUPPORTEDMODE: +        ; +    } + +    if(DDCreatePrimarySurface(wc) == GL_FALSE) +        return initFail(hwnd, wc); + +    if(wc->db_flag) +        return DDCreateOffScreen(wc); +} /* DDInit */ + +static void DDFree( WMesaContext wc) +{ +    if( wc->lpDD != NULL ) +    { +        DDFreePrimarySurface(wc); +        DDDeleteOffScreen(wc); +        wc->lpDD->lpVtbl->Release(wc->lpDD); +        wc->lpDD = NULL; +    } +    // Clean up the screen on exit +    RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | +        RDW_ALLCHILDREN ); + +} +#endif + +void WMesaMove(void) +{ +    WMesaContext wc = Current; +    POINT   pt; +    if (Current != NULL){ +        GetClientRect( wc->hwnd, &(wc->rectSurface) ); +        pt.x = pt.y = 0; +        ClientToScreen( wc->hwnd, &pt ); +        OffsetRect(&(wc->rectSurface), pt.x, pt.y); +    } +} + + + +/* +* Like PACK_8A8B8G8R() but don't use alpha.  This is usually an acceptable +* shortcut. +*/ +#define PACK_8B8G8R( R, G, B )   ( ((B) << 16) | ((G) << 8) | (R) ) + + +/**********************************************************************/ +/***                   Triangle rendering                            ***/ +/**********************************************************************/ + +/* + * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle. + */ +static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx, +                                       GLuint v0, GLuint v1, GLuint v2, +                                       GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),    \ +    FixedToInt(ffb) );          \ +    zRow[i] = z;                            \ +    }                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    ffz += fdzdx;                           \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, smooth, depth-buffered, PF_8R8G8B triangle. +*/ +static void smooth_8R8G8B_z_triangle( GLcontext *ctx, +                                     GLuint v0, GLuint v1, GLuint v2, +                                     GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),    \ +    FixedToInt(ffb) );          \ +    zRow[i] = z;                            \ +    }                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    ffz += fdzdx;                           \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + + +/* +* XImage, smooth, depth-buffered, PF_5R6G5B triangle. +*/ +static void smooth_5R6G5B_z_triangle( GLcontext *ctx, +                                     GLuint v0, GLuint v1, GLuint v2, +                                     GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg),    \ +    FixedToInt(ffb) );          \ +    zRow[i] = z;                            \ +    }                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    ffz += fdzdx;                           \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + +/* +* XImage, flat, depth-buffered, PF_8A8B8G8R triangle. +*/ +static void flat_8A8B8G8R_z_triangle( GLcontext *ctx, GLuint v0, +                                     GLuint v1, GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8B8G8R( VB->Color[pv][0],    \ +    VB->Color[pv][1], VB->Color[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint i, len = RIGHT-LEFT;                      \ +    for (i=0;i<len;i++) {                       \ +    GLdepth z = FixedToDepth(ffz);                  \ +    if (z < zRow[i]) {                      \ +    pRow[i] = p;                            \ +    zRow[i] = z;                            \ +    }                                   \ +    ffz += fdzdx;                           \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, flat, depth-buffered, PF_8R8G8B triangle. +*/ +static void flat_8R8G8B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8R8G8B( VB->Color[pv][0],    \ +    VB->Color[pv][1], VB->Color[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint i, len = RIGHT-LEFT;              \ +    for (i=0;i<len;i++) {               \ +    GLdepth z = FixedToDepth(ffz);          \ +    if (z < zRow[i]) {              \ +    pRow[i] = p;                    \ +    zRow[i] = z;                    \ +    }                           \ +    ffz += fdzdx;                   \ +    }                           \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, flat, depth-buffered, PF_5R6G5B triangle. +*/ +static void flat_5R6G5B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_5R6G5B( VB->Color[pv][0],    \ +    VB->Color[pv][1], VB->Color[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint i, len = RIGHT-LEFT;              \ +    for (i=0;i<len;i++) {               \ +    GLdepth z = FixedToDepth(ffz);          \ +    if (z < zRow[i]) {              \ +    pRow[i] = p;                    \ +    zRow[i] = z;                    \ +    }                           \ +    ffz += fdzdx;                   \ +    }                           \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle. +*/ +static void smooth_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                     GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),     \ +                FixedToInt(ffb) );          \ +                ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle. +*/ +static void smooth_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),     \ +                FixedToInt(ffb) );          \ +                ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle. +*/ +static void smooth_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                   GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg),     \ +                FixedToInt(ffb) );          \ +                ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;         \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + + +/* +* XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle. +*/ +static void flat_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, +                                   GLuint v1, GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8B8G8R( VB->Color[pv][0],    \ +    VB->Color[pv][1], VB->Color[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint xx;                       \ +    PIXEL_TYPE *pixel = pRow;               \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \ +    *pixel = p;                 \ +    }                           \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, flat, NON-depth-buffered, PF_8R8G8B triangle. +*/ +static void flat_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                 GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y) +#define PIXEL_TYPE GLuint +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_8R8G8B( VB->Color[pv][0],    \ +    VB->Color[pv][1], VB->Color[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint xx;                       \ +    PIXEL_TYPE *pixel = pRow;               \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \ +    *pixel = p;                 \ +    }                           \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, flat, NON-depth-buffered, PF_5R6G5B triangle. +*/ +static void flat_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                 GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y) +#define PIXEL_TYPE GLushort +    //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line) +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                  \ +    unsigned long p = PACK_5R6G5B( VB->Color[pv][0],    \ +    VB->Color[pv][1], VB->Color[pv][2] ); +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint xx;                       \ +    PIXEL_TYPE *pixel = pRow;               \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \ +    *pixel = p;                 \ +    }                           \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle. +*/ + +static void smooth_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                 GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_INDEX 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                                \ +    {                                                                   \ +    GLint i, len = RIGHT-LEFT;                                      \ +    for (i=0;i<len;i++) {                                           \ +    GLdepth z = FixedToDepth(ffz);                              \ +    if (z < zRow[i]) {                                          \ +    pRow[i] = FixedToInt(ffi);                                  \ +    zRow[i] = z;                                                \ +    }                                                               \ +    ffi += fdidx;                                                   \ +    ffz += fdzdx;                                                   \ +    }                                                               \ +    } + +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle. +*/ + +static void flat_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                               GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                                                  \ +    GLuint index = VB->Index[pv];                                   \ +    if (!VB->MonoColor) {                                           \ +    /* set the color index */                                       \ +    (*ctx->Driver.Index)( ctx, index );                         \ +    } +#define INNER_LOOP( LEFT, RIGHT, Y )                                \ +    {                                                                   \ +    GLint i, len = RIGHT-LEFT;                                      \ +    for (i=0;i<len;i++) {                                           \ +    GLdepth z = FixedToDepth(ffz);                              \ +    if (z < zRow[i]) {                                          \ +    pRow[i] = index;                                            \ +    zRow[i] = z;                                                \ +    }                                                               \ +    ffz += fdzdx;                                                   \ +    }                                                               \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + + +/* +* XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle. +*/ + +static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                               GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define INTERP_INDEX 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                    \ +    {                                   \ +    GLint xx;                               \ +    PIXEL_TYPE *pixel = pRow;                       \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \ +    *pixel = FixedToInt(ffi);           \ +    ffi += fdidx;           \ +    }                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + +/* +* XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle. +*/ +static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                             GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define SETUP_CODE                                                  \ +    GLuint index = VB->Index[pv];                                   \ +    if (!VB->MonoColor) {                                           \ +    /* set the color index */                                       \ +    (*ctx->Driver.Index)( ctx, index );                         \ +    } +#define INNER_LOOP( LEFT, RIGHT, Y )            \ +    {                           \ +    GLint xx;                       \ +    PIXEL_TYPE *pixel = pRow;               \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \ +    *pixel = index;                 \ +    }                           \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + +/* +* XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle. +*/ +static void smooth_DITHER8_z_triangle( GLcontext *ctx, +                                      GLuint v0, GLuint v1, GLuint v2, +                                      GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define INTERP_Z 1 +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT;                 \ +    for (i=0;i<len;i++,xx++) {                                          \ +    GLdepth z = FixedToDepth(ffz);                                  \ +    if (z < zRow[i]) {                                              \ +    DITHER_RGB_TO_8BIT( FixedToInt(ffr), FixedToInt(ffg),           \ +    FixedToInt(ffb), xx, yy);               \ +    pRow[i] = pixelDithered;                                        \ +    zRow[i] = z;                                                    \ +    }                                                                   \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                     \ +    ffz += fdzdx;                                                       \ +    }                                                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + +/* +* XImage, flat, depth-buffered, 8-bit PF_DITHER triangle. +*/ +static void flat_DITHER8_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                    GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define INTERP_Z 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) + +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT;                 \ +    for (i=0;i<len;i++,xx++) {                                          \ +    GLdepth z = FixedToDepth(ffz);                                  \ +    if (z < zRow[i]) {                                              \ +    DITHER_RGB_TO_8BIT( VB->Color[pv][0],                           \ +             VB->Color[pv][1], VB->Color[pv][2], xx, yy);               \ +             pRow[i] = pixelDithered;                                       \ +             zRow[i] = z;                                                   \ +    }                                                                   \ +    ffz += fdzdx;                                                       \ +    }                                                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + +/* +* XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle. +*/ +static void smooth_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                    GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint xx, yy = FLIP(Y);                                             \ +    PIXEL_TYPE *pixel = pRow;                                           \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \ +    DITHER_RGB_TO_8BIT( VB->Color[pv][0],   VB->Color[pv][1], VB->Color[pv][2], xx, yy);\ +    *pixel = pixelDithered;                                         \ +    ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                     \ +    }                                                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + +/* +* XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle. +*/ + +static void flat_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1, +                                  GLuint v2, GLuint pv ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    DITHER_RGB_TO_8BIT_SETUP +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (wmesa->ScanWidth) + +#define INNER_LOOP( LEFT, RIGHT, Y )                                    \ +    {                                                                       \ +    GLint xx, yy = FLIP(Y);                                             \ +    PIXEL_TYPE *pixel = pRow;                                           \ +    for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \ +    DITHER_RGB_TO_8BIT( VB->Color[pv][0],                               \ +             VB->Color[pv][1], VB->Color[pv][2], xx, yy);               \ +             *pixel = pixelDithered;                                            \ +    }                                                                   \ +    } +#ifdef WIN32 +	#include "..\tritemp.h" +#else +	#include "tritemp.h" +#endif +} + + + + +static triangle_func choose_triangle_function( GLcontext *ctx ) +{ +    WMesaContext wmesa = (WMesaContext) ctx->DriverCtx; +    int depth = wmesa->cColorBits; + +    if (ctx->Polygon.SmoothFlag)     return NULL; +    if (ctx->Texture.Enabled)        return NULL; +    if (!wmesa->db_flag) return NULL; +    /*if (wmesa->xm_buffer->buffer==XIMAGE)*/ { +    if (   ctx->Light.ShadeModel==GL_SMOOTH +        && ctx->RasterMask==DEPTH_BIT +        && ctx->Depth.Func==GL_LESS +        && ctx->Depth.Mask==GL_TRUE +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return smooth_8A8B8G8R_z_triangle; +        case PF_8R8G8B: +            return smooth_8R8G8B_z_triangle; +        case PF_5R6G5B: +            return smooth_5R6G5B_z_triangle; +        case PF_DITHER8: +            return  smooth_DITHER8_z_triangle; +        case PF_INDEX8: +            return smooth_ci_z_triangle; +        default: +            return NULL; +        } +    } +    if (   ctx->Light.ShadeModel==GL_FLAT +        && ctx->RasterMask==DEPTH_BIT +        && ctx->Depth.Func==GL_LESS +        && ctx->Depth.Mask==GL_TRUE +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return flat_8A8B8G8R_z_triangle; +        case PF_8R8G8B: +            return flat_8R8G8B_z_triangle; +        case PF_5R6G5B: +            return flat_5R6G5B_z_triangle; +        case PF_DITHER8: +            return flat_DITHER8_z_triangle; +        case PF_INDEX8: +            return flat_ci_z_triangle; +        default: +            return NULL; +        } +    } +    if (   ctx->RasterMask==0   /* no depth test */ +        && ctx->Light.ShadeModel==GL_SMOOTH +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return smooth_8A8B8G8R_triangle; +        case PF_8R8G8B: +            return smooth_8R8G8B_triangle; +        case PF_5R6G5B: +            return smooth_5R6G5B_triangle; +        case PF_DITHER8: +            return smooth_DITHER8_triangle; +        case PF_INDEX8: +            return smooth_ci_triangle; +        default: +            return NULL; +        } +    } + +    if (   ctx->RasterMask==0   /* no depth test */ +        && ctx->Light.ShadeModel==GL_FLAT +        && ctx->Polygon.StippleFlag==GL_FALSE) { +        switch (wmesa->pixelformat) { +        case PF_8A8B8G8R: +            return flat_8A8B8G8R_triangle; +        case PF_8R8G8B: +            return flat_8R8G8B_triangle; +        case PF_5R6G5B: +            return flat_5R6G5B_triangle; +        case PF_DITHER8: +            return flat_DITHER8_triangle; +        case PF_INDEX8: +            return flat_ci_triangle; +        default: +            return NULL; +        } +    } + +    return NULL; +    } +} + +/* +* Define a new viewport and reallocate auxillary buffers if the size of +* the window (color buffer) has changed. +*/ +void WMesaViewport( GLcontext *ctx, +                   GLint x, GLint y, GLsizei width, GLsizei 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.Sx = (GLfloat) width / 2.0F; +    ctx->Viewport.Tx = ctx->Viewport.Sx + x; +    ctx->Viewport.Sy = (GLfloat) height / 2.0F; +    ctx->Viewport.Ty = ctx->Viewport.Sy + y; +} diff --git a/src/mesa/drivers/windows/wmesaOld.c b/src/mesa/drivers/windows/wmesaOld.c new file mode 100644 index 0000000000..afaeecebcf --- /dev/null +++ b/src/mesa/drivers/windows/wmesaOld.c @@ -0,0 +1,2737 @@ +/*
 + *	File name	:	wmesa.c
 + *  Version		:	2.3
 + *
 + *  Display driver for Mesa 2.3  under
 + *	Windows95 and WindowsNT
 + *
 + *	Copyright (C) 1996-  Li Wei
 + *  Address		:		Institute of Artificial Intelligence
 + *				:			& Robotics
 + *				:		Xi'an Jiaotong University
 + *  Email		:		liwei@aiar.xjtu.edu.cn
 + *  Web page	:		http://sun.aiar.xjtu.edu.cn
 + *
 + *  This file and its associations are partially borrowed from the
 + *  Windows NT driver for Mesa 1.8 , written by Mark Leaming
 + *  (mark@rsinc.com).
 + */
 +
 +
 +/*
 + * $Log: wmesaOld.c,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.2  1999/01/03 03:08:57  brianp + * Ted Jump's changes + *
 + * Revision 1.0  1997/06/14 17:51:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
 + * New display driver for Mesa 2.x using Microsoft Direct Draw
 + * Initial vision
 + */
 +
 +
 +#define WMESA_STEREO_C
 +
 +#include <windows.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <GL/wmesa.h>
 +#include "wmesadef.h"
 +#include "context.h"
 +#include "dd.h"
 +#include "xform.h"
 +#include "vb.h"
 +#include "matrix.h"
 +#include "depth.h"
 +
 +#ifdef PROFILE
 +//	#include "profile.h"
 +#endif
 +
 +#ifdef DITHER
 +	#include <wing.h>
 +#endif
 +
 +#ifdef __CYGWIN32__
 +#include "macros.h"
 +#include <string.h>
 +#define CopyMemory memcpy
 +#endif
 +#include "mesa_extend.h"
 +#include "colors.h"
 +
 +#if !defined(NO_STEREO)
 +
 +	#include "gl\glu.h"
 +	#include "stereo.h"
 +
 +#endif
 +#if !defined(NO_PARALLEL)
 +//	#include "parallel.h"
 +#endif
 +
 +struct DISPLAY_OPTIONS displayOptions;
 +
 +GLenum stereoCompile = GL_FALSE ;
 +GLenum stereoShowing  = GL_FALSE ;
 +GLenum stereoBuffer = GL_FALSE;
 +#if !defined(NO_STEREO)
 +GLint displayList = MAXIMUM_DISPLAY_LIST ;
 +#endif
 +GLint stereo_flag = 0 ;
 +
 +/* end of added code*/
 +
 +static PWMC Current = NULL;
 +WMesaContext WC = NULL;
 +
 +#ifdef NDEBUG
 +  #define assert(ignore)	((void) 0)
 +#else
 +  void Mesa_Assert(void *Cond,void *File,unsigned Line)
 +  {
 +    char Msg[512];
 +    sprintf(Msg,"%s %s %d",Cond,File,Line);
 +    MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
 +    exit(1);
 +  }
 +  #define assert(e)	if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
 +#endif
 +
 +//#define DD_GETDC (Current->hDC )
 +#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
 +//#define DD_GETDC ((Current->db_flag) ? Current->hDCPrimary : Current->hDCBack )
 +#define DD_RELEASEDC
 +
 +//#define BEGINGDICALL	if(Current->rgb_flag)wmFlushBits(Current);
 +#define BEGINGDICALL
 +//#define ENDGDICALL		if(Current->rgb_flag)wmGetBits(Current);
 +#define ENDGDICALL
 +
 +//#define FLIP(Y)  (Current->dither_flag? Y : Current->height-(Y)-1)
 +//#define FLIP(Y)  (Current->height-(Y)-1)
 +//#define FLIP(Y) Y
 +#define FLIP(Y)  (Current->db_flag? Y: Current->height-(Y)-1)
 +#define STARTPROFILE
 +#define ENDPROFILE(PARA)
 +
 +#define DITHER_RGB_TO_8BIT_SETUP			\
 +		GLubyte pixelDithered;
 +
 +#define DITHER_RGB_TO_8BIT(red, green, blue, pixel, scanline)				\
 +{																			\
 +	char unsigned redtemp, greentemp, bluetemp, paletteindex;				\
 +    redtemp = aDividedBy51[red]												\
 +          + (aModulo51[red] > aHalftone8x8[(pixel%8)*8						\
 +          + scanline%8]);													\
 +    greentemp = aDividedBy51[(char unsigned)green]							\
 +          + (aModulo51[green] > aHalftone8x8[								\
 +          (pixel%8)*8 + scanline%8]);										\
 +    bluetemp = aDividedBy51[(char unsigned)blue]							\
 +          + (aModulo51[blue] > aHalftone8x8[								\
 +          (pixel%8)*8 +scanline%8]);										\
 +    paletteindex = redtemp + aTimes6[greentemp] + aTimes36[bluetemp];		\
 +	pixelDithered = aWinGHalftoneTranslation[paletteindex];					\
 +}
 +
 +
 +#ifdef DDRAW
 +	static BOOL DDInit( WMesaContext wc, HWND hwnd);
 +	static void DDFree( WMesaContext wc);
 +	static HRESULT DDRestoreAll( WMesaContext wc );
 +	static void DDDeleteOffScreen(WMesaContext wc);
 +	static BOOL DDCreateOffScreen(WMesaContext wc);
 +#endif
 +
 +static void FlushToFile(PWMC pwc, PSTR	szFile);
 +
 +BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize);
 +BOOL wmDeleteBackingStore(PWMC pwc);
 +void wmCreatePalette( PWMC pwdc );
 +BOOL wmSetDibColors(PWMC pwc);
 +void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
 +
 +void wmCreateDIBSection(
 +	HDC	 hDC,
 +    PWMC pwc,	// handle of device context
 +    CONST BITMAPINFO *pbmi,	// address of structure containing bitmap size, format, and color data
 +    UINT iUsage	// color data type indicator: RGB values or palette indices
 +    );
 +
 +
 +void WMesaViewport( GLcontext *ctx,
 +                  GLint x, GLint y, GLsizei width, GLsizei height );
 +
 +static triangle_func choose_triangle_function( GLcontext *ctx );
 +
 +static void wmSetPixelFormat( PWMC wc, HDC hDC)
 +{
 +	if(wc->rgb_flag)
 +		wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
 +	else
 +	    wc->cColorBits = 8;
 +	switch(wc->cColorBits){
 +		case 8:
 +			if(wc->dither_flag != GL_TRUE)
 +				wc->pixelformat = PF_INDEX8;
 +			else
 +				wc->pixelformat = PF_DITHER8;
 +			break;
 +		case 16:
 +			wc->pixelformat = PF_5R6G5B;
 +			break;
 +		case 32:
 +			wc->pixelformat = PF_8R8G8B;
 +			break;
 +		default:
 +			wc->pixelformat = PF_BADFORMAT;
 +	}
 +}
 +
 +//
 +// This function sets the color table of a DIB section
 +// to match that of the destination DC
 +//
 +BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc)
 +{
 +    RGBQUAD			*pColTab, *pRGB;
 +    PALETTEENTRY	*pPal, *pPE;
 +    int				i, nColors;
 +	BOOL			bRet=TRUE;
 +	DWORD			dwErr=0;
 +
 +    /* Build a color table in the DIB that maps to the
 +       selected palette in the DC.
 +	*/
 +    nColors = 1 << pwc->cColorBits;
 +	pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
 +    memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
 +    GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
 +    pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
 +    for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
 +        pRGB->rgbRed = pPE->peRed;
 +        pRGB->rgbGreen = pPE->peGreen;
 +        pRGB->rgbBlue = pPE->peBlue;
 +    }
 +	if(pwc->db_flag)
 +	    bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab );
 +
 +	if(!bRet)
 +		dwErr = GetLastError();
 +
 +    free( pColTab );
 +    free( pPal );
 +
 +	return(bRet);
 +}
 +
 +
 +//
 +// Free up the dib section that was created
 +//
 +BOOL wmDeleteBackingStore(PWMC pwc)
 +{
 +	SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
 +	DeleteDC(pwc->dib.hDC);
 +	DeleteObject(pwc->hbmDIB);
 +	UnmapViewOfFile(pwc->dib.base);
 +	CloseHandle(pwc->dib.hFileMap);
 +	return TRUE;
 +}
 +
 +
 +//
 +// This function creates the DIB section that is used for combined
 +// GL and GDI calls
 +//
 +BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
 +{
 +    HDC hdc = pwc->hDC;
 +    LPBITMAPINFO pbmi = &(pwc->bmi);
 +	int		iUsage;
 +
 +    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 +    pbmi->bmiHeader.biWidth = lxSize;
 +    pbmi->bmiHeader.biHeight= -lySize;
 +    pbmi->bmiHeader.biPlanes = 1;
 +	if(pwc->rgb_flag)
 +		pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
 +	else
 +		pbmi->bmiHeader.biBitCount = 8;
 +    pbmi->bmiHeader.biCompression = BI_RGB;
 +    pbmi->bmiHeader.biSizeImage = 0;
 +    pbmi->bmiHeader.biXPelsPerMeter = 0;
 +    pbmi->bmiHeader.biYPelsPerMeter = 0;
 +    pbmi->bmiHeader.biClrUsed = 0;
 +    pbmi->bmiHeader.biClrImportant = 0;
 +
 +	iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
 +
 +	pwc->cColorBits = pbmi->bmiHeader.biBitCount;
 +	pwc->ScanWidth = pwc->pitch = lxSize;
 +
 +	wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
 +
 +	if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
 +		wmCreatePalette( pwc );
 +		wmSetDibColors( pwc );
 +	}
 +	wmSetPixelFormat(pwc, pwc->hDC);
 +	return(TRUE);
 +
 +}
 +
 +
 +//
 +// This function copies one scan line in a DIB section to another
 +//
 +BOOL GLWINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
 +{
 +	UINT uiScans = 0;
 +	LPBYTE	pDest = pwc->pbPixels;
 +	DWORD	dwNextScan = uiScanWidth;
 +	DWORD	dwNewScan = uiNewWidth;
 +	DWORD	dwScanWidth = (uiScanWidth * nBypp);
 +
 +	//
 +	// We need to round up to the nearest DWORD
 +	// and multiply by the number of bytes per
 +	// pixel
 +	//
 +	dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
 +	dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);
 +
 +	for(uiScans = 0; uiScans < uiNumScans; uiScans++){
 +		CopyMemory(pDest, pBits, dwScanWidth);
 +		pBits += dwNextScan;
 +		pDest += dwNewScan;
 +	}
 +
 +	return(TRUE);
 +
 +}
 +
 +
 +BOOL wmFlush(PWMC pwc);
 +
 +/*
 + * Useful macros:
 +   Modified from file osmesa.c
 + */
 +
 +
 +#define PIXELADDR(X,Y)  ((GLubyte *)Current->pbPixels + (Current->height-Y-1)* Current->ScanWidth + (X)*nBypp)
 +#define PIXELADDR1( X, Y )  \
 +	((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X))
 +#define PIXELADDR2( X, Y )  \
 +	((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*2)
 +#define PIXELADDR4( X, Y )  \
 +	((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*4)
 +
 +
 +BYTE DITHER_RGB_2_8BIT( int r, int g, int b, int x, int y);
 +
 +/* Finish all pending operations and synchronize. */
 +static void finish(GLcontext* ctx)
 +{
 + /* No op */
 +}
 +
 +
 +//
 +// We cache all gl draw routines until a flush is made
 +//
 +static void flush(GLcontext* ctx)
 +{
 +	STARTPROFILE
 +	if((Current->rgb_flag /*&& !(Current->dib.fFlushed)*/&&!(Current->db_flag))
 +		||(!Current->rgb_flag))
 +	{
 +		wmFlush(Current);
 +	}
 +	ENDPROFILE(flush)
 +
 +}
 +
 +
 +
 +/*
 + * Set the color index used to clear the color buffer.
 + */
 +static void clear_index(GLcontext* ctx, GLuint index)
 +{
 +  STARTPROFILE
 +  Current->clearpixel = index;
 +  ENDPROFILE(clear_index)
 +}
 +
 +
 +
 +/*
 + * Set the color used to clear the color buffer.
 + */
 +static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +  STARTPROFILE
 +  Current->clearpixel=RGB(r, g, b );
 +  ENDPROFILE(clear_color)
 +}
 +
 +
 +
 +/*
 + * Clear the specified region of the color buffer using the clear color
 + * or index as specified by one of the two functions above.
 + */
 +static void clear(GLcontext* ctx,
 +				  GLboolean all,GLint x, GLint y, GLint width, GLint height )
 +{
 +	DWORD	dwColor;
 +	WORD	wColor;
 +	BYTE	bColor;
 +	LPDWORD	lpdw = (LPDWORD)Current->pbPixels;
 +	LPWORD	lpw = (LPWORD)Current->pbPixels;
 +	LPBYTE	lpb = Current->pbPixels;
 +	int		lines;
 +
 +    STARTPROFILE
 +
 +	if (all){
 +		x=y=0;
 +		width=Current->width;
 +		height=Current->height;
 +	}
 +	if(Current->db_flag==GL_TRUE){
 +		UINT	nBypp = Current->cColorBits / 8;
 +		int		i = 0;
 +		int		iSize;
 +
 +		if(nBypp ==1 ){
 +			/* Need rectification */
 +			iSize = Current->width/4;
 +			bColor  = BGR8(GetRValue(Current->clearpixel),
 +						   GetGValue(Current->clearpixel),
 +						   GetBValue(Current->clearpixel));
 +			wColor  = MAKEWORD(bColor,bColor);
 +			dwColor = MAKELONG(wColor, wColor);
 +		}
 +		if(nBypp == 2){
 +			iSize = Current->width / 2;
 +			wColor = BGR16(GetRValue(Current->clearpixel),
 +						   GetGValue(Current->clearpixel),
 +						   GetBValue(Current->clearpixel));
 +			dwColor = MAKELONG(wColor, wColor);
 +		}
 +		else if(nBypp == 4){
 +			iSize = Current->width;
 +			dwColor = BGR32(GetRValue(Current->clearpixel),
 +						   GetGValue(Current->clearpixel),
 +						   GetBValue(Current->clearpixel));
 +		}
 +
 +		while(i < iSize){
 +			*lpdw = dwColor;
 +			lpdw++;
 +			i++;
 +		}
 +
 +		//
 +		// This is the 24bit case
 +		//
 +		if (nBypp == 3) {
 +			iSize = Current->width *3/4;
 +			dwColor = BGR24(GetRValue(Current->clearpixel),
 +						   GetGValue(Current->clearpixel),
 +						   GetBValue(Current->clearpixel));
 +			while(i < iSize){
 +				*lpdw = dwColor;
 +				lpb += nBypp;
 +				lpdw = (LPDWORD)lpb;
 +				i++;
 +			}
 +		}
 +
 +		i = 0;
 +		if(stereo_flag) lines = height /2;
 +		else lines = height;
 +		do{
 +			lpb += Current->ScanWidth;
 +			memcpy(lpb, Current->pbPixels, iSize*4);
 +			i++;
 +		}
 +		while(i<lines-1);
 +	}
 +	else{ // For single buffer
 +		 HDC DC=DD_GETDC;
 +		 HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
 +		 HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
 +		 HPEN Old_Pen=SelectObject(DC,Pen);
 +		 HBRUSH Old_Brush=SelectObject(DC,Brush);
 +		 Rectangle(DC,x,y,x+width,y+height);
 +		 SelectObject(DC,Old_Pen);
 +		 SelectObject(DC,Old_Brush);
 +		 DeleteObject(Pen);
 +		 DeleteObject(Brush);
 +		 DD_RELEASEDC;
 +  	}
 +
 +
 +
 +	ENDPROFILE(clear)
 +}
 +
 +
 +
 +/* Set the current color index. */
 +static void set_index(GLcontext* ctx, GLuint index)
 +{
 +  STARTPROFILE
 +  Current->pixel=index;
 +  ENDPROFILE(set_index)
 +}
 +
 +
 +
 +/* Set the current RGBA color. */
 +static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +  STARTPROFILE
 +  Current->pixel = RGB( r, g, b );
 +  ENDPROFILE(set_color)
 +}
 +
 +
 +
 +/* Set the index mode bitplane mask. */
 +static GLboolean index_mask(GLcontext* ctx, GLuint mask)
 +{
 +   /* can't implement */
 +   return GL_FALSE;
 +}
 +
 +
 +
 +/* Set the RGBA drawing mask. */
 +static GLboolean color_mask( GLcontext* ctx,
 +							 GLboolean rmask, GLboolean gmask,
 +							 GLboolean bmask, GLboolean amask)
 +{
 +   /* can't implement */
 +   return GL_FALSE;
 +}
 +
 +
 +
 +/*
 + * Set the pixel logic operation.  Return GL_TRUE if the device driver
 + * can perform the operation, otherwise return GL_FALSE.  If GL_FALSE
 + * is returned, the logic op will be done in software by Mesa.
 + */
 +GLboolean logicop( GLcontext* ctx, GLenum op )
 +{
 +   /* can't implement */
 +   return GL_FALSE;
 +}
 +
 +
 +static void dither( GLcontext* ctx, GLboolean enable )
 +{
 +	if(enable == GL_FALSE){
 +	   Current->dither_flag = GL_FALSE;
 +	   if(Current->cColorBits == 8)
 +		   Current->pixelformat = PF_INDEX8;
 +   }
 +   else{
 +	   if (Current->rgb_flag && Current->cColorBits == 8){
 +		   Current->pixelformat = PF_DITHER8;
 +		   Current->dither_flag = GL_TRUE;
 +	   }
 +	   else
 +		   Current->dither_flag = GL_FALSE;
 +   }
 +}
 +
 +
 +
 +static GLboolean set_buffer( GLcontext* ctx, GLenum mode )
 +{
 +   STARTPROFILE
 +   /* TODO: this could be better */
 +   if (mode==GL_FRONT || mode==GL_BACK) {
 +      return GL_TRUE;
 +   }
 +   else {
 +      return GL_FALSE;
 +   }
 +   ENDPROFILE(set_buffer)
 +}
 +
 +
 +
 +/* Return characteristics of the output buffer. */
 +static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height /*, GLuint *depth */)
 +{
 +
 +	int New_Size;
 +	RECT CR;
 +
 +	STARTPROFILE
 +	GetClientRect(Current->Window,&CR);
 +
 +	*width=CR.right;
 +	*height=CR.bottom;
 +//	*depth = Current->depth;
 +
 +	New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
 +
 +	if (New_Size){
 +		Current->width=*width;
 +		Current->height=*height;
 +		Current->ScanWidth=Current->width;
 +	    if ((Current->ScanWidth%sizeof(long))!=0)
 +			Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
 +
 +		if (Current->db_flag){
 +#ifdef DDRAW
 +			DDDeleteOffScreen(Current);
 +			DDCreateOffScreen(Current);
 +#else
 +		if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
 +				wmDeleteBackingStore(Current);
 +				wmCreateBackingStore(Current, Current->width, Current->height);
 +			}
 +#endif
 +			}
 +
 +//	Resize OsmesaBuffer if in Parallel mode
 +#if !defined(NO_PARALLEL)
 +			if(parallelFlag)
 +			PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth,
 +			Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem);
 +#endif
 +		}
 +   ENDPROFILE(buffer_size)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****           Accelerated point, line, polygon rendering       *****/
 +/**********************************************************************/
 +
 +
 +static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
 +{
 +   GLuint i;
 + //  HDC DC=DD_GETDC;
 +	PWMC	pwc = Current;
 +
 +	STARTPROFILE
 +
 +	if (Current->gl_ctx->VB->MonoColor) {
 +      /* all drawn with current color */
 +      for (i=first;i<=last;i++) {
 +         if (!Current->gl_ctx->VB->ClipMask[i]) {
 +            int x, y;
 +            x =       (GLint) Current->gl_ctx->VB->Win[i][0];
 +            y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
 +			wmSetPixel(pwc, y,x,GetRValue(Current->pixel),
 +					    GetGValue(Current->pixel), GetBValue(Current->pixel));
 +         }
 +      }
 +   }
 +   else {
 +      /* draw points of different colors */
 +      for (i=first;i<=last;i++) {
 +         if (!Current->gl_ctx->VB->ClipMask[i]) {
 +            int x, y;
 +            unsigned long pixel=RGB(Current->gl_ctx->VB->Color[i][0]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][1]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][2]*255.0);
 +            x =       (GLint) Current->gl_ctx->VB->Win[i][0];
 +            y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
 +			wmSetPixel(pwc, y,x,Current->gl_ctx->VB->Color[i][0]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][1]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][2]*255.0);
 +         }
 +      }
 +   }
 +//   DD_RELEASEDC;
 +   ENDPROFILE(fast_rgb_points)
 +}
 +
 +
 +
 +/* Return pointer to accerated points function */
 +extern points_func choose_points_function( GLcontext* ctx )
 +{
 +   STARTPROFILE
 +   if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0
 +       && !ctx->Texture.Enabled  && ctx->Visual->RGBAflag) {
 +   ENDPROFILE(choose_points_function)
 +      return fast_rgb_points;
 +   }
 +   else {
 +   ENDPROFILE(choose_points_function)
 +      return NULL;
 +   }
 +}
 +
 +
 +
 +/* Draw a line using the color specified by Current->gl_ctx->VB->Color[pv] */
 +static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv )
 +{
 +	STARTPROFILE
 +	int x0, y0, x1, y1;
 +	unsigned long pixel;
 +	HDC DC=DD_GETDC;
 +	HPEN Pen;
 +	HPEN Old_Pen;
 +
 +	if (Current->gl_ctx->VB->MonoColor) {
 +	  pixel = Current->pixel;  /* use current color */
 +	}
 +	else {
 +	  pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0);
 +	}
 +
 +	x0 =       (int) Current->gl_ctx->VB->Win[v0][0];
 +	y0 = FLIP( (int) Current->gl_ctx->VB->Win[v0][1] );
 +	x1 =       (int) Current->gl_ctx->VB->Win[v1][0];
 +	y1 = FLIP( (int) Current->gl_ctx->VB->Win[v1][1] );
 +
 +
 +	BEGINGDICALL
 +
 +	Pen=CreatePen(PS_SOLID,1,pixel);
 +	Old_Pen=SelectObject(DC,Pen);
 +	MoveToEx(DC,x0,y0,NULL);
 +	LineTo(DC,x1,y1);
 +	SelectObject(DC,Old_Pen);
 +	DeleteObject(Pen);
 +	DD_RELEASEDC;
 +
 +	ENDGDICALL
 +
 +	ENDPROFILE(fast_flat_rgb_line)
 +}
 +
 +
 +
 +/* Return pointer to accerated line function */
 +static line_func choose_line_function( GLcontext* ctx )
 +{
 +	STARTPROFILE
 +   if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag
 +       && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
 +       && !ctx->Texture.Enabled && Current->rgb_flag) {
 +   ENDPROFILE(choose_line_function)
 +      return fast_flat_rgb_line;
 +   }
 +   else {
 +   ENDPROFILE(choose_line_function)
 +      return NULL;
 +   }
 +}
 +
 +
 +/**********************************************************************/
 +/*****                 Span-based pixel drawing                   *****/
 +/**********************************************************************/
 +
 +
 +/* Write a horizontal span of color-index pixels with a boolean mask. */
 +static void write_index_span( GLcontext* ctx,
 +							  GLuint n, GLint x, GLint y,
 +							  const GLuint index[],
 +                              const GLubyte mask[] )
 +{
 +	  STARTPROFILE
 +	  GLuint i;
 +	  PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
 +	  assert(Current->rgb_flag==GL_FALSE);
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +		  Mem[i]=index[i];
 +	   ENDPROFILE(write_index_span)
 +}
 +
 +
 +
 +/*
 + * Write a horizontal span of pixels with a boolean mask.  The current
 + * color index is used for all pixels.
 + */
 +static void write_monoindex_span(GLcontext* ctx,
 +								 GLuint n,GLint x,GLint y,
 +								 const GLubyte mask[])
 +{
 +	  STARTPROFILE
 +	  GLuint i;
 +	  BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
 +	  assert(Current->rgb_flag==GL_FALSE);
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +		  Mem[i]=Current->pixel;
 +	  ENDPROFILE(write_monoindex_span)
 +}
 +
 +/*
 +	To improve the performance of this routine, frob the data into an actual scanline
 +	and call bitblt on the complete scan line instead of SetPixel.
 +*/
 +
 +/* Write a horizontal span of color pixels with a boolean mask. */
 +static void write_color_span( GLcontext* ctx,
 +			  GLuint n, GLint x, GLint y,
 +			  const GLubyte
 +			  red[], const GLubyte green[],
 +			  const GLubyte blue[], const GLubyte alpha[],
 +			  const GLubyte mask[] )
 +{
 +	STARTPROFILE
 +
 +	PWMC	pwc = Current;
 +
 +	if (pwc->rgb_flag==GL_TRUE)
 +	{
 +		GLuint i;
 +		HDC DC=DD_GETDC;
 +		y=FLIP(y);
 +
 +		if (mask) {
 +			for (i=0; i<n; i++)
 +				if (mask[i])
 +					wmSetPixel(pwc, y, x + i,red[i], green[i], blue[i]);
 +		}
 +
 +		else {
 +			for (i=0; i<n; i++)
 +				wmSetPixel(pwc, y, x + i, red[i], green[i], blue[i]);
 +		}
 +
 +		DD_RELEASEDC;
 +
 +	}
 +
 +  else
 +  {
 +		GLuint i;
 +		BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
 +		y=FLIP(y);
 +		if (mask) {
 +		   for (i=0; i<n; i++)
 +			 if (mask[i])
 +			   Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
 +		}
 +		else {
 +		   for (i=0; i<n; i++)
 +			 Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
 +			}
 +	}
 +   ENDPROFILE(write_color_span)
 +
 +}
 +
 +/*
 + * Write a horizontal span of pixels with a boolean mask.  The current color
 + * is used for all pixels.
 + */
 +static void write_monocolor_span( GLcontext* ctx,
 +								  GLuint n, GLint x, GLint y,
 +								  const GLubyte mask[])
 +{
 +  STARTPROFILE
 +  GLuint i;
 +  HDC DC=DD_GETDC;
 +  PWMC	pwc = Current;
 +
 +  assert(Current->rgb_flag==GL_TRUE);
 +  y=FLIP(y);
 +
 +  if(Current->rgb_flag==GL_TRUE){
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +// Trying
 +		wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel));
 +  }
 +  else {
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +			SetPixel(DC, y, x+i, Current->pixel);
 +  }
 +
 +	DD_RELEASEDC;
 +
 +	ENDPROFILE(write_monocolor_span)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****                   Array-based pixel drawing                *****/
 +/**********************************************************************/
 +
 +
 +/* Write an array of pixels with a boolean mask. */
 +static void write_index_pixels( GLcontext* ctx,
 +							    GLuint n, const GLint x[], const GLint y[],
 +								const GLuint index[], const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +   GLuint i;
 +   assert(Current->rgb_flag==GL_FALSE);
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +         BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
 +		   *Mem = index[i];
 +      }
 +   }
 +   ENDPROFILE(write_index_pixels)
 +}
 +
 +
 +
 +/*
 + * Write an array of pixels with a boolean mask.  The current color
 + * index is used for all pixels.
 + */
 +static void write_monoindex_pixels( GLcontext* ctx,
 +								    GLuint n,
 +									const GLint x[], const GLint y[],
 +                                    const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +   GLuint i;
 +   assert(Current->rgb_flag==GL_FALSE);
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +         BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
 +			*Mem = Current->pixel;
 +      }
 +   }
 +   ENDPROFILE(write_monoindex_pixels)
 +}
 +
 +
 +
 +/* Write an array of pixels with a boolean mask. */
 +static void write_color_pixels( GLcontext* ctx,
 +							    GLuint n, const GLint x[], const GLint y[],
 +								const GLubyte r[], const GLubyte g[],
 +                                const GLubyte b[], const GLubyte a[],
 +                                const GLubyte mask[] )
 +{
 +	STARTPROFILE
 +	GLuint i;
 +	PWMC	pwc = Current;
 +	HDC DC=DD_GETDC;
 +	assert(Current->rgb_flag==GL_TRUE);
 +	for (i=0; i<n; i++)
 +		if (mask[i])
 +			wmSetPixel(pwc, FLIP(y[i]),x[i],r[i],g[i],b[i]);
 +	DD_RELEASEDC;
 +	ENDPROFILE(write_color_pixels)
 +}
 +
 +
 +
 +/*
 + * Write an array of pixels with a boolean mask.  The current color
 + * is used for all pixels.
 + */
 +static void write_monocolor_pixels( GLcontext* ctx,
 +								    GLuint n,
 +									const GLint x[], const GLint y[],
 +                                    const GLubyte mask[] )
 +{
 +	STARTPROFILE
 +	GLuint i;
 +	PWMC	pwc = Current;
 +	HDC DC=DD_GETDC;
 +	assert(Current->rgb_flag==GL_TRUE);
 +	for (i=0; i<n; i++)
 +		if (mask[i])
 +			wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel),
 +					    GetGValue(Current->pixel), GetBValue(Current->pixel));
 +	DD_RELEASEDC;
 +	ENDPROFILE(write_monocolor_pixels)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****            Read spans/arrays of pixels                     *****/
 +/**********************************************************************/
 +
 +
 +/* Read a horizontal span of color-index pixels. */
 +static void read_index_span( GLcontext* ctx, GLuint n, GLint x, GLint y, GLuint index[])
 +{
 +  STARTPROFILE
 +  GLuint i;
 +  BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
 +  assert(Current->rgb_flag==GL_FALSE);
 +  for (i=0; i<n; i++)
 +    index[i]=Mem[i];
 +  ENDPROFILE(read_index_span)
 +
 +}
 +
 +
 +
 +
 +/* Read an array of color index pixels. */
 +static void read_index_pixels( GLcontext* ctx,
 +							   GLuint n, const GLint x[], const GLint y[],
 +							   GLuint indx[], const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +   GLuint i;
 +  assert(Current->rgb_flag==GL_FALSE);
 +  for (i=0; i<n; i++) {
 +     if (mask[i]) {
 +        indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]);
 +     }
 +  }
 +   ENDPROFILE(read_index_pixels)
 +}
 +
 +
 +
 +/* Read a horizontal span of color pixels. */
 +static void read_color_span( GLcontext* ctx,
 +							 GLuint n, GLint x, GLint y,
 +							 GLubyte red[], GLubyte green[],
 +                             GLubyte blue[], GLubyte alpha[] )
 +{
 +   STARTPROFILE
 +  UINT i;
 +  COLORREF Color;
 +  HDC DC=DD_GETDC;
 +  assert(Current->rgb_flag==GL_TRUE);
 +  y=FLIP(y);
 +  for (i=0; i<n; i++)
 +  {
 +    Color=GetPixel(DC,x+i,y);
 +    red[i]=GetRValue(Color);
 +    green[i]=GetGValue(Color);
 +    blue[i]=GetBValue(Color);
 +    alpha[i]=255;
 +  }
 +  DD_RELEASEDC;
 +  memset(alpha,0,n*sizeof(GLint));
 +   ENDPROFILE(read_color_span)
 +}
 +
 +
 +/* Read an array of color pixels. */
 +static void read_color_pixels( GLcontext* ctx,
 +							   GLuint n, const GLint x[], const GLint y[],
 +							   GLubyte red[], GLubyte green[],
 +                               GLubyte blue[], GLubyte alpha[],
 +                               const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +  GLuint i;
 +  COLORREF Color;
 +  HDC DC=DD_GETDC;
 +  assert(Current->rgb_flag==GL_TRUE);
 +  for (i=0; i<n; i++) {
 +     if (mask[i]) {
 +        Color=GetPixel(DC,x[i],FLIP(y[i]));
 +        red[i]=GetRValue(Color);
 +        green[i]=GetGValue(Color);
 +        blue[i]=GetBValue(Color);
 +        alpha[i]=255;
 +     }
 +  }
 +  DD_RELEASEDC;
 +  memset(alpha,0,n*sizeof(GLint));
 +   ENDPROFILE(read_color_pixels)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/**********************************************************************/
 +
 +
 +
 +void setup_DD_pointers( GLcontext* ctx )
 +{
 +   ctx->Driver.UpdateState = setup_DD_pointers;
 +   ctx->Driver.GetBufferSize = buffer_size;
 +   ctx->Driver.Finish = finish;
 +   ctx->Driver.Flush = flush;
 +
 +   ctx->Driver.ClearIndex = clear_index;
 +   ctx->Driver.ClearColor = clear_color;
 +   ctx->Driver.Clear = clear;
 +
 +   ctx->Driver.Index = set_index;
 +   ctx->Driver.Color = set_color;
 +   ctx->Driver.IndexMask = index_mask;
 +   ctx->Driver.ColorMask = color_mask;
 +
 +   ctx->Driver.LogicOp = logicop;
 +   ctx->Driver.Dither = dither;
 +
 +   ctx->Driver.SetBuffer = set_buffer;
 +   ctx->Driver.GetBufferSize = buffer_size;
 +
 +   ctx->Driver.PointsFunc = choose_points_function(ctx);
 +   ctx->Driver.LineFunc = choose_line_function(ctx);
 +   ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
 +
 +   /* Pixel/span writing functions: */
 +   ctx->Driver.WriteColorSpan       = write_color_span;
 +   ctx->Driver.WriteMonocolorSpan   = write_monocolor_span;
 +   ctx->Driver.WriteColorPixels     = write_color_pixels;
 +   ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
 +   ctx->Driver.WriteIndexSpan       = write_index_span;
 +   ctx->Driver.WriteMonoindexSpan   = write_monoindex_span;
 +   ctx->Driver.WriteIndexPixels     = write_index_pixels;
 +   ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
 +
 +   /* Pixel/span reading functions: */
 +   ctx->Driver.ReadIndexSpan = read_index_span;
 +   ctx->Driver.ReadColorSpan = read_color_span;
 +   ctx->Driver.ReadIndexPixels = read_index_pixels;
 +   ctx->Driver.ReadColorPixels = read_color_pixels;
 +}
 +
 +
 +/**********************************************************************/
 +/*****                  WMesa API Functions                       *****/
 +/**********************************************************************/
 +
 +
 +
 +#define PAL_SIZE 256
 +static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
 +{
 +   STARTPROFILE
 +	int i;
 +	HDC hdc;
 +	struct
 +	{
 +		WORD Version;
 +		WORD NumberOfEntries;
 +		PALETTEENTRY aEntries[PAL_SIZE];
 +	} Palette =
 +	{
 +		0x300,
 +		PAL_SIZE
 +	};
 +	hdc=GetDC(NULL);
 +	if (Pal!=NULL)
 +    GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
 +  else
 +    GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
 +	if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
 +	{
 +		for(i = 0; i <PAL_SIZE; i++)
 +			Palette.aEntries[i].peFlags = PC_RESERVED;
 +		Palette.aEntries[255].peRed = 255;
 +		Palette.aEntries[255].peGreen = 255;
 +		Palette.aEntries[255].peBlue = 255;
 +		Palette.aEntries[255].peFlags = 0;
 +		Palette.aEntries[0].peRed = 0;
 +		Palette.aEntries[0].peGreen = 0;
 +		Palette.aEntries[0].peBlue = 0;
 +		Palette.aEntries[0].peFlags = 0;
 +	}
 +	else
 +	{
 +		int nStaticColors;
 +		int nUsableColors;
 +		nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
 +		for (i=0; i<nStaticColors; i++)
 +			Palette.aEntries[i].peFlags = 0;
 +		nUsableColors = PAL_SIZE-nStaticColors;
 +		for (; i<nUsableColors; i++)
 +			Palette.aEntries[i].peFlags = PC_RESERVED;
 +		for (; i<PAL_SIZE-nStaticColors; i++)
 +			Palette.aEntries[i].peFlags = PC_RESERVED;
 +		for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
 +			Palette.aEntries[i].peFlags = 0;
 +	}
 +	ReleaseDC(NULL,hdc);
 +  for (i=0; i<PAL_SIZE; i++)
 +  {
 +    aRGB[i].rgbRed=Palette.aEntries[i].peRed;
 +    aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
 +    aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
 +    aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
 +  }
 +  	  ENDPROFILE(GetPalette)
 +}
 +
 +
 +WMesaContext WMesaCreateContext( HWND hWnd, HPALETTE* Pal,
 +											  GLboolean rgb_flag,
 +											  GLboolean db_flag )
 +{
 +  RECT CR;
 +  WMesaContext c;
 +  GLboolean true_color_flag;
 +  c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
 +  if (!c)
 +    return NULL;
 +
 +  c->Window=hWnd;
 +  c->hDC = GetDC(hWnd);
 +  true_color_flag = GetDeviceCaps(c->hDC, BITSPIXEL) > 8;
 +#ifdef DDRAW
 +  if(true_color_flag) c->rgb_flag = rgb_flag = GL_TRUE;
 +#endif
 +
 +
 +#ifdef DITHER
 +  if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){
 +	c->dither_flag = GL_TRUE;
 +	c->hPalHalfTone = WinGCreateHalftonePalette();
 +  }
 +  else
 +	c->dither_flag = GL_FALSE;
 +#else
 +	c->dither_flag = GL_FALSE;
 +#endif
 +
 +
 +  if (rgb_flag==GL_FALSE)
 +  {
 +    c->rgb_flag = GL_FALSE;
 +//    c->pixel = 1;
 +    c->db_flag = db_flag =GL_TRUE; // WinG requires double buffering
 +	printf("Single buffer is not supported in color index mode, setting to double buffer.\n");
 +  }
 +  else
 +  {
 +    c->rgb_flag = GL_TRUE;
 +//    c->pixel = 0;
 +  }
 +  GetClientRect(c->Window,&CR);
 +  c->width=CR.right;
 +  c->height=CR.bottom;
 +  if (db_flag)
 +  {
 +    c->db_flag = 1;
 +	/* Double buffered */
 +#ifndef DDRAW
 +//	if (c->rgb_flag==GL_TRUE && c->dither_flag != GL_TRUE )
 +    {
 +		wmCreateBackingStore(c, c->width, c->height);
 +
 +    }
 +#endif
 +  }
 +  else
 +  {
 +    /* Single Buffered */
 +	if (c->rgb_flag)
 +	  c->db_flag = 0;
 +  }
 +#ifdef DDRAW
 +  if (DDInit(c,hWnd) == GL_FALSE) {
 +		free( (void *) c );
 +		exit(1);
 +		}
 +#endif
 +
 +
 +  c->gl_visual = gl_create_visual(rgb_flag,
 +								  GL_FALSE,	/* software alpha */
 +                                  db_flag,	/* db_flag */
 +                                  16,		/* depth_bits */
 +                                  8,		/* stencil_bits */
 +                                  8,		/* accum_bits */
 +                                  8,
 +                                  255.0, 255.0, 255.0, 255.0,
 +								  8,8,8,8 );
 +
 +	if (!c->gl_visual) {
 +         return NULL;
 +      }
 +
 +  /* allocate a new Mesa context */
 +  c->gl_ctx = gl_create_context( c->gl_visual, NULL,c);
 +
 +  if (!c->gl_ctx) {
 +         gl_destroy_visual( c->gl_visual );
 +         free(c);
 +         return NULL;
 +      }
 +
 +      c->gl_buffer = gl_create_framebuffer( c->gl_visual );
 +      if (!c->gl_buffer) {
 +         gl_destroy_visual( c->gl_visual );
 +         gl_destroy_context( c->gl_ctx );
 +         free(c);
 +         return NULL;
 +      }
 +//  setup_DD_pointers(c->gl_ctx);
 +
 +  return c;
 +}
 +
 +void WMesaDestroyContext( void )
 +{
 +	WMesaContext c = Current;
 +	ReleaseDC(c->Window,c->hDC);
 +	WC = c;
 +	if(c->hPalHalfTone != NULL)
 +		DeleteObject(c->hPalHalfTone);
 +    gl_destroy_visual( c->gl_visual );
 +    gl_destroy_framebuffer( c->gl_buffer );
 +	gl_destroy_context( c->gl_ctx );
 +
 +	if (c->db_flag)
 +#ifdef DDRAW
 +		DDFree(c);
 +#else
 +		wmDeleteBackingStore(c);
 +#endif
 +	free( (void *) c );
 +//Following code is added to enable parallel render
 +// Parallel render only work in double buffer mode
 +#if !defined(NO_PARALLEL)
 +	if(parallelMachine)
 +		PRDestroyRenderBuffer();
 +#endif
 +// End modification
 +}
 +
 +
 +
 +void /*APIENTRY*/ WMesaMakeCurrent( WMesaContext c )
 +{
 +	if(!c){
 +		Current = c;
 +		return;
 +	}
 +
 +	//
 +	// A little optimization
 +	// If it already is current,
 +	// don't set it again
 +	//
 +	if(Current == c)
 +		return;
 +
 +	//gl_set_context( c->gl_ctx );
 +	gl_make_current(c->gl_ctx, c->gl_buffer);
 +	Current = c;
 +	setup_DD_pointers(c->gl_ctx);
 +	if (Current->gl_ctx->Viewport.Width==0) {
 +	  /* initialize viewport to window size */
 +	  gl_Viewport( Current->gl_ctx,
 +		           0, 0, Current->width, Current->height );
 +	}
 +	if ((c->cColorBits <= 8 ) && (c->rgb_flag == GL_TRUE)){
 +			WMesaPaletteChange(c->hPalHalfTone);
 +	}
 +}
 +
 +
 +
 +void /*APIENTRY*/ WMesaSwapBuffers( void )
 +{
 +  HDC DC = Current->hDC;
 +  if (Current->db_flag)
 +	wmFlush(Current);
 +}
 +
 +
 +
 +void /*APIENTRY*/ WMesaPaletteChange(HPALETTE Pal)
 +{
 +  int vRet;
 +  LPPALETTEENTRY pPal;
 +  if (Current && (Current->rgb_flag==GL_FALSE || Current->dither_flag == GL_TRUE))
 +  {
 +	pPal = (PALETTEENTRY *)malloc( 256 * sizeof(PALETTEENTRY));
 +	Current->hPal=Pal;
 +//	GetPaletteEntries( Pal, 0, 256, pPal );
 +	GetPalette( Pal, pPal );
 +#ifdef DDRAW
 +	Current->lpDD->lpVtbl->CreatePalette(Current->lpDD,DDPCAPS_8BIT,
 +		pPal, &(Current->lpDDPal), NULL);
 +	if (Current->lpDDPal)
 +        Current->lpDDSPrimary->lpVtbl->SetPalette(Current->lpDDSPrimary,Current->lpDDPal);
 +#else
 +    vRet = SetDIBColorTable(Current->dib.hDC,0,256,pPal);
 +#endif
 +	free( pPal );
 +  }
 +
 +}
 +
 +
 +
 +
 +static unsigned char threeto8[8] = {
 +	0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
 +};
 +
 +static unsigned char twoto8[4] = {
 +	0, 0x55, 0xaa, 0xff
 +};
 +
 +static unsigned char oneto8[2] = {
 +	0, 255
 +};
 +
 +static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
 +{
 +	unsigned char val;
 +
 +	val = i >> shift;
 +	switch (nbits) {
 +
 +		case 1:
 +			val &= 0x1;
 +			return oneto8[val];
 +
 +		case 2:
 +			val &= 0x3;
 +			return twoto8[val];
 +
 +		case 3:
 +			val &= 0x7;
 +			return threeto8[val];
 +
 +		default:
 +			return 0;
 +	}
 +}
 +
 +void /*WINAPI*/ wmCreatePalette( PWMC pwdc )
 +{
 +    /* Create a compressed and re-expanded 3:3:2 palette */
 +  	int            i;
 +	LOGPALETTE     *pPal;
 +    BYTE           rb, rs, gb, gs, bb, bs;
 +
 +    pwdc->nColors = 0x100;
 +
 +	pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY));
 +    memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
 +
 +	pPal->palVersion = 0x300;
 +
 +    rb = REDBITS;
 +    rs = REDSHIFT;
 +    gb = GREENBITS;
 +    gs = GREENSHIFT;
 +    bb = BLUEBITS;
 +    bs = BLUESHIFT;
 +
 +    if (pwdc->db_flag) {
 +
 +        /* Need to make two palettes: one for the screen DC and one for the DIB. */
 +	    pPal->palNumEntries = pwdc->nColors;
 +	    for (i = 0; i < pwdc->nColors; i++) {
 +		    pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
 +		    pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
 +		    pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
 +		    pPal->palPalEntry[i].peFlags = 0;
 +	    }
 +    	pwdc->hGLPalette = CreatePalette( pPal );
 +    	pwdc->hPalette = CreatePalette( pPal );
 +    }
 +
 +	else {
 +	    pPal->palNumEntries = pwdc->nColors;
 +	    for (i = 0; i < pwdc->nColors; i++) {
 +		    pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
 +		    pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
 +		    pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
 +		    pPal->palPalEntry[i].peFlags = 0;
 +	    }
 +    	pwdc->hGLPalette = CreatePalette( pPal );
 +    }
 +
 +	free(pPal);
 +
 +}
 +
 +void /*WINAPI*/ wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
 +{
 +	if(Current->db_flag){
 +		LPBYTE	lpb = pwc->pbPixels;
 +		LPDWORD	lpdw;
 +		LPWORD	lpw;
 +		UINT	nBypp = pwc->cColorBits / 8;
 +		UINT	nOffset = iPixel % nBypp;
 +
 +		// Move the pixel buffer pointer to the scanline that we
 +		// want to access
 +
 +//		pwc->dib.fFlushed = FALSE;
 +
 +		lpb += pwc->ScanWidth * iScanLine;
 +		// Now move to the desired pixel
 +		lpb += iPixel * nBypp;
 +		lpb = PIXELADDR(iPixel, iScanLine);
 +		lpdw = (LPDWORD)lpb;
 +		lpw = (LPWORD)lpb;
 +
 +		if(nBypp == 1){
 +			if(pwc->dither_flag)
 +				*lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
 +			else
 +				*lpb = BGR8(r,g,b);
 +		}
 +		else if(nBypp == 2)
 +			*lpw = BGR16(r,g,b);
 +		else if (nBypp == 3){
 +			*lpdw = BGR24(r,g,b);
 +		}
 +		else if (nBypp == 4)
 +			*lpdw = BGR32(r,g,b);
 +	}
 +	else{
 +		HDC DC = DD_GETDC;
 +		SetPixel(DC, iPixel, iScanLine, RGB(r,g,b));
 +		DD_RELEASEDC;
 +	}
 +}
 +
 +void /*WINAPI*/ wmCreateDIBSection(
 +	HDC	 hDC,
 +    PWMC pwc,	// handle of device context
 +    CONST BITMAPINFO *pbmi,	// address of structure containing bitmap size, format, and color data
 +    UINT iUsage	// color data type indicator: RGB values or palette indices
 +)
 +{
 +	DWORD	dwSize = 0;
 +	DWORD	dwScanWidth;
 +	UINT	nBypp = pwc->cColorBits / 8;
 +	HDC		hic;
 +
 +	dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
 +
 +	pwc->ScanWidth =pwc->pitch = dwScanWidth;
 +
 +	if (stereo_flag)
 +		pwc->ScanWidth = 2* pwc->pitch;
 +
 +	dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
 +
 +	pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
 +										  NULL,
 +										  PAGE_READWRITE | SEC_COMMIT,
 +										  0,
 +										  dwSize,
 +										  NULL);
 +
 +	if (!pwc->dib.hFileMap)
 +		return;
 +
 +	pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
 +								  FILE_MAP_ALL_ACCESS,
 +								  0,
 +								  0,
 +								  0);
 +
 +	if(!pwc->dib.base){
 +		CloseHandle(pwc->dib.hFileMap);
 +		return;
 +	}
 +
 +//	pwc->pbPixels = pwc->addrOffScreen = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO);
 +
 +//	pwc->dib.hDC = CreateCompatibleDC(hDC);
 +
 +	CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
 +
 +	hic = CreateIC("display", NULL, NULL, NULL);
 +	pwc->dib.hDC = CreateCompatibleDC(hic);
 +
 +
 +/*	pwc->hbmDIB = CreateDIBitmap(hic,
 +						 &(pwc->bmi.bmiHeader),
 +						 CBM_INIT,
 +						 pwc->pbPixels,
 +						 &(pwc->bmi),
 +						 DIB_RGB_COLORS);
 +*/
 +  pwc->hbmDIB = CreateDIBSection(hic,
 +						&(pwc->bmi),
 +						(iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
 +						&(pwc->pbPixels),
 +						pwc->dib.hFileMap,
 +						0);
 +  /*
 +	pwc->hbmDIB = CreateDIBSection(hic,
 +						&(pwc->bmi),
 +						DIB_RGB_COLORS,
 +						&(pwc->pbPixels),
 +						pwc->dib.hFileMap,
 +						0);
 +	*/
 +	pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels;
 +	pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
 +
 +	DeleteDC(hic);
 +
 +	return;
 +
 +}
 +
 +//
 +// Blit memory DC to screen DC
 +//
 +BOOL /*WINAPI*/ wmFlush(PWMC pwc)
 +{
 +	BOOL	bRet = 0;
 +	DWORD	dwErr = 0;
 +	HRESULT             ddrval;
 +
 +    // Now search through the torus frames and mark used colors
 +	if(pwc->db_flag){
 +#ifdef DDRAW
 +		if (pwc->lpDDSOffScreen == NULL)
 +		if(DDCreateOffScreen(pwc) == GL_FALSE)
 +			return;
 +
 +		pwc->lpDDSOffScreen->lpVtbl->Unlock(pwc->lpDDSOffScreen, NULL);
 +
 +		while( 1 )
 +		{
 +			ddrval = pwc->lpDDSPrimary->lpVtbl->Blt( pwc->lpDDSPrimary,
 +					&(pwc->rectSurface), pwc->lpDDSOffScreen, &(pwc->rectOffScreen), 0, NULL );
 +
 +			if( ddrval == DD_OK )
 +			{
 +				break;
 +			}
 +			if( ddrval == DDERR_SURFACELOST )
 +			{
 +				if(!DDRestoreAll(pwc))
 +				{
 +					break;
 +				}
 +			}
 +			if( ddrval != DDERR_WASSTILLDRAWING )
 +			{
 +				break;
 +			}
 +		}
 +
 +		while (pwc->lpDDSOffScreen->lpVtbl->Lock(pwc->lpDDSOffScreen,
 +						NULL, &(pwc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
 +			;
 +
 +		if(ddrval != DD_OK)
 +    		dwErr = GetLastError();
 +#else
 +	bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height,
 +		   pwc->dib.hDC, 0, 0, SRCCOPY);
 +#endif
 +	}
 +
 +	return(TRUE);
 +
 +}
 +
 +
 +// The following code is added by Li Wei to enable stereo display
 +
 +#if !defined(NO_STEREO)
 +
 +void WMesaShowStereo(GLuint list)
 +{
 +
 +	GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
 +	GLfloat cm[16];
 +	GLint matrix_mode;
 +	// Must use double Buffer
 +	if( ! Current-> db_flag )
 +		return;
 +
 +
 +    glGetIntegerv(GL_MATRIX_MODE,&matrix_mode);
 +
 +//	glPushMatrix();  //****
 +	WMesaViewport(Current->gl_ctx,0,Current->height/2,Current->width,Current->height/2);
 +//	Current->gl_ctx->NewState = 0;
 +
 +	//	glViewport(0,0,Current->width,Current->height/2);
 +	if(matrix_mode!=GL_MODELVIEW)
 +        glMatrixMode(GL_MODELVIEW);
 +
 +	glGetFloatv(GL_MODELVIEW_MATRIX,cm);
 +	glLoadIdentity();
 +	gluLookAt(viewDistance/2,0.0,0.0 ,
 +			 viewDistance/2,0.0,-1.0,
 +			 0.0,1.0,0.0 );
 +//	glTranslatef(viewDistance/2.0,0.,0.);
 +	glMultMatrixf( cm );
 +
 +	Current->ScreenMem = Current->pbPixels = Current->addrOffScreen;
 +	//glPushMatrix();
 +	glCallList( list );
 +	//glPopMatrix();
 +
 +    glGetFloatv(GL_MODELVIEW_MATRIX,cm);
 +	glLoadIdentity();
 +	gluLookAt(-viewDistance/2,0.0,0.0 ,
 +			 -viewDistance/2,0.0,-1.0,
 +			 0.0,1.0,0.0 );
 +//	glTranslatef(-viewDistance/2.0,0.,0.);
 +	glMultMatrixf(cm);
 +
 +	Current->ScreenMem = Current->pbPixels = Current->addrOffScreen + Current->pitch;
 +	glCallList(list);
 +	if(matrix_mode!=GL_MODELVIEW)
 +		glMatrixMode(matrix_mode);
 +
 +//	glPopMatrix();
 +	glFlush();
 +
 +	WMesaViewport(Current->gl_ctx,0,0,Current->width,Current->height);
 +//	Current->gl_ctx->NewState = 0;
 +	WMesaSwapBuffers();
 +
 +}
 +
 +void toggleStereoMode()
 +{
 +	if(!Current->db_flag)
 +		return;
 +	if(!stereo_flag){
 +		stereo_flag = 1;
 +		if(stereoBuffer==GL_FALSE)
 +#if !defined(NO_PARALLEL)
 +			if(!parallelFlag)
 +#endif
 +		{
 +			Current->ScanWidth = Current->pitch*2;
 +			}
 +	}
 +	else {
 +		stereo_flag = 0;
 +#if !defined(NO_PARALLEL)
 +		if(!parallelFlag)
 +#endif
 +		Current->ScanWidth = Current->pitch;
 +		Current->pbPixels = Current->addrOffScreen;
 +	}
 +}
 +
 +/* if in stereo mode, the following function is called */
 +void glShowStereo(GLuint list)
 +{
 +	WMesaShowStereo(list);
 +}
 +
 +#endif // End if NO_STEREO not defined
 +
 +#if !defined(NO_PARALLEL)
 +
 +void toggleParallelMode(void)
 +{
 +	if(!parallelFlag){
 +		parallelFlag = GL_TRUE;
 +		if(parallelMachine==GL_FALSE){
 +				PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX,
 +									  Current->cColorBits/8,
 +									  Current->width ,Current->height,
 +									  Current->ScanWidth,
 +									  Current->rgb_flag? Current->pbPixels: Current->ScreenMem);
 +				parallelMachine = GL_TRUE;
 +				}
 +		}
 +	else {
 +		parallelFlag = GL_FALSE;
 +		if(parallelMachine==GL_TRUE){
 +				PRDestroyRenderBuffer();
 +				parallelMachine=GL_FALSE;
 +				ReadyForNextFrame = GL_TRUE;
 +				}
 +
 +/***********************************************
 +// Seems something wrong!!!!
 +************************************************/
 +
 +		WMesaMakeCurrent(Current);
 +#if !defined(NO_STEREO)
 +		stereo_flag = GL_FALSE ;
 +#endif
 +	}
 +}
 +
 +void PRShowRenderResult(void)
 +{
 +	int flag = 0;
 +if(!glImageRendered())
 +		return;
 +
 +  if (parallelFlag)
 +	{
 +	  WMesaSwapBuffers();
 +	 }
 +
 +}
 +#endif //End if NO_PARALLEL not defined
 +
 +//end modification
 +
 +BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline)
 +{
 +    char unsigned redtemp, greentemp, bluetemp, paletteindex;
 +
 +	//*** now, look up each value in the halftone matrix
 +    //*** using an 8x8 ordered dither.
 +    redtemp = aDividedBy51[red]
 +          + (aModulo51[red] > aHalftone8x8[(pixel%8)*8
 +          + scanline%8]);
 +    greentemp = aDividedBy51[(char unsigned)green]
 +          + (aModulo51[green] > aHalftone8x8[
 +          (pixel%8)*8 + scanline%8]);
 +    bluetemp = aDividedBy51[(char unsigned)blue]
 +          + (aModulo51[blue] > aHalftone8x8[
 +          (pixel%8)*8 +scanline%8]);
 +
 +    //*** recombine the halftoned rgb values into a palette index
 +    paletteindex =
 +    redtemp + aTimes6[greentemp] + aTimes36[bluetemp];
 +
 +    //*** and translate through the wing halftone palette
 +    //*** translation vector to give the correct value.
 +    return aWinGHalftoneTranslation[paletteindex];
 +}
 +
 +#ifdef DDRAW
 +/*
 + * restoreAll
 + *
 + * restore all lost objects
 + */
 +HRESULT DDRestoreAll( WMesaContext wc )
 +{
 +    HRESULT     ddrval;
 +
 +    ddrval = wc->lpDDSPrimary->lpVtbl->Restore(wc->lpDDSPrimary);
 +    if( ddrval == DD_OK )
 +    {
 +        ddrval = wc->lpDDSOffScreen->lpVtbl->Restore(wc->lpDDSOffScreen);
 +    }
 +    return ddrval;
 +
 +} /* restoreAll */
 +
 +
 +/*
 + * This function is called if the initialization function fails
 + */
 +BOOL initFail( HWND hwnd, WMesaContext wc )
 +{
 +    DDFree(wc);
 +    MessageBox( hwnd, "DirectDraw Init FAILED", "", MB_OK );
 +    return FALSE;
 +
 +} /* initFail */
 +
 +
 +static void DDDeleteOffScreen(WMesaContext wc)
 +{
 +		if( wc->lpDDSOffScreen != NULL )
 +		{
 +			wc->lpDDSOffScreen->lpVtbl->Unlock(wc->lpDDSOffScreen,NULL);
 +            wc->lpDDSOffScreen->lpVtbl->Release(wc->lpDDSOffScreen);
 +            wc->lpDDSOffScreen = NULL;
 +		}
 +
 +}
 +
 +static void DDFreePrimarySurface(WMesaContext wc)
 +{
 +		if( wc->lpDDSPrimary != NULL )
 +		{
 +			if(wc->db_flag == GL_FALSE)
 +				wc->lpDDSPrimary->lpVtbl->ReleaseDC(wc->lpDDSPrimary, wc->hDC);
 +			wc->lpDDSPrimary->lpVtbl->Release(wc->lpDDSPrimary);
 +            wc->lpDDSPrimary = NULL;
 +		}
 +}
 +
 +static BOOL DDCreatePrimarySurface(WMesaContext wc)
 +{
 +	HRESULT ddrval;
 +	DDSCAPS             ddscaps;
 +	wc->ddsd.dwSize = sizeof( wc->ddsd );
 +    wc->ddsd.dwFlags = DDSD_CAPS;
 +    wc->ddsd.ddsCaps.dwCaps =	DDSCAPS_PRIMARYSURFACE;
 +
 +    ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD,&(wc->ddsd), &(wc->lpDDSPrimary), NULL );
 +    if( ddrval != DD_OK )
 +    {
 +        return initFail(wc->hwnd , wc);
 +    }
 +	if(wc->db_flag == GL_FALSE)
 +		 wc->lpDDSPrimary->lpVtbl->GetDC(wc->lpDDSPrimary, wc->hDC);
 +	return TRUE;
 +}
 +
 +static BOOL DDCreateOffScreen(WMesaContext wc)
 +{
 +	POINT	pt;
 +	HRESULT		ddrval;
 +	if(wc->lpDD == NULL)
 +		return FALSE;
 +	GetClientRect( wc->hwnd, &(wc->rectOffScreen) );
 +	wc->ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
 +    wc->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
 +    wc->ddsd.dwHeight = wc->rectOffScreen.bottom - wc->rectOffScreen.top;
 +    wc->ddsd.dwWidth = wc->rectOffScreen.right - wc->rectOffScreen.left;
 +
 +    ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD, &(wc->ddsd), &(wc->lpDDSOffScreen), NULL );
 +    if( ddrval != DD_OK )
 +    {
 +		return FALSE;
 +    }
 +
 +	while (wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
 +        ;
 +//	while ((ddrval = wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), DDLOCK_SURFACEMEMORYPTR , NULL)) != DD_OK)
 +		;
 +	if(wc->ddsd.lpSurface==NULL)
 +		return initFail(wc->hwnd, wc);
 +
 +	wc->ScreenMem = wc->pbPixels = wc->addrOffScreen = (PBYTE)(wc->ddsd.lpSurface);
 +	wc->ScanWidth = wc->pitch = wc->ddsd.lPitch;
 +	if (stereo_flag)
 +		wc->ScanWidth = wc->ddsd.lPitch*2;
 +
 +	GetClientRect( wc->hwnd, &(wc->rectSurface) );
 +	pt.x = pt.y = 0;
 +    ClientToScreen( wc->hwnd, &pt );
 +    OffsetRect(&(wc->rectSurface), pt.x, pt.y);
 +	wmSetPixelFormat(wc, wc->hDC);
 +	return TRUE;
 +}
 +
 +/*
 + * doInit - do work required for every instance of the application:
 + *                create the window, initialize data
 + */
 +static BOOL DDInit( WMesaContext wc, HWND hwnd)
 +{
 +    HRESULT             ddrval;
 +	DWORD dwFrequency;
 +
 +	LPDIRECTDRAW            lpDD;           // DirectDraw object
 +	LPDIRECTDRAW2            lpDD2;
 +
 +
 +	wc->fullScreen = displayOptions.fullScreen;
 +	wc->gMode = displayOptions.mode;
 +	wc->hwnd = hwnd;
 +	stereo_flag = displayOptions.stereo;
 +	if(wc->db_flag!= GL_TRUE)
 +		stereo_flag = GL_FALSE;
 +    /*
 +     * create the main DirectDraw object
 +     */
 +    ddrval = DirectDrawCreate( NULL, &(wc->lpDD), NULL );
 +    if( ddrval != DD_OK )
 +    {
 +        return initFail(hwnd,wc);
 +    }
 +
 +    // Get exclusive mode if requested
 +    if(wc->fullScreen)
 +    {
 +        ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
 +    }
 +    else
 +    {
 +        ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_NORMAL );
 +    }
 +    if( ddrval != DD_OK )
 +    {
 +        return initFail(hwnd , wc);
 +    }
 +
 +
 +/*	ddrval = wc->lpDD->lpVtbl->QueryInterface(wc->lpDD, IID_IDirectDraw2,
 +			(LPVOID *)((wc->lpDD2)));
 +
 +*/
 +	if(ddrval != DD_OK)
 +        return initFail(hwnd , wc);
 +
 +
 +   //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
 + //  wc->lpDD2->lpVtbl->GetMonitorFrequency(wc->lpDD, &dwFrequency);
 +    switch( wc->gMode )
 +    {
 +        case 1:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 640, 480, displayOptions.bpp); break;
 +        case 2:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 800, 600, displayOptions.bpp); break;
 +        case 3:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1024, 768, displayOptions.bpp); break;
 +		case 4:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1152, 864, displayOptions.bpp); break;
 +        case 5:  ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1280, 1024, displayOptions.bpp); break;
 +    }
 +
 +    if( ddrval != DD_OK )
 +    {
 +		printf("Can't modify display mode, current mode used\n");
 +//        return initFail(hwnd , wc);
 +    }
 +//ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
 +switch(ddrval){
 +case DDERR_INVALIDOBJECT:
 +	break;
 +case DDERR_INVALIDPARAMS:
 +	break;
 +case DDERR_UNSUPPORTEDMODE:
 +	;
 +}
 +
 +	if(DDCreatePrimarySurface(wc) == GL_FALSE)
 +		return initFail(hwnd, wc);
 +
 +	if(wc->db_flag)
 +		return DDCreateOffScreen(wc);
 +} /* DDInit */
 +
 +static void DDFree( WMesaContext wc)
 +{
 +    if( wc->lpDD != NULL )
 +    {
 +		DDFreePrimarySurface(wc);
 +		DDDeleteOffScreen(wc);
 +        wc->lpDD->lpVtbl->Release(wc->lpDD);
 +        wc->lpDD = NULL;
 +    }
 +    // Clean up the screen on exit
 +    RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
 +                     RDW_ALLCHILDREN );
 +
 +}
 +#endif
 +
 +void WMesaMove(void)
 +{
 +	WMesaContext wc = Current;
 +	POINT	pt;
 +	if (Current != NULL){
 +		GetClientRect( wc->hwnd, &(wc->rectSurface) );
 +		pt.x = pt.y = 0;
 +		ClientToScreen( wc->hwnd, &pt );
 +		OffsetRect(&(wc->rectSurface), pt.x, pt.y);
 +	}
 +}
 +
 +/*
 + * Like PACK_8A8B8G8R() but don't use alpha.  This is usually an acceptable
 + * shortcut.
 + */
 +#define PACK_8B8G8R( R, G, B )   ( ((B) << 16) | ((G) << 8) | (R) )
 +
 +
 +/**********************************************************************/
 +/***                   Triangle rendering                            ***/
 +/**********************************************************************/
 +
 +
 +
 +/*
 + * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle.
 + */
 +static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx,
 +                                         GLuint v0, GLuint v1, GLuint v2,
 +                                         GLuint pv )
 +{
 +WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint i, len = RIGHT-LEFT;						\
 +   for (i=0;i<len;i++) {						\
 +      GLdepth z = FixedToDepth(ffz);					\
 +      if (z < zRow[i]) {						\
 +         pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),	\
 +				 FixedToInt(ffb) );			\
 +         zRow[i] = z;							\
 +      }									\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;			\
 +      ffz += fdzdx;							\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, smooth, depth-buffered, PF_8R8G8B triangle.
 + */
 +static void smooth_8R8G8B_z_triangle( GLcontext *ctx,
 +                                         GLuint v0, GLuint v1, GLuint v2,
 +                                         GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint i, len = RIGHT-LEFT;						\
 +   for (i=0;i<len;i++) {						\
 +      GLdepth z = FixedToDepth(ffz);					\
 +      if (z < zRow[i]) {						\
 +         pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),	\
 +				 FixedToInt(ffb) );			\
 +         zRow[i] = z;							\
 +      }									\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;			\
 +      ffz += fdzdx;							\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +
 +/*
 + * XImage, smooth, depth-buffered, PF_5R6G5B triangle.
 + */
 +static void smooth_5R6G5B_z_triangle( GLcontext *ctx,
 +                                         GLuint v0, GLuint v1, GLuint v2,
 +                                         GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
 +#define PIXEL_TYPE GLushort
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint i, len = RIGHT-LEFT;						\
 +   for (i=0;i<len;i++) {						\
 +      GLdepth z = FixedToDepth(ffz);					\
 +      if (z < zRow[i]) {						\
 +         pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg),	\
 +				 FixedToInt(ffb) );			\
 +         zRow[i] = z;							\
 +      }									\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;			\
 +      ffz += fdzdx;							\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +/*
 + * XImage, flat, depth-buffered, PF_8A8B8G8R triangle.
 + */
 +static void flat_8A8B8G8R_z_triangle( GLcontext *ctx, GLuint v0,
 +                        	      GLuint v1, GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE					\
 +   unsigned long p = PACK_8B8G8R( VB->Color[pv][0],	\
 +		 VB->Color[pv][1], VB->Color[pv][2] );
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint i, len = RIGHT-LEFT;						\
 +   for (i=0;i<len;i++) {						\
 +      GLdepth z = FixedToDepth(ffz);					\
 +      if (z < zRow[i]) {						\
 +	 pRow[i] = p;							\
 +         zRow[i] = z;							\
 +      }									\
 +      ffz += fdzdx;							\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, flat, depth-buffered, PF_8R8G8B triangle.
 + */
 +static void flat_8R8G8B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                    GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE					\
 +   unsigned long p = PACK_8R8G8B( VB->Color[pv][0],	\
 +		 VB->Color[pv][1], VB->Color[pv][2] );
 +#define INNER_LOOP( LEFT, RIGHT, Y )			\
 +{							\
 +   GLint i, len = RIGHT-LEFT;				\
 +   for (i=0;i<len;i++) {				\
 +      GLdepth z = FixedToDepth(ffz);			\
 +      if (z < zRow[i]) {				\
 +	 pRow[i] = p;					\
 +         zRow[i] = z;					\
 +      }							\
 +      ffz += fdzdx;					\
 +   }							\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, flat, depth-buffered, PF_5R6G5B triangle.
 + */
 +static void flat_5R6G5B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                    GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
 +#define PIXEL_TYPE GLushort
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE					\
 +   unsigned long p = PACK_5R6G5B( VB->Color[pv][0],	\
 +		 VB->Color[pv][1], VB->Color[pv][2] );
 +#define INNER_LOOP( LEFT, RIGHT, Y )			\
 +{							\
 +   GLint i, len = RIGHT-LEFT;				\
 +   for (i=0;i<len;i++) {				\
 +      GLdepth z = FixedToDepth(ffz);			\
 +      if (z < zRow[i]) {				\
 +	 pRow[i] = p;					\
 +         zRow[i] = z;					\
 +      }							\
 +      ffz += fdzdx;					\
 +   }							\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle.
 + */
 +static void smooth_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +				      GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint xx;								\
 +   PIXEL_TYPE *pixel = pRow;						\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {				\
 +      *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),		\
 +				FixedToInt(ffb) );			\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;			\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
 + */
 +static void smooth_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                    GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint xx;								\
 +   PIXEL_TYPE *pixel = pRow;						\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {				\
 +      *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),		\
 +				FixedToInt(ffb) );			\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;			\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle.
 + */
 +static void smooth_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +				    GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
 +#define PIXEL_TYPE GLushort
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint xx;								\
 +   PIXEL_TYPE *pixel = pRow;						\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {				\
 +      *pixel = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg),		\
 +				FixedToInt(ffb) );			\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;			\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +
 +/*
 + * XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle.
 + */
 +static void flat_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0,
 +                        	    GLuint v1, GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE					\
 +   unsigned long p = PACK_8B8G8R( VB->Color[pv][0],	\
 +		 VB->Color[pv][1], VB->Color[pv][2] );
 +#define INNER_LOOP( LEFT, RIGHT, Y )			\
 +{							\
 +   GLint xx;						\
 +   PIXEL_TYPE *pixel = pRow;				\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {		\
 +      *pixel = p;					\
 +   }							\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, flat, NON-depth-buffered, PF_8R8G8B triangle.
 + */
 +static void flat_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                  GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
 +#define PIXEL_TYPE GLuint
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE					\
 +   unsigned long p = PACK_8R8G8B( VB->Color[pv][0],	\
 +		 VB->Color[pv][1], VB->Color[pv][2] );
 +#define INNER_LOOP( LEFT, RIGHT, Y )			\
 +{							\
 +   GLint xx;						\
 +   PIXEL_TYPE *pixel = pRow;				\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {		\
 +      *pixel = p;					\
 +   }							\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, flat, NON-depth-buffered, PF_5R6G5B triangle.
 + */
 +static void flat_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                  GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
 +#define PIXEL_TYPE GLushort
 +//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE					\
 +   unsigned long p = PACK_5R6G5B( VB->Color[pv][0],	\
 +		 VB->Color[pv][1], VB->Color[pv][2] );
 +#define INNER_LOOP( LEFT, RIGHT, Y )			\
 +{							\
 +   GLint xx;						\
 +   PIXEL_TYPE *pixel = pRow;				\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {		\
 +      *pixel = p;					\
 +   }							\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle.
 + */
 +
 +static void smooth_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                       GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define INTERP_INDEX 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )								\
 +{																	\
 +   GLint i, len = RIGHT-LEFT;										\
 +   for (i=0;i<len;i++) {											\
 +      GLdepth z = FixedToDepth(ffz);								\
 +      if (z < zRow[i]) {											\
 +         pRow[i] = FixedToInt(ffi);									\
 +         zRow[i] = z;												\
 +      }																\
 +      ffi += fdidx;													\
 +      ffz += fdzdx;													\
 +   }																\
 +}
 +
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle.
 + */
 +
 +static void flat_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                        	     GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE													\
 +   GLuint index = VB->Index[pv];									\
 +   if (!VB->MonoColor) {											\
 +      /* set the color index */										\
 +      (*ctx->Driver.Index)( ctx, index );							\
 +   }
 +#define INNER_LOOP( LEFT, RIGHT, Y )								\
 +{																	\
 +   GLint i, len = RIGHT-LEFT;										\
 +   for (i=0;i<len;i++) {											\
 +      GLdepth z = FixedToDepth(ffz);								\
 +      if (z < zRow[i]) {											\
 +		 pRow[i] = index;											\
 +         zRow[i] = z;												\
 +      }																\
 +      ffz += fdzdx;													\
 +   }																\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +
 +/*
 + * XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
 + */
 +
 +static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                     GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define INTERP_INDEX 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )					\
 +{									\
 +   GLint xx;								\
 +   PIXEL_TYPE *pixel = pRow;						\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {				\
 +      *pixel = FixedToInt(ffi);			\
 +      ffi += fdidx;			\
 +   }									\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +/*
 + * XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
 + */
 +static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                        	     GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +#define INTERP_Z 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define SETUP_CODE													\
 +   GLuint index = VB->Index[pv];									\
 +   if (!VB->MonoColor) {											\
 +      /* set the color index */										\
 +      (*ctx->Driver.Index)( ctx, index );							\
 +   }
 +#define INNER_LOOP( LEFT, RIGHT, Y )			\
 +{							\
 +   GLint xx;						\
 +   PIXEL_TYPE *pixel = pRow;				\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {		\
 +      *pixel = index;					\
 +   }							\
 +}
 +#include "tritemp.h"
 +}
 +
 +/*
 + * XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle.
 + */
 +static void smooth_DITHER8_z_triangle( GLcontext *ctx,
 +                                       GLuint v0, GLuint v1, GLuint v2,
 +                                       GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +   DITHER_RGB_TO_8BIT_SETUP
 +#define INTERP_Z 1
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )									\
 +{																		\
 +   GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT;					\
 +   for (i=0;i<len;i++,xx++) {											\
 +      GLdepth z = FixedToDepth(ffz);									\
 +      if (z < zRow[i]) {												\
 +		 DITHER_RGB_TO_8BIT( FixedToInt(ffr), FixedToInt(ffg),			\
 +								FixedToInt(ffb), xx, yy);				\
 +		 pRow[i] = pixelDithered;										\
 +         zRow[i] = z;													\
 +      }																	\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;						\
 +      ffz += fdzdx;														\
 +   }																	\
 +}
 +#include "tritemp.h"
 +}
 +
 +/*
 + * XImage, flat, depth-buffered, 8-bit PF_DITHER triangle.
 + */
 +static void flat_DITHER8_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                     GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +   DITHER_RGB_TO_8BIT_SETUP
 +#define INTERP_Z 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +
 +#define INNER_LOOP( LEFT, RIGHT, Y )									\
 +{																		\
 +   GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT;					\
 +   for (i=0;i<len;i++,xx++) {											\
 +      GLdepth z = FixedToDepth(ffz);									\
 +      if (z < zRow[i]) {												\
 +		DITHER_RGB_TO_8BIT( VB->Color[pv][0],							\
 +			 VB->Color[pv][1], VB->Color[pv][2], xx, yy);				\
 +		pRow[i] = pixelDithered;										\
 +         zRow[i] = z;													\
 +      }																	\
 +      ffz += fdzdx;														\
 +   }																	\
 +}
 +#include "tritemp.h"
 +}
 +
 +/*
 + * XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle.
 + */
 +static void smooth_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +				     GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +   DITHER_RGB_TO_8BIT_SETUP
 +#define INTERP_RGB 1
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +#define INNER_LOOP( LEFT, RIGHT, Y )									\
 +{																		\
 +   GLint xx, yy = FLIP(Y);												\
 +   PIXEL_TYPE *pixel = pRow;											\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {								\
 +	  DITHER_RGB_TO_8BIT( VB->Color[pv][0],	VB->Color[pv][1], VB->Color[pv][2], xx, yy);\
 +	  *pixel = pixelDithered;											\
 +	  ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;						\
 +   }																	\
 +}
 +#include "tritemp.h"
 +}
 +
 +/*
 + * XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle.
 + */
 +
 +static void flat_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                   GLuint v2, GLuint pv )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +   DITHER_RGB_TO_8BIT_SETUP
 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
 +#define PIXEL_TYPE GLubyte
 +#define BYTES_PER_ROW (wmesa->ScanWidth)
 +
 +#define INNER_LOOP( LEFT, RIGHT, Y )									\
 +{																		\
 +   GLint xx, yy = FLIP(Y);												\
 +   PIXEL_TYPE *pixel = pRow;											\
 +   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {								\
 +      DITHER_RGB_TO_8BIT( VB->Color[pv][0],								\
 +			 VB->Color[pv][1], VB->Color[pv][2], xx, yy);				\
 +	  *pixel = pixelDithered;											\
 +   }																	\
 +}
 +#include "tritemp.h"
 +}
 +
 +
 +
 +
 +static triangle_func choose_triangle_function( GLcontext *ctx )
 +{
 +   WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
 +   int depth = wmesa->cColorBits;
 +
 +   if (ctx->Polygon.SmoothFlag)     return NULL;
 +   if (ctx->Texture.Enabled)        return NULL;
 +   if (!wmesa->db_flag) return NULL;
 +   /*if (wmesa->xm_buffer->buffer==XIMAGE)*/ {
 +      if (   ctx->Light.ShadeModel==GL_SMOOTH
 +          && ctx->RasterMask==DEPTH_BIT
 +          && ctx->Depth.Func==GL_LESS
 +          && ctx->Depth.Mask==GL_TRUE
 +          && ctx->Polygon.StippleFlag==GL_FALSE) {
 +         switch (wmesa->pixelformat) {
 +            case PF_8A8B8G8R:
 +               return smooth_8A8B8G8R_z_triangle;
 +            case PF_8R8G8B:
 +               return smooth_8R8G8B_z_triangle;
 +            case PF_5R6G5B:
 +               return smooth_5R6G5B_z_triangle;
 +            case PF_DITHER8:
 +               return  smooth_DITHER8_z_triangle;
 +            case PF_INDEX8:
 +               return smooth_ci_z_triangle;
 +            default:
 +               return NULL;
 +         }
 +      }
 +      if (   ctx->Light.ShadeModel==GL_FLAT
 +          && ctx->RasterMask==DEPTH_BIT
 +          && ctx->Depth.Func==GL_LESS
 +          && ctx->Depth.Mask==GL_TRUE
 +          && ctx->Polygon.StippleFlag==GL_FALSE) {
 +         switch (wmesa->pixelformat) {
 +            case PF_8A8B8G8R:
 +               return flat_8A8B8G8R_z_triangle;
 +            case PF_8R8G8B:
 +               return flat_8R8G8B_z_triangle;
 +            case PF_5R6G5B:
 +               return flat_5R6G5B_z_triangle;
 +            case PF_DITHER8:
 +               return flat_DITHER8_z_triangle;
 +            case PF_INDEX8:
 +               return flat_ci_z_triangle;
 +			default:
 +               return NULL;
 +         }
 +      }
 +      if (   ctx->RasterMask==0   /* no depth test */
 +          && ctx->Light.ShadeModel==GL_SMOOTH
 +          && ctx->Polygon.StippleFlag==GL_FALSE) {
 +         switch (wmesa->pixelformat) {
 +            case PF_8A8B8G8R:
 +               return smooth_8A8B8G8R_triangle;
 +            case PF_8R8G8B:
 +               return smooth_8R8G8B_triangle;
 +            case PF_5R6G5B:
 +               return smooth_5R6G5B_triangle;
 +            case PF_DITHER8:
 +               return smooth_DITHER8_triangle;
 +			case PF_INDEX8:
 +               return smooth_ci_triangle;
 +            default:
 +               return NULL;
 +         }
 +      }
 +
 +      if (   ctx->RasterMask==0   /* no depth test */
 +          && ctx->Light.ShadeModel==GL_FLAT
 +          && ctx->Polygon.StippleFlag==GL_FALSE) {
 +         switch (wmesa->pixelformat) {
 +            case PF_8A8B8G8R:
 +               return flat_8A8B8G8R_triangle;
 +            case PF_8R8G8B:
 +               return flat_8R8G8B_triangle;
 +            case PF_5R6G5B:
 +               return flat_5R6G5B_triangle;
 +            case PF_DITHER8:
 +               return flat_DITHER8_triangle;
 +			case PF_INDEX8:
 +               return flat_ci_triangle;
 +            default:
 +               return NULL;
 +         }
 +      }
 +
 +      return NULL;
 +   }
 +}
 +
 +/*
 + * Define a new viewport and reallocate auxillary buffers if the size of
 + * the window (color buffer) has changed.
 + */
 +void WMesaViewport( GLcontext *ctx,
 +                  GLint x, GLint y, GLsizei width, GLsizei 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.Sx = (GLfloat) width / 2.0F;
 +   ctx->Viewport.Tx = ctx->Viewport.Sx + x;
 +   ctx->Viewport.Sy = (GLfloat) height / 2.0F;
 +   ctx->Viewport.Ty = ctx->Viewport.Sy + y;
 +}
 diff --git a/src/mesa/drivers/windows/wmesa_stereo.c b/src/mesa/drivers/windows/wmesa_stereo.c new file mode 100644 index 0000000000..ea721a13b6 --- /dev/null +++ b/src/mesa/drivers/windows/wmesa_stereo.c @@ -0,0 +1,1872 @@ +/*
 +	WMesa_stereo.c
 +*/
 +// Stereo display feature added by Li Wei
 +// Updated 1996/10/06	11:16:15 CST
 +// Paralell render feature added by Li Wei
 +// liwei@aiar.xjtu.edu.cn
 +// http://sun.aiar.xjtu.edu.cn
 +
 +#define WMESA_STEREO_C
 +
 +#include <windows.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <wmesadef.h>
 +
 +#include <GL\wmesa.h>
 +#include "context.h"
 +#include "dd.h"
 +#include "xform.h"
 +#include "vb.h"
 +#include "matrix.h"
 +#include "depth.h"
 +
 +#ifdef PROFILE
 +	#include "profile.h"
 +#endif
 +
 +#include <wing.h>
 +
 +// Code added by Li Wei to enable stereo display  and Paralell render
 +
 +
 +/*#include "mesa_extend.h"*/
 +
 +#if !defined(NO_STEREO)
 +
 +	#include "gl\glu.h"
 +	#include "stereo.h"
 +
 +	PBYTE Buffer_Stereo;
 +
 +	void WMesaCreateStereoBuffer(void);
 +
 +	void WMesaInterleave( GLenum aView);
 +
 +	void WMesaDestroyStereoBuffer(void);
 +
 +	void WMesaShowStereo(GLuint list);
 +#endif
 +#if !defined(NO_PARALLEL)
 +	#include "parallel.h"
 +#endif
 +
 +/* end of added code*/
 +
 +/* Bit's used for dest: */
 +#define FRONT_PIXMAP	1
 +#define BACK_PIXMAP	2
 +#define BACK_XIMAGE	4
 +
 +static PWMC Current = NULL;
 +WMesaContext WC = NULL;
 +
 +#ifdef NDEBUG
 +  #define assert(ignore)	((void) 0)
 +#else
 +  void Mesa_Assert(void *Cond,void *File,unsigned Line)
 +  {
 +    char Msg[512];
 +    sprintf(Msg,"%s %s %d",Cond,File,Line);
 +    MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
 +    exit(1);
 +  }
 +  #define assert(e)	if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
 +#endif
 +
 +#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
 +#define DD_RELEASEDC
 +
 +//#define BEGINGDICALL	if(Current->rgb_flag)wmFlushBits(Current);
 +#define BEGINGDICALL
 +//#define ENDGDICALL		if(Current->rgb_flag)wmGetBits(Current);
 +#define ENDGDICALL
 +
 +#define FLIP(Y)  (Current->height-(Y)-1)
 +
 +#define STARTPROFILE
 +#define ENDPROFILE(PARA)
 +
 +static void FlushToFile(PWMC pwc, PSTR	szFile);
 +
 +BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize);
 +
 +BOOL wmDeleteBackingStore(PWMC pwc);
 +
 +void wmCreatePalette( PWMC pwdc );
 +BOOL wmSetDibColors(PWMC pwc);
 +void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
 +
 +void wmCreateDIBSection(
 +	HDC	 hDC,
 +    PWMC pwc,	// handle of device context
 +    CONST BITMAPINFO *pbmi,	// address of structure containing bitmap size, format, and color data
 +    UINT iUsage	// color data type indicator: RGB values or palette indices
 +    );
 +
 +BOOL wmFlush(PWMC pwc);
 +
 +/*
 + * Useful macros:
 +   Modified from file osmesa.c
 + */
 +
 +#define PIXELADDR(X,Y)  ((GLbyte *)Current->pbPixels + (Current->height-Y)* Current->ScanWidth + (X)*nBypp)
 +
 +
 +/* Finish all pending operations and synchronize. */
 +static void finish(GLcontext* ctx)
 +{
 +   /* no op */
 +}
 +
 +
 +//
 +// We cache all gl draw routines until a flush is made
 +//
 +static void flush(GLcontext* ctx)
 +{
 +	STARTPROFILE
 +	if(Current->rgb_flag && !(Current->dib.fFlushed)&&!(Current->db_flag)){
 +		wmFlush(Current);
 +	}
 +	ENDPROFILE(flush)
 +
 +}
 +
 +
 +
 +/*
 + * Set the color index used to clear the color buffer.
 + */
 +static void clear_index(GLcontext* ctx, GLuint index)
 +{
 +  STARTPROFILE
 +  Current->clearpixel = index;
 +  ENDPROFILE(clear_index)
 +}
 +
 +
 +
 +/*
 + * Set the color used to clear the color buffer.
 + */
 +static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +  STARTPROFILE
 +  Current->clearpixel=RGB(r, g, b );
 +  ENDPROFILE(clear_color)
 +}
 +
 +
 +
 +/*
 + * Clear the specified region of the color buffer using the clear color
 + * or index as specified by one of the two functions above.
 + */
 +static void clear(GLcontext* ctx,
 +				  GLboolean all,GLint x, GLint y, GLint width, GLint height )
 +{
 +	DWORD	dwColor;
 +	WORD	wColor;
 +	LPDWORD	lpdw = (LPDWORD)Current->pbPixels;
 +	LPWORD	lpw = (LPWORD)Current->pbPixels;
 +	LPBYTE	lpb = Current->pbPixels;
 +
 +    STARTPROFILE
 +
 +	if (all){
 +		x=y=0;
 +		width=Current->width;
 +		height=Current->height;
 +	}
 +	if (Current->rgb_flag==GL_TRUE){
 +		if(Current->db_flag==GL_TRUE){
 +			UINT	nBypp = Current->cColorBits / 8;
 +			int		i = 0;
 +			int		iSize;
 +
 +			if(nBypp == 2){
 +				iSize = (Current->width * Current->height) / nBypp;
 +
 +				wColor = BGR16(GetRValue(Current->clearpixel),
 +							   GetGValue(Current->clearpixel),
 +							   GetBValue(Current->clearpixel));
 +				dwColor = MAKELONG(wColor, wColor);
 +			}
 +			else if(nBypp == 4){
 +				iSize = (Current->width * Current->height);
 +
 +				dwColor = BGR32(GetRValue(Current->clearpixel),
 +							   GetGValue(Current->clearpixel),
 +							   GetBValue(Current->clearpixel));
 +			}
 +			//
 +			// This is the 24bit case
 +			//
 +			else {
 +
 +				iSize = (Current->width * Current->height) / nBypp;
 +
 +				dwColor = BGR24(GetRValue(Current->clearpixel),
 +							   GetGValue(Current->clearpixel),
 +							   GetBValue(Current->clearpixel));
 +
 +
 +				while(i < iSize){
 +					*lpdw = dwColor;
 +					lpb += nBypp;
 +					lpdw = (LPDWORD)lpb;
 +					i++;
 +				}
 +
 +	//			ENDPROFILE(clear)
 +
 +				return;
 +			}
 +
 +			while(i < iSize){
 +				*lpdw = dwColor;
 +				lpdw++;
 +				i++;
 +			}
 +		}
 +		else{ // For single buffer
 +		 HDC DC=DD_GETDC;
 +		 HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
 +		 HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
 +		 HPEN Old_Pen=SelectObject(DC,Pen);
 +		 HBRUSH Old_Brush=SelectObject(DC,Brush);
 +		 Rectangle(DC,x,y,x+width,y+height);
 +		 SelectObject(DC,Old_Pen);
 +		 SelectObject(DC,Old_Brush);
 +		 DeleteObject(Pen);
 +		 DeleteObject(Brush);
 +		 DD_RELEASEDC;
 +  		}
 +	}
 +	else {
 +		int i;
 +		char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
 +		for (i=0; i<height; i++){
 +			memset(Mem,Current->clearpixel,width);
 +			Mem+=width;
 +		}
 +	}
 +	ENDPROFILE(clear)
 +}
 +
 +
 +
 +/* Set the current color index. */
 +static void set_index(GLcontext* ctx, GLuint index)
 +{
 +  STARTPROFILE
 +  Current->pixel=index;
 +  ENDPROFILE(set_index)
 +}
 +
 +
 +
 +/* Set the current RGBA color. */
 +static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
 +{
 +  STARTPROFILE
 +  Current->pixel = RGB( r, g, b );
 +  ENDPROFILE(set_color)
 +}
 +
 +
 +
 +/* Set the index mode bitplane mask. */
 +static GLboolean index_mask(GLcontext* ctx, GLuint mask)
 +{
 +   /* can't implement */
 +   return GL_FALSE;
 +}
 +
 +
 +
 +/* Set the RGBA drawing mask. */
 +static GLboolean color_mask( GLcontext* ctx,
 +							 GLboolean rmask, GLboolean gmask,
 +							 GLboolean bmask, GLboolean amask)
 +{
 +   /* can't implement */
 +   return GL_FALSE;
 +}
 +
 +
 +
 +/*
 + * Set the pixel logic operation.  Return GL_TRUE if the device driver
 + * can perform the operation, otherwise return GL_FALSE.  If GL_FALSE
 + * is returned, the logic op will be done in software by Mesa.
 + */
 +GLboolean logicop( GLcontext* ctx, GLenum op )
 +{
 +   /* can't implement */
 +   return GL_FALSE;
 +}
 +
 +
 +static void dither( GLcontext* ctx, GLboolean enable )
 +{
 +   /* No op */
 +}
 +
 +
 +
 +static GLboolean set_buffer( GLcontext* ctx, GLenum mode )
 +{
 +   STARTPROFILE
 +   /* TODO: this could be better */
 +   if (mode==GL_FRONT || mode==GL_BACK) {
 +      return GL_TRUE;
 +   }
 +   else {
 +      return GL_FALSE;
 +   }
 +   ENDPROFILE(set_buffer)
 +}
 +
 +
 +
 +/* Return characteristics of the output buffer. */
 +static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height /*, GLuint *depth */)
 +{
 +
 +	int New_Size;
 +	RECT CR;
 +
 +	STARTPROFILE
 +	GetClientRect(Current->Window,&CR);
 +
 +	*width=CR.right;
 +	*height=CR.bottom;
 +//	*depth = Current->depth;
 +
 +	New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
 +
 +	if (New_Size){
 +		Current->width=*width;
 +		Current->height=*height;
 +		Current->ScanWidth=Current->width;
 +	    if ((Current->ScanWidth%sizeof(long))!=0)
 +			Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
 +
 +		if (Current->db_flag){
 +			if (Current->rgb_flag==GL_TRUE){
 +				wmDeleteBackingStore(Current);
 +				wmCreateBackingStore(Current, Current->width, Current->height);
 +			}
 +			else{
 +				Current->ScanWidth=Current->width;
 +			    if ((Current->ScanWidth%sizeof(long))!=0)
 +				Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
 +
 +				Current->IndexFormat->bmiHeader.biWidth=Current->width;
 +
 +				if (Current->IndexFormat->bmiHeader.biHeight<0)
 +					Current->IndexFormat->bmiHeader.biHeight=-(Current->height);
 +				else
 +					Current->IndexFormat->bmiHeader.biHeight=Current->height;
 +
 +				Current->Compat_BM=WinGCreateBitmap(Current->dib.hDC,Current->IndexFormat,&((void *) Current->ScreenMem));
 +
 +				DeleteObject(SelectObject(Current->dib.hDC,Current->Compat_BM));
 +			}
 +//Code added by Li Wei to enable stereo display
 +// Recreate stereo buffer when stereo_flag is TRUE while parallelFlag is FALSE
 +#if !defined(NO_STEREO)
 +			if(stereo_flag
 +#if !defined(NO_PARALLEL)
 +				&&!parallelFlag
 +#endif
 +				) {
 +			if(stereoBuffer == GL_TRUE)
 +				WMesaDestroyStereoBuffer();
 +			WMesaCreateStereoBuffer();
 +			}
 +#endif
 +//	Resize OsmesaBuffer if in Parallel mode
 +#if !defined(NO_PARALLEL)
 +			if(parallelFlag)
 +			PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth,
 +			Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem);
 +#endif
 +//end modification
 +
 +		}
 +	}
 +
 +   ENDPROFILE(buffer_size)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****           Accelerated point, line, polygon rendering       *****/
 +/**********************************************************************/
 +
 +
 +static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
 +{
 +   GLuint i;
 + //  HDC DC=DD_GETDC;
 +	PWMC	pwc = Current;
 +
 +	STARTPROFILE
 +
 +	if (Current->gl_ctx->VB->MonoColor) {
 +      /* all drawn with current color */
 +      for (i=first;i<=last;i++) {
 +         if (Current->gl_ctx->VB->ClipMask[i]==0) {
 +            int x, y;
 +            x =       (GLint) Current->gl_ctx->VB->Win[i][0];
 +            y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
 +			wmSetPixel(pwc, y,x,GetRValue(Current->pixel),
 +					    GetGValue(Current->pixel), GetBValue(Current->pixel));
 +         }
 +      }
 +   }
 +   else {
 +      /* draw points of different colors */
 +      for (i=first;i<=last;i++) {
 +         if (Current->gl_ctx->VB->ClipMask[i]==0) {
 +            int x, y;
 +            unsigned long pixel=RGB(Current->gl_ctx->VB->Color[i][0]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][1]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][2]*255.0);
 +            x =       (GLint) Current->gl_ctx->VB->Win[i][0];
 +            y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
 +			wmSetPixel(pwc, y,x,Current->gl_ctx->VB->Color[i][0]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][1]*255.0,
 +                                    Current->gl_ctx->VB->Color[i][2]*255.0);
 +         }
 +      }
 +   }
 +//   DD_RELEASEDC;
 +   ENDPROFILE(fast_rgb_points)
 +}
 +
 +
 +
 +/* Return pointer to accerated points function */
 +extern points_func choose_points_function( GLcontext* ctx )
 +{
 +   STARTPROFILE
 +   if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0
 +       && !ctx->Texture.Enabled  && ctx->Visual->RGBAflag) {
 +   ENDPROFILE(choose_points_function)
 +      return fast_rgb_points;
 +   }
 +   else {
 +   ENDPROFILE(choose_points_function)
 +      return NULL;
 +   }
 +}
 +
 +
 +
 +/* Draw a line using the color specified by Current->gl_ctx->VB->Color[pv] */
 +static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv )
 +{
 +	STARTPROFILE
 +	int x0, y0, x1, y1;
 +	unsigned long pixel;
 +	HDC DC=DD_GETDC;
 +	HPEN Pen;
 +	HPEN Old_Pen;
 +
 +	if (Current->gl_ctx->VB->MonoColor) {
 +	  pixel = Current->pixel;  /* use current color */
 +	}
 +	else {
 +	  pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0);
 +	}
 +
 +	x0 =       (int) Current->gl_ctx->VB->Win[v0][0];
 +	y0 = FLIP( (int) Current->gl_ctx->VB->Win[v0][1] );
 +	x1 =       (int) Current->gl_ctx->VB->Win[v1][0];
 +	y1 = FLIP( (int) Current->gl_ctx->VB->Win[v1][1] );
 +
 +
 +	BEGINGDICALL
 +
 +	Pen=CreatePen(PS_SOLID,1,pixel);
 +	Old_Pen=SelectObject(DC,Pen);
 +	MoveToEx(DC,x0,y0,NULL);
 +	LineTo(DC,x1,y1);
 +	SelectObject(DC,Old_Pen);
 +	DeleteObject(Pen);
 +	DD_RELEASEDC;
 +
 +	ENDGDICALL
 +
 +	ENDPROFILE(fast_flat_rgb_line)
 +}
 +
 +
 +
 +/* Return pointer to accerated line function */
 +static line_func choose_line_function( GLcontext* ctx )
 +{
 +	STARTPROFILE
 +   if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag
 +       && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
 +       && !ctx->Texture.Enabled && Current->rgb_flag) {
 +   ENDPROFILE(choose_line_function)
 +      return fast_flat_rgb_line;
 +   }
 +   else {
 +   ENDPROFILE(choose_line_function)
 +      return NULL;
 +   }
 +}
 +
 +/**********************************************************************/
 +/*****                 Optimized triangle rendering               *****/
 +/**********************************************************************/
 +
 +
 +/*
 + * Smooth-shaded, z-less triangle, RGBA color.
 + */
 +static void smooth_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                     GLuint v2, GLuint pv )
 +{
 +UINT	nBypp = Current->cColorBits / 8;
 +GLbyte* img;
 +GLushort* img16;
 +GLuint *img24 ,*img32;
 +#define INTERP_Z 1
 +#define INTERP_RGB 1
 +#define INTERP_ALPHA 1
 +#define INNER_LOOP( LEFT, RIGHT, Y )							\
 +{																\
 +   GLint i, len = RIGHT-LEFT;									\
 +   img = PIXELADDR(LEFT,Y);   									\
 +   for (i=0;i<len;i++,img+=nBypp) {								\
 +      GLdepth z = FixedToDepth(ffz);							\
 +      if (z < zRow[i]) {										\
 +		 img16 = img24 = img32 = img;							\
 +		 if(nBypp == 2)											\
 +			*img16 = BGR16(	FixedToInt(ffr), FixedToInt(ffg),	\
 +							FixedToInt(ffb));					\
 +		 if(nBypp == 3)											\
 +			*img24 = BGR24(	FixedToInt(ffr), FixedToInt(ffg),	\
 +							FixedToInt(ffb));					\
 +   		 if(nBypp == 4)											\
 +			*img32 = BGR32(	FixedToInt(ffr), FixedToInt(ffg),	\
 +							FixedToInt(ffb));					\
 +         zRow[i] = z;											\
 +      }															\
 +      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;  ffa += fdadx;\
 +      ffz += fdzdx;												\
 +   }															\
 +}
 +
 +	#include "tritemp.h"
 + }
 +
 +
 +
 +
 +/*
 + * Flat-shaded, z-less triangle, RGBA color.
 + */
 +static void flat_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
 +                                   GLuint v2, GLuint pv )
 +{
 +GLbyte* img;
 +GLushort* img16;
 +GLuint *img24, *img32;
 +UINT	nBypp = Current->cColorBits / 8;
 +GLubyte r, g, b ;
 +GLushort pixel16 = BGR16(r,g,b);
 +GLuint   pixel24 = BGR24(r,g,b);
 +GLuint   pixel32 = BGR32(r,g,b);
 +
 +#define INTERP_Z 1
 +#define SETUP_CODE			\
 +   r = VB->Color[pv][0];	\
 +   g = VB->Color[pv][1];	\
 +   b = VB->Color[pv][2];
 +
 +#define INNER_LOOP( LEFT, RIGHT, Y )							\
 +{																\
 +   GLint i, len = RIGHT-LEFT;									\
 +   img = PIXELADDR(LEFT,Y);										\
 +   for (i=0;i<len;i++,img+=nBypp) {								\
 +      GLdepth z = FixedToDepth(ffz);							\
 +      if (z < zRow[i]) {										\
 +         img16 = img24 = img32 = img;							\
 +		 if(nBypp == 2)											\
 +			*img16 = pixel16;									\
 +		 if(nBypp == 3)											\
 +			*img24 = pixel24;									\
 +   		 if(nBypp == 4)											\
 +			*img32 = pixel32;									\
 +         zRow[i] = z;											\
 +      }															\
 +      ffz += fdzdx;												\
 +   }															\
 +}
 +
 +#include "tritemp.h"
 +}
 +
 +
 +
 +/*
 + * Return pointer to an accelerated triangle function if possible.
 + */
 +static triangle_func choose_triangle_function( GLcontext *ctx )
 +{
 +   if (ctx->Polygon.SmoothFlag)     return NULL;
 +   if (ctx->Polygon.StippleFlag)    return NULL;
 +   if (ctx->Texture.Enabled)        return NULL;
 +
 +   if (ctx->RasterMask==DEPTH_BIT
 +       && ctx->Depth.Func==GL_LESS
 +       && ctx->Depth.Mask==GL_TRUE
 +       && ctx->Visual->RGBAflag) {
 +	if (ctx->Light.ShadeModel==GL_SMOOTH) {
 +         return smooth_color_z_triangle;
 +      }
 +      else {
 +         return flat_color_z_triangle;
 +      }
 +   }
 +   return NULL;
 +}
 +
 +
 +/* Draw a convex polygon using color Current->gl_ctx->VB->Color[pv] */
 +static void fast_flat_rgb_polygon( GLcontext* ctx, GLuint n, GLuint vlist[], GLuint pv )
 +{
 +   STARTPROFILE
 +   POINT *Pts=(POINT *) malloc(n*sizeof(POINT));
 +   HDC DC=DD_GETDC;
 +   HPEN Pen;
 +   HBRUSH Brush;
 +   HPEN Old_Pen;
 +   HBRUSH Old_Brush;
 +   GLint pixel;
 +   GLuint i;
 +
 +   if (Current->gl_ctx->VB->MonoColor) {
 +      pixel = Current->pixel;  /* use current color */
 +   }
 +   else {
 +      pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0);
 +   }
 +
 +   Pen=CreatePen(PS_SOLID,1,pixel);
 +   Brush=CreateSolidBrush(pixel);
 +   Old_Pen=SelectObject(DC,Pen);
 +   Old_Brush=SelectObject(DC,Brush);
 +
 +   for (i=0; i<n; i++) {
 +      int j = vlist[i];
 +      Pts[i].x =       (int) Current->gl_ctx->VB->Win[j][0];
 +      Pts[i].y = FLIP( (int) Current->gl_ctx->VB->Win[j][1] );
 +   }
 +
 +   BEGINGDICALL
 +
 +   Polygon(DC,Pts,n);
 +   SelectObject(DC,Old_Pen);
 +   SelectObject(DC,Old_Brush);
 +   DeleteObject(Pen);
 +   DeleteObject(Brush);
 +   DD_RELEASEDC;
 +   free(Pts);
 +
 +   ENDGDICALL
 +
 +  ENDPROFILE(fast_flat_rgb_polygon)
 +}
 +
 +
 +
 +/* Return pointer to accerated polygon function */
 +static polygon_func choose_polygon_function( GLcontext* ctx )
 +{
 +	STARTPROFILE
 +   if (!ctx->Polygon.SmoothFlag && !ctx->Polygon.StippleFlag
 +       && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
 +       && !ctx->Texture.Enabled && Current->rgb_flag==GL_TRUE) {
 +   ENDPROFILE(choose_polygon_function)
 +      return fast_flat_rgb_polygon;
 +   }
 +   else {
 +   ENDPROFILE(choose_polygon_function)
 +      return NULL;
 +   }
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****                 Span-based pixel drawing                   *****/
 +/**********************************************************************/
 +
 +
 +/* Write a horizontal span of color-index pixels with a boolean mask. */
 +static void write_index_span( GLcontext* ctx,
 +							  GLuint n, GLint x, GLint y,
 +							  const GLuint index[],
 +                              const GLubyte mask[] )
 +{
 +	  STARTPROFILE
 +	  GLuint i;
 +	  char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
 +	  assert(Current->rgb_flag==GL_FALSE);
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +		  Mem[i]=index[i];
 +	   ENDPROFILE(write_index_span)
 +}
 +
 +
 +
 +/*
 + * Write a horizontal span of pixels with a boolean mask.  The current
 + * color index is used for all pixels.
 + */
 +static void write_monoindex_span(GLcontext* ctx,
 +								 GLuint n,GLint x,GLint y,
 +								 const GLubyte mask[])
 +{
 +	  STARTPROFILE
 +	  GLuint i;
 +	  char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
 +	  assert(Current->rgb_flag==GL_FALSE);
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +		  Mem[i]=Current->pixel;
 +	  ENDPROFILE(write_monoindex_span)
 +}
 +
 +/*
 +	To improve the performance of this routine, frob the data into an actual scanline
 +	and call bitblt on the complete scan line instead of SetPixel.
 +*/
 +
 +/* Write a horizontal span of color pixels with a boolean mask. */
 +static void write_color_span( GLcontext* ctx,
 +			  GLuint n, GLint x, GLint y,
 +			  const GLubyte
 +			  red[], const GLubyte green[],
 +			  const GLubyte blue[], const GLubyte alpha[],
 +			  const GLubyte mask[] )
 +{
 +	STARTPROFILE
 +
 +	PWMC	pwc = Current;
 +
 +	if (pwc->rgb_flag==GL_TRUE)
 +	{
 +		GLuint i;
 +		HDC DC=DD_GETDC;
 +		y=FLIP(y);
 +
 +		if (mask) {
 +			for (i=0; i<n; i++)
 +				if (mask[i])
 +					wmSetPixel(pwc, y, x + i,red[i], green[i], blue[i]);
 +		}
 +
 +		else {
 +			for (i=0; i<n; i++)
 +				wmSetPixel(pwc, y, x + i, red[i], green[i], blue[i]);
 +		}
 +
 +		DD_RELEASEDC;
 +
 +	}
 +
 +  else
 +  {
 +		GLuint i;
 +		char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
 +		if (mask) {
 +		   for (i=0; i<n; i++)
 +			 if (mask[i])
 +			   Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
 +		}
 +		else {
 +		   for (i=0; i<n; i++)
 +			 Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
 +			}
 +	}
 +   ENDPROFILE(write_color_span)
 +
 +}
 +
 +/*
 + * Write a horizontal span of pixels with a boolean mask.  The current color
 + * is used for all pixels.
 + */
 +static void write_monocolor_span( GLcontext* ctx,
 +								  GLuint n, GLint x, GLint y,
 +								  const GLubyte mask[])
 +{
 +  STARTPROFILE
 +  GLuint i;
 +  HDC DC=DD_GETDC;
 +  PWMC	pwc = Current;
 +
 +  assert(Current->rgb_flag==GL_TRUE);
 +  y=FLIP(y);
 +
 +  if(Current->rgb_flag==GL_TRUE){
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +// Trying
 +		wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel));
 +  }
 +  else {
 +	  for (i=0; i<n; i++)
 +		if (mask[i])
 +			SetPixel(DC, y, x+i, Current->pixel);
 +  }
 +
 +	DD_RELEASEDC;
 +
 +	ENDPROFILE(write_monocolor_span)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****                   Array-based pixel drawing                *****/
 +/**********************************************************************/
 +
 +
 +/* Write an array of pixels with a boolean mask. */
 +static void write_index_pixels( GLcontext* ctx,
 +							    GLuint n, const GLint x[], const GLint y[],
 +								const GLuint index[], const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +   GLuint i;
 +   assert(Current->rgb_flag==GL_FALSE);
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +         char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
 +		   *Mem = index[i];
 +      }
 +   }
 +   ENDPROFILE(write_index_pixels)
 +}
 +
 +
 +
 +/*
 + * Write an array of pixels with a boolean mask.  The current color
 + * index is used for all pixels.
 + */
 +static void write_monoindex_pixels( GLcontext* ctx,
 +								    GLuint n,
 +									const GLint x[], const GLint y[],
 +                                    const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +   GLuint i;
 +   assert(Current->rgb_flag==GL_FALSE);
 +   for (i=0; i<n; i++) {
 +      if (mask[i]) {
 +         char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
 +			*Mem = Current->pixel;
 +      }
 +   }
 +   ENDPROFILE(write_monoindex_pixels)
 +}
 +
 +
 +
 +/* Write an array of pixels with a boolean mask. */
 +static void write_color_pixels( GLcontext* ctx,
 +							    GLuint n, const GLint x[], const GLint y[],
 +								const GLubyte r[], const GLubyte g[],
 +                                const GLubyte b[], const GLubyte a[],
 +                                const GLubyte mask[] )
 +{
 +	STARTPROFILE
 +	GLuint i;
 +	PWMC	pwc = Current;
 +	HDC DC=DD_GETDC;
 +	assert(Current->rgb_flag==GL_TRUE);
 +	for (i=0; i<n; i++)
 +		if (mask[i])
 +			wmSetPixel(pwc, FLIP(y[i]),x[i],r[i],g[i],b[i]);
 +	DD_RELEASEDC;
 +	ENDPROFILE(write_color_pixels)
 +}
 +
 +
 +
 +/*
 + * Write an array of pixels with a boolean mask.  The current color
 + * is used for all pixels.
 + */
 +static void write_monocolor_pixels( GLcontext* ctx,
 +								    GLuint n,
 +									const GLint x[], const GLint y[],
 +                                    const GLubyte mask[] )
 +{
 +	STARTPROFILE
 +	GLuint i;
 +	PWMC	pwc = Current;
 +	HDC DC=DD_GETDC;
 +	assert(Current->rgb_flag==GL_TRUE);
 +	for (i=0; i<n; i++)
 +		if (mask[i])
 +			wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel),
 +					    GetGValue(Current->pixel), GetBValue(Current->pixel));
 +	DD_RELEASEDC;
 +	ENDPROFILE(write_monocolor_pixels)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/*****            Read spans/arrays of pixels                     *****/
 +/**********************************************************************/
 +
 +
 +/* Read a horizontal span of color-index pixels. */
 +static void read_index_span( GLcontext* ctx, GLuint n, GLint x, GLint y, GLuint index[])
 +{
 +  STARTPROFILE
 +  GLuint i;
 +  char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
 +  assert(Current->rgb_flag==GL_FALSE);
 +  for (i=0; i<n; i++)
 +    index[i]=Mem[i];
 +  ENDPROFILE(read_index_span)
 +
 +}
 +
 +
 +
 +
 +/* Read an array of color index pixels. */
 +static void read_index_pixels( GLcontext* ctx,
 +							   GLuint n, const GLint x[], const GLint y[],
 +							   GLuint indx[], const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +   GLuint i;
 +  assert(Current->rgb_flag==GL_FALSE);
 +  for (i=0; i<n; i++) {
 +     if (mask[i]) {
 +        indx[i]=*(Current->ScreenMem+y[i]*Current->ScanWidth+x[i]);
 +     }
 +  }
 +   ENDPROFILE(read_index_pixels)
 +}
 +
 +
 +
 +/* Read a horizontal span of color pixels. */
 +static void read_color_span( GLcontext* ctx,
 +							 GLuint n, GLint x, GLint y,
 +							 GLubyte red[], GLubyte green[],
 +                             GLubyte blue[], GLubyte alpha[] )
 +{
 +   STARTPROFILE
 +  UINT i;
 +  COLORREF Color;
 +  HDC DC=DD_GETDC;
 +  assert(Current->rgb_flag==GL_TRUE);
 +  y=FLIP(y);
 +  for (i=0; i<n; i++)
 +  {
 +    Color=GetPixel(DC,x+i,y);
 +    red[i]=GetRValue(Color);
 +    green[i]=GetGValue(Color);
 +    blue[i]=GetBValue(Color);
 +    alpha[i]=255;
 +  }
 +  DD_RELEASEDC;
 +  memset(alpha,0,n*sizeof(GLint));
 +   ENDPROFILE(read_color_span)
 +}
 +
 +
 +/* Read an array of color pixels. */
 +static void read_color_pixels( GLcontext* ctx,
 +							   GLuint n, const GLint x[], const GLint y[],
 +							   GLubyte red[], GLubyte green[],
 +                               GLubyte blue[], GLubyte alpha[],
 +                               const GLubyte mask[] )
 +{
 +   STARTPROFILE
 +  GLuint i;
 +  COLORREF Color;
 +  HDC DC=DD_GETDC;
 +  assert(Current->rgb_flag==GL_TRUE);
 +  for (i=0; i<n; i++) {
 +     if (mask[i]) {
 +        Color=GetPixel(DC,x[i],FLIP(y[i]));
 +        red[i]=GetRValue(Color);
 +        green[i]=GetGValue(Color);
 +        blue[i]=GetBValue(Color);
 +        alpha[i]=255;
 +     }
 +  }
 +  DD_RELEASEDC;
 +  memset(alpha,0,n*sizeof(GLint));
 +   ENDPROFILE(read_color_pixels)
 +}
 +
 +
 +
 +/**********************************************************************/
 +/**********************************************************************/
 +
 +
 +
 +void setup_DD_pointers( GLcontext* ctx )
 +{
 +   ctx->Driver.Finish = finish;
 +   ctx->Driver.Flush = flush;
 +
 +   ctx->Driver.ClearIndex = clear_index;
 +   ctx->Driver.ClearColor = clear_color;
 +   ctx->Driver.Clear = clear;
 +
 +   ctx->Driver.Index = set_index;
 +   ctx->Driver.Color = set_color;
 +   ctx->Driver.IndexMask = index_mask;
 +   ctx->Driver.ColorMask = color_mask;
 +
 +   ctx->Driver.LogicOp = logicop;
 +   ctx->Driver.Dither = dither;
 +
 +   ctx->Driver.SetBuffer = set_buffer;
 +   ctx->Driver.GetBufferSize = buffer_size;
 +
 +   ctx->Driver.PointsFunc = choose_points_function(ctx);
 +   ctx->Driver.LineFunc = choose_line_function(ctx);
 +   ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
 +   //   ctx->Driver.TriangleFunc = choose_polygon_function(ctx);
 +
 +   /* Pixel/span writing functions: */
 +   ctx->Driver.WriteColorSpan       = write_color_span;
 +   ctx->Driver.WriteMonocolorSpan   = write_monocolor_span;
 +   ctx->Driver.WriteColorPixels     = write_color_pixels;
 +   ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
 +   ctx->Driver.WriteIndexSpan       = write_index_span;
 +   ctx->Driver.WriteMonoindexSpan   = write_monoindex_span;
 +   ctx->Driver.WriteIndexPixels     = write_index_pixels;
 +   ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
 +
 +   /* Pixel/span reading functions: */
 +   ctx->Driver.ReadIndexSpan = read_index_span;
 +   ctx->Driver.ReadColorSpan = read_color_span;
 +   ctx->Driver.ReadIndexPixels = read_index_pixels;
 +   ctx->Driver.ReadColorPixels = read_color_pixels;
 +}
 +
 +//
 +// MesaGL32 is the DLL version of MesaGL for Win32
 +//
 +
 +/**********************************************************************/
 +/*****                  WMesa API Functions                       *****/
 +/**********************************************************************/
 +
 +
 +
 +#define PAL_SIZE 256
 +static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
 +{
 +   STARTPROFILE
 +	int i;
 +	HDC hdc;
 +	struct
 +	{
 +		WORD Version;
 +		WORD NumberOfEntries;
 +		PALETTEENTRY aEntries[PAL_SIZE];
 +	} Palette =
 +	{
 +		0x300,
 +		PAL_SIZE
 +	};
 +	hdc=GetDC(NULL);
 +	if (Pal!=NULL)
 +    GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
 +  else
 +    GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
 +	if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
 +	{
 +		for(i = 0; i <PAL_SIZE; i++)
 +			Palette.aEntries[i].peFlags = PC_RESERVED;
 +		Palette.aEntries[255].peRed = 255;
 +		Palette.aEntries[255].peGreen = 255;
 +		Palette.aEntries[255].peBlue = 255;
 +		Palette.aEntries[255].peFlags = 0;
 +		Palette.aEntries[0].peRed = 0;
 +		Palette.aEntries[0].peGreen = 0;
 +		Palette.aEntries[0].peBlue = 0;
 +		Palette.aEntries[0].peFlags = 0;
 +	}
 +	else
 +	{
 +		int nStaticColors;
 +		int nUsableColors;
 +		nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
 +		for (i=0; i<nStaticColors; i++)
 +			Palette.aEntries[i].peFlags = 0;
 +		nUsableColors = PAL_SIZE-nStaticColors;
 +		for (; i<nUsableColors; i++)
 +			Palette.aEntries[i].peFlags = PC_RESERVED;
 +		for (; i<PAL_SIZE-nStaticColors; i++)
 +			Palette.aEntries[i].peFlags = PC_RESERVED;
 +		for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
 +			Palette.aEntries[i].peFlags = 0;
 +	}
 +	ReleaseDC(NULL,hdc);
 +  for (i=0; i<PAL_SIZE; i++)
 +  {
 +    aRGB[i].rgbRed=Palette.aEntries[i].peRed;
 +    aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
 +    aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
 +    aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
 +  }
 +  	  ENDPROFILE(GetPalette)
 +}
 +
 +
 +WMesaContext /*APIENTRY*/ WMesaCreateContext( HWND hWnd, HPALETTE Pal,
 +											 /*HDC hDC,*/ GLboolean rgb_flag,
 +											  GLboolean db_flag )
 +{
 +  BITMAPINFO *Rec;
 +  //HDC DC;
 +  RECT CR;
 +  WMesaContext c;
 +
 +  c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
 +  if (!c)
 +    return NULL;
 +
 +  c->Window=hWnd;
 +  c->hDC = GetDC(hWnd);
 +
 +  if (rgb_flag==GL_FALSE)
 +  {
 +    c->rgb_flag = GL_FALSE;
 +    c->pixel = 1;
 +    db_flag=GL_TRUE; // WinG requires double buffering
 +    //c->gl_ctx->BufferDepth = windepth;
 +  }
 +  else
 +  {
 +    c->rgb_flag = GL_TRUE;
 +    c->pixel = 0;
 +  }
 +  GetClientRect(c->Window,&CR);
 +  c->width=CR.right;
 +  c->height=CR.bottom;
 +  if (db_flag)
 +  {
 +    c->db_flag = 1;
 +//	c->hDC GetDC(c->Window);
 +	/* Double buffered */
 +    if (c->rgb_flag==GL_TRUE)
 +    {
 +      //DC = c->hDC = hDC;
 +
 +//		DC = c->hDC = GetDC(c->Window);
 +		wmCreateBackingStore(c, c->width, c->height);
 +//		ReleaseDC(c->Window,DC);
 +    }
 +    else
 +    {
 +      c->dib.hDC=WinGCreateDC();
 +      Rec=(BITMAPINFO *) malloc(sizeof(BITMAPINFO)+(PAL_SIZE-1)*sizeof(RGBQUAD));
 +      c->hPal=Pal;
 +      GetPalette(Pal,Rec->bmiColors);
 +      WinGRecommendDIBFormat(Rec);
 +      Rec->bmiHeader.biWidth=c->width;
 +      Rec->bmiHeader.biHeight*=c->height;
 +      Rec->bmiHeader.biClrUsed=PAL_SIZE;
 +      if (Rec->bmiHeader.biPlanes!=1 || Rec->bmiHeader.biBitCount!=8)
 +      {
 +        MessageBox(NULL,"Error.","This code presumes a 256 color, single plane, WinG Device.\n",MB_OK);
 +        exit(1);
 +      }
 +      c->Compat_BM=WinGCreateBitmap(c->dib.hDC,Rec,&((void *) c->ScreenMem));
 +      c->Old_Compat_BM=SelectObject(c->dib.hDC,c->Compat_BM);
 +      WinGSetDIBColorTable(c->dib.hDC,0,PAL_SIZE,Rec->bmiColors);
 +      c->IndexFormat=Rec;
 +      c->ScanWidth=c->width;
 +	  c->cColorBits = 8;
 +      if ((c->ScanWidth%sizeof(long))!=0)
 +        c->ScanWidth+=(sizeof(long)-(c->ScanWidth%sizeof(long)));
 +    }
 +  }
 +  else
 +  {
 +    /* Single Buffered */
 +	c->db_flag = 0;
 +
 +//	wmCreateBackingStore(c, c->width, c->height);
 +  }
 +
 +
 +
 +  c->gl_visual = gl_create_visual(rgb_flag,
 +								  GL_FALSE,	/* software alpha */
 +                                  db_flag,	/* db_flag */
 +                                  16,		/* depth_bits */
 +                                  8,		/* stencil_bits */
 +                                  8,		/* accum_bits */
 +                                  8,
 +                                  255.0, 255.0, 255.0, 255.0 );
 +
 +	if (!c->gl_visual) {
 +         return NULL;
 +      }
 +
 +  /* allocate a new Mesa context */
 +  c->gl_ctx = gl_create_context( c->gl_visual, NULL,c);
 +
 +  if (!c->gl_ctx) {
 +         gl_destroy_visual( c->gl_visual );
 +         free(c);
 +         return NULL;
 +      }
 +
 +      c->gl_buffer = gl_create_framebuffer( c->gl_visual );
 +      if (!c->gl_buffer) {
 +         gl_destroy_visual( c->gl_visual );
 +         gl_destroy_context( c->gl_ctx );
 +         free(c);
 +         return NULL;
 +      }
 +//  setup_DD_pointers(c->gl_ctx);
 +
 +  return c;
 +}
 +
 +
 +
 +void /*APIENTRY*/ WMesaDestroyContext( void )
 +{
 +	WMesaContext c = Current;
 +	ReleaseDC(c->Window,c->hDC);
 +	WC = c;
 +
 +    gl_destroy_visual( c->gl_visual );
 +    gl_destroy_framebuffer( c->gl_buffer );
 +	gl_destroy_context( c->gl_ctx );
 +
 +	if (c->db_flag){
 +		wmDeleteBackingStore(c);
 +
 +//Code added by Li Wei to enable parallel render
 +#if !defined(NO_STEREO)
 +		if(stereoBuffer==GL_TRUE){
 +			WMesaDestroyStereoBuffer();
 +			stereoBuffer=GL_FALSE;
 +		}
 +#endif
 +// End modification
 +	}
 +	free( (void *) c );
 +//Code added by Li Wei to enable parallel render
 +// Parallel render only work in double buffer mode
 +#if !defined(NO_PARALLEL)
 +	if(parallelMachine)
 +		PRDestroyRenderBuffer();
 +#endif
 +// End modification
 +}
 +
 +
 +
 +void /*APIENTRY*/ WMesaMakeCurrent( WMesaContext c )
 +{
 +	if(!c){
 +		Current = c;
 +		return;
 +	}
 +
 +	//
 +	// A little optimization
 +	// If it already is current,
 +	// don't set it again
 +	//
 +	if(Current == c)
 +		return;
 +
 +	//gl_set_context( c->gl_ctx );
 +	gl_make_current(c->gl_ctx, c->gl_buffer);
 +	Current = c;
 +	setup_DD_pointers(c->gl_ctx);
 +	if (Current->gl_ctx->Viewport.Width==0) {
 +	  /* initialize viewport to window size */
 +	  gl_Viewport( Current->gl_ctx,
 +		           0, 0, Current->width, Current->height );
 +	}
 +}
 +
 +
 +
 +void /*APIENTRY*/ WMesaSwapBuffers( void )
 +{
 +  HDC DC = Current->hDC;
 +  if (Current->db_flag)
 +  {
 +    if (Current->rgb_flag)
 +		wmFlush(Current);
 +    else
 +      WinGBitBlt(DC,0,0,Current->width,Current->height,Current->dib.hDC,0,0);
 +  }
 +}
 +
 +
 +
 +void /*APIENTRY*/ WMesaPaletteChange(HPALETTE Pal)
 +{
 +  if (Current && Current->rgb_flag==GL_FALSE)
 +  {
 +    Current->hPal=Pal;
 +    GetPalette(Pal,Current->IndexFormat->bmiColors);
 +    WinGSetDIBColorTable(Current->dib.hDC,0,PAL_SIZE,Current->IndexFormat->bmiColors);
 +  }
 +}
 +
 +//
 +// Free up the dib section that was created
 +//
 +BOOL wmDeleteBackingStore(PWMC pwc)
 +{
 +	SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
 +	DeleteDC(pwc->dib.hDC);
 +	DeleteObject(pwc->hbmDIB);
 +	UnmapViewOfFile(pwc->dib.base);
 +	CloseHandle(pwc->dib.hFileMap);
 +	return TRUE;
 +}
 +
 +
 +//
 +// This function creates the DIB section that is used for combined
 +// GL and GDI calls
 +//
 +BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
 +{
 +    HDC hdc = pwc->hDC;
 +    LPBITMAPINFO pbmi = &(pwc->bmi);
 +	int		iUsage;
 +
 +    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 +    pbmi->bmiHeader.biWidth = lxSize;
 +    pbmi->bmiHeader.biHeight= -lySize;
 +    pbmi->bmiHeader.biPlanes = 1;
 +    pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
 +    pbmi->bmiHeader.biCompression = BI_RGB;
 +    pbmi->bmiHeader.biSizeImage = 0;
 +    pbmi->bmiHeader.biXPelsPerMeter = 0;
 +    pbmi->bmiHeader.biYPelsPerMeter = 0;
 +    pbmi->bmiHeader.biClrUsed = 0;
 +    pbmi->bmiHeader.biClrImportant = 0;
 +
 +	iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
 +
 +	pwc->cColorBits = pbmi->bmiHeader.biBitCount;
 +	pwc->ScanWidth = lxSize;
 +
 +	wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
 +
 +	if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
 +		wmCreatePalette( pwc );
 +		wmSetDibColors( pwc );
 +	}
 +
 +	return(TRUE);
 +
 +}
 +
 +
 +//
 +// This function copies one scan line in a DIB section to another
 +//
 +BOOL GLWINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
 +{
 +	UINT uiScans = 0;
 +	LPBYTE	pDest = pwc->pbPixels;
 +	DWORD	dwNextScan = uiScanWidth;
 +	DWORD	dwNewScan = uiNewWidth;
 +	DWORD	dwScanWidth = (uiScanWidth * nBypp);
 +
 +	//
 +	// We need to round up to the nearest DWORD
 +	// and multiply by the number of bytes per
 +	// pixel
 +	//
 +	dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
 +	dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);
 +
 +	for(uiScans = 0; uiScans < uiNumScans; uiScans++){
 +		CopyMemory(pDest, pBits, dwScanWidth);
 +		pBits += dwNextScan;
 +		pDest += dwNewScan;
 +	}
 +
 +	return(TRUE);
 +
 +}
 +
 +BOOL GLWINAPI wmSetPixelFormat( PWMC pwdc, HDC hDC, DWORD dwFlags )
 +{
 +	return(TRUE);
 +}
 +
 +static unsigned char threeto8[8] = {
 +	0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
 +};
 +
 +static unsigned char twoto8[4] = {
 +	0, 0x55, 0xaa, 0xff
 +};
 +
 +static unsigned char oneto8[2] = {
 +	0, 255
 +};
 +
 +static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
 +{
 +	unsigned char val;
 +
 +	val = i >> shift;
 +	switch (nbits) {
 +
 +		case 1:
 +			val &= 0x1;
 +			return oneto8[val];
 +
 +		case 2:
 +			val &= 0x3;
 +			return twoto8[val];
 +
 +		case 3:
 +			val &= 0x7;
 +			return threeto8[val];
 +
 +		default:
 +			return 0;
 +	}
 +}
 +
 +void /*WINAPI*/ wmCreatePalette( PWMC pwdc )
 +{
 +    /* Create a compressed and re-expanded 3:3:2 palette */
 +  	int            i;
 +	LOGPALETTE     *pPal;
 +    BYTE           rb, rs, gb, gs, bb, bs;
 +
 +    pwdc->nColors = 0x100;
 +
 +	pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY));
 +    memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
 +
 +	pPal->palVersion = 0x300;
 +
 +    rb = REDBITS;
 +    rs = REDSHIFT;
 +    gb = GREENBITS;
 +    gs = GREENSHIFT;
 +    bb = BLUEBITS;
 +    bs = BLUESHIFT;
 +
 +    if (pwdc->db_flag) {
 +
 +        /* Need to make two palettes: one for the screen DC and one for the DIB. */
 +	    pPal->palNumEntries = pwdc->nColors;
 +	    for (i = 0; i < pwdc->nColors; i++) {
 +		    pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
 +		    pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
 +		    pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
 +		    pPal->palPalEntry[i].peFlags = 0;
 +	    }
 +    	pwdc->hGLPalette = CreatePalette( pPal );
 +    	pwdc->hPalette = CreatePalette( pPal );
 +    }
 +
 +	else {
 +	    pPal->palNumEntries = pwdc->nColors;
 +	    for (i = 0; i < pwdc->nColors; i++) {
 +		    pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
 +		    pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
 +		    pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
 +		    pPal->palPalEntry[i].peFlags = 0;
 +	    }
 +    	pwdc->hGLPalette = CreatePalette( pPal );
 +    }
 +
 +	free(pPal);
 +
 +}
 +
 +//
 +// This function sets the color table of a DIB section
 +// to match that of the destination DC
 +//
 +BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc)
 +{
 +    RGBQUAD			*pColTab, *pRGB;
 +    PALETTEENTRY	*pPal, *pPE;
 +    int				i, nColors;
 +	BOOL			bRet=TRUE;
 +	DWORD			dwErr=0;
 +
 +    /* Build a color table in the DIB that maps to the
 +       selected palette in the DC.
 +	*/
 +    nColors = 1 << pwc->cColorBits;
 +	pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
 +    memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
 +    GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
 +    pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
 +    for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
 +        pRGB->rgbRed = pPE->peRed;
 +        pRGB->rgbGreen = pPE->peGreen;
 +        pRGB->rgbBlue = pPE->peBlue;
 +    }
 +	if(pwc->db_flag)
 +	    bRet = SetDIBColorTable(pwc->hDC, 0, nColors, pColTab );
 +
 +	if(!bRet)
 +		dwErr = GetLastError();
 +
 +    free( pColTab );
 +    free( pPal );
 +
 +	return(bRet);
 +}
 +
 +void /*WINAPI*/ wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
 +{
 +	if(Current->db_flag){
 +		LPBYTE	lpb = pwc->pbPixels;
 +		LPDWORD	lpdw;
 +		LPWORD	lpw;
 +		UINT	nBypp = pwc->cColorBits / 8;
 +		UINT	nOffset = iPixel % nBypp;
 +
 +		// Move the pixel buffer pointer to the scanline that we
 +		// want to access
 +
 +		pwc->dib.fFlushed = FALSE;
 +
 +		lpb += pwc->ScanWidth * iScanLine;
 +		// Now move to the desired pixel
 +		lpb += iPixel * nBypp;
 +
 +		lpdw = (LPDWORD)lpb;
 +		lpw = (LPWORD)lpb;
 +
 +		if(nBypp == 2)
 +			*lpw = BGR16(r,g,b);
 +		else if (nBypp == 3){
 +			*lpdw = BGR24(r,g,b);
 +		}
 +		else
 +			*lpdw = BGR32(r,g,b);
 +	}
 +	else{
 +		HDC DC = DD_GETDC;
 +		SetPixel(DC, iPixel, iScanLine, RGB(r,g,b));
 +		DD_RELEASEDC;
 +	}
 +}
 +
 +void /*WINAPI*/ wmCreateDIBSection(
 +	HDC	 hDC,
 +    PWMC pwc,	// handle of device context
 +    CONST BITMAPINFO *pbmi,	// address of structure containing bitmap size, format, and color data
 +    UINT iUsage	// color data type indicator: RGB values or palette indices
 +)
 +{
 +	DWORD	dwSize = 0;
 +	DWORD	dwScanWidth;
 +	UINT	nBypp = pwc->cColorBits / 8;
 +	HDC		hic;
 +
 +	dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
 +
 +	pwc->ScanWidth = dwScanWidth;
 +
 +	dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
 +
 +	pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
 +										  NULL,
 +										  PAGE_READWRITE | SEC_COMMIT,
 +										  0,
 +										  dwSize,
 +										  NULL);
 +
 +	if (!pwc->dib.hFileMap)
 +		return;
 +
 +	pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
 +								  FILE_MAP_ALL_ACCESS,
 +								  0,
 +								  0,
 +								  0);
 +
 +	if(!pwc->dib.base){
 +		CloseHandle(pwc->dib.hFileMap);
 +		return;
 +	}
 +
 +	pwc->pbPixels = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO);
 +
 +	pwc->dib.hDC = CreateCompatibleDC(hDC);
 +
 +	CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
 +
 +	hic = CreateIC("display", NULL, NULL, NULL);
 +
 +/*	pwc->hbmDIB = CreateDIBitmap(hic,
 +						 &(pwc->bmi.bmiHeader),
 +						 CBM_INIT,
 +						 pwc->pbPixels,
 +						 &(pwc->bmi),
 +						 DIB_RGB_COLORS);
 +*/
 +  pwc->hbmDIB = CreateDIBSection(hic,
 +						&(pwc->bmi.bmiHeader),
 +						DIB_RGB_COLORS,
 +						&(pwc->pbPixels),
 +						pwc->dib.hFileMap,
 +						0);
 +	pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
 +
 +	DeleteDC(hic);
 +
 +	return;
 +
 +}
 +
 +//
 +// Blit memory DC to screen DC
 +//
 +BOOL /*WINAPI*/ wmFlush(PWMC pwc)
 +{
 +	BOOL	bRet = 0;
 +	DWORD	dwErr = 0;
 +
 +
 +//	wmFlushBits(pwc);
 +
 +	bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height,
 +		   pwc->dib.hDC, 0, 0, SRCCOPY);
 +
 +	if(!bRet)
 +		dwErr = GetLastError();
 +
 +	pwc->dib.fFlushed = TRUE;
 +
 +	return(TRUE);
 +
 +}
 +
 +
 +// The following code is added by Li Wei to enable stereo display
 +
 +#if !defined(NO_STEREO)
 +
 +void WMesaCreateStereoBuffer()
 +{
 +	/* Must use double buffer and not in parallelMode */
 +	if (! Current->db_flag
 +#if !defined(NO_PARALLEL)
 +		|| parallelFlag
 +#endif
 +		)
 +		return;
 +
 +	Buffer_Stereo = malloc( Current->ScanWidth * Current->height);
 +	ZeroMemory(Buffer_Stereo,Current->ScanWidth * Current->height);
 +	stereoBuffer = GL_TRUE ;
 +}
 +
 +void WMesaDestroyStereoBuffer()
 +{
 +	/* Must use double buffer and not in parallelMode */
 +	if (! Current->db_flag
 +#if !defined(NO_PARALLEL)
 +		|| parallelFlag
 +#endif
 +		)
 +		return;
 +	if(stereoBuffer){
 +		free(Buffer_Stereo);
 +		stereoBuffer = GL_FALSE ;
 +	}
 +}
 +
 +void WMesaInterleave(GLenum aView)
 +{
 +	int offset;
 +	unsigned line;
 +	LPBYTE dest;
 +	LPBYTE src;
 +	if(aView == FIRST)
 +		offset = 0;
 +	else offset = 1;
 +
 +	dest = Buffer_Stereo + offset * Current->ScanWidth;
 +	if(Current->rgb_flag )
 +		src = Current->pbPixels + Current->ScanWidth*(Current->height/2);
 +	else
 +		src = Current->ScreenMem;
 +
 +	for(line = 0; line<Current->height/2; line ++){
 +		CopyMemory(dest, src, Current->ScanWidth);
 +		dest += 2*Current->ScanWidth;
 +		src += Current->ScanWidth;
 +	}
 +	if(aView == SECOND)
 +		if(Current->rgb_flag)
 +			CopyMemory(Current->pbPixels, Buffer_Stereo, Current->ScanWidth*Current->height);
 +		else
 +			CopyMemory(Current->ScreenMem, Buffer_Stereo, Current->ScanWidth*Current->height);
 +}
 +
 +void WMesaShowStereo(GLuint list)
 +{
 +
 +	GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
 +	GLfloat cm[16];
 +	// Must use double Buffer
 +	if( ! Current-> db_flag )
 +		return;
 +
 +	glViewport(0,0,Current->width,Current->height/2);
 +
 +	glGetFloatv(GL_MODELVIEW_MATRIX,cm);
 +	glMatrixMode(GL_MODELVIEW);
 +	glLoadIdentity();
 +	gluLookAt(viewDistance/2,0.0,0.0 ,
 +			 viewDistance/2,0.0,-1.0,
 +			 0.0,1.0,0.0 );
 +	glMultMatrixf( cm );
 +	glMatrixMode(GL_MODELVIEW);
 +	glPushMatrix();
 +	glCallList( list );
 +	glPopMatrix();
 +	glFlush();
 +	WMesaInterleave( FIRST );
 +
 +	glGetFloatv(GL_MODELVIEW_MATRIX,cm);
 +	glMatrixMode(GL_MODELVIEW);
 +	glLoadIdentity();
 +	gluLookAt(-viewDistance/2,0.0,0.0 ,
 +			 -viewDistance/2,0.0,-1.0,
 +			 0.0,1.0,0.0 );
 +	glMultMatrixf(cm);
 +	glMatrixMode(GL_MODELVIEW);
 +	glCallList(list);
 +	glFlush();
 +	WMesaInterleave( SECOND );
 +	glViewport(0,0,Current->width,Current->height);
 +	WMesaSwapBuffers();
 +
 +}
 +
 +void toggleStereoMode()
 +{
 +	if(!Current->db_flag)
 +		return;
 +	if(!stereo_flag){
 +		stereo_flag = 1;
 +		if(stereoBuffer==GL_FALSE)
 +#if !defined(NO_PARALLEL)
 +			if(!parallelFlag)
 +#endif
 +		{
 +			WMesaCreateStereoBuffer();
 +			}
 +	}
 +	else {
 +		stereo_flag = 0;
 +	if(stereoBuffer==GL_TRUE)
 +#if !defined(NO_PARALLEL)
 +		if(!parallelFlag)
 +#endif
 +			if(stereoBuffer==GL_TRUE){
 +				WMesaDestroyStereoBuffer();
 +			}
 +	}
 +}
 +
 +/* if in stereo mode, the following function is called */
 +void glShowStereo(GLuint list)
 +{
 +	WMesaShowStereo(list);
 +}
 +
 +#endif // End if NO_STEREO not defined
 +
 +#if !defined(NO_PARALLEL)
 +
 +void toggleParallelMode(void)
 +{
 +	if(!parallelFlag){
 +		parallelFlag = GL_TRUE;
 +		if(parallelMachine==GL_FALSE){
 +				PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX,
 +									  Current->cColorBits/8,
 +									  Current->width ,Current->height,
 +									  Current->ScanWidth,
 +									  Current->rgb_flag? Current->pbPixels: Current->ScreenMem);
 +				parallelMachine = GL_TRUE;
 +				}
 +		}
 +	else {
 +		parallelFlag = GL_FALSE;
 +		if(parallelMachine==GL_TRUE){
 +				PRDestroyRenderBuffer();
 +				parallelMachine=GL_FALSE;
 +				ReadyForNextFrame = GL_TRUE;
 +				}
 +
 +/***********************************************
 +// Seems something wrong!!!!
 +************************************************/
 +
 +		WMesaMakeCurrent(Current);
 +#if !defined(NO_STEREO)
 +		stereo_flag = GL_FALSE ;
 +#endif
 +	}
 +}
 +
 +void PRShowRenderResult(void)
 +{
 +	int flag = 0;
 +if(!glImageRendered())
 +		return;
 +
 +  if (parallelFlag)
 +	{
 +	  WMesaSwapBuffers();
 +	 }
 +
 +}
 +#endif //End if NO_PARALLEL not defined
 +
 +//end modification
 diff --git a/src/mesa/drivers/windows/wmesadef.h b/src/mesa/drivers/windows/wmesadef.h new file mode 100644 index 0000000000..7cd4bb9a7d --- /dev/null +++ b/src/mesa/drivers/windows/wmesadef.h @@ -0,0 +1,154 @@ +/*	File name	:	wmesadef.h
 + *  Version		:	2.3
 + *
 + *  Header file for display driver for Mesa 2.3  under
 + *	Windows95, WindowsNT and Win32
 + *
 + *	Copyright (C) 1996-  Li Wei
 + *  Address		:		Institute of Artificial Intelligence
 + *				:			& Robotics
 + *				:		Xi'an Jiaotong University
 + *  Email		:		liwei@aiar.xjtu.edu.cn
 + *  Web page	:		http://sun.aiar.xjtu.edu.cn
 + *
 + *  This file and its associations are partially based on the
 + *  Windows NT driver for Mesa, written by Mark Leaming
 + *  (mark@rsinc.com).
 + */
 +
 +/*
 + * $Log: wmesadef.h,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.3  1999/01/03 03:08:57  brianp + * Ted Jump's changes + *
 + * Initial version 1997/6/14 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
 + */
 +
 +/*
 + * $Log: wmesadef.h,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.3  1999/01/03 03:08:57  brianp + * Ted Jump's changes + *
 + * Revision 2.1  1996/11/15 10:54:00  CST by Li Wei(liwei@aiar.xjtu.edu.cn)
 + * a new element added to wmesa_context :
 + * dither_flag
 + */
 +
 +/*
 + * $Log: wmesadef.h,v $ + * Revision 1.1  1999/08/19 00:55:42  jtg + * Initial revision + * + * Revision 1.3  1999/01/03 03:08:57  brianp + * Ted Jump's changes + *
 + * Revision 2.0  1996/11/15 10:54:00  CST by Li Wei(liwei@aiar.xjtu.edu.cn)
 + * Initial revision
 + */
 +
 +
 +
 +#ifndef DDMESADEF_H
 +#define DDMESADEF_H
 +
 +#include <windows.h>
 +#include <GL\gl.h>
 +#include "context.h"
 +#ifdef DDRAW
 +	#include <ddraw.h>
 +#endif
 +//#include "profile.h"
 +
 +#define REDBITS		0x03
 +#define REDSHIFT	0x00
 +#define GREENBITS	0x03
 +#define GREENSHIFT	0x03
 +#define BLUEBITS	0x02
 +#define BLUESHIFT	0x06
 +
 +typedef struct _dibSection{
 +	HDC		hDC;
 +	HANDLE	hFileMap;
 +	BOOL	fFlushed;
 +	LPVOID	base;
 +}WMDIBSECTION, *PWMDIBSECTION;
 +
 +
 +typedef struct wmesa_context{
 +    GLcontext *gl_ctx;		/* The core GL/Mesa context */
 +	GLvisual *gl_visual;		/* Describes the buffers */
 +    GLframebuffer *gl_buffer;	/* Depth, stencil, accum, etc buffers */
 +
 +
 +	HWND				Window;
 +    HDC                 hDC;
 +    HPALETTE            hPalette;
 +    HPALETTE            hOldPalette;
 +    HPEN                hPen;
 +    HPEN                hOldPen;
 +    HCURSOR             hOldCursor;
 +    COLORREF            crColor;
 +    // 3D projection stuff
 +    RECT                drawRect;
 +    UINT                uiDIBoffset;
 +    // OpenGL stuff
 +    HPALETTE            hGLPalette;
 +	GLuint				width;
 +	GLuint				height;
 +	GLuint				ScanWidth;
 +	GLboolean			db_flag;	//* double buffered?
 +	GLboolean			rgb_flag;	//* RGB mode?
 +	GLboolean			dither_flag;	//* use dither when 256 color mode for RGB?
 +	GLuint				depth;		//* bits per pixel (1, 8, 24, etc)
 +	ULONG				pixel;	// current color index or RGBA pixel value
 +	ULONG				clearpixel; //* pixel for clearing the color buffers
 +	PBYTE				ScreenMem; // WinG memory
 +	BITMAPINFO			*IndexFormat;
 +	HPALETTE			hPal; // Current Palette
 +	HPALETTE			hPalHalfTone;
 +
 +
 +	WMDIBSECTION		dib;
 +    BITMAPINFO          bmi;
 +    HBITMAP             hbmDIB;
 +    HBITMAP             hOldBitmap;
 +	HBITMAP				Old_Compat_BM;
 +	HBITMAP				Compat_BM;            // Bitmap for double buffering
 +    PBYTE               pbPixels;
 +    int                 nColors;
 +	BYTE				cColorBits;
 +	int					pixelformat;
 +
 +#ifdef DDRAW
 +	LPDIRECTDRAW            lpDD;           // DirectDraw object
 +//	LPDIRECTDRAW2            lpDD2;           // DirectDraw object
 +	LPDIRECTDRAWSURFACE     lpDDSPrimary;   // DirectDraw primary surface
 +	LPDIRECTDRAWSURFACE     lpDDSOffScreen;	// DirectDraw off screen surface
 +	LPDIRECTDRAWPALETTE     lpDDPal;        // DirectDraw palette
 +	BOOL                    bActive;        // is application active?
 +	DDSURFACEDESC	        ddsd;
 +	int 					fullScreen;
 +	int			            gMode ;
 +#endif
 +	RECT					rectOffScreen;
 +	RECT					rectSurface;
 +	HWND					hwnd;
 +	DWORD					pitch;
 +	PBYTE					addrOffScreen;
 +//#ifdef PROFILE
 +//	MESAPROF	profile;
 +//#endif
 +}  *PWMC;
 +
 +
 +#define PAGE_FILE		0xffffffff
 +
 +
 +
 +#endif
 diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c new file mode 100644 index 0000000000..12567fe19c --- /dev/null +++ b/src/mesa/drivers/x11/fakeglx.c @@ -0,0 +1,1516 @@ +/* $Id: fakeglx.c,v 1.1 1999/08/19 00:55:42 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 pseudo-GLX implementation to allow OpenGL/GLX programs to work with Mesa. + * The Fake_glX*() functions implemented here are called from glxapi.c + * + * Thanks to the contributors: + * + * Initial version:  Philip Brown (philb@CSUA.Berkeley.EDU) + * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu) + * Further visual-handling refinements: Wolfram Gloger + *    (wmglo@Dent.MED.Uni-Muenchen.DE). + * + * Notes: + *   Don't be fooled, stereo isn't supported yet. + */ + + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "GL/gl.h" +#include "GL/xmesa.h" +#include "context.h" +#include "config.h" +#include "fakeglx.h" +#include "macros.h" +#include "types.h" +#include "xmesaP.h" + + + +#define DONT_CARE -1 + + + +#define MAX_VISUALS 100 +static XMesaVisual VisualTable[MAX_VISUALS]; +static int NumVisuals = 0; + + + +/* + * This struct and some code fragments borrowed + * from Mark Kilgard's GLUT library. + */ +typedef struct _OverlayInfo { +  /* Avoid 64-bit portability problems by being careful to use +     longs due to the way XGetWindowProperty is specified. Note +     that these parameters are passed as CARD32s over X +     protocol. */ +  unsigned long overlay_visual; +  long transparent_type; +  long value; +  long layer; +} OverlayInfo; + + + +/* Macro to handle c_class vs class field name in XVisualInfo struct */ +#if defined(__cplusplus) || defined(c_plusplus) +#define CLASS c_class +#else +#define CLASS class +#endif + + + + +/* + * Test if the given XVisualInfo is usable for Mesa rendering. + */ +static GLboolean is_usable_visual( XVisualInfo *vinfo ) +{ +   switch (vinfo->CLASS) { +      case StaticGray: +      case GrayScale: +         /* Any StaticGray/GrayScale visual works in RGB or CI mode */ +         return GL_TRUE; +      case StaticColor: +      case PseudoColor: +	 /* Any StaticColor/PseudoColor visual of at least 4 bits */ +	 if (vinfo->depth>=4) { +	    return GL_TRUE; +	 } +	 else { +	    return GL_FALSE; +	 } +      case TrueColor: +      case DirectColor: +	 /* Any depth of TrueColor or DirectColor works in RGB mode */ +	 return GL_TRUE; +      default: +	 /* This should never happen */ +	 return GL_FALSE; +   } +} + + + +/* + * Return the level (overlay, normal, underlay) of a given XVisualInfo. + * Input:  dpy - the X display + *         vinfo - the XVisualInfo to test + * Return:  level of the visual: + *             0 = normal planes + *            >0 = overlay planes + *            <0 = underlay planes + */ +static int level_of_visual( Display *dpy, XVisualInfo *vinfo ) +{ +   Atom overlayVisualsAtom; +   OverlayInfo *overlay_info = NULL; +   int numOverlaysPerScreen; +   Status status; +   Atom actualType; +   int actualFormat; +   unsigned long sizeData, bytesLeft; +   int i; + +   /* +    * The SERVER_OVERLAY_VISUALS property on the root window contains +    * a list of overlay visuals.  Get that list now. +    */ +   overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True); +   if (overlayVisualsAtom == None) { +      return 0; +   } + +   status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ), +                               overlayVisualsAtom, 0L, (long) 10000, False, +                               overlayVisualsAtom, &actualType, &actualFormat, +                               &sizeData, &bytesLeft, +                               (unsigned char **) &overlay_info ); + +   if (status != Success || actualType != overlayVisualsAtom || +       actualFormat != 32 || sizeData < 4) { +      /* something went wrong */ +      XFree((void *) overlay_info); +      return 0; +   } + +   /* search the overlay visual list for the visual ID of interest */ +   numOverlaysPerScreen = (int) (sizeData / 4); +   for (i=0;i<numOverlaysPerScreen;i++) { +      OverlayInfo *ov; +      ov = overlay_info + i; +      if (ov->overlay_visual==vinfo->visualid) { +         /* found the visual */ +         if (/*ov->transparent_type==1 &&*/ ov->layer!=0) { +            int level = ov->layer; +            XFree((void *) overlay_info); +            return level; +         } +         else { +            XFree((void *) overlay_info); +            return 0; +         } +      } +   } + +   /* The visual ID was not found in the overlay list. */ +   XFree((void *) overlay_info); +   return 0; +} + + + + +/* + * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the + * configuration in our list of GLX visuals. + */ +static XMesaVisual +save_glx_visual( Display *dpy, XVisualInfo *vinfo, +                 GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag, +                 GLboolean stereoFlag, +                 GLint depth_size, GLint stencil_size, +                 GLint accum_size, GLint level ) +{ +   GLboolean ximageFlag = GL_TRUE; +   XMesaVisual xmvis; +   GLint i; +   GLboolean comparePointers; + +   if (dbFlag) { +      /* Check if the MESA_BACK_BUFFER env var is set */ +      char *backbuffer = getenv("MESA_BACK_BUFFER"); +      if (backbuffer) { +         if (backbuffer[0]=='p' || backbuffer[0]=='P') { +            ximageFlag = GL_FALSE; +         } +         else if (backbuffer[0]=='x' || backbuffer[0]=='X') { +            ximageFlag = GL_TRUE; +         } +         else { +            fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER "); +            fprintf(stderr, "environment variable, using an XImage.\n"); +         } +      } +   } + +   /* Comparing IDs uses less memory but sometimes fails. */ +   /* XXX revisit this after 3.0 is finished. */ +   if (getenv("MESA_GLX_VISUAL_HACK")) +      comparePointers = GL_TRUE; +   else +      comparePointers = GL_FALSE; + +   /* First check if a matching visual is already in the list */ +   for (i=0; i<NumVisuals; i++) { +      XMesaVisual v = VisualTable[i]; +      if (v->display == dpy +          && v->level == level +          && v->ximage_flag == ximageFlag +          && v->gl_visual->RGBAflag == rgbFlag +          && v->gl_visual->DBflag == dbFlag +          && v->gl_visual->StereoFlag == stereoFlag +          && (v->gl_visual->AlphaBits > 0) == alphaFlag +          && (v->gl_visual->DepthBits >= depth_size || depth_size == 0) +          && (v->gl_visual->StencilBits >= stencil_size || stencil_size == 0) +          && (v->gl_visual->AccumBits >= accum_size || accum_size == 0)) { +         /* now either compare XVisualInfo pointers or visual IDs */ +         if ((!comparePointers && v->vishandle->visualid == vinfo->visualid) +             || (comparePointers && v->vishandle == vinfo)) { +            return v; +         } +      } +   } + +   /* Create a new visual and add it to the list. */ + +   if (NumVisuals>=MAX_VISUALS) { +      fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n"); +      return NULL; +   } + +   xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag, +                              stereoFlag, ximageFlag, +                              depth_size, stencil_size, accum_size, level ); +   if (xmvis) { +      VisualTable[NumVisuals] = xmvis; +      NumVisuals++; +   } +   return xmvis; +} + + + +/* + * Create a GLX visual from a regular XVisualInfo. + */ +static XMesaVisual +create_glx_visual( Display *dpy, XVisualInfo *visinfo ) +{ +   int vislevel; + +   vislevel = level_of_visual( dpy, visinfo ); +   if (vislevel) { +      /* Configure this visual as a CI, single-buffered overlay */ +      return save_glx_visual( dpy, visinfo, +                              GL_FALSE,  /* rgb */ +                              GL_FALSE,  /* alpha */ +                              GL_FALSE,  /* double */ +                              GL_FALSE,  /* stereo */ +                              0,         /* depth bits */ +                              0,         /* stencil bits */ +                              0,         /* accum bits */ +                              vislevel   /* level */ +                            ); +   } +   else if (is_usable_visual( visinfo )) { +      /* Configure this visual as RGB, double-buffered, depth-buffered. */ +      /* This is surely wrong for some people's needs but what else */ +      /* can be done?  They should use glXChooseVisual(). */ +      return save_glx_visual( dpy, visinfo, +                              GL_TRUE,   /* rgb */ +                              GL_FALSE,  /* alpha */ +                              GL_TRUE,   /* double */ +                              GL_FALSE,  /* stereo */ +                              8*sizeof(GLdepth), +                              8*sizeof(GLstencil), +                              8*sizeof(GLaccum), +                              0          /* level */ +                            ); +   } +   else { +      fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n"); +      return NULL; +   } +} + + + +/* + * Find the GLX visual associated with an XVisualInfo. + */ +static XMesaVisual +find_glx_visual( Display *dpy, XVisualInfo *vinfo ) +{ +   int i; + +   /* First try to match pointers */ +   for (i=0;i<NumVisuals;i++) { +      if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) { +         return VisualTable[i]; +      } +   } +   /* try to match visual id */ +   for (i=0;i<NumVisuals;i++) { +      if (VisualTable[i]->display==dpy +          && VisualTable[i]->visinfo->visualid == vinfo->visualid) { +         return VisualTable[i]; +      } +   } +   return NULL; +} + + + +/* + * Return the transparent pixel value for a GLX visual. + * Input:  glxvis - the glx_visual + * Return:  a pixel value or -1 if no transparent pixel + */ +static int transparent_pixel( XMesaVisual glxvis ) +{ +   Display *dpy = glxvis->display; +   XVisualInfo *vinfo = glxvis->visinfo; +   Atom overlayVisualsAtom; +   OverlayInfo *overlay_info = NULL; +   int numOverlaysPerScreen; +   Status status; +   Atom actualType; +   int actualFormat; +   unsigned long sizeData, bytesLeft; +   int i; + +   /* +    * The SERVER_OVERLAY_VISUALS property on the root window contains +    * a list of overlay visuals.  Get that list now. +    */ +   overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True); +   if (overlayVisualsAtom == None) { +      return -1; +   } + +   status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ), +                               overlayVisualsAtom, 0L, (long) 10000, False, +                               overlayVisualsAtom, &actualType, &actualFormat, +                               &sizeData, &bytesLeft, +                               (unsigned char **) &overlay_info ); + +   if (status != Success || actualType != overlayVisualsAtom || +       actualFormat != 32 || sizeData < 4) { +      /* something went wrong */ +      XFree((void *) overlay_info); +      return -1; +   } + +   /* search the overlay visual list for the visual ID of interest */ +   numOverlaysPerScreen = (int) (sizeData / 4); +   for (i=0;i<numOverlaysPerScreen;i++) { +      OverlayInfo *ov; +      ov = overlay_info + i; +      if (ov->overlay_visual==vinfo->visualid) { +         /* found it! */ +         if (ov->transparent_type==0) { +            /* type 0 indicates no transparency */ +            XFree((void *) overlay_info); +            return -1; +         } +         else { +            /* ov->value is the transparent pixel */ +            XFree((void *) overlay_info); +            return ov->value; +         } +      } +   } + +   /* The visual ID was not found in the overlay list. */ +   XFree((void *) overlay_info); +   return -1; +} + + + +/* + * Return number of bits set in n. + */ +static int bitcount( unsigned long n ) +{ +   int bits; +   for (bits=0; n>0; n=n>>1) { +      if (n&1) { +         bits++; +      } +   } +   return bits; +} + + +/* + * Try to get an X visual which matches the given arguments. + */ +static XVisualInfo *get_visual( Display *dpy, int scr, +			        unsigned int depth, int xclass ) +{ +   XVisualInfo temp, *vis; +   long mask; +   int n; +   unsigned int default_depth; +   int default_class; + +   mask = VisualScreenMask | VisualDepthMask | VisualClassMask; +   temp.screen = scr; +   temp.depth = depth; +   temp.CLASS = xclass; + +   default_depth = DefaultDepth(dpy,scr); +   default_class = DefaultVisual(dpy,scr)->CLASS; + +   if (depth==default_depth && xclass==default_class) { +      /* try to get root window's visual */ +      temp.visualid = DefaultVisual(dpy,scr)->visualid; +      mask |= VisualIDMask; +   } + +   vis = XGetVisualInfo( dpy, mask, &temp, &n ); + +   /* In case bits/pixel > 24, make sure color channels are still <=8 bits. +    * An SGI Infinite Reality system, for example, can have 30bpp pixels: +    * 10 bits per color channel.  Mesa's limited to a max of 8 bits/channel. +    */ +   if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) { +      if (bitcount(vis->red_mask) <= 8 +          && bitcount(vis->green_mask) <= 8 +          && bitcount(vis->blue_mask) <= 8) { +         return vis; +      } +      else { +         XFree((void *) vis); +         return NULL; +      } +   } + +   return vis; +} + + + +/* + * Retrieve the value of the given environment variable and find + * the X visual which matches it. + * Input:  dpy - the display + *         screen - the screen number + *         varname - the name of the environment variable + * Return:  an XVisualInfo pointer to NULL if error. + */ +static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname) +{ +   char value[100], type[100]; +   int depth, xclass = -1; +   XVisualInfo *vis; + +   if (!getenv( varname )) { +      return NULL; +   } + +   strncpy( value, getenv(varname), 100 ); +   value[99] = 0; + +   sscanf( value, "%s %d", type, &depth ); + +   if (strcmp(type,"TrueColor")==0)          xclass = TrueColor; +   else if (strcmp(type,"DirectColor")==0)   xclass = DirectColor; +   else if (strcmp(type,"PseudoColor")==0)   xclass = PseudoColor; +   else if (strcmp(type,"StaticColor")==0)   xclass = StaticColor; +   else if (strcmp(type,"GrayScale")==0)     xclass = GrayScale; +   else if (strcmp(type,"StaticGray")==0)    xclass = StaticGray; + +   if (xclass>-1 && depth>0) { +      vis = get_visual( dpy, scr, depth, xclass ); +      if (vis) { +	 return vis; +      } +   } + +   fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n", +	    type, depth ); +   return NULL; +} + + + +/* + * Select an X visual which satisfies the RGBA/CI flag and minimum depth. + * Input:  dpy, screen - X display and screen number + *         rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode + *         min_depth - minimum visual depth + *         preferred_class - preferred GLX visual class or DONT_CARE + * Return:  pointer to an XVisualInfo or NULL. + */ +static XVisualInfo *choose_x_visual( Display *dpy, int screen, +				     GLboolean rgba, int min_depth, +                                     int preferred_class ) +{ +   XVisualInfo *vis; +   int xclass, visclass; +   int depth; + +   if (rgba) { +      Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True); +      /* First see if the MESA_RGB_VISUAL env var is defined */ +      vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" ); +      if (vis) { +	 return vis; +      } +      /* Otherwise, search for a suitable visual */ +      if (preferred_class==DONT_CARE) { +         for (xclass=0;xclass<6;xclass++) { +            switch (xclass) { +               case 0:  visclass = TrueColor;    break; +               case 1:  visclass = DirectColor;  break; +               case 2:  visclass = PseudoColor;  break; +               case 3:  visclass = StaticColor;  break; +               case 4:  visclass = GrayScale;    break; +               case 5:  visclass = StaticGray;   break; +            } +            if (min_depth==0) { +               /* start with shallowest */ +               for (depth=0;depth<=32;depth++) { +                  if (visclass==TrueColor && depth==8 && !hp_cr_maps) { +                     /* Special case:  try to get 8-bit PseudoColor before */ +                     /* 8-bit TrueColor */ +                     vis = get_visual( dpy, screen, 8, PseudoColor ); +                     if (vis) { +                        return vis; +                     } +                  } +                  vis = get_visual( dpy, screen, depth, visclass ); +                  if (vis) { +                     return vis; +                  } +               } +            } +            else { +               /* start with deepest */ +               for (depth=32;depth>=min_depth;depth--) { +                  if (visclass==TrueColor && depth==8 && !hp_cr_maps) { +                     /* Special case:  try to get 8-bit PseudoColor before */ +                     /* 8-bit TrueColor */ +                     vis = get_visual( dpy, screen, 8, PseudoColor ); +                     if (vis) { +                        return vis; +                     } +                  } +                  vis = get_visual( dpy, screen, depth, visclass ); +                  if (vis) { +                     return vis; +                  } +               } +            } +         } +      } +      else { +         /* search for a specific visual class */ +         switch (preferred_class) { +            case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break; +            case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break; +            case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break; +            case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break; +            case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break; +            case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break; +            default:   return NULL; +         } +         if (min_depth==0) { +            /* start with shallowest */ +            for (depth=0;depth<=32;depth++) { +               vis = get_visual( dpy, screen, depth, visclass ); +               if (vis) { +                  return vis; +               } +            } +         } +         else { +            /* start with deepest */ +            for (depth=32;depth>=min_depth;depth--) { +               vis = get_visual( dpy, screen, depth, visclass ); +               if (vis) { +                  return vis; +               } +            } +         } +      } +   } +   else { +      /* First see if the MESA_CI_VISUAL env var is defined */ +      vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" ); +      if (vis) { +	 return vis; +      } +      /* Otherwise, search for a suitable visual, starting with shallowest */ +      if (preferred_class==DONT_CARE) { +         for (xclass=0;xclass<4;xclass++) { +            switch (xclass) { +               case 0:  visclass = PseudoColor;  break; +               case 1:  visclass = StaticColor;  break; +               case 2:  visclass = GrayScale;    break; +               case 3:  visclass = StaticGray;   break; +            } +            /* try 8-bit up through 16-bit */ +            for (depth=8;depth<=16;depth++) { +               vis = get_visual( dpy, screen, depth, visclass ); +               if (vis) { +                  return vis; +               } +            } +            /* try min_depth up to 8-bit */ +            for (depth=min_depth;depth<8;depth++) { +               vis = get_visual( dpy, screen, depth, visclass ); +               if (vis) { +                  return vis; +               } +            } +         } +      } +      else { +         /* search for a specific visual class */ +         switch (preferred_class) { +            case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break; +            case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break; +            case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break; +            case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break; +            case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break; +            case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break; +            default:   return NULL; +         } +         /* try 8-bit up through 16-bit */ +         for (depth=8;depth<=16;depth++) { +            vis = get_visual( dpy, screen, depth, visclass ); +            if (vis) { +               return vis; +            } +         } +         /* try min_depth up to 8-bit */ +         for (depth=min_depth;depth<8;depth++) { +            vis = get_visual( dpy, screen, depth, visclass ); +            if (vis) { +               return vis; +            } +         } +      } +   } + +   /* didn't find a visual */ +   return NULL; +} + + + +/* + * Find the deepest X over/underlay visual of at least min_depth. + * Input:  dpy, screen - X display and screen number + *         level - the over/underlay level + *         trans_type - transparent pixel type: GLX_NONE_EXT, + *                      GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT, + *                      or DONT_CARE + *         trans_value - transparent pixel value or DONT_CARE + *         min_depth - minimum visual depth + *         preferred_class - preferred GLX visual class or DONT_CARE + * Return:  pointer to an XVisualInfo or NULL. + */ +static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr, +                                             int level, int trans_type, +                                             int trans_value, +                                             int min_depth, +                                             int preferred_class ) +{ +   Atom overlayVisualsAtom; +   OverlayInfo *overlay_info; +   int numOverlaysPerScreen; +   Status status; +   Atom actualType; +   int actualFormat; +   unsigned long sizeData, bytesLeft; +   int i; +   XVisualInfo *deepvis; +   int deepest; + +   /*DEBUG int tt, tv; */ + +   switch (preferred_class) { +      case GLX_TRUE_COLOR_EXT:    preferred_class = TrueColor;    break; +      case GLX_DIRECT_COLOR_EXT:  preferred_class = DirectColor;  break; +      case GLX_PSEUDO_COLOR_EXT:  preferred_class = PseudoColor;  break; +      case GLX_STATIC_COLOR_EXT:  preferred_class = StaticColor;  break; +      case GLX_GRAY_SCALE_EXT:    preferred_class = GrayScale;    break; +      case GLX_STATIC_GRAY_EXT:   preferred_class = StaticGray;   break; +      default:                    preferred_class = DONT_CARE; +   } + +   /* +    * The SERVER_OVERLAY_VISUALS property on the root window contains +    * a list of overlay visuals.  Get that list now. +    */ +   overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True); +   if (overlayVisualsAtom == (Atom) None) { +      return NULL; +   } + +   status = XGetWindowProperty(dpy, RootWindow( dpy, scr ), +                               overlayVisualsAtom, 0L, (long) 10000, False, +                               overlayVisualsAtom, &actualType, &actualFormat, +                               &sizeData, &bytesLeft, +                               (unsigned char **) &overlay_info ); + +   if (status != Success || actualType != overlayVisualsAtom || +       actualFormat != 32 || sizeData < 4) { +      /* something went wrong */ +      return NULL; +   } + +   /* Search for the deepest overlay which satisifies all criteria. */ +   deepest = min_depth; +   deepvis = NULL; + +   numOverlaysPerScreen = (int) (sizeData / 4); +   for (i=0;i<numOverlaysPerScreen;i++) { +      XVisualInfo *vislist, vistemplate; +      int count; +      OverlayInfo *ov; +      ov = overlay_info + i; + +      if (ov->layer!=level) { +         /* failed overlay level criteria */ +         continue; +      } +      if (!(trans_type==DONT_CARE +            || (trans_type==GLX_TRANSPARENT_INDEX_EXT +                && ov->transparent_type>0) +            || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) { +         /* failed transparent pixel type criteria */ +         continue; +      } +      if (trans_value!=DONT_CARE && trans_value!=ov->value) { +         /* failed transparent pixel value criteria */ +         continue; +      } + +      /* get XVisualInfo and check the depth */ +      vistemplate.visualid = ov->overlay_visual; +      vistemplate.screen = scr; +      vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask, +                                &vistemplate, &count ); + +      if (count!=1) { +         /* something went wrong */ +         continue; +      } +      if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) { +         /* wrong visual class */ +         continue; +      } + +      if (deepvis==NULL || vislist->depth > deepest) { +         /* YES!  found a satisfactory visual */ +         if (deepvis) { +            free( deepvis ); +         } +         deepest = vislist->depth; +         deepvis = vislist; +         /* DEBUG  tt = ov->transparent_type;*/ +         /* DEBUG  tv = ov->value; */ +      } +   } + +/*DEBUG +   if (deepvis) { +      printf("chose 0x%x:  layer=%d depth=%d trans_type=%d trans_value=%d\n", +             deepvis->visualid, level, deepvis->depth, tt, tv ); +   } +*/ +   return deepvis; +} + + + +XVisualInfo *Fake_glXChooseVisual( Display *dpy, int screen, int *list ) +{ +   int *parselist; +   XVisualInfo *vis; +   int min_ci = 0; +   int min_red=0, min_green=0, min_blue=0; +   GLboolean rgb_flag = GL_FALSE; +   GLboolean alpha_flag = GL_FALSE; +   GLboolean double_flag = GL_FALSE; +   GLboolean stereo_flag = GL_FALSE; +   GLint depth_size = 0; +   GLint stencil_size = 0; +   GLint accum_size = 0; +   int level = 0; +   int visual_type = DONT_CARE; +   int trans_type = DONT_CARE; +   int trans_value = DONT_CARE; + +   parselist = list; + +   while (*parselist) { + +      switch (*parselist) { +	 case GLX_USE_GL: +	    /* ignore */ +	    parselist++; +	    break; +	 case GLX_BUFFER_SIZE: +	    parselist++; +	    min_ci = *parselist++; +	    break; +	 case GLX_LEVEL: +	    parselist++; +            level = *parselist++; +	    break; +	 case GLX_RGBA: +	    rgb_flag = GL_TRUE; +	    parselist++; +	    break; +	 case GLX_DOUBLEBUFFER: +	    double_flag = GL_TRUE; +	    parselist++; +	    break; +	 case GLX_STEREO: +            stereo_flag = GL_TRUE; +            return NULL; +	 case GLX_AUX_BUFFERS: +	    /* ignore */ +	    parselist++; +	    parselist++; +	    break; +	 case GLX_RED_SIZE: +	    parselist++; +	    min_red = *parselist++; +	    break; +	 case GLX_GREEN_SIZE: +	    parselist++; +	    min_green = *parselist++; +	    break; +	 case GLX_BLUE_SIZE: +	    parselist++; +	    min_blue = *parselist++; +	    break; +	 case GLX_ALPHA_SIZE: +	    parselist++; +            { +               GLint size = *parselist++; +               alpha_flag = size>0 ? 1 : 0; +            } +	    break; +	 case GLX_DEPTH_SIZE: +	    parselist++; +	    depth_size = *parselist++; +	    break; +	 case GLX_STENCIL_SIZE: +	    parselist++; +	    stencil_size = *parselist++; +	    break; +	 case GLX_ACCUM_RED_SIZE: +	 case GLX_ACCUM_GREEN_SIZE: +	 case GLX_ACCUM_BLUE_SIZE: +	 case GLX_ACCUM_ALPHA_SIZE: +	    parselist++; +            { +               GLint size = *parselist++; +               accum_size = MAX2( accum_size, size ); +            } +	    break; + +         /* +          * GLX_EXT_visual_info extension +          */ +         case GLX_X_VISUAL_TYPE_EXT: +            parselist++; +            visual_type = *parselist++; +            break; +         case GLX_TRANSPARENT_TYPE_EXT: +            parselist++; +            trans_type = *parselist++; +            break; +         case GLX_TRANSPARENT_INDEX_VALUE_EXT: +            parselist++; +            trans_value = *parselist++; +            break; +         case GLX_TRANSPARENT_RED_VALUE_EXT: +         case GLX_TRANSPARENT_GREEN_VALUE_EXT: +         case GLX_TRANSPARENT_BLUE_VALUE_EXT: +         case GLX_TRANSPARENT_ALPHA_VALUE_EXT: +	    /* ignore */ +	    parselist++; +	    parselist++; +	    break; +          +	 case None: +	    break; +	 default: +	    /* undefined attribute */ +	    return NULL; +      } +   } + +   /* +    * Since we're only simulating the GLX extension this function will never +    * find any real GL visuals.  Instead, all we can do is try to find an RGB +    * or CI visual of appropriate depth.  Other requested attributes such as +    * double buffering, depth buffer, etc. will be associated with the X +    * visual and stored in the VisualTable[]. +    */ +   if (level==0) { +      /* normal color planes */ +      if (rgb_flag) { +         /* Get an RGB visual */ +         int min_rgb = min_red + min_green + min_blue; +         if (min_rgb>1 && min_rgb<8) { +            /* a special case to be sure we can get a monochrome visual */ +            min_rgb = 1; +         } +         vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type ); +      } +      else { +         /* Get a color index visual */ +         vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type ); +         accum_size = 0; +      } +   } +   else { +      /* over/underlay planes */ +      vis = choose_x_overlay_visual( dpy, screen, level, trans_type, +                                     trans_value, min_ci, visual_type ); +   } + +   if (vis) { +      if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, +                            stereo_flag, +                            depth_size, stencil_size, accum_size, level )) +         return NULL; +   } + +   return vis; +} + + + + +GLXContext Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, +                                  GLXContext share_list, Bool direct ) +{ +   XMesaVisual glxvis; +   XMesaContext xmctx; + +   /* deallocate unused windows/buffers */ +   XMesaGarbageCollect(); + +   glxvis = find_glx_visual( dpy, visinfo ); +   if (!glxvis) { +      /* This visual wasn't found with glXChooseVisual() */ +      glxvis = create_glx_visual( dpy, visinfo ); +      if (!glxvis) { +         /* unusable visual */ +         return NULL; +      } +   } + +   xmctx = XMesaCreateContext( glxvis, (XMesaContext) share_list ); +   if (xmctx) { +      /* set the direct/indirect flag */ +      xmctx->direct = direct; +   } +   return (GLXContext) xmctx; +} + + +static GLXDrawable MakeCurrent_PrevDrawable = 0; +static GLXContext MakeCurrent_PrevContext = 0; +static XMesaBuffer MakeCurrent_PrevBuffer = 0; + +Bool Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ +   if (ctx && drawable) { +      XMesaBuffer buffer; + +      if (drawable==MakeCurrent_PrevDrawable && ctx==MakeCurrent_PrevContext) { +         buffer = MakeCurrent_PrevBuffer; +      } +      else { +         buffer = XMesaFindBuffer( dpy, drawable ); +      } +      if (!buffer) { +         /* drawable must be a new window! */ +         buffer = XMesaCreateWindowBuffer2( ctx->xm_visual, drawable, ctx ); +         if (!buffer) { +            /* Out of memory, or context/drawable depth mismatch */ +            return False; +         } +      } +      MakeCurrent_PrevContext = ctx; +      MakeCurrent_PrevDrawable = drawable; +      MakeCurrent_PrevBuffer = buffer; + +      /* Now make current! */ +      return (Bool) XMesaMakeCurrent( (XMesaContext) ctx, buffer ); +   } +   else if (!ctx && !drawable) { +      /* release current context w/out assigning new one. */ +      XMesaMakeCurrent( NULL, NULL ); +      MakeCurrent_PrevContext = 0; +      MakeCurrent_PrevDrawable = 0; +      MakeCurrent_PrevBuffer = 0; +      return True; +   } +   else { +      /* ctx XOR drawable is NULL, this is an error */ +      return False; +   } +} + + + +GLXPixmap Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, +                                   Pixmap pixmap ) +{ +   XMesaVisual v; +   XMesaBuffer b; + +   v = find_glx_visual( dpy, visinfo ); +   if (!v) { +      v = create_glx_visual( dpy, visinfo ); +      if (!v) { +         /* unusable visual */ +         return 0; +      } +   } + +   b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); +   if (!b) { +      return 0; +   } +   return b->frontbuffer; +} + + +#ifdef GLX_MESA_pixmap_colormap + +GLXPixmap Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, +                                       Pixmap pixmap, Colormap cmap ) +{ +   XMesaVisual v; +   XMesaBuffer b; + +   v = find_glx_visual( dpy, visinfo ); +   if (!v) { +      v = create_glx_visual( dpy, visinfo ); +      if (!v) { +         /* unusable visual */ +         return 0; +      } +   } + +   b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); +   if (!b) { +      return 0; +   } +   return b->frontbuffer; +} + +#endif + + +void Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +{ +   XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); +   if (b) { +      XMesaDestroyBuffer(b); +   } +   else if (getenv("MESA_DEBUG")) { +      fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); +   } +} + + +void Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, +                          GLuint mask ) +{ +   XMesaContext xm_src = (XMesaContext) src; +   XMesaContext xm_dst = (XMesaContext) dst; +   (void) dpy; +   gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, mask ); +} + + + +Bool Fake_glXQueryExtension( Display *dpy, int *errorb, int *event ) +{ +   /* Mesa's GLX isn't really an X extension but we try to act like one. */ +   (void) dpy; +   (void) errorb; +   (void) event; +   return True; +} + + +void _kw_ungrab_all( Display *dpy ) +{ +   XUngrabPointer( dpy, CurrentTime ); +   XUngrabKeyboard( dpy, CurrentTime ); +} + + +void Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) +{ +   (void) dpy; +   MakeCurrent_PrevContext = 0; +   MakeCurrent_PrevDrawable = 0; +   MakeCurrent_PrevBuffer = 0; +   XMesaDestroyContext( (XMesaContext) ctx ); +   XMesaGarbageCollect(); +} + + + +Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx ) +{ +   (void) dpy; +   return ((XMesaContext) ctx)->direct; +} + + + +void Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ +   XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); +   static GLXDrawable last = 0; +   static Window window = 0; +   if (drawable != last && 0) { +      XSetWindowAttributes cwa; + +      _kw_ungrab_all( dpy ); +      cwa.override_redirect = 0; +      XChangeWindowAttributes( dpy, drawable, CWOverrideRedirect, +			       &cwa ); +/*       printf("KW: Ungrab display %s\n", DisplayString(dpy)); */ + + +/*       last = drawable; */ + + +      if (!window) { +	 XSetWindowAttributes cwa; + +	 if ((window = XCreateSimpleWindow( dpy,  +					    RootWindow( dpy, 0 ), +					    10,10,100,100, 0,  +					    WhitePixel( dpy, 0 ), +					    BlackPixel( dpy, 0 ))) == 0) +	 { +	    printf("Failed to open radar window\n"); +	    abort(); +	 } +    +	 cwa.event_mask = (PointerMotionMask | +			   ButtonPressMask | +			   ButtonReleaseMask | +			   KeyPressMask | +			   KeyReleaseMask | +			   ExposureMask ); + +	 XChangeWindowAttributes( dpy, window,  +				  CWEventMask, +				  &cwa ); + +	 XMapWindow( dpy, window ); +	 XFlush( dpy ); +      } +   } +   if (buffer) { +      XMesaSwapBuffers(buffer); +   } +   else if (getenv("MESA_DEBUG")) { +      fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n"); +   } +} + + +void Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, +				int x, int y, int width, int height ) +{ +   XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); +   if (buffer) { +      XMesaCopySubBuffer(buffer, x, y, width, height); +   } +   else if (getenv("MESA_DEBUG")) { +      fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n"); +   } +} + + + +Bool Fake_glXQueryVersion( Display *dpy, int *maj, int *min ) +{ +   (void) dpy; +   /* Return GLX version, not Mesa version */ +   *maj = 1; +   *min = 1; +   return True; +} + + + +/* + * Query the GLX attributes of the given XVisualInfo. + */ +int Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, +                       int attrib, int *value ) +{ +   XMesaVisual glxvis; + +   glxvis = find_glx_visual( dpy, visinfo ); +   if (!glxvis) { +      /* this visual wasn't obtained with glXChooseVisual */ +      glxvis = create_glx_visual( dpy, visinfo ); +      if (!glxvis) { +	 /* this visual can't be used for GL rendering */ +	 if (attrib==GLX_USE_GL) { +	    *value = (int) False; +	    return 0; +	 } +	 else { +	    /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/ +	    return GLX_BAD_VISUAL; +	 } +      } +   } + +   switch(attrib) { +      case GLX_USE_GL: +         *value = (int) True; +	 return 0; +      case GLX_BUFFER_SIZE: +	 *value = visinfo->depth; +	 return 0; +      case GLX_LEVEL: +	 *value = glxvis->level; +	 return 0; +      case GLX_RGBA: +	 if (glxvis->gl_visual->RGBAflag) { +	    *value = True; +	 } +	 else { +	    *value = False; +	 } +	 return 0; +      case GLX_DOUBLEBUFFER: +	 *value = (int) glxvis->gl_visual->DBflag; +	 return 0; +      case GLX_STEREO: +	 *value = (int) glxvis->gl_visual->StereoFlag; +	 return 0; +      case GLX_AUX_BUFFERS: +	 *value = (int) False; +	 return 0; +      case GLX_RED_SIZE: +         *value = glxvis->gl_visual->RedBits; +	 return 0; +      case GLX_GREEN_SIZE: +         *value = glxvis->gl_visual->GreenBits; +	 return 0; +      case GLX_BLUE_SIZE: +         *value = glxvis->gl_visual->BlueBits; +	 return 0; +      case GLX_ALPHA_SIZE: +         *value = glxvis->gl_visual->AlphaBits; +	 return 0; +      case GLX_DEPTH_SIZE: +         *value = glxvis->gl_visual->DepthBits; +	 return 0; +      case GLX_STENCIL_SIZE: +	 *value = glxvis->gl_visual->StencilBits; +	 return 0; +      case GLX_ACCUM_RED_SIZE: +      case GLX_ACCUM_GREEN_SIZE: +      case GLX_ACCUM_BLUE_SIZE: +	 *value = glxvis->gl_visual->AccumBits; +	 return 0; +      case GLX_ACCUM_ALPHA_SIZE: +         if (glxvis->gl_visual->AlphaBits > 0) +            *value = glxvis->gl_visual->AccumBits; +         else +            *value = 0; +	 return 0; + +      /* +       * GLX_EXT_visual_info extension +       */ +      case GLX_X_VISUAL_TYPE_EXT: +         switch (glxvis->visinfo->CLASS) { +            case StaticGray:   *value = GLX_STATIC_GRAY_EXT;   return 0; +            case GrayScale:    *value = GLX_GRAY_SCALE_EXT;    return 0; +            case StaticColor:  *value = GLX_STATIC_GRAY_EXT;   return 0; +            case PseudoColor:  *value = GLX_PSEUDO_COLOR_EXT;  return 0; +            case TrueColor:    *value = GLX_TRUE_COLOR_EXT;    return 0; +            case DirectColor:  *value = GLX_DIRECT_COLOR_EXT;  return 0; +         } +         return 0; +      case GLX_TRANSPARENT_TYPE_EXT: +         if (glxvis->level==0) { +            /* normal planes */ +            *value = GLX_NONE_EXT; +         } +         else if (glxvis->level>0) { +            /* overlay */ +            if (glxvis->gl_visual->RGBAflag) { +               *value = GLX_TRANSPARENT_RGB_EXT; +            } +            else { +               *value = GLX_TRANSPARENT_INDEX_EXT; +            } +         } +         else if (glxvis->level<0) { +            /* underlay */ +            *value = GLX_NONE_EXT; +         } +         return 0; +      case GLX_TRANSPARENT_INDEX_VALUE_EXT: +         { +            int pixel = transparent_pixel( glxvis ); +            if (pixel>=0) { +               *value = pixel; +            } +            /* else undefined */ +         } +         return 0; +      case GLX_TRANSPARENT_RED_VALUE_EXT: +         /* undefined */ +         return 0; +      case GLX_TRANSPARENT_GREEN_VALUE_EXT: +         /* undefined */ +         return 0; +      case GLX_TRANSPARENT_BLUE_VALUE_EXT: +         /* undefined */ +         return 0; +      case GLX_TRANSPARENT_ALPHA_VALUE_EXT: +         /* undefined */ +         return 0; + +      /* +       * Extensions +       */ +      default: +	 return GLX_BAD_ATTRIBUTE; +   } +} + + + +GLXContext Fake_glXGetCurrentContext( void ) +{ +   return (GLXContext) XMesaGetCurrentContext(); +} + + + +GLXDrawable Fake_glXGetCurrentDrawable( void ) +{ +   XMesaBuffer b = XMesaGetCurrentBuffer(); +   if (b) { +      return b->frontbuffer; +   } +   else { +      return 0; +   } +} + + +void Fake_glXWaitGL( void ) +{ +   XMesaContext xmesa = XMesaGetCurrentContext(); +   XMesaFlush( xmesa ); +} + + + +void Fake_glXWaitX( void ) +{ +   XMesaContext xmesa = XMesaGetCurrentContext(); +   XMesaFlush( xmesa ); +} + + + +#define EXTENSIONS "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync" + + +/* GLX 1.1 and later */ +const char *Fake_glXQueryExtensionsString( Display *dpy, int screen ) +{ +   static char *extensions = EXTENSIONS; +   (void) dpy; +   (void) screen; +   return extensions; +} + + + +/* GLX 1.1 and later */ +const char *Fake_glXQueryServerString( Display *dpy, int screen, int name ) +{ +   static char *extensions = EXTENSIONS; +   static char *vendor = "Brian Paul"; +   static char *version = "1.1 Mesa 3.0"; + +   (void) dpy; +   (void) screen; + +   switch (name) { +      case GLX_EXTENSIONS: +         return extensions; +      case GLX_VENDOR: +	 return vendor; +      case GLX_VERSION: +	 return version; +      default: +         return NULL; +   } +} + + + +/* GLX 1.1 and later */ +const char *Fake_glXGetClientString( Display *dpy, int name ) +{ +   static char *extensions = EXTENSIONS; +   static char *vendor = "Brian Paul"; +   static char *version = "1.1 Mesa 3.0"; + +   (void) dpy; + +   switch (name) { +      case GLX_EXTENSIONS: +         return extensions; +      case GLX_VENDOR: +	 return vendor; +      case GLX_VERSION: +	 return version; +      default: +         return NULL; +   } +} + + + +/* + * Release the depth, stencil, accum buffers attached to a GLXDrawable + * (a window or pixmap) prior to destroying the GLXDrawable. + */ +Bool Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +{ +   XMesaBuffer b = XMesaFindBuffer(dpy, d); +   if (b) { +      XMesaDestroyBuffer(b); +      return True; +   } +   return False; +} + + +/* Silence compiler warnings */ +void Fake_glXDummyFunc( void ) +{ +   (void) kernel8; +   (void) DitherValues; +   (void) HPCR_DRGB; +   (void) kernel1; +} diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c new file mode 100644 index 0000000000..b65bada72b --- /dev/null +++ b/src/mesa/drivers/x11/glxapi.c @@ -0,0 +1,405 @@ +/* $Id: glxapi.c,v 1.1 1999/08/19 00:55:42 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. + */ + + + + + +/* + * GLX API functions which either call fake or real GLX implementations + * + * To enable real GLX encoding the REALGLX preprocessor symbol should be + * defined on the command line. + */ + + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "GL/glx.h" +#include "fakeglx.h" +#include "realglx.h" + + +#ifdef REALGLX +static Display *CurrentDisplay = NULL; +#endif + + +/* + * This functions determines whether a call to a glX*() function should + * be routed to the "fake" (Mesa) or "real" (GLX-encoder) functions. + * Input:  dpy - the X display. + * Return:   GL_TRUE if the given display supports the real GLX extension, + *           GL_FALSE otherwise. + */ +static GLboolean display_has_glx( Display *dpy ) +{ +   /* TODO: we should use a lookup table to avoid calling XQueryExtension +    * every time. +    */ +   int ignore; +   if (XQueryExtension( dpy, "GLX", &ignore, &ignore, &ignore )) { +      return GL_TRUE; +   } +   else { +      return GL_FALSE; +   } +} + + + +XVisualInfo *glXChooseVisual( Display *dpy, int screen, int *list ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXChooseVisual( dpy, screen, list ); +   else +#endif +      return Fake_glXChooseVisual( dpy, screen, list ); +} + + + +int glXGetConfig( Display *dpy, XVisualInfo *visinfo, int attrib, int *value ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXGetConfig( dpy, visinfo, attrib, value ); +   else +#endif +      return Fake_glXGetConfig( dpy, visinfo, attrib, value ); +} + + + +GLXContext glXCreateContext( Display *dpy, XVisualInfo *visinfo, +			     GLXContext shareList, Bool direct ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXCreateContext( dpy, visinfo, shareList, direct ); +   else +#endif +      return Fake_glXCreateContext( dpy, visinfo, shareList, direct ); +} + + + +void glXDestroyContext( Display *dpy, GLXContext ctx ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      Real_glXDestroyContext( dpy, ctx ); +   else +#endif +      Fake_glXDestroyContext( dpy, ctx ); +} + + + +void glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, +		     GLuint mask ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      Real_glXCopyContext( dpy, src, dst, mask ); +   else +#endif +      Fake_glXCopyContext( dpy, src, dst, mask ); +} + + + +Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) { +      if (Real_glXMakeCurrent( dpy, drawable, ctx )) { +         CurrentDisplay = dpy; +         return True; +      } +      else { +         return False; +      } +   } +   else { +      if (Fake_glXMakeCurrent( dpy, drawable, ctx )) { +         CurrentDisplay = dpy; +         return True; +      } +      else { +         return False; +      } +   } +#else +   return Fake_glXMakeCurrent( dpy, drawable, ctx ); +#endif +} + + + +GLXContext glXGetCurrentContext( void ) +{ +#ifdef REALGLX +   if (display_has_glx(CurrentDisplay)) +      return Real_glXGetCurrentContext(); +   else +#endif +      return Fake_glXGetCurrentContext(); +} + + + +GLXDrawable glXGetCurrentDrawable( void ) +{ +#ifdef REALGLX +   if (display_has_glx(CurrentDisplay)) +      return Real_glXGetCurrentDrawable(); +   else +#endif +      return Fake_glXGetCurrentDrawable(); +} + + + +GLXPixmap glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, +                              Pixmap pixmap ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXCreateGLXPixmap( dpy, visinfo, pixmap ); +   else +#endif +      return Fake_glXCreateGLXPixmap( dpy, visinfo, pixmap ); +} + + +void glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      Real_glXDestroyGLXPixmap( dpy, pixmap ); +   else +#endif +      Fake_glXDestroyGLXPixmap( dpy, pixmap ); +} + + + +Bool glXQueryExtension( Display *dpy, int *errorb, int *event ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXQueryExtension( dpy, errorb, event ); +   else +#endif +      return Fake_glXQueryExtension( dpy, errorb, event ); +} + + + +Bool glXIsDirect( Display *dpy, GLXContext ctx ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXIsDirect( dpy, ctx ); +   else +#endif +      return Fake_glXIsDirect( dpy, ctx ); +} + + + +void glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      Real_glXSwapBuffers( dpy, drawable ); +   else +#endif +      Fake_glXSwapBuffers( dpy, drawable ); +} + + + +void glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, +                           int x, int y, int width, int height ) +{ +#ifdef REALGLX +   /* can't implement! */ +   return; +#endif +   Fake_glXCopySubBufferMESA( dpy, drawable, x, y, width, height ); +} + + + +Bool glXQueryVersion( Display *dpy, int *maj, int *min ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXQueryVersion( dpy, maj, min ); +   else +#endif +      return Fake_glXQueryVersion( dpy, maj, min ); +} + + + +void glXUseXFont( Font font, int first, int count, int listBase ) +{ +#ifdef REALGLX +   if (display_has_glx(CurrentDisplay)) +      Real_glXUseXFont( font, first, count, listBase ); +   else +#endif +      Fake_glXUseXFont( font, first, count, listBase ); +} + + +void glXWaitGL( void ) +{ +#ifdef REALGLX +   if (display_has_glx(CurrentDisplay)) +      Real_glXWaitGL(); +   else +#endif +      Fake_glXWaitGL(); +} + + + +void glXWaitX( void ) +{ +#ifdef REALGLX +   if (display_has_glx(CurrentDisplay)) +      Real_glXWaitX(); +   else +#endif +      Fake_glXWaitX(); +} + + + +/* GLX 1.1 and later */ +const char *glXQueryExtensionsString( Display *dpy, int screen ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXQueryExtensionsString( dpy, screen ); +   else +#endif +      return Fake_glXQueryExtensionsString( dpy, screen ); +} + + + +/* GLX 1.1 and later */ +const char *glXQueryServerString( Display *dpy, int screen, int name ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXQueryServerString( dpy, screen, name ); +   else +#endif +      return Fake_glXQueryServerString( dpy, screen, name ); +} + + + +/* GLX 1.1 and later */ +const char *glXGetClientString( Display *dpy, int name ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return Real_glXGetClientString( dpy, name ); +   else +#endif +      return Fake_glXGetClientString( dpy, name ); +} + + + +#ifdef GLX_MESA_release_buffers +Bool glXReleaseBuffersMESA( Display *dpy, Window w ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return GL_FALSE; +   else +#endif +      return Fake_glXReleaseBuffersMESA( dpy, w ); +} +#endif + + +#ifdef GLX_MESA_pixmap_colormap +GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, +                                  Pixmap pixmap, Colormap cmap ) +{ +#ifdef REALGLX +   if (display_has_glx(dpy)) +      return 0; +   else +#endif +      return Fake_glXCreateGLXPixmapMESA( dpy, visinfo, pixmap, cmap ); +} +#endif + + + +#ifdef GLX_SGI_video_sync + +/* + * This function doesn't really do anything.  But, at least one + * application uses the function so this stub is useful. + */ +int glXGetVideoSyncSGI(unsigned int *count) +{ +   static unsigned int counter = 0; +   *count = counter++; +   return 0; +} + + +/* + * Again, this is really just a stub function. + */ +int glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +{ +   static unsigned int counter = 0; +   while (counter % divisor != remainder) +      counter++; +   *count = counter; +   return 0; +} + +#endif diff --git a/src/mesa/drivers/x11/realglx.c b/src/mesa/drivers/x11/realglx.c new file mode 100644 index 0000000000..79a280419a --- /dev/null +++ b/src/mesa/drivers/x11/realglx.c @@ -0,0 +1,239 @@ +/* $Id: realglx.c,v 1.1 1999/08/19 00:55:42 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. + */ + + + + + +/* + * Real GLX-encoder functions.  Called from glxapi.c + * + * Steven Parker's code for the GLX client API functions should be + * put in this file. + * + * Also, the main API functions in api.c should somehow hook into the + * GLX-encoding functions... + */ + + + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "realglx.h" + + + +XVisualInfo *Real_glXChooseVisual( Display *dpy, int screen, int *list ) +{ +   (void) dpy; +   (void) screen; +   (void) list; +   return 0; +} + + + +int Real_glXGetConfig( Display *dpy, XVisualInfo *visinfo, +                       int attrib, int *value ) +{ +   (void) dpy; +   (void) visinfo; +   (void) attrib; +   (void) value; +   return 0; +} + + + +GLXContext Real_glXCreateContext( Display *dpy, XVisualInfo *visinfo, +                                  GLXContext shareList, Bool direct ) +{ +   (void) dpy; +   (void) visinfo; +   (void) shareList; +   (void) direct; +   return 0; +} + + + +void Real_glXDestroyContext( Display *dpy, GLXContext ctx ) +{ +   (void) dpy; +   (void) ctx; +} + + + +void Real_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, +                          GLuint mask ) +{ +   (void) dpy; +   (void) src; +   (void) dst; +   (void) mask; +} + + + +Bool Real_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ +   (void) dpy; +   (void) drawable; +   (void) ctx; +   return 0; +} + + + +GLXContext Real_glXGetCurrentContext( void ) +{ +   return 0; +} + + + +GLXDrawable Real_glXGetCurrentDrawable( void ) +{ +   return 0; +} + + + +GLXPixmap Real_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, +				   Pixmap pixmap ) +{ +   (void) dpy; +   (void) visinfo; +   (void) pixmap; +   return 0; +} + + +void Real_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +{ +   (void) dpy; +   (void) pixmap; +} + + + +Bool Real_glXQueryExtension( Display *dpy, int *errorb, int *event ) +{ +   (void) dpy; +   (void) errorb; +   (void) event; +   return 0; +} + + + +Bool Real_glXIsDirect( Display *dpy, GLXContext ctx ) +{ +   (void) dpy; +   (void) ctx; +   return 0; +} + + + +void Real_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ +   (void) dpy; +   (void) drawable; +} + + + +Bool Real_glXQueryVersion( Display *dpy, int *maj, int *min ) +{ +   (void) dpy; +   (void) maj; +   (void) min; +   return 0; +} + + + +void Real_glXUseXFont( Font font, int first, int count, int listBase ) +{ +   (void) font; +   (void) first; +   (void) count; +   (void) listBase; +} + + +typedef struct { +   struct { +      int major_opcode; +   } codes; + + + +} XExtDisplayInfo; + + +void Real_glXWaitGL( void ) +{ +} + + + +void Real_glXWaitX( void ) +{ +} + + + +/* GLX 1.1 and later */ +const char *Real_glXQueryExtensionsString( Display *dpy, int screen ) +{ +   (void) dpy; +   (void) screen; +   return 0; +} + + + +/* GLX 1.1 and later */ +const char *Real_glXQueryServerString( Display *dpy, int screen, int name ) +{ +   (void) dpy; +   (void) screen; +   (void) name; +   return 0; +} + + + +/* GLX 1.1 and later */ +const char *Real_glXGetClientString( Display *dpy, int name ) +{ +   (void) dpy; +   (void) name; +   return 0; +} diff --git a/src/mesa/drivers/x11/realglx.h b/src/mesa/drivers/x11/realglx.h new file mode 100644 index 0000000000..9587db60c9 --- /dev/null +++ b/src/mesa/drivers/x11/realglx.h @@ -0,0 +1,111 @@ +/* $Id: realglx.h,v 1.1 1999/08/19 00:55:42 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 REALGLX_H +#define REALGLX_H + + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "GL/glx.h" + + + +extern XVisualInfo *Real_glXChooseVisual( Display *dpy, +                                          int screen, int *list ); + + +extern int Real_glXGetConfig( Display *dpy, XVisualInfo *visinfo, +                              int attrib, int *value ); + + +extern GLXContext Real_glXCreateContext( Display *dpy, XVisualInfo *visinfo, +                                         GLXContext shareList, Bool direct ); + + +extern void Real_glXDestroyContext( Display *dpy, GLXContext ctx ); + + +extern void Real_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, +                                 GLuint mask ); + + +extern Bool Real_glXMakeCurrent( Display *dpy, GLXDrawable drawable, +                                 GLXContext ctx ); + + +extern GLXContext Real_glXGetCurrentContext( void ); + + +extern GLXDrawable Real_glXGetCurrentDrawable( void ); + + +extern GLXPixmap Real_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, +                                          Pixmap pixmap ); + + +extern void Real_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ); + + +extern Bool Real_glXQueryExtension( Display *dpy, int *errorb, int *event ); + + +extern Bool Real_glXIsDirect( Display *dpy, GLXContext ctx ); + + +extern void Real_glXSwapBuffers( Display *dpy, GLXDrawable drawable ); + + +extern Bool Real_glXQueryVersion( Display *dpy, int *maj, int *min ); + + +extern void Real_glXUseXFont( Font font, int first, int count, int listBase ); + + +extern void Real_glXWaitGL( void ); + + +extern void Real_glXWaitX( void ); + + +/* GLX 1.1 and later */ +extern const char *Real_glXQueryExtensionsString( Display *dpy, int screen ); + + +/* GLX 1.1 and later */ +extern const char *Real_glXQueryServerString( Display *dpy, int screen, +                                              int name ); + + +/* GLX 1.1 and later */ +extern const char *Real_glXGetClientString( Display *dpy, int name ); + + +#endif diff --git a/src/mesa/drivers/x11/xfonts.c b/src/mesa/drivers/x11/xfonts.c new file mode 100644 index 0000000000..c0e0a5fcd0 --- /dev/null +++ b/src/mesa/drivers/x11/xfonts.c @@ -0,0 +1,398 @@ +/* $Id: xfonts.c,v 1.1 1999/08/19 00:55:42 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. + */ + + +/* xfonts.c -- glXUseXFont() for Mesa written by + * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "GL/gl.h" +#include "GL/glx.h" +#include "GL/xmesa.h" +#include "context.h" +#include "fakeglx.h" +#include "macros.h" +#include "xmesaP.h" + +/* Some debugging info.  */ + +#ifdef DEBUG +#undef _R +#undef _G +#undef _B +#include <ctype.h> + +int debug_xfonts = 0; + +static void +dump_char_struct (XCharStruct *ch, char *prefix) +{ +  printf ("%slbearing = %d, rbearing = %d, width = %d\n", +          prefix, ch->lbearing, ch->rbearing, ch->width); +  printf ("%sascent = %d, descent = %d, attributes = %u\n", +          prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes); +} + +static void +dump_font_struct (XFontStruct *font) +{ +  printf ("ascent = %d, descent = %d\n", font->ascent, font->descent); +  printf ("char_or_byte2 = (%u,%u)\n", +          font->min_char_or_byte2, font->max_char_or_byte2); +  printf ("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1); +  printf ("all_chars_exist = %s\n", font->all_chars_exist ? "True" :  +"False"); +  printf ("default_char = %c (\\%03o)\n", +          (char) (isprint (font->default_char) ? font->default_char : ' '), +          font->default_char); +  dump_char_struct (&font->min_bounds, "min> "); +  dump_char_struct (&font->max_bounds, "max> "); +#if 0 +  for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) +    { +      char prefix[8]; +      sprintf (prefix, "%d> ", c); +      dump_char_struct (&font->per_char[c], prefix); +    } +#endif +} + +static void +dump_bitmap (unsigned int width, unsigned int height, GLubyte *bitmap) +{ +  unsigned int x, y; + +  printf ("    "); +  for (x = 0; x < 8*width; x++) +    printf ("%o", 7 - (x % 8)); +  putchar ('\n'); +  for (y = 0; y < height; y++) +    { +      printf ("%3o:", y); +      for (x = 0; x < 8*width; x++) +        putchar ((bitmap[width*(height - y - 1) + x/8] & (1 << (7 - (x %  +8)))) +                 ? '*' : '.'); +      printf ("   "); +      for (x = 0; x < width; x++) +        printf ("0x%02x, ", bitmap[width*(height - y - 1) + x]); +      putchar ('\n'); +    } +} +#endif /* DEBUG */ + + +/* Implementation.  */ + +/* Fill a BITMAP with a character C from thew current font +   in the graphics context GC.  WIDTH is the width in bytes +   and HEIGHT is the height in bits. + +   Note that the generated bitmaps must be used with + +        glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); +        glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); +        glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); +        glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); +        glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); +        glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + +   Possible optimizations: + +     * use only one reusable pixmap with the maximum dimensions. +     * draw the entire font into a single pixmap (careful with +       proportional fonts!). +*/ + + +/* + * Generate OpenGL-compatible bitmap. + */ +static void +fill_bitmap (Display *dpy, Window win, GC gc, +             unsigned int width, unsigned int height, +             int x0, int y0, unsigned int c, GLubyte *bitmap) +{ +  XImage *image; +  unsigned int x, y; +  Pixmap pixmap; +  XChar2b char2b; + +  pixmap = XCreatePixmap (dpy, win, 8*width, height, 1); +  XSetForeground(dpy, gc, 0); +  XFillRectangle (dpy, pixmap, gc, 0, 0, 8*width, height); +  XSetForeground(dpy, gc, 1); + +  char2b.byte1 = (c >> 8) & 0xff; +  char2b.byte2 = (c & 0xff); + +  XDrawString16 (dpy, pixmap, gc, x0, y0, &char2b, 1); + +  image = XGetImage (dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap); +  if (image) { +    /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */ +    for (y = 0; y < height; y++) +      for (x = 0; x < 8*width; x++) +        if (XGetPixel (image, x, y)) +          bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8))); +    XDestroyImage (image); +  } + +  XFreePixmap (dpy, pixmap); +} + +/* + * determine if a given glyph is valid and return the + * corresponding XCharStruct. + */ +static XCharStruct *isvalid(XFontStruct *fs, int which) +{ +  unsigned int  rows,pages; +  int           byte1,byte2; +  int           i,valid = 1; + +  rows = fs->max_byte1 - fs->min_byte1 + 1; +  pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + +  if (rows == 1) { +    /* "linear" fonts */ +    if ((fs->min_char_or_byte2 > which) || +        (fs->max_char_or_byte2 < which)) valid = 0; +  } else { +    /* "matrix" fonts */ +    byte2 = which & 0xff; +    byte1 = which >> 8; +    if ((fs->min_char_or_byte2 > byte2) || +        (fs->max_char_or_byte2 < byte2) || +        (fs->min_byte1 > byte1) || +        (fs->max_byte1 < byte1)) valid = 0; +  } + +  if (valid) { +    if (fs->per_char) { +      if (rows == 1) { +        /* "linear" fonts */ +        return(fs->per_char + (which-fs->min_char_or_byte2) ); +      } else { +        /* "matrix" fonts */ +        i = ((byte1 - fs->min_byte1) * pages) + +             (byte2 - fs->min_char_or_byte2); +        return(fs->per_char + i); +      } +    } else { +        return(&fs->min_bounds); +    } +  } +  return(NULL); +} + + +void Fake_glXUseXFont( Font font, int first, int count, int listbase ) +{ +  XMesaContext CC; +  Display *dpy; +  Window win; +  Pixmap pixmap; +  GC gc; +  XGCValues values; +  unsigned long valuemask; +  XFontStruct *fs; + +  GLint swapbytes, lsbfirst, rowlength; +  GLint skiprows, skippixels, alignment; + +  unsigned int max_width, max_height, max_bm_width, max_bm_height; +  GLubyte *bm; + +  int i; + +  CC = XMesaGetCurrentContext(); +  dpy = CC->display; +  win = CC->xm_buffer->frontbuffer; + +  fs = XQueryFont (dpy, font); +  if (!fs) +    { +      gl_error (CC->gl_ctx, GL_INVALID_VALUE, +                "Couldn't get font structure information"); +      return; +    } + +  /* Allocate a bitmap that can fit all characters.  */ +  max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; +  max_height = fs->max_bounds.ascent + fs->max_bounds.descent; +  max_bm_width = (max_width + 7) / 8; +  max_bm_height = max_height; + +  bm = (GLubyte *) malloc ((max_bm_width * max_bm_height) * sizeof  +(GLubyte)); +  if (!bm) { +      XFreeFontInfo( NULL, fs, 0 ); +      gl_error (CC->gl_ctx, GL_OUT_OF_MEMORY, +                "Couldn't allocate bitmap in glXUseXFont()"); +      return; +    } + +#if 0 +  /* get the page info */ +  pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; +  firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; +  lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; +  rows = fs->max_byte1 - fs->min_byte1 + 1; +  unsigned int first_char, last_char, pages, rows; +#endif + +  /* Save the current packing mode for bitmaps.  */ +  glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes); +  glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst); +  glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength); +  glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows); +  glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels); +  glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment); + +  /* Enforce a standard packing mode which is compatible with +     fill_bitmap() from above.  This is actually the default mode, +     except for the (non)alignment.  */ +  glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); +  glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); +  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); +  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); +  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); +  glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + +  pixmap = XCreatePixmap (dpy, win, 10, 10, 1); +  values.foreground = BlackPixel (dpy, DefaultScreen (dpy)); +  values.background = WhitePixel (dpy, DefaultScreen (dpy)); +  values.font = fs->fid; +  valuemask = GCForeground | GCBackground | GCFont; +  gc = XCreateGC (dpy, pixmap, valuemask, &values); +  XFreePixmap (dpy, pixmap); + +#ifdef DEBUG +  if (debug_xfonts) +    dump_font_struct (fs); +#endif + +  for (i = 0; i < count; i++) +    { +      unsigned int width, height, bm_width, bm_height; +      GLfloat x0, y0, dx, dy; +      XCharStruct *ch; +      int x, y; +      unsigned int c = first + i; +      int list = listbase + i; +      int valid; + +      /* check on index validity and get the bounds */ +      ch = isvalid(fs, c); +      if (!ch) { +        ch = &fs->max_bounds; +        valid = 0; +      } else { +        valid = 1; +      } + +#ifdef DEBUG +      if (debug_xfonts) { +          char s[7]; +          sprintf (s, isprint (c) ? "%c> " : "\\%03o> ", c); +          dump_char_struct (ch, s); +      } +#endif + +      /* glBitmap()' parameters: +         straight from the glXUseXFont(3) manpage.  */ +      width = ch->rbearing - ch->lbearing; +      height = ch->ascent + ch->descent; +      x0 = - ch->lbearing; +      y0 = ch->descent - 1; +      dx = ch->width; +      dy = 0; + +      /* X11's starting point.  */ +      x = - ch->lbearing; +      y = ch->ascent; + +      /* Round the width to a multiple of eight.  We will use this also +         for the pixmap for capturing the X11 font.  This is slightly +         inefficient, but it makes the OpenGL part real easy.  */ +      bm_width = (width + 7) / 8; +      bm_height = height; + +      glNewList (list, GL_COMPILE); +        if (valid && (bm_width > 0) && (bm_height > 0)) { + +            MEMSET (bm, '\0', bm_width * bm_height); +            fill_bitmap (dpy, win, gc, bm_width, bm_height, x, y, c, bm); + +            glBitmap (width, height, x0, y0, dx, dy, bm); +#ifdef DEBUG +            if (debug_xfonts) { +                printf ("width/height = %u/%u\n", width, height); +                printf ("bm_width/bm_height = %u/%u\n", bm_width,  +bm_height); +                dump_bitmap (bm_width, bm_height, bm); +              } +#endif +          } else { +            glBitmap (0, 0, 0.0, 0.0, dx, dy, NULL); +          } +      glEndList (); +    } + +  free (bm); +  XFreeFontInfo( NULL, fs, 0 ); +  XFreeGC (dpy, gc); + +  /* Restore saved packing modes.  */ +  glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); +  glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); +  glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); +  glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); +  glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); +  glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); +} + +void xmesa_xfonts_dummy( void ) +{ +   /* silence unused var warnings */ +   (void) kernel8; +   (void) DitherValues; +   (void) HPCR_DRGB; +   (void) kernel1; +} + +/* The End. */ diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h new file mode 100644 index 0000000000..256a47f0a6 --- /dev/null +++ b/src/mesa/drivers/x11/xmesaP.h @@ -0,0 +1,499 @@ +/* $Id: xmesaP.h,v 1.1 1999/08/19 00:55:42 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 XMESAP_H +#define XMESAP_H + + +#ifdef XFree86Server +#include "xf86glx_util.h" +#else +#ifdef SHM +#include <X11/extensions/XShm.h> +#endif +#endif +#include "GL/xmesa.h" +#include "types.h" +#ifdef FX +#include "GL/fxmesa.h" +#include "../FX/fxdrv.h" +#endif + + +/* for PF_8R8G8B24 pixel format */ +typedef struct { +   GLubyte b; +   GLubyte g; +   GLubyte r; +} bgr_t; + + +/* + * "Derived" from gl_visual.  Basically corresponds to an XVisualInfo. + */ +struct xmesa_visual { +   GLvisual *gl_visual;		/* Device independent visual parameters */ +   XMesaDisplay *display;	/* The X11 display */ +#ifndef XFree86Server +   XVisualInfo *vishandle;	/* The pointer returned by glXChooseVisual */ +#endif +   XMesaVisualInfo visinfo;	/* X's visual info */ + +   GLint level;			/* 0=normal, 1=overlay, etc */ + +   GLboolean ximage_flag;	/* Use XImage for back buffer (not pixmap)? */ + +   GLuint dithered_pf;		/* Pixel format when dithering */ +   GLuint undithered_pf;	/* Pixel format when not dithering */ + +   GLfloat RedGamma;		/* Gamma values, 1.0 is default */ +   GLfloat GreenGamma; +   GLfloat BlueGamma; + +   GLint rmult, gmult, bmult;	/* Range of color values */ +   GLint index_bits;		/* Bits per pixel in CI mode */ + +   /* For PF_TRUECOLOR */ +   GLint rshift, gshift, bshift;/* Pixel color component shifts */ +   GLubyte Kernel[16];		/* Dither kernel */ +   unsigned long RtoPixel[512];	/* RGB to pixel conversion */ +   unsigned long GtoPixel[512]; +   unsigned long BtoPixel[512]; +   GLubyte PixelToR[256];	/* Pixel to RGB conversion */ +   GLubyte PixelToG[256]; +   GLubyte PixelToB[256]; + +   /* For PF_HPCR */ +   short       hpcr_rgbTbl[3][256]; +   GLboolean   hpcr_clear_flag; +   GLubyte     hpcr_clear_ximage_pattern[2][16]; +   XMesaImage *hpcr_clear_ximage; +   XMesaPixmap hpcr_clear_pixmap; + +   /* For PF_1BIT */ +   int bitFlip; +}; + + + +/* + * "Derived" from gl_context.  Basically corresponds to a GLXContext. + */ +struct xmesa_context { +   GLcontext *gl_ctx;		/* the core library context */ +   XMesaVisual xm_visual;	/* Describes the buffers */ +   XMesaBuffer xm_buffer;	/* current framebuffer */ + +   XMesaDisplay *display;	/* == xm_visual->display */ +   GLboolean swapbytes;		/* Host byte order != display byte order? */ +   GLboolean direct;		/* Direct rendering context? */ + +   GLuint pixelformat;		/* Current pixel format */ + +   GLubyte red, green, blue, alpha;	/* current drawing color */ +   unsigned long pixel;			/* current drawing pixel value */ + +   GLubyte clearcolor[4];		/* current clearing color */ +   unsigned long clearpixel;		/* current clearing pixel value */ +}; + + + +/* + * "Derived" from gl_buffer.  Basically corresponds to a GLXDrawable. + */ +struct xmesa_buffer { +   GLboolean wasCurrent;	/* was ever the current buffer? */ +   GLframebuffer *gl_buffer;	/* depth, stencil, accum, etc buffers */ +   XMesaVisual xm_visual;	/* the X/Mesa visual */ + +   XMesaContext xm_context;     /* the context associated with this buffer */ +   XMesaDisplay *display; +   GLboolean pixmap_flag;	/* is the buffer a Pixmap? */ +   XMesaDrawable frontbuffer;	/* either a window or pixmap */ +   XMesaPixmap backpixmap;	/* back buffer Pixmap */ +   XMesaImage *backimage;	/* back buffer simulated XImage */ + +   XMesaDrawable buffer;	/* the current buffer, either equal to */ +				/* frontbuffer, backpixmap or XIMAGE (None) */ + +   XMesaColormap cmap;		/* the X colormap */ + +   GLint db_state;		/* 0 = single buffered */ +				/* BACK_PIXMAP = use Pixmap for back buffer */ +				/* BACK_XIMAGE = use XImage for back buffer */ + +#ifndef XFree86Server +   GLuint shm;			/* X Shared Memory extension status:	*/ +				/*    0 = not available			*/ +				/*    1 = XImage support available	*/ +				/*    2 = Pixmap support available too	*/ +#ifdef SHM +   XShmSegmentInfo shminfo; +#endif +#endif + +   XMesaImage *rowimage;	/* Used for optimized span writing */ + +   GLuint width, height;	/* size of buffer */ + +   GLint bottom;		/* used for FLIP macro below */ +   GLubyte *ximage_origin1;	/* used for PIXELADDR1 macro */ +   GLint ximage_width1; +   GLushort *ximage_origin2;	/* used for PIXELADDR2 macro */ +   GLint ximage_width2; +   bgr_t *ximage_origin3;	/* used for PIXELADDR3 macro */ +   GLint ximage_width3; +   GLuint *ximage_origin4;	/* used for PIXELADDR4 macro */ +   GLint ximage_width4; + +   XMesaPixmap stipple_pixmap;	/* For polygon stippling */ +   XMesaGC stipple_gc;		/* For polygon stippling */ + +   XMesaGC gc1;			/* GC for infrequent color changes */ +   XMesaGC gc2;			/* GC for frequent color changes */ +   XMesaGC cleargc;		/* GC for clearing the color buffer */ + +   /* The following are here instead of in the XMesaVisual +    * because they depend on the window's colormap. +    */ + +   /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */ +   unsigned long color_table[576];	/* RGB -> pixel value */ + +   /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */ +   GLubyte pixel_to_r[65536];		/* pixel value -> red */ +   GLubyte pixel_to_g[65536];		/* pixel value -> green */ +   GLubyte pixel_to_b[65536];		/* pixel value -> blue */ + +   /* Used to do XAllocColor/XFreeColors accounting: */ +   int num_alloced; +   unsigned long alloced_colors[256]; + +#ifdef FX +   /* For 3Dfx Glide only */ +   GLboolean FXisHackUsable;	/* Can we render into window? */ +   GLboolean FXwindowHack;	/* Are we rendering into a window? */ +   fxMesaContext FXctx; +#endif + +   struct xmesa_buffer *Next;	/* Linked list pointer: */ +}; + + + +/* Values for xmesa->dest: */ +#define FRONT_PIXMAP	1 +#define BACK_PIXMAP	2 +#define BACK_XIMAGE	4 + + +/* Values for xmesa->pixelformat: */ +#define PF_INDEX          1	/* Color Index mode */ +#define PF_TRUECOLOR      2	/* TrueColor or DirectColor, any depth */ +#define PF_TRUEDITHER     3	/* TrueColor with dithering */ +#define PF_8A8B8G8R       4	/* 32-bit TrueColor:  8-A, 8-B, 8-G, 8-R */ +#define PF_8R8G8B         5	/* 32-bit TrueColor:  8-R, 8-G, 8-B bits */ +#define PF_5R6G5B         6	/* 16-bit TrueColor:  5-R, 6-G, 5-B bits */ +#define PF_DITHER         7	/* Color-mapped RGB with dither */ +#define PF_LOOKUP         8	/* Color-mapped RGB without dither */ +#define PF_HPCR           9	/* HP Color Recovery (ad@lms.be 30/08/95) */ +#define PF_1BIT          10	/* monochrome dithering of RGB */ +#define PF_GRAYSCALE     11	/* Grayscale or StaticGray */ +#define PF_8R8G8B24      12	/* 24-bit TrueColor: 8-R, 8-G, 8-B bits */ +#define PF_DITHER_5R6G5B 13	/* 16-bit dithered TrueColor: 5-R, 6-G, 5-B */ + + +/* + * If pixelformat==PF_TRUECOLOR: + */ +#define PACK_TRUECOLOR( PIXEL, R, G, B )	\ +   PIXEL = xmesa->xm_visual->RtoPixel[R]	\ +         | xmesa->xm_visual->GtoPixel[G]	\ +         | xmesa->xm_visual->BtoPixel[B];	\ + + +/* + * If pixelformat==PF_TRUEDITHER: + */ +#define PACK_TRUEDITHER( PIXEL, X, Y, R, G, B )			\ +{								\ +   int d = xmesa->xm_visual->Kernel[((X)&3) | (((Y)&3)<<2)];	\ +   PIXEL = xmesa->xm_visual->RtoPixel[(R)+d]			\ +         | xmesa->xm_visual->GtoPixel[(G)+d]			\ +         | xmesa->xm_visual->BtoPixel[(B)+d];			\ +} + + + +/* + * If pixelformat==PF_8A8B8G8R: + */ +#define PACK_8A8B8G8R( R, G, B, A )	\ +	( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) ) + + +/* + * Like PACK_8A8B8G8R() but don't use alpha.  This is usually an acceptable + * shortcut. + */ +#define PACK_8B8G8R( R, G, B )   ( ((B) << 16) | ((G) << 8) | (R) ) + + + +/* + * If pixelformat==PF_8R8G8B: + */ +#define PACK_8R8G8B( R, G, B)	 ( ((R) << 16) | ((G) << 8) | (B) ) + + +/* + * If pixelformat==PF_5R6G5B: + */ +#define PACK_5R6G5B( R, G, B)	 ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) + + + +/* + * If pixelformat==PF_DITHER: + * + * Improved 8-bit RGB dithering code contributed by Bob Mercier + * (mercier@hollywood.cinenet.net).  Thanks Bob! + */ +#undef _R +#undef _G +#undef _B +#ifdef DITHER666 +# define _R   6 +# define _G   6 +# define _B   6 +# define _MIX(r,g,b)  (((r)*_G+(g))*_B+(b)) +#else +# define _R	5 +# define _G	9 +# define _B	5 +# define _MIX(r,g,b)	( ((g)<<6) | ((b)<<3) | (r) ) +#endif +#define _DX	4 +#define _DY	4 +#define _D	(_DX*_DY) + +/*#define _DITH(C,c,d)	(((unsigned)((_D*(C-1)+1)*c+d))/(_D*256))*/ +#define _DITH(C,c,d)	(((unsigned)((_D*(C-1)+1)*c+d)) >> 12) + +#define MAXC	256 +static int kernel8[_DY*_DX] = { +    0 * MAXC,  8 * MAXC,  2 * MAXC, 10 * MAXC, +   12 * MAXC,  4 * MAXC, 14 * MAXC,  6 * MAXC, +    3 * MAXC, 11 * MAXC,  1 * MAXC,  9 * MAXC, +   15 * MAXC,  7 * MAXC, 13 * MAXC,  5 * MAXC, +}; +/*static int __d;*/ + +/* Dither for random X,Y */ +#define DITHER_SETUP						\ +	int __d;						\ +	unsigned long *ctable = xmesa->xm_buffer->color_table; + +#define DITHER( X, Y, R, G, B )				\ +	(__d = kernel8[(((Y)&3)<<2) | ((X)&3)],		\ +	 ctable[_MIX(_DITH(_R, (R), __d),		\ +		     _DITH(_G, (G), __d),		\ +		     _DITH(_B, (B), __d))]) + +/* Dither for random X, fixed Y */ +#define XDITHER_SETUP(Y)					\ +	int __d;						\ +	unsigned long *ctable = xmesa->xm_buffer->color_table;	\ +	int *kernel = &kernel8[ ((Y)&3) << 2 ]; + +#define XDITHER( X, R, G, B )				\ +	(__d = kernel[(X)&3],				\ +	ctable[_MIX(_DITH(_R, (R), __d),		\ +		    _DITH(_G, (G), __d),		\ +		    _DITH(_B, (B), __d))]) + + + +/* + * Dithering for flat-shaded triangles.  Precompute all 16 possible + * pixel values given the triangle's RGB color.  Contributed by Martin Shenk. + */ +static GLushort DitherValues[16];   /* array of (up to) 16-bit pixel values */ + +#define FLAT_DITHER_SETUP( R, G, B )					\ +	{								\ +	   unsigned long *ctable = xmesa->xm_buffer->color_table;	\ +	   int msdr = (_D*((_R)-1)+1) * (R);				\ +	   int msdg = (_D*((_G)-1)+1) * (G);				\ +	   int msdb = (_D*((_B)-1)+1) * (B);				\ +	   int i;							\ +	   for (i=0;i<16;i++) {						\ +	      int k = kernel8[i];					\ +	      int j = _MIX( (msdr+k)>>12, (msdg+k)>>12, (msdb+k)>>12 );	\ +	      DitherValues[i] = (GLushort) ctable[j];			\ +	   }								\ +        } + +#define FLAT_DITHER_ROW_SETUP(Y)					\ +	GLushort *ditherRow = DitherValues + ( ((Y)&3) << 2); + +#define FLAT_DITHER(X)  ditherRow[(X)&3] + + + +/* + * If pixelformat==PF_LOOKUP: + */ +#define _DITH0(C,c)	(((unsigned)((_D*(C-1)+1)*c)) >> 12) + +#define LOOKUP_SETUP						\ +	unsigned long *ctable = xmesa->xm_buffer->color_table + +#define LOOKUP( R, G, B )			\ +	ctable[_MIX(_DITH0(_R, (R)),		\ +		    _DITH0(_G, (G)),		\ +		    _DITH0(_B, (B)))] + + + +/* + * If pixelformat==PF_HPCR: + * + *      HP Color Recovery dithering               (ad@lms.be 30/08/95) + *      HP has on it's 8-bit 700-series computers, a feature called + *      'Color Recovery'.  This allows near 24-bit output (so they say). + *      It is enabled by selecting the 8-bit  TrueColor  visual AND + *      corresponding  colormap (see tkInitWindow) AND doing some special + *      dither. + */ +static const short HPCR_DRGB[3][2][16] = { +{ +    { 16, -4,  1,-11, 14, -6,  3, -9, 15, -5,  2,-10, 13, -7,  4, -8}, +    {-15,  5,  0, 12,-13,  7, -2, 10,-14,  6, -1, 11,-12,  8, -3,  9}  +}, +{ +    {-11, 15, -7,  3, -8, 14, -4,  2,-10, 16, -6,  4, -9, 13, -5,  1}, +    { 12,-14,  8, -2,  9,-13,  5, -1, 11,-15,  7, -3, 10,-12,  6,  0}  +}, +{ +    {  6,-18, 26,-14,  2,-22, 30,-10,  8,-16, 28,-12,  4,-20, 32, -8}, +    { -4, 20,-24, 16,  0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}  +} +}; + +#define DITHER_HPCR( X, Y, R, G, B )					   \ +  ( ((xmesa->xm_visual->hpcr_rgbTbl[0][R] + HPCR_DRGB[0][(Y)&1][(X)&15]) & 0xE0)     \ +  |(((xmesa->xm_visual->hpcr_rgbTbl[1][G] + HPCR_DRGB[1][(Y)&1][(X)&15]) & 0xE0)>>3) \ +  | ((xmesa->xm_visual->hpcr_rgbTbl[2][B] + HPCR_DRGB[2][(Y)&1][(X)&15])>>6)	   \ +  ) + + + +/* + * If pixelformat==PF_1BIT: + */ +static int const kernel1[16] = { +   0*47,  9*47,  4*47, 12*47,     /* 47 = (255*3)/16 */ +   6*47,  2*47, 14*47,  8*47, +  10*47,  1*47,  5*47, 11*47, +   7*47, 13*47,  3*47, 15*47 }; + +#define SETUP_1BIT  int bitFlip = xmesa->xm_visual->bitFlip +#define DITHER_1BIT( X, Y, R, G, B )	\ +	(( ((int)(R)+(int)(G)+(int)(B)) > kernel1[(((Y)&3) << 2) | ((X)&3)] ) ^ bitFlip) + + + +/* + * If pixelformat==PF_GRAYSCALE: + */ +#define GRAY_RGB( R, G, B )   xmesa->xm_buffer->color_table[((R) + (G) + (B))/3] + + + +#define XIMAGE None + + +/* + * Converts a GL window Y coord to an X window Y coord: + */ +#define FLIP(Y)  (xmesa->xm_buffer->bottom-(Y)) + + +/* + * Return the address of a 1, 2 or 4-byte pixel in the back XImage: + * X==0 is left, Y==0 is bottom. + */ +#define PIXELADDR1( X, Y )  \ +      ( xmesa->xm_buffer->ximage_origin1 - (Y) * xmesa->xm_buffer->ximage_width1 + (X) ) + +#define PIXELADDR2( X, Y )  \ +      ( xmesa->xm_buffer->ximage_origin2 - (Y) * xmesa->xm_buffer->ximage_width2 + (X) ) + +#define PIXELADDR3( X, Y )  \ +      ( xmesa->xm_buffer->ximage_origin3 - (Y) * xmesa->xm_buffer->ximage_width3 + (X) ) + +#define PIXELADDR4( X, Y )  \ +      ( xmesa->xm_buffer->ximage_origin4 - (Y) * xmesa->xm_buffer->ximage_width4 + (X) ) + + + +/* + * External functions: + */ + +extern unsigned long xmesa_color_to_pixel( XMesaContext xmesa, +		                  GLubyte r, GLubyte g, GLubyte b, GLubyte a ); + +extern void xmesa_alloc_back_buffer( XMesaBuffer b ); + +extern void xmesa_update_state( GLcontext *ctx ); + +extern points_func xmesa_get_points_func( GLcontext *ctx ); + +extern line_func xmesa_get_line_func( GLcontext *ctx ); + +extern triangle_func xmesa_get_triangle_func( GLcontext *ctx ); + + +/* XXX this is a hack to implement shared display lists with 3Dfx */ +extern XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, +					     XMesaWindow w, +					     XMesaContext c ); + + +/* + * These are the extra routines required for integration with XFree86. + * None of these routines should be user visible. -KEM + */ +extern void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ); +extern GLboolean XMesaForceCurrent(XMesaContext c); +extern GLboolean XMesaLoseCurrent(XMesaContext c); +extern void XMesaReset( void ); + +#endif diff --git a/src/mesa/main/Imakefile b/src/mesa/main/Imakefile new file mode 100644 index 0000000000..115f16c8c3 --- /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 0000000000..9c9076bfed --- /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 0000000000..27c3556ab9 --- /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 0000000000..e6419b555a --- /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 0000000000..29a8a134f2 --- /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 0000000000..dd641da456 --- /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 0000000000..78f4d05b2c --- /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 0000000000..0661c26123 --- /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 0000000000..10119ac3b3 --- /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 0000000000..837ea9d6bf --- /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 0000000000..9feaf2472e --- /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 0000000000..03e09ca7e5 --- /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 0000000000..22d785ba51 --- /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 0000000000..8e75f13dac --- /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 0000000000..0b35aba7dc --- /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 0000000000..55c7467821 --- /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 0000000000..f136da42b2 --- /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 0000000000..479d73edd1 --- /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 0000000000..6d5a2be237 --- /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 0000000000..559afc64fb --- /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 0000000000..d6ab05799d --- /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 0000000000..001de0367b --- /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 0000000000..c5a5918190 --- /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 0000000000..a78f345a81 --- /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 0000000000..cb517ced03 --- /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 0000000000..7f661fb75f --- /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 0000000000..92a916a984 --- /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 0000000000..69b520ef40 --- /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 0000000000..028c9b4654 --- /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 0000000000..74604a21c4 --- /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 0000000000..cde76b08dd --- /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 0000000000..55687294d1 --- /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 0000000000..a19dc47920 --- /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 0000000000..4251aae01a --- /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 0000000000..99a4b7aeb1 --- /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 0000000000..1579c8c47c --- /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 0000000000..cf9dcebaf7 --- /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 0000000000..65a682c547 --- /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 0000000000..c4e55041f6 --- /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 0000000000..3d533c82e8 --- /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 0000000000..a38159ce09 --- /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 0000000000..46c33a67d9 --- /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 0000000000..3fd2ca8b33 --- /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 0000000000..cc396f85a5 --- /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 0000000000..18d25e9828 --- /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 0000000000..ed671d7a82 --- /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 0000000000..f85a7a4910 --- /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 0000000000..61e8974836 --- /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 0000000000..c6459947fe --- /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 0000000000..f89993e316 --- /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 0000000000..d24ee6bd9f --- /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 0000000000..316c357af1 --- /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 0000000000..c592d06853 --- /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 0000000000..928acc8891 --- /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 0000000000..a53ce9b2d2 --- /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 0000000000..83690035ff --- /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 0000000000..ac591bbda4 --- /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 0000000000..000af375ba --- /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 0000000000..44dfbab0d6 --- /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 0000000000..994d955b7f --- /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 0000000000..69bd70188b --- /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 0000000000..989cd988fe --- /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 0000000000..f2f301e398 --- /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 0000000000..eb72f961e5 --- /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 0000000000..78691d24f2 --- /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 0000000000..655c823753 --- /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 0000000000..eee5eaa0e4 --- /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 0000000000..870693bfa7 --- /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 0000000000..b63d6a7cce --- /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 0000000000..fc81a61c72 --- /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 + + + diff --git a/src/mesa/x86/3dnow.c b/src/mesa/x86/3dnow.c new file mode 100644 index 0000000000..f91a90b33f --- /dev/null +++ b/src/mesa/x86/3dnow.c @@ -0,0 +1,168 @@ +/* $Id: 3dnow.c,v 1.1 1999/08/19 00:55:42 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. + */ + + +/* + * 3DNow! optimizations contributed by + * Holger Waechtler <holger@akaflieg.extern.tu-berlin.de> + */ +#if defined(USE_3DNOW_ASM) +#include "3dnow.h" + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include "context.h" +#include "types.h" +#include "xform.h" + +#ifdef DEBUG +#include "debug_xform.h" +#endif + + + + +#define XFORM_ARGS      GLvector4f *to_vec,             \ +                        const GLmatrix *mat,            \ +                        const GLvector4f *from_vec,     \ +                        const GLubyte *mask,            \ +                        const GLubyte flag + + + +#define DECLARE_XFORM_GROUP(pfx, v, masked) \ + extern void gl_##pfx##_transform_points##v##_general_##masked(XFORM_ARGS);    \ + extern void gl_##pfx##_transform_points##v##_identity_##masked(XFORM_ARGS);   \ + extern void gl_##pfx##_transform_points##v##_3d_no_rot_##masked(XFORM_ARGS);  \ + extern void gl_##pfx##_transform_points##v##_perspective_##masked(XFORM_ARGS);\ + extern void gl_##pfx##_transform_points##v##_2d_##masked(XFORM_ARGS);         \ + extern void gl_##pfx##_transform_points##v##_2d_no_rot_##masked(XFORM_ARGS);  \ + extern void gl_##pfx##_transform_points##v##_3d_##masked(XFORM_ARGS); + + + +#define ASSIGN_XFORM_GROUP( pfx, cma, vsize, masked )           \ + gl_transform_tab[cma][vsize][MATRIX_GENERAL]                   \ +  = gl_##pfx##_transform_points##vsize##_general_##masked;      \ + gl_transform_tab[cma][vsize][MATRIX_IDENTITY]                  \ +  = gl_##pfx##_transform_points##vsize##_identity_##masked;     \ + gl_transform_tab[cma][vsize][MATRIX_3D_NO_ROT]                 \ +  = gl_##pfx##_transform_points##vsize##_3d_no_rot_##masked;    \ + gl_transform_tab[cma][vsize][MATRIX_PERSPECTIVE]               \ +  = gl_##pfx##_transform_points##vsize##_perspective_##masked;  \ + gl_transform_tab[cma][vsize][MATRIX_2D]                        \ +  = gl_##pfx##_transform_points##vsize##_2d_##masked;           \ + gl_transform_tab[cma][vsize][MATRIX_2D_NO_ROT]                 \ +  = gl_##pfx##_transform_points##vsize##_2d_no_rot_##masked;    \ + gl_transform_tab[cma][vsize][MATRIX_3D]                        \ +  = gl_##pfx##_transform_points##vsize##_3d_##masked; + + + + +#define NORM_ARGS       const GLmatrix *mat,        \ +                        GLfloat scale,              \ +                        const GLvector3f *in,       \ +                        const GLfloat *lengths,     \ +                        const GLubyte mask[],       \ +                        GLvector3f *dest  + + + +#define DECLARE_NORM_GROUP(pfx, masked)                                        \ + extern void gl_##pfx##_rescale_normals_##masked## (NORM_ARGS);                \ + extern void gl_##pfx##_normalize_normals_##masked## (NORM_ARGS);              \ + extern void gl_##pfx##_transform_normals_##masked## (NORM_ARGS);              \ + extern void gl_##pfx##_transform_normals_no_rot_##masked## (NORM_ARGS);       \ + extern void gl_##pfx##_transform_rescale_normals_##masked## (NORM_ARGS);      \ + extern void gl_##pfx##_transform_rescale_normals_no_rot_##masked## (NORM_ARGS); \ + extern void gl_##pfx##_transform_normalize_normals_##masked## (NORM_ARGS);    \ + extern void gl_##pfx##_transform_normalize_normals_no_rot_##masked## (NORM_ARGS); + + + +#define ASSIGN_NORM_GROUP( pfx, cma, masked )                                 \ +   gl_normal_tab[NORM_RESCALE][cma]   =                                       \ +      gl_##pfx##_rescale_normals_##masked##;                                  \ +   gl_normal_tab[NORM_NORMALIZE][cma] =                                       \ +      gl_##pfx##_normalize_normals_##masked##;                                \ +   gl_normal_tab[NORM_TRANSFORM][cma] =                                       \ +      gl_##pfx##_transform_normals_##masked##;                                \ +   gl_normal_tab[NORM_TRANSFORM_NO_ROT][cma] =                                \ +      gl_##pfx##_transform_normals_no_rot_##masked##;                         \ +   gl_normal_tab[NORM_TRANSFORM | NORM_RESCALE][cma] =                        \ +      gl_##pfx##_transform_rescale_normals_##masked##;                        \ +   gl_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE][cma] =                 \ +      gl_##pfx##_transform_rescale_normals_no_rot_##masked##;                 \ +   gl_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE][cma] =                      \ +      gl_##pfx##_transform_normalize_normals_##masked##;                      \ +   gl_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE][cma] =               \ +      gl_##pfx##_transform_normalize_normals_no_rot_##masked##; + + + + +void gl_init_3dnow_asm_transforms (void) +{ +   DECLARE_XFORM_GROUP( 3dnow, 1, raw ) +   DECLARE_XFORM_GROUP( 3dnow, 2, raw ) +   DECLARE_XFORM_GROUP( 3dnow, 3, raw ) +   DECLARE_XFORM_GROUP( 3dnow, 4, raw ) + +   DECLARE_XFORM_GROUP( 3dnow, 1, masked ) +   DECLARE_XFORM_GROUP( 3dnow, 2, masked ) +   DECLARE_XFORM_GROUP( 3dnow, 3, masked ) +   DECLARE_XFORM_GROUP( 3dnow, 4, masked ) + +   DECLARE_NORM_GROUP( 3dnow, raw ) +/* DECLARE_NORM_GROUP( 3dnow, masked ) +*/ + +   ASSIGN_XFORM_GROUP( 3dnow, 0, 1, raw ) +   ASSIGN_XFORM_GROUP( 3dnow, 0, 2, raw ) +   ASSIGN_XFORM_GROUP( 3dnow, 0, 3, raw ) +   ASSIGN_XFORM_GROUP( 3dnow, 0, 4, raw ) + +   ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 1, masked ) +   ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 2, masked ) +   ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 3, masked ) +   ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 4, masked ) + +   ASSIGN_NORM_GROUP( 3dnow, 0, raw ) +/* ASSIGN_NORM_GROUP( 3dnow, CULL_MASK_ACTIVE, masked ) +*/ + +#ifdef DEBUG +   gl_test_all_transform_functions("3Dnow!"); +   gl_test_all_normal_transform_functions("3Dnow!"); +#endif +}  + +#endif + diff --git a/src/mesa/x86/3dnow.h b/src/mesa/x86/3dnow.h new file mode 100644 index 0000000000..b06cc5b288 --- /dev/null +++ b/src/mesa/x86/3dnow.h @@ -0,0 +1,95 @@ +/* $Id: 3dnow.h,v 1.1 1999/08/19 00:55:42 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. + */ + + +/* + * 3DNow! optimizations contributed by + * Holger Waechtler <holger@akaflieg.extern.tu-berlin.de> + */ + + +#ifndef _3dnow_h +#define _3dnow_h + + + +#include "xform.h" + + +void gl_init_3dnow_asm_transforms (void); + + + + +#if 0 +GLvector4f *gl_project_points( GLvector4f *proj_vec, +                               const GLvector4f *clip_vec ) +{ +   __asm__ ( +   "   femms                                                              \n" +   "                                                                      \n" +   "   movq       (%0),     %%mm0      # x1             | x0              \n" +   "   movq       8(%0),    %%mm1      # oow            | x2              \n" +   "                                                                      \n" +   "1: movq       %%mm1,    %%mm2      # oow            | x2              \n" +   "   addl       %2,       %0         # next point                       \n" +   "                                                                      \n" +   "   punpckhdq  %%mm2,    %%mm2      # oow            | oow             \n" +   "   addl       $16,      %1         # next point                       \n" +   "                                                                      \n" +   "   pfrcp      %%mm2,    %%mm3      # 1/oow          | 1/oow           \n" +   "   decl       %3                                                      \n" +   "                                                                      \n" +   "   pfmul      %%mm3,    %%mm0      # x1/oow         | x0/oow          \n" +   "   movq       %%mm0,    -16(%1)    # write r0, r1                     \n" +   "                                                                      \n" +   "   pfmul      %%mm3,    %%mm1      # 1              | x2/oow          \n" +   "   movq       (%0),     %%mm0      # x1             | x0              \n" +   "                                                                      \n" +   "   movd       %%mm1,    8(%1)      # write r2                         \n" +   "   movd       %%mm3,    12(%1)     # write r3                         \n" +   "                                                                      \n" +   "   movq       8(%0),    %%mm1      # oow            | x2              \n" +   "   ja         1b                                                      \n" +   "                                                                      \n" +   "   femms                                                              \n" +   "                                                                        " +   ::"a" (clip_vec->start), +   "c" (proj_vec->start), +   "g" (clip_vec->stride), +   "d" (clip_vec->count) +   ); + +   proj_vec->flags |= VEC_SIZE_4; +   proj_vec->size = 3; +   proj_vec->count = clip_vec->count; +   return proj_vec; +} +#endif + + + +#endif diff --git a/src/mesa/x86/assyntax.h b/src/mesa/x86/assyntax.h new file mode 100644 index 0000000000..3c922201dd --- /dev/null +++ b/src/mesa/x86/assyntax.h @@ -0,0 +1,1629 @@ +#ifndef __ASSYNTAX_H__ +#define	__ASSYNTAX_H__ + +/* + * Copyright 1992 Vrije Universiteit, The Netherlands + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the Vrije Universiteit not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission.  The Vrije Universiteit makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * The Vrije Universiteit DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL The Vrije Universiteit BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * assyntax.h + * + * Select the syntax appropriate to the 386 assembler being used + * To add support for more assemblers add more columns to the CHOICE + * macro.  Note that register names must also have uppercase names + * to avoid macro recursion. e.g., #define ah %ah recurses! + * + * NB 1.  Some of the macros for certain assemblers imply that the code is to + *	  run in protected mode!!  Caveat emptor. + * + * NB 2.  486 specific instructions are not included.  This is to discourage + *	  their accidental use in code that is intended to run on 386 and 486 + *	  systems. + * + * Supported assemblers: + * + * (a) AT&T SysVr4 as(1):	define ATT_ASSEMBLER + * (b) GNU Assembler gas:	define GNU_ASSEMBLER (default) + * (c) Amsterdam Compiler kit:	define ACK_ASSEMBLER + * (d) The Netwide Assembler:	define NASM_ASSEMBLER + * (e) Microsoft Assembler:	define MASM_ASSEMBLER (UNTESTED!) + * + * The following naming conventions have been used to identify the various + * data types: + *		_SR = segment register version + *	Integer: + *		_Q = quadword	= 64 bits + *		_L = long	= 32 bits + *		_W = short	= 16 bits + *		_B = byte	=  8 bits + *	Floating-point: + *		_X = m80real	= 80 bits + *		_D = double	= 64 bits + *		_S = single	= 32 bits + * + * Author: Gregory J. Sharp, Sept 1992 + *         Vrije Universiteit, Amsterdam, The Netherlands + * + *         [support for Intel syntax added by Josh Vanderhoof, 1999] + */ + +#if !(defined(NASM_ASSEMBLER) || defined(MASM_ASSEMBLER)) + +#if !defined(ATT_ASSEMBLER) && !defined(GNU_ASSEMBLER) && !defined(ACK_ASSEMBLER) +#define GNU_ASSEMBLER +#endif + +#if (defined(__STDC__) && !defined(UNIXCPP)) || (defined (sun) && defined (i386) \ + && defined (SVR4) && defined (__STDC__) && !defined (__GNUC__))  +#define	CONCAT(x, y)	x ## y +#else +#define	CONCAT(x, y)	x/**/y +#endif + +#ifdef ACK_ASSEMBLER + +/* Assume we write code for 32-bit protected mode! */ + +/* Redefine register names for GAS & AT&T assemblers */ +#define	AL	al +#define	AH	ah +#define	AX	ax +#define	EAX	ax +#define	BL	bl +#define	BH	bh +#define	BX	bx +#define	EBX	bx +#define	CL	cl +#define	CH	ch +#define	CX	cx +#define	ECX	cx +#define	DL	dl +#define	DH	dh +#define	DX	dx +#define	EDX	dx +#define	BP	bp +#define	EBP	bp +#define	SI	si +#define	ESI	si +#define	DI	di +#define	EDI	di +#define	SP	sp +#define	ESP	sp +#define	CS	cs +#define	SS	ss +#define	DS	ds +#define	ES	es +#define	FS	fs +#define	GS	gs +/* Control Registers */ +#define	CR0	cr0 +#define	CR1	cr1 +#define	CR2	cr2 +#define	CR3	cr3 +/* Debug Registers */ +#define	DR0	dr0 +#define	DR1	dr1 +#define	DR2	dr2 +#define	DR3	dr3 +#define	DR4	dr4 +#define	DR5	dr5 +#define	DR6	dr6 +#define	DR7	dr7 +/* Floating-point Stack */ +#define	ST	st + +#define	AS_BEGIN	.sect .text; .sect .rom; .sect .data; .sect .bss; .sect .text + + +#define	_WTOG		o16	/* word toggle for _W instructions */ +#define	_LTOG			/* long toggle for _L instructions */ +#define	ADDR_TOGGLE	a16 +#define	OPSZ_TOGGLE	o16 +#define	USE16		.use16 +#define	USE32		.use32 + +#define	CHOICE(a,b,c)	c + +#else /* AT&T or GAS */ + +/* Redefine register names for GAS & AT&T assemblers */ +#define	AL	%al +#define	AH	%ah +#define	AX	%ax +#define	EAX	%eax +#define	BL	%bl +#define	BH	%bh +#define	BX	%bx +#define	EBX	%ebx +#define	CL	%cl +#define	CH	%ch +#define	CX	%cx +#define	ECX	%ecx +#define	DL	%dl +#define	DH	%dh +#define	DX	%dx +#define	EDX	%edx +#define	BP	%bp +#define	EBP	%ebp +#define	SI	%si +#define	ESI	%esi +#define	DI	%di +#define	EDI	%edi +#define	SP	%sp +#define	ESP	%esp +#define	CS	%cs +#define	SS	%ss +#define	DS	%ds +#define	ES	%es +#define	FS	%fs +#define	GS	%gs +/* Control Registers */ +#define	CR0	%cr0 +#define	CR1	%cr1 +#define	CR2	%cr2 +#define	CR3	%cr3 +/* Debug Registers */ +#define	DR0	%db0 +#define	DR1	%db1 +#define	DR2	%db2 +#define	DR3	%db3 +#define	DR4	%db4 +#define	DR5	%db5 +#define	DR6	%db6 +#define	DR7	%db7 +/* Floating-point Stack */ +#define	ST	%st +/* MMX Registers */ +#define MM0 	%mm0 +#define MM1 	%mm1 +#define MM2 	%mm2 +#define MM3 	%mm3 +#define MM4 	%mm4 +#define MM5 	%mm5 +#define MM6 	%mm6 +#define MM7 	%mm7 +/* SSE Registers */ +#define XMM0 	%xmm0 +#define XMM1 	%xmm1 +#define XMM2 	%xmm2 +#define XMM3 	%xmm3 +#define XMM4 	%xmm4 +#define XMM5 	%xmm5 +#define XMM6 	%xmm6 +#define XMM7 	%xmm7 + +#define	AS_BEGIN +#define	USE16 +#define	USE32 + +#ifdef GNU_ASSEMBLER + +#define	ADDR_TOGGLE	aword +#define	OPSZ_TOGGLE	word + +#define	CHOICE(a,b,c)	b + +#else +/* + * AT&T ASSEMBLER SYNTAX + * ********************* + */ +#define	CHOICE(a,b,c)	a + +#define	ADDR_TOGGLE	addr16 +#define	OPSZ_TOGGLE	data16 + +#endif /* GNU_ASSEMBLER */ +#endif /* ACK_ASSEMBLER */ + + +#if defined(Lynx) || (defined(SYSV) || defined(SVR4)) && !defined(ACK_ASSEMBLER) \ + || (defined(linux) || defined(__OS2ELF__)) && defined(__ELF__) +#define GLNAME(a)       a +#else +#define GLNAME(a)       CONCAT(_,a) +#endif + + +	/****************************************/ +	/*					*/ +	/*	Select the various choices	*/ +	/*					*/ +	/****************************************/ + + +/* Redefine assembler directives */ +/*********************************/ +#define GLOBL		CHOICE(.globl, .globl, .extern) +/* +#define	ALIGNTEXT32	CHOICE(.align 32, .align ARG2(5,0x90), .align 32) +*/ +#define	ALIGNTEXT32	CHOICE(.align 32, .balign 32, .align 32) +#define	ALIGNTEXT16	CHOICE(.align 16, .balign 16, .align 16) +#define	ALIGNTEXT8	CHOICE(.align 8, .balign 8, .align 8) +#define	ALIGNTEXT4	CHOICE(.align 4, .balign 4, .align 4) +#define	ALIGNTEXT2	CHOICE(.align 2, .balign 2, .align 2) +/* ALIGNTEXT4ifNOP is the same as ALIGNTEXT4, but only if the space is + * guaranteed to be filled with NOPs.  Otherwise it does nothing. + */ +#define	ALIGNTEXT32ifNOP	CHOICE(.align 32, .balign ARG2(32,0x90), /*can't do it*/) +#define	ALIGNTEXT16ifNOP	CHOICE(.align 16, .balign ARG2(16,0x90), /*can't do it*/) +#define	ALIGNTEXT8ifNOP	CHOICE(.align 8, .balign ARG2(8,0x90), /*can't do it*/) +#define	ALIGNTEXT4ifNOP	CHOICE(.align 4, .balign ARG2(4,0x90), /*can't do it*/) +#define	ALIGNDATA32	CHOICE(.align 32, .balign ARG2(32,0x0), .align 32) +#define	ALIGNDATA16	CHOICE(.align 16, .balign ARG2(16,0x0), .align 16) +#define	ALIGNDATA8	CHOICE(.align 8, .balign ARG2(8,0x0), .align 8) +#define	ALIGNDATA4	CHOICE(.align 4, .balign ARG2(4,0x0), .align 4) +#define	ALIGNDATA2	CHOICE(.align 2, .balign ARG2(2,0x0), .align 2) +#define	FILE(s)		CHOICE(.file s, .file s, .file s) +#define	STRING(s)	CHOICE(.string s, .asciz s, .asciz s) +#define	D_LONG		CHOICE(.long, .long, .data4) +#define	D_WORD		CHOICE(.value, .short, .data2) +#define	D_BYTE		CHOICE(.byte, .byte, .data1) +#define	SPACE		CHOICE(.comm, .space, .space) +#define	COMM		CHOICE(.comm, .comm, .comm) +#define	SEG_DATA	CHOICE(.data, .data, .sect .data) +#define	SEG_TEXT	CHOICE(.text, .text, .sect .text) +#define	SEG_BSS		CHOICE(.bss, .bss, .sect .bss) + +#ifdef GNU_ASSEMBLER +#define	D_SPACE(n)	. = . + n +#else +#define	D_SPACE(n)	.space n +#endif + +/* Addressing Modes */ +/* Immediate Mode */ +#define	ADDR(a)		CHOICE(CONCAT($,a), CONCAT($,a), a) +#define	CONST(a)	CHOICE(CONCAT($,a), CONCAT($,a), a) + +/* Indirect Mode */ +#define	CONTENT(a)	CHOICE(a, a, (a))	 /* take contents of variable */ +#define	REGIND(a)	CHOICE((a), (a), (a))	 /* Register a indirect */ +/* Register b indirect plus displacement a */ +#define	REGOFF(a, b)	CHOICE(a(b), a(b), a(b)) +/* Reg indirect Base + Index + Displacement  - this is mainly for 16-bit mode + * which has no scaling + */ +#define	REGBID(b,i,d)	CHOICE(d(b,i), d(b,i), d(b)(i)) +/* Reg indirect Base + (Index * Scale) + Displacement */ +#define	REGBISD(b,i,s,d) CHOICE(d(b,i,s), d(b,i,s), d(b)(i*s)) +/* Displaced Scaled Index: */ +#define REGDIS(d,i,s)	CHOICE(d(,i,s), d(,i,s), d(i * s)) +/* Indexed Base: */ +#define REGBI(b,i)	CHOICE((b,i), (b,i), (b)(i)) +/* Displaced Base: */ +#define REGDB(d,b)	CHOICE(d(b), d(b), d(b)) +/* Variable indirect: */ +#define VARINDIRECT(var) CHOICE(*var, *var, (var)) +/* Use register contents as jump/call target: */ +#define CODEPTR(reg)	CHOICE(*reg, *reg, reg) + +/* For expressions requiring bracketing + * eg. (CRT0_PM | CRT_EM) + */ + +#define	EXPR(a)		CHOICE([a], (a), [a]) +#define	ENOT(a)		CHOICE(0!a, ~a, ~a) +#define	EMUL(a,b)	CHOICE(a\*b, a*b, a*b) +#define	EDIV(a,b)	CHOICE(a\/b, a/b, a/b) + +/* + * We have to beat the problem of commas within arguments to choice. + * eg. choice (add a,b, add b,a) will get argument mismatch.  Luckily ANSI + * and other known cpp definitions evaluate arguments before substitution + * so the following works. + */ +#define	ARG2(a, b)	a,b +#define	ARG3(a,b,c)	a,b,c + +/* Redefine assembler commands */ +#define	AAA		CHOICE(aaa, aaa, aaa) +#define	AAD		CHOICE(aad, aad, aad) +#define	AAM		CHOICE(aam, aam, aam) +#define	AAS		CHOICE(aas, aas, aas) +#define	ADC_L(a, b)	CHOICE(adcl ARG2(a,b), adcl ARG2(a,b), _LTOG adc ARG2(b,a)) +#define	ADC_W(a, b)	CHOICE(adcw ARG2(a,b), adcw ARG2(a,b), _WTOG adc ARG2(b,a)) +#define	ADC_B(a, b)	CHOICE(adcb ARG2(a,b), adcb ARG2(a,b), adcb ARG2(b,a)) +#define	ADD_L(a, b)	CHOICE(addl ARG2(a,b), addl ARG2(a,b), _LTOG add ARG2(b,a)) +#define	ADD_W(a, b)	CHOICE(addw ARG2(a,b), addw ARG2(a,b), _WTOG add ARG2(b,a)) +#define	ADD_B(a, b)	CHOICE(addb ARG2(a,b), addb ARG2(a,b), addb ARG2(b,a)) +#define	AND_L(a, b)	CHOICE(andl ARG2(a,b), andl ARG2(a,b), _LTOG and ARG2(b,a)) +#define	AND_W(a, b)	CHOICE(andw ARG2(a,b), andw ARG2(a,b), _WTOG and ARG2(b,a)) +#define	AND_B(a, b)	CHOICE(andb ARG2(a,b), andb ARG2(a,b), andb ARG2(b,a)) +#define	ARPL(a,b)	CHOICE(arpl ARG2(a,b), arpl ARG2(a,b), arpl ARG2(b,a)) +#define	BOUND_L(a, b)	CHOICE(boundl ARG2(a,b), boundl ARG2(b,a), _LTOG bound ARG2(b,a)) +#define	BOUND_W(a, b)	CHOICE(boundw ARG2(a,b), boundw ARG2(b,a), _WTOG bound ARG2(b,a)) +#define	BSF_L(a, b)	CHOICE(bsfl ARG2(a,b), bsfl ARG2(a,b), _LTOG bsf ARG2(b,a)) +#define	BSF_W(a, b)	CHOICE(bsfw ARG2(a,b), bsfw ARG2(a,b), _WTOG bsf ARG2(b,a)) +#define	BSR_L(a, b)	CHOICE(bsrl ARG2(a,b), bsrl ARG2(a,b), _LTOG bsr ARG2(b,a)) +#define	BSR_W(a, b)	CHOICE(bsrw ARG2(a,b), bsrw ARG2(a,b), _WTOG bsr ARG2(b,a)) +#define	BT_L(a, b)	CHOICE(btl ARG2(a,b), btl ARG2(a,b), _LTOG bt ARG2(b,a)) +#define	BT_W(a, b)	CHOICE(btw ARG2(a,b), btw ARG2(a,b), _WTOG bt ARG2(b,a)) +#define	BTC_L(a, b)	CHOICE(btcl ARG2(a,b), btcl ARG2(a,b), _LTOG btc ARG2(b,a)) +#define	BTC_W(a, b)	CHOICE(btcw ARG2(a,b), btcw ARG2(a,b), _WTOG btc ARG2(b,a)) +#define	BTR_L(a, b)	CHOICE(btrl ARG2(a,b), btrl ARG2(a,b), _LTOG btr ARG2(b,a)) +#define	BTR_W(a, b)	CHOICE(btrw ARG2(a,b), btrw ARG2(a,b), _WTOG btr ARG2(b,a)) +#define	BTS_L(a, b)	CHOICE(btsl ARG2(a,b), btsl ARG2(a,b), _LTOG bts ARG2(b,a)) +#define	BTS_W(a, b)	CHOICE(btsw ARG2(a,b), btsw ARG2(a,b), _WTOG bts ARG2(b,a)) +#define	CALL(a)		CHOICE(call a, call a, call a) +#define	CALLF(s,a)	CHOICE(lcall ARG2(s,a), lcall ARG2(s,a), callf s:a) +#define	CBW		CHOICE(cbtw, cbw, cbw) +#define	CWDE		CHOICE(cwtd, cwde, cwde) +#define	CLC		CHOICE(clc, clc, clc) +#define	CLD		CHOICE(cld, cld, cld) +#define	CLI		CHOICE(cli, cli, cli) +#define	CLTS		CHOICE(clts, clts, clts) +#define	CMC		CHOICE(cmc, cmc, cmc) +#define	CMP_L(a, b)	CHOICE(cmpl ARG2(a,b), cmpl ARG2(a,b), _LTOG cmp ARG2(b,a)) +#define	CMP_W(a, b)	CHOICE(cmpw ARG2(a,b), cmpw ARG2(a,b), _WTOG cmp ARG2(b,a)) +#define	CMP_B(a, b)	CHOICE(cmpb ARG2(a,b), cmpb ARG2(a,b), cmpb ARG2(b,a)) +#define	CMPS_L		CHOICE(cmpsl, cmpsl, _LTOG cmps) +#define	CMPS_W		CHOICE(cmpsw, cmpsw, _WTOG cmps) +#define	CMPS_B		CHOICE(cmpsb, cmpsb, cmpsb) +#define	CWD		CHOICE(cwtl, cwd, cwd) +#define	CDQ		CHOICE(cltd, cdq, cdq) +#define	DAA		CHOICE(daa, daa, daa) +#define	DAS		CHOICE(das, das, das) +#define	DEC_L(a)	CHOICE(decl a, decl a, _LTOG dec a) +#define	DEC_W(a)	CHOICE(decw a, decw a, _WTOG dec a) +#define	DEC_B(a)	CHOICE(decb a, decb a, decb a) +#define	DIV_L(a)	CHOICE(divl a, divl a, div a) +#define	DIV_W(a)	CHOICE(divw a, divw a, div a) +#define	DIV_B(a)	CHOICE(divb a, divb a, divb a) +#define	ENTER(a,b)	CHOICE(enter ARG2(a,b), enter ARG2(a,b), enter ARG2(b,a)) +#define	HLT		CHOICE(hlt, hlt, hlt) +#define	IDIV_L(a)	CHOICE(idivl a, idivl a, _LTOG idiv a) +#define	IDIV_W(a)	CHOICE(idivw a, idivw a, _WTOG idiv a) +#define	IDIV_B(a)	CHOICE(idivb a, idivb a, idivb a) +/* More forms than this for imul!! */ +#define	IMUL_L(a, b)	CHOICE(imull ARG2(a,b), imull ARG2(a,b), _LTOG imul ARG2(b,a)) +#define	IMUL_W(a, b)	CHOICE(imulw ARG2(a,b), imulw ARG2(a,b), _WTOG imul ARG2(b,a)) +#define	IMUL_B(a)	CHOICE(imulb a, imulb a, imulb a) +#define	IN_L		CHOICE(inl (DX), inl ARG2(DX,EAX), _LTOG in DX) +#define	IN_W		CHOICE(inw (DX), inw ARG2(DX,AX), _WTOG in DX) +#define	IN_B		CHOICE(inb (DX), inb ARG2(DX,AL), inb DX) +/* Please AS code writer: use the following ONLY, if you refer to ports<256 + * directly, but not in IN1_W(DX), for instance, even if IN1_ looks nicer + */ +#if defined (sun) +#define IN1_L(a)    CHOICE(inl (a), inl ARG2(a,EAX), _LTOG in a) +#define IN1_W(a)    CHOICE(inw (a), inw ARG2(a,AX), _WTOG in a) +#define IN1_B(a)    CHOICE(inb (a), inb ARG2(a,AL), inb a) +#else +#define	IN1_L(a)	CHOICE(inl a, inl ARG2(a,EAX), _LTOG in a) +#define	IN1_W(a)	CHOICE(inw a, inw ARG2(a,AX), _WTOG in a) +#define	IN1_B(a)	CHOICE(inb a, inb ARG2(a,AL), inb a) +#endif +#define	INC_L(a)	CHOICE(incl a, incl a, _LTOG inc a) +#define	INC_W(a)	CHOICE(incw a, incw a, _WTOG inc a) +#define	INC_B(a)	CHOICE(incb a, incb a, incb a) +#define	INS_L		CHOICE(insl, insl, _LTOG ins) +#define	INS_W		CHOICE(insw, insw, _WTOG ins) +#define	INS_B		CHOICE(insb, insb, insb) +#define	INT(a)		CHOICE(int a, int a, int a) +#define	INT3		CHOICE(int CONST(3), int3, int CONST(3)) +#define	INTO		CHOICE(into, into, into) +#define	IRET		CHOICE(iret, iret, iret) +#define	IRETD		CHOICE(iret, iret, iretd) +#define	JA(a)		CHOICE(ja a, ja a, ja a) +#define	JAE(a)		CHOICE(jae a, jae a, jae a) +#define	JB(a)		CHOICE(jb a, jb a, jb a) +#define	JBE(a)		CHOICE(jbe a, jbe a, jbe a) +#define	JC(a)		CHOICE(jc a, jc a, jc a) +#define	JE(a)		CHOICE(je a, je a, je a) +#define	JG(a)		CHOICE(jg a, jg a, jg a) +#define	JGE(a)		CHOICE(jge a, jge a, jge a) +#define	JL(a)		CHOICE(jl a, jl a, jl a) +#define	JLE(a)		CHOICE(jle a, jle a, jle a) +#define	JNA(a)		CHOICE(jna a, jna a, jna a) +#define	JNAE(a)		CHOICE(jnae a, jnae a, jnae a) +#define	JNB(a)		CHOICE(jnb a, jnb a, jnb a) +#define	JNBE(a)		CHOICE(jnbe a, jnbe a, jnbe a) +#define	JNC(a)		CHOICE(jnc a, jnc a, jnc a) +#define	JNE(a)		CHOICE(jne a, jne a, jne a) +#define	JNG(a)		CHOICE(jng a, jng a, jng a) +#define	JNGE(a)		CHOICE(jnge a, jnge a, jnge a) +#define	JNL(a)		CHOICE(jnl a, jnl a, jnl a) +#define	JNLE(a)		CHOICE(jnle a, jnle a, jnle a) +#define	JNO(a)		CHOICE(jno a, jno a, jno a) +#define	JNP(a)		CHOICE(jnp a, jnp a, jnp a) +#define	JNS(a)		CHOICE(jns a, jns a, jns a) +#define	JNZ(a)		CHOICE(jnz a, jnz a, jnz a) +#define	JO(a)		CHOICE(jo a, jo a, jo a) +#define	JP(a)		CHOICE(jp a, jp a, jp a) +#define	JPE(a)		CHOICE(jpe a, jpe a, jpe a) +#define	JPO(a)		CHOICE(jpo a, jpo a, jpo a) +#define	JS(a)		CHOICE(js a, js a, js a) +#define	JZ(a)		CHOICE(jz a, jz a, jz a) +#define	JMP(a)		CHOICE(jmp a, jmp a, jmp a) +#define	JMPF(s,a)	CHOICE(ljmp ARG2(s,a), ljmp ARG2(s,a), jmpf s:a) +#define	LAHF		CHOICE(lahf, lahf, lahf) +#if !defined(_REAL_MODE) && !defined(_V86_MODE) +#define	LAR(a, b)	CHOICE(lar ARG2(a, b), lar ARG2(a, b), lar ARG2(b, a)) +#endif +#define	LEA_L(a, b)	CHOICE(leal ARG2(a,b), leal ARG2(a,b), _LTOG lea ARG2(b,a)) +#define	LEA_W(a, b)	CHOICE(leaw ARG2(a,b), leaw ARG2(a,b), _WTOG lea ARG2(b,a)) +#define	LEAVE		CHOICE(leave, leave, leave) +#define	LGDT(a)		CHOICE(lgdt a, lgdt a, lgdt a) +#define	LIDT(a)		CHOICE(lidt a, lidt a, lidt a) +#define	LDS(a, b)	CHOICE(ldsl ARG2(a,b), lds ARG2(a,b), lds ARG2(b,a)) +#define	LES(a, b)	CHOICE(lesl ARG2(a,b), les ARG2(a,b), les ARG2(b,a)) +#define	LFS(a, b)	CHOICE(lfsl ARG2(a,b), lfs ARG2(a,b), lfs ARG2(b,a)) +#define	LGS(a, b)	CHOICE(lgsl ARG2(a,b), lgs ARG2(a,b), lgs ARG2(b,a)) +#define	LSS(a, b)	CHOICE(lssl ARG2(a,b), lss ARG2(a,b), lss ARG2(b,a)) +#define	LLDT(a)		CHOICE(lldt a, lldt a, lldt a) +#define	LMSW(a)		CHOICE(lmsw a, lmsw a, lmsw a) +#define LOCK		CHOICE(lock, lock, lock) +#define	LODS_L		CHOICE(lodsl, lodsl, _LTOG lods) +#define	LODS_W		CHOICE(lodsw, lodsw, _WTOG lods) +#define	LODS_B		CHOICE(lodsb, lodsb, lodsb) +#define	LOOP(a)		CHOICE(loop a, loop a, loop a) +#define	LOOPE(a)	CHOICE(loope a, loope a, loope a) +#define	LOOPZ(a)	CHOICE(loopz a, loopz a, loopz a) +#define	LOOPNE(a)	CHOICE(loopne a, loopne a, loopne a) +#define	LOOPNZ(a)	CHOICE(loopnz a, loopnz a, loopnz a) +#if !defined(_REAL_MODE) && !defined(_V86_MODE) +#define	LSL(a, b)	CHOICE(lsl ARG2(a,b), lsl ARG2(a,b), lsl ARG2(b,a)) +#endif +#define	LTR(a)		CHOICE(ltr a, ltr a, ltr a) +#define	MOV_SR(a, b)	CHOICE(movw ARG2(a,b), mov ARG2(a,b), mov ARG2(b,a)) +#define	MOV_L(a, b)	CHOICE(movl ARG2(a,b), movl ARG2(a,b), _LTOG mov ARG2(b,a)) +#define	MOV_W(a, b)	CHOICE(movw ARG2(a,b), movw ARG2(a,b), _WTOG mov ARG2(b,a)) +#define	MOV_B(a, b)	CHOICE(movb ARG2(a,b), movb ARG2(a,b), movb ARG2(b,a)) +#define	MOVS_L		CHOICE(movsl, movsl, _LTOG movs) +#define	MOVS_W		CHOICE(movsw, movsw, _WTOG movs) +#define	MOVS_B		CHOICE(movsb, movsb, movsb) +#define	MOVSX_BL(a, b)	CHOICE(movsbl ARG2(a,b), movsbl ARG2(a,b), movsx ARG2(b,a)) +#define	MOVSX_BW(a, b)	CHOICE(movsbw ARG2(a,b), movsbw ARG2(a,b), movsx ARG2(b,a)) +#define	MOVSX_WL(a, b)	CHOICE(movswl ARG2(a,b), movswl ARG2(a,b), movsx ARG2(b,a)) +#define	MOVZX_BL(a, b)	CHOICE(movzbl ARG2(a,b), movzbl ARG2(a,b), movzx ARG2(b,a)) +#define	MOVZX_BW(a, b)	CHOICE(movzbw ARG2(a,b), movzbw ARG2(a,b), movzx ARG2(b,a)) +#define	MOVZX_WL(a, b)	CHOICE(movzwl ARG2(a,b), movzwl ARG2(a,b), movzx ARG2(b,a)) +#define	MUL_L(a)	CHOICE(mull a, mull a, _LTOG mul a) +#define	MUL_W(a)	CHOICE(mulw a, mulw a, _WTOG mul a) +#define	MUL_B(a)	CHOICE(mulb a, mulb a, mulb a) +#define	NEG_L(a)	CHOICE(negl a, negl a, _LTOG neg a) +#define	NEG_W(a)	CHOICE(negw a, negw a, _WTOG neg a) +#define	NEG_B(a)	CHOICE(negb a, negb a, negb a) +#define	NOP		CHOICE(nop, nop, nop) +#define	NOT_L(a)	CHOICE(notl a, notl a, _LTOG not a) +#define	NOT_W(a)	CHOICE(notw a, notw a, _WTOG not a) +#define	NOT_B(a)	CHOICE(notb a, notb a, notb a) +#define	OR_L(a,b)	CHOICE(orl ARG2(a,b), orl ARG2(a,b), _LTOG or ARG2(b,a)) +#define	OR_W(a,b)	CHOICE(orw ARG2(a,b), orw ARG2(a,b), _WTOG or ARG2(b,a)) +#define	OR_B(a,b)	CHOICE(orb ARG2(a,b), orb ARG2(a,b), orb ARG2(b,a)) +#define	OUT_L		CHOICE(outl (DX), outl ARG2(EAX,DX), _LTOG out DX) +#define	OUT_W		CHOICE(outw (DX), outw ARG2(AX,DX), _WTOG out DX) +#define	OUT_B		CHOICE(outb (DX), outb ARG2(AL,DX), outb DX) +/* Please AS code writer: use the following ONLY, if you refer to ports<256 + * directly, but not in OUT1_W(DX), for instance, even if OUT1_ looks nicer + */ +#define	OUT1_L(a)	CHOICE(outl (a), outl ARG2(EAX,a), _LTOG out a) +#define	OUT1_W(a)	CHOICE(outw (a), outw ARG2(AX,a), _WTOG out a) +#define	OUT1_B(a)	CHOICE(outb (a), outb ARG2(AL,a), outb a) +#define	OUTS_L		CHOICE(outsl, outsl, _LTOG outs) +#define	OUTS_W		CHOICE(outsw, outsw, _WTOG outs) +#define	OUTS_B		CHOICE(outsb, outsb, outsb) +#define	POP_SR(a)	CHOICE(pop a, pop a, pop a) +#define	POP_L(a)	CHOICE(popl a, popl a, _LTOG pop a) +#define	POP_W(a)	CHOICE(popw a, popw a, _WTOG pop a) +#define	POPA_L		CHOICE(popal, popal, _LTOG popa) +#define	POPA_W		CHOICE(popaw, popaw, _WTOG popa) +#define	POPF_L		CHOICE(popfl, popfl, _LTOG popf) +#define	POPF_W		CHOICE(popfw, popfw, _WTOG popf) +#define	PUSH_SR(a)	CHOICE(push a, push a, push a) +#define	PUSH_L(a)	CHOICE(pushl a, pushl a, _LTOG push a) +#define	PUSH_W(a)	CHOICE(pushw a, pushw a, _WTOG push a) +#define	PUSH_B(a)	CHOICE(push a, pushb a, push a) +#define	PUSHA_L		CHOICE(pushal, pushal, _LTOG pusha) +#define	PUSHA_W		CHOICE(pushaw, pushaw, _WTOG pusha) +#define	PUSHF_L		CHOICE(pushfl, pushfl, _LTOG pushf) +#define	PUSHF_W		CHOICE(pushfw, pushfw, _WTOG pushf) +#define	RCL_L(a, b)	CHOICE(rcll ARG2(a,b), rcll ARG2(a,b), _LTOG rcl ARG2(b,a)) +#define	RCL_W(a, b)	CHOICE(rclw ARG2(a,b), rclw ARG2(a,b), _WTOG rcl ARG2(b,a)) +#define	RCL_B(a, b)	CHOICE(rclb ARG2(a,b), rclb ARG2(a,b), rclb ARG2(b,a)) +#define	RCR_L(a, b)	CHOICE(rcrl ARG2(a,b), rcrl ARG2(a,b), _LTOG rcr ARG2(b,a)) +#define	RCR_W(a, b)	CHOICE(rcrw ARG2(a,b), rcrw ARG2(a,b), _WTOG rcr ARG2(b,a)) +#define	RCR_B(a, b)	CHOICE(rcrb ARG2(a,b), rcrb ARG2(a,b), rcrb ARG2(b,a)) +#define	ROL_L(a, b)	CHOICE(roll ARG2(a,b), roll ARG2(a,b), _LTOG rol ARG2(b,a)) +#define	ROL_W(a, b)	CHOICE(rolw ARG2(a,b), rolw ARG2(a,b), _WTOG rol ARG2(b,a)) +#define	ROL_B(a, b)	CHOICE(rolb ARG2(a,b), rolb ARG2(a,b), rolb ARG2(b,a)) +#define	ROR_L(a, b)	CHOICE(rorl ARG2(a,b), rorl ARG2(a,b), _LTOG ror ARG2(b,a)) +#define	ROR_W(a, b)	CHOICE(rorw ARG2(a,b), rorw ARG2(a,b), _WTOG ror ARG2(b,a)) +#define	ROR_B(a, b)	CHOICE(rorb ARG2(a,b), rorb ARG2(a,b), rorb ARG2(b,a)) +#define	REP		CHOICE(rep ;, rep ;, repe) +#define	REPE		CHOICE(repz ;, repe ;, repe) +#define	REPNE		CHOICE(repnz ;, repne ;, repne) +#define	REPNZ		REPNE +#define	REPZ		REPE +#define	RET		CHOICE(ret, ret, ret) +#define	SAHF		CHOICE(sahf, sahf, sahf) +#define	SAL_L(a, b)	CHOICE(sall ARG2(a,b), sall ARG2(a,b), _LTOG sal ARG2(b,a)) +#define	SAL_W(a, b)	CHOICE(salw ARG2(a,b), salw ARG2(a,b), _WTOG sal ARG2(b,a)) +#define	SAL_B(a, b)	CHOICE(salb ARG2(a,b), salb ARG2(a,b), salb ARG2(b,a)) +#define	SAR_L(a, b)	CHOICE(sarl ARG2(a,b), sarl ARG2(a,b), _LTOG sar ARG2(b,a)) +#define	SAR_W(a, b)	CHOICE(sarw ARG2(a,b), sarw ARG2(a,b), _WTOG sar ARG2(b,a)) +#define	SAR_B(a, b)	CHOICE(sarb ARG2(a,b), sarb ARG2(a,b), sarb ARG2(b,a)) +#define	SBB_L(a, b)	CHOICE(sbbl ARG2(a,b), sbbl ARG2(a,b), _LTOG sbb ARG2(b,a)) +#define	SBB_W(a, b)	CHOICE(sbbw ARG2(a,b), sbbw ARG2(a,b), _WTOG sbb ARG2(b,a)) +#define	SBB_B(a, b)	CHOICE(sbbb ARG2(a,b), sbbb ARG2(a,b), sbbb ARG2(b,a)) +#define	SCAS_L		CHOICE(scasl, scasl, _LTOG scas) +#define	SCAS_W		CHOICE(scasw, scasw, _WTOG scas) +#define	SCAS_B		CHOICE(scasb, scasb, scasb) +#define	SETA(a)		CHOICE(seta a, seta a, seta a) +#define	SETAE(a)	CHOICE(setae a, setae a, setae a) +#define	SETB(a)		CHOICE(setb a, setb a, setb a) +#define	SETBE(a)	CHOICE(setbe a, setbe a, setbe a) +#define	SETC(a)		CHOICE(setc a, setb a, setb a) +#define	SETE(a)		CHOICE(sete a, sete a, sete a) +#define	SETG(a)		CHOICE(setg a, setg a, setg a) +#define	SETGE(a)	CHOICE(setge a, setge a, setge a) +#define	SETL(a)		CHOICE(setl a, setl a, setl a) +#define	SETLE(a)	CHOICE(setle a, setle a, setle a) +#define	SETNA(a)	CHOICE(setna a, setna a, setna a) +#define	SETNAE(a)	CHOICE(setnae a, setnae a, setnae a) +#define	SETNB(a)	CHOICE(setnb a, setnb a, setnb a) +#define	SETNBE(a)	CHOICE(setnbe a, setnbe a, setnbe a) +#define	SETNC(a)	CHOICE(setnc a, setnb a, setnb a) +#define	SETNE(a)	CHOICE(setne a, setne a, setne a) +#define	SETNG(a)	CHOICE(setng a, setng a, setng a) +#define	SETNGE(a)	CHOICE(setnge a, setnge a, setnge a) +#define	SETNL(a)	CHOICE(setnl a, setnl a, setnl a) +#define	SETNLE(a)	CHOICE(setnle a, setnle a, setnle a) +#define	SETNO(a)	CHOICE(setno a, setno a, setno a) +#define	SETNP(a)	CHOICE(setnp a, setnp a, setnp a) +#define	SETNS(a)	CHOICE(setns a, setns a, setna a) +#define	SETNZ(a)	CHOICE(setnz a, setnz a, setnz a) +#define	SETO(a)		CHOICE(seto a, seto a, seto a) +#define	SETP(a)		CHOICE(setp a, setp a, setp a) +#define	SETPE(a)	CHOICE(setpe a, setpe a, setpe a) +#define	SETPO(a)	CHOICE(setpo a, setpo a, setpo a) +#define	SETS(a)		CHOICE(sets a, sets a, seta a) +#define	SETZ(a)		CHOICE(setz a, setz a, setz a) +#define	SGDT(a)		CHOICE(sgdt a, sgdt a, sgdt a) +#define	SIDT(a)		CHOICE(sidt a, sidt a, sidt a) +#define	SHL_L(a, b)	CHOICE(shll ARG2(a,b), shll ARG2(a,b), _LTOG shl ARG2(b,a)) +#define	SHL_W(a, b)	CHOICE(shlw ARG2(a,b), shlw ARG2(a,b), _WTOG shl ARG2(b,a)) +#define	SHL_B(a, b)	CHOICE(shlb ARG2(a,b), shlb ARG2(a,b), shlb ARG2(b,a)) +#define	SHLD_L(a,b,c)	CHOICE(shldl ARG3(a,b,c), shldl ARG3(a,b,c), _LTOG shld ARG3(c,b,a)) +#define	SHLD2_L(a,b)	CHOICE(shldl ARG2(a,b), shldl ARG3(CL,a,b), _LTOG shld ARG3(b,a,CL)) +#define	SHLD_W(a,b,c)	CHOICE(shldw ARG3(a,b,c), shldw ARG3(a,b,c), _WTOG shld ARG3(c,b,a)) +#define	SHLD2_W(a,b)	CHOICE(shldw ARG2(a,b), shldw ARG3(CL,a,b), _WTOG shld ARG3(b,a,CL)) +#define	SHR_L(a, b)	CHOICE(shrl ARG2(a,b), shrl ARG2(a,b), _LTOG shr ARG2(b,a)) +#define	SHR_W(a, b)	CHOICE(shrw ARG2(a,b), shrw ARG2(a,b), _WTOG shr ARG2(b,a)) +#define	SHR_B(a, b)	CHOICE(shrb ARG2(a,b), shrb ARG2(a,b), shrb ARG2(b,a)) +#define	SHRD_L(a,b,c)	CHOICE(shrdl ARG3(a,b,c), shrdl ARG3(a,b,c), _LTOG shrd ARG3(c,b,a)) +#define	SHRD2_L(a,b)	CHOICE(shrdl ARG2(a,b), shrdl ARG3(CL,a,b), _LTOG shrd ARG3(b,a,CL)) +#define	SHRD_W(a,b,c)	CHOICE(shrdw ARG3(a,b,c), shrdw ARG3(a,b,c), _WTOG shrd ARG3(c,b,a)) +#define	SHRD2_W(a,b)	CHOICE(shrdw ARG2(a,b), shrdw ARG3(CL,a,b), _WTOG shrd ARG3(b,a,CL)) +#define	SLDT(a)		CHOICE(sldt a, sldt a, sldt a) +#define	SMSW(a)		CHOICE(smsw a, smsw a, smsw a) +#define	STC		CHOICE(stc, stc, stc) +#define	STD		CHOICE(std, std, std) +#define	STI		CHOICE(sti, sti, sti) +#define	STOS_L		CHOICE(stosl, stosl, _LTOG stos) +#define	STOS_W		CHOICE(stosw, stosw, _WTOG stos) +#define	STOS_B		CHOICE(stosb, stosb, stosb) +#define	STR(a)		CHOICE(str a, str a, str a) +#define	SUB_L(a, b)	CHOICE(subl ARG2(a,b), subl ARG2(a,b), _LTOG sub ARG2(b,a)) +#define	SUB_W(a, b)	CHOICE(subw ARG2(a,b), subw ARG2(a,b), _WTOG sub ARG2(b,a)) +#define	SUB_B(a, b)	CHOICE(subb ARG2(a,b), subb ARG2(a,b), subb ARG2(b,a)) +#define	TEST_L(a, b)	CHOICE(testl ARG2(a,b), testl ARG2(a,b), _LTOG test ARG2(b,a)) +#define	TEST_W(a, b)	CHOICE(testw ARG2(a,b), testw ARG2(a,b), _WTOG test ARG2(b,a)) +#define	TEST_B(a, b)	CHOICE(testb ARG2(a,b), testb ARG2(a,b), testb ARG2(b,a)) +#define	VERR(a)		CHOICE(verr a, verr a, verr a) +#define	VERW(a)		CHOICE(verw a, verw a, verw a) +#define	WAIT		CHOICE(wait, wait, wait) +#define	XCHG_L(a, b)	CHOICE(xchgl ARG2(a,b), xchgl ARG2(a,b), _LTOG xchg ARG2(b,a)) +#define	XCHG_W(a, b)	CHOICE(xchgw ARG2(a,b), xchgw ARG2(a,b), _WTOG xchg ARG2(b,a)) +#define	XCHG_B(a, b)	CHOICE(xchgb ARG2(a,b), xchgb ARG2(a,b), xchgb ARG2(b,a)) +#define	XLAT		CHOICE(xlat, xlat, xlat) +#define	XOR_L(a, b)	CHOICE(xorl ARG2(a,b), xorl ARG2(a,b), _LTOG xor ARG2(b,a)) +#define	XOR_W(a, b)	CHOICE(xorw ARG2(a,b), xorw ARG2(a,b), _WTOG xor ARG2(b,a)) +#define	XOR_B(a, b)	CHOICE(xorb ARG2(a,b), xorb ARG2(a,b), xorb ARG2(b,a)) + + +/* Floating Point Instructions */ +#define	F2XM1		CHOICE(f2xm1, f2xm1, f2xm1) +#define	FABS		CHOICE(fabs, fabs, fabs) +#define	FADD_D(a)	CHOICE(faddl a, faddl a, faddd a) +#define	FADD_S(a)	CHOICE(fadds a, fadds a, fadds a) +#define	FADD2(a, b)	CHOICE(fadd ARG2(a,b), fadd ARG2(a,b), fadd ARG2(b,a)) +#define	FADDP(a, b)	CHOICE(faddp ARG2(a,b), faddp ARG2(a,b), faddp ARG2(b,a)) +#define	FIADD_L(a)	CHOICE(fiaddl a, fiaddl a, fiaddl a) +#define	FIADD_W(a)	CHOICE(fiadd a, fiadds a, fiadds a) +#define	FBLD(a)		CHOICE(fbld a, fbld a, fbld a) +#define	FBSTP(a)	CHOICE(fbstp a, fbstp a, fbstp a) +#define	FCHS		CHOICE(fchs, fchs, fchs) +#define	FCLEX		CHOICE(fclex, wait; fnclex, wait; fclex) +#define	FNCLEX		CHOICE(fnclex, fnclex, fclex) +#define	FCOM(a)		CHOICE(fcom a, fcom a, fcom a) +#define	FCOM_D(a)	CHOICE(fcoml a, fcoml a, fcomd a) +#define	FCOM_S(a)	CHOICE(fcoms a, fcoms a, fcoms a) +#define	FCOMP(a)	CHOICE(fcomp a, fcomp a, fcomp a) +#define	FCOMP_D(a)	CHOICE(fcompl a, fcompl a, fcompd a) +#define	FCOMP_S(a)	CHOICE(fcomps a, fcomps a, fcomps a) +#define	FCOMPP		CHOICE(fcompp, fcompp, fcompp) +#define	FCOS		CHOICE(fcos, fcos, fcos) +#define	FDECSTP		CHOICE(fdecstp, fdecstp, fdecstp) +#define	FDIV_D(a)	CHOICE(fdivl a, fdivl a, fdivd a) +#define	FDIV_S(a)	CHOICE(fdivs a, fdivs a, fdivs a) +#define	FDIV2(a, b)	CHOICE(fdiv ARG2(a,b), fdiv ARG2(a,b), fdiv ARG2(b,a)) +#define	FDIVP(a, b)	CHOICE(fdivp ARG2(a,b), fdivp ARG2(a,b), fdivp ARG2(b,a)) +#define	FIDIV_L(a)	CHOICE(fidivl a, fidivl a, fidivl a) +#define	FIDIV_W(a)	CHOICE(fidiv a, fidivs a, fidivs a) +#define	FDIVR_D(a)	CHOICE(fdivrl a, fdivrl a, fdivrd a) +#define	FDIVR_S(a)	CHOICE(fdivrs a, fdivrs a, fdivrs a) +#define	FDIVR2(a, b)	CHOICE(fdivr ARG2(a,b), fdivr ARG2(a,b), fdivr ARG2(b,a)) +#define	FDIVRP(a, b)	CHOICE(fdivrp ARG2(a,b), fdivrp ARG2(a,b), fdivrp ARG2(b,a)) +#define	FIDIVR_L(a)	CHOICE(fidivrl a, fidivrl a, fidivrl a) +#define	FIDIVR_W(a)	CHOICE(fidivr a, fidivrs a, fidivrs a) +#define	FFREE(a)	CHOICE(ffree a, ffree a, ffree a) +#define	FICOM_L(a)	CHOICE(ficoml a, ficoml a, ficoml a) +#define	FICOM_W(a)	CHOICE(ficom a, ficoms a, ficoms a) +#define	FICOMP_L(a)	CHOICE(ficompl a, ficompl a, ficompl a) +#define	FICOMP_W(a)	CHOICE(ficomp a, ficomps a, ficomps a) +#define	FILD_Q(a)	CHOICE(fildll a, fildq a, fildq a) +#define	FILD_L(a)	CHOICE(fildl a, fildl a, fildl a) +#define	FILD_W(a)	CHOICE(fild a, filds a, filds a) +#define	FINCSTP		CHOICE(fincstp, fincstp, fincstp) +#define	FINIT		CHOICE(finit, wait; fninit, wait; finit) +#define	FNINIT		CHOICE(fninit, fninit, finit) +#define	FIST_L(a)	CHOICE(fistl a, fistl a, fistl a) +#define	FIST_W(a)	CHOICE(fist a, fists a, fists a) +#define	FISTP_Q(a)	CHOICE(fistpll a, fistpq a, fistpq a) +#define	FISTP_L(a)	CHOICE(fistpl a, fistpl a, fistpl a) +#define	FISTP_W(a)	CHOICE(fistp a, fistps a, fistps a) +#define	FLD_X(a)	CHOICE(fldt a, fldt a, fldx a) /* 80 bit data type! */ +#define	FLD_D(a)	CHOICE(fldl a, fldl a, fldd a) +#define	FLD_S(a)	CHOICE(flds a, flds a, flds a) +#define	FLD1		CHOICE(fld1, fld1, fld1) +#define	FLDL2T		CHOICE(fldl2t, fldl2t, fldl2t) +#define	FLDL2E		CHOICE(fldl2e, fldl2e, fldl2e) +#define	FLDPI		CHOICE(fldpi, fldpi, fldpi) +#define	FLDLG2		CHOICE(fldlg2, fldlg2, fldlg2) +#define	FLDLN2		CHOICE(fldln2, fldln2, fldln2) +#define	FLDZ		CHOICE(fldz, fldz, fldz) +#define	FLDCW(a)	CHOICE(fldcw a, fldcw a, fldcw a) +#define	FLDENV(a)	CHOICE(fldenv a, fldenv a, fldenv a) +#define	FMUL_S(a)	CHOICE(fmuls a, fmuls a, fmuls a) +#define	FMUL_D(a)	CHOICE(fmull a, fmull a, fmuld a) +#define	FMUL2(a, b)	CHOICE(fmul ARG2(a,b), fmul ARG2(a,b), fmul ARG2(b,a)) +#define	FMULP(a, b)	CHOICE(fmulp ARG2(a,b), fmulp ARG2(a,b), fmulp ARG2(b,a)) +#define	FIMUL_L(a)	CHOICE(fimull a, fimull a, fimull a) +#define	FIMUL_W(a)	CHOICE(fimul a, fimuls a, fimuls a) +#define	FNOP		CHOICE(fnop, fnop, fnop) +#define	FPATAN		CHOICE(fpatan, fpatan, fpatan) +#define	FPREM		CHOICE(fprem, fprem, fprem) +#define	FPREM1		CHOICE(fprem1, fprem1, fprem1) +#define	FPTAN		CHOICE(fptan, fptan, fptan) +#define	FRNDINT		CHOICE(frndint, frndint, frndint) +#define	FRSTOR(a)	CHOICE(frstor a, frstor a, frstor a) +#define	FSAVE(a)	CHOICE(fsave a, wait; fnsave a, wait; fsave a) +#define	FNSAVE(a)	CHOICE(fnsave a, fnsave a, fsave a) +#define	FSCALE		CHOICE(fscale, fscale, fscale) +#define	FSIN		CHOICE(fsin, fsin, fsin) +#define	FSINCOS		CHOICE(fsincos, fsincos, fsincos) +#define	FSQRT		CHOICE(fsqrt, fsqrt, fsqrt) +#define	FST_D(a)	CHOICE(fstl a, fstl a, fstd a) +#define	FST_S(a)	CHOICE(fsts a, fsts a, fsts a) +#define	FSTP_X(a)	CHOICE(fstpt a, fstpt a, fstpx a) +#define	FSTP_D(a)	CHOICE(fstpl a, fstpl a, fstpd a) +#define	FSTP_S(a)	CHOICE(fstps a, fstps a, fstps a) +#define	FSTP(a)		CHOICE(fstp a, fstp a, fstp a) +#define	FSTCW(a)	CHOICE(fstcw a, wait; fnstcw a, wait; fstcw a) +#define	FNSTCW(a)	CHOICE(fnstcw a, fnstcw a, fstcw a) +#define	FSTENV(a)	CHOICE(fstenv a, wait; fnstenv a, fstenv a) +#define	FNSTENV(a)	CHOICE(fnstenv a, fnstenv a, fstenv a) +#define	FSTSW(a)	CHOICE(fstsw a, wait; fnstsw a, wait; fstsw a) +#define	FNSTSW(a)	CHOICE(fnstsw a, fnstsw a, fstsw a) +#define	FSUB_S(a)	CHOICE(fsubs a, fsubs a, fsubs a) +#define	FSUB_D(a)	CHOICE(fsubl a, fsubl a, fsubd a) +#define	FSUB2(a, b)	CHOICE(fsub ARG2(a,b), fsub ARG2(a,b), fsub ARG2(b,a)) +#define	FSUBP(a, b)	CHOICE(fsubp ARG2(a,b), fsubp ARG2(a,b), fsubp ARG2(b,a)) +#define	FISUB_L(a)	CHOICE(fisubl a, fisubl a, fisubl a) +#define	FISUB_W(a)	CHOICE(fisub a, fisubs a, fisubs a) +#define	FSUBR_S(a)	CHOICE(fsubrs a, fsubrs a, fsubrs a) +#define	FSUBR_D(a)	CHOICE(fsubrl a, fsubrl a, fsubrd a) +#define	FSUBR2(a, b)	CHOICE(fsubr ARG2(a,b), fsubr ARG2(a,b), fsubr ARG2(b,a)) +#define	FSUBRP(a, b)	CHOICE(fsubrp ARG2(a,b), fsubrp ARG2(a,b), fsubrp ARG2(b,a)) +#define	FISUBR_L(a)	CHOICE(fisubrl a, fisubrl a, fisubrl a) +#define	FISUBR_W(a)	CHOICE(fisubr a, fisubrs a, fisubrs a) +#define	FTST		CHOICE(ftst, ftst, ftst) +#define	FUCOM(a)	CHOICE(fucom a, fucom a, fucom a) +#define	FUCOMP(a)	CHOICE(fucomp a, fucomp a, fucomp a) +#define	FUCOMPP		CHOICE(fucompp, fucompp, fucompp) +#define	FWAIT		CHOICE(wait, wait, wait) +#define	FXAM		CHOICE(fxam, fxam, fxam) +#define	FXCH(a)		CHOICE(fxch a, fxch a, fxch a) +#define	FXTRACT		CHOICE(fxtract, fxtract, fxtract) +#define	FYL2X		CHOICE(fyl2x, fyl2x, fyl2x) +#define	FYL2XP1		CHOICE(fyl2xp1, fyl2xp1, fyl2xp1) + +/* New instructions */ +#define	CPUID		CHOICE(D_BYTE ARG2(15, 162), cpuid, D_BYTE ARG2(15, 162)) +#define	RDTSC		CHOICE(D_BYTE ARG2(15, 49), rdtsc, D_BYTE ARG2(15, 49)) + +#else /* NASM_ASSEMBLER || MASM_ASSEMBLER is defined */ + +	/****************************************/ +	/*					*/ +	/*	Intel style assemblers.		*/ +	/*	(NASM and MASM)			*/ +	/*					*/ +	/****************************************/ + +#define P_EAX 	EAX +#define L_EAX 	EAX +#define W_AX 	AX +#define B_AH 	AH +#define B_AL 	AL + +#define P_EBX 	EBX +#define L_EBX 	EBX +#define W_BX 	BX +#define B_BH 	BH +#define B_BL 	BL + +#define P_ECX 	ECX +#define L_ECX 	ECX +#define W_CX 	CX +#define B_CH 	CH +#define B_CL 	CL + +#define P_EDX 	EDX +#define L_EDX 	EDX +#define W_DX 	DX +#define B_DH 	DH +#define B_DL 	DL + +#define P_EBP 	EBP +#define L_EBP 	EBP +#define W_BP 	BP + +#define P_ESI 	ESI +#define L_ESI 	ESI +#define W_SI 	SI + +#define P_EDI 	EDI +#define L_EDI 	EDI +#define W_DI 	DI + +#define P_ESP 	ESP +#define L_ESP 	ESP +#define W_SP 	SP + +#define W_CS 	CS +#define W_SS 	SS +#define W_DS 	DS +#define W_ES 	ES +#define W_FS 	FS +#define W_GS 	GS + +#define X_ST 	ST +#define D_ST 	ST +#define L_ST 	ST + +#define P_MM0 	mm0 +#define P_MM1 	mm1 +#define P_MM2 	mm2 +#define P_MM3 	mm3 +#define P_MM4 	mm4 +#define P_MM5 	mm5 +#define P_MM6 	mm6 +#define P_MM7 	mm7 + +#define P_XMM0 	xmm0 +#define P_XMM1 	xmm1 +#define P_XMM2 	xmm2 +#define P_XMM3 	xmm3 +#define P_XMM4 	xmm4 +#define P_XMM5 	xmm5 +#define P_XMM6 	xmm6 +#define P_XMM7 	xmm7 + +#if defined(NASM_ASSEMBLER) + +#define ST(n) st ## n + +#define TBYTE_PTR tword +#define QWORD_PTR qword +#define DWORD_PTR dword +#define WORD_PTR word +#define BYTE_PTR byte + +#define OFFSET + +#define GLOBL GLOBAL +#define ALIGNTEXT32 ALIGN 32 +#define ALIGNTEXT16 ALIGN 16 +#define ALIGNTEXT8 ALIGN 8 +#define ALIGNTEXT4 ALIGN 4 +#define ALIGNTEXT2 ALIGN 2 +#define ALIGNTEXT32ifNOP ALIGN 32 +#define ALIGNTEXT16ifNOP ALIGN 16 +#define ALIGNTEXT8ifNOP ALIGN 8 +#define ALIGNTEXT4ifNOP ALIGN 4 +#define ALIGNDATA32 ALIGN 32 +#define ALIGNDATA16 ALIGN 16 +#define ALIGNDATA8 ALIGN 8 +#define ALIGNDATA4 ALIGN 4 +#define ALIGNDATA2 ALIGN 2 +#define FILE(s) +#define STRING(s) db s +#define D_LONG dd +#define D_WORD dw +#define D_BYTE db +/* #define SPACE */ +/* #define COMM */ +#define SEG_DATA SECTION .data +#define SEG_TEXT SECTION .text +#define SEG_BSS SECTION .bss + +#define D_SPACE(n) db n REP 0 + +#define AS_BEGIN + +#define NEAR near 	/* Jcc's should be handled better than this... */ + +#else /* MASM */ + +#define TBYTE_PTR tbyte ptr +#define QWORD_PTR qword ptr +#define DWORD_PTR dword ptr +#define WORD_PTR word ptr +#define BYTE_PTR byte ptr + +#define OFFSET offset + +#define GLOBL GLOBAL +#define ALIGNTEXT32 ALIGN 32 +#define ALIGNTEXT16 ALIGN 16 +#define ALIGNTEXT8 ALIGN 8 +#define ALIGNTEXT4 ALIGN 4 +#define ALIGNTEXT2 ALIGN 2 +#define ALIGNTEXT32ifNOP ALIGN 32 +#define ALIGNTEXT16ifNOP ALIGN 16 +#define ALIGNTEXT8ifNOP ALIGN 8 +#define ALIGNTEXT4ifNOP ALIGN 4 +#define ALIGNDATA32 ALIGN 32 +#define ALIGNDATA16 ALIGN 16 +#define ALIGNDATA8 ALIGN 8 +#define ALIGNDATA4 ALIGN 4 +#define ALIGNDATA2 ALIGN 2 +#define FILE(s) +#define STRING(s) db s +#define D_LONG dd +#define D_WORD dw +#define D_BYTE db +/* #define SPACE */ +/* #define COMM */ +#define SEG_DATA .DATA +#define SEG_TEXT .CODE +#define SEG_BSS .DATA + +#define D_SPACE(n) db n REP 0 + +#define AS_BEGIN + +#define NEAR + +#endif + +#if defined(Lynx) || (defined(SYSV) || defined(SVR4)) \ +|| (defined(linux) || defined(__OS2ELF__)) && defined(__ELF__) +#define GLNAME(a) a +#else +#define GLNAME(a) _ ## a +#endif + +/* + * 	Addressing Modes + */ + +/* Immediate Mode */ +#define P_ADDR(a) 	OFFSET a +#define X_ADDR(a) 	OFFSET a +#define D_ADDR(a) 	OFFSET a +#define L_ADDR(a) 	OFFSET a +#define W_ADDR(a) 	OFFSET a +#define B_ADDR(a) 	OFFSET a + +#define P_CONST(a) 	a +#define X_CONST(a) 	a +#define D_CONST(a) 	a +#define L_CONST(a) 	a +#define W_CONST(a) 	a +#define B_CONST(a) 	a + +/* Indirect Mode */ +#define P_CONTENT(a) 	a +#define X_CONTENT(a) 	TBYTE_PTR a +#define D_CONTENT(a) 	QWORD_PTR a +#define L_CONTENT(a) 	DWORD_PTR a +#define W_CONTENT(a) 	WORD_PTR a +#define B_CONTENT(a) 	BYTE_PTR a + +/* Register a indirect */ +#define P_REGIND(a) 	[a] +#define X_REGIND(a) 	TBYTE_PTR [a] +#define D_REGIND(a) 	QWORD_PTR [a] +#define L_REGIND(a) 	DWORD_PTR [a] +#define W_REGIND(a) 	WORD_PTR [a] +#define B_REGIND(a) 	BYTE_PTR [a] + +/* Register b indirect plus displacement a */ +#define P_REGOFF(a, b) 	[a + b] +#define X_REGOFF(a, b) 	TBYTE_PTR [a + b] +#define D_REGOFF(a, b) 	QWORD_PTR [a + b] +#define L_REGOFF(a, b) 	DWORD_PTR [a + b] +#define W_REGOFF(a, b) 	WORD_PTR [a + b] +#define B_REGOFF(a, b) 	BYTE_PTR [a + b] + +/* Reg indirect Base + Index + Displacement  - this is mainly for 16-bit mode + * which has no scaling + */ +#define P_REGBID(b, i, d) 	[b + i + d] +#define X_REGBID(b, i, d) 	TBYTE_PTR [b + i + d] +#define D_REGBID(b, i, d) 	QWORD_PTR [b + i + d] +#define L_REGBID(b, i, d) 	DWORD_PTR [b + i + d] +#define W_REGBID(b, i, d) 	WORD_PTR [b + i + d] +#define B_REGBID(b, i, d) 	BYTE_PTR [b + i + d] + +/* Reg indirect Base + (Index * Scale) + Displacement */ +#define P_REGBISD(b, i, s, d) 	[b + i * s + d] +#define X_REGBISD(b, i, s, d) 	TBYTE_PTR [b + i * s + d] +#define D_REGBISD(b, i, s, d) 	QWORD_PTR [b + i * s + d] +#define L_REGBISD(b, i, s, d) 	DWORD_PTR [b + i * s + d] +#define W_REGBISD(b, i, s, d) 	WORD_PTR [b + i * s + d] +#define B_REGBISD(b, i, s, d) 	BYTE_PTR [b + i * s + d] + +/* Displaced Scaled Index: */ +#define P_REGDIS(d, i, s) 	[i * s + d] +#define X_REGDIS(d, i, s) 	TBYTE_PTR [i * s + d] +#define D_REGDIS(d, i, s) 	QWORD_PTR [i * s + d] +#define L_REGDIS(d, i, s) 	DWORD_PTR [i * s + d] +#define W_REGDIS(d, i, s) 	WORD_PTR [i * s + d] +#define B_REGDIS(d, i, s) 	BYTE_PTR [i * s + d] + +/* Indexed Base: */ +#define P_REGBI(b, i) 	[b + i] +#define X_REGBI(b, i) 	TBYTE_PTR [b + i] +#define D_REGBI(b, i) 	QWORD_PTR [b + i] +#define L_REGBI(b, i) 	DWORD_PTR [b + i] +#define W_REGBI(b, i) 	WORD_PTR [b + i] +#define B_REGBI(b, i) 	BYTE_PTR [b + i] + +/* Displaced Base: */ +#define P_REGDB(d, b) 	[b + d] +#define X_REGDB(d, b) 	TBYTE_PTR [b + d] +#define D_REGDB(d, b) 	QWORD_PTR [b + d] +#define L_REGDB(d, b) 	DWORD_PTR [b + d] +#define W_REGDB(d, b) 	WORD_PTR [b + d] +#define B_REGDB(d, b) 	BYTE_PTR [b + d] + +/* Variable indirect: */ +#define VARINDIRECT(var) 	[var] + +/* Use register contents as jump/call target: */ +#define CODEPTR(reg) 	[reg] + +/* + * 	Redefine assembler commands + */ + +#define P_(a) 	P_ ## a +#define X_(a) 	X_ ## a +#define D_(a) 	D_ ## a +#define S_(a) 	L_ ## a +#define L_(a) 	L_ ## a +#define W_(a) 	W_ ## a +#define B_(a) 	B_ ## a + +#define	AAA		aaa		 +#define	AAD		aad		 +#define	AAM		aam		 +#define	AAS		aas		 +#define	ADC_L(a, b)	adc L_(b), L_(a) +#define	ADC_W(a, b)	adc W_(b), W_(a) +#define	ADC_B(a, b)	adc B_(b), B_(a) +#define	ADD_L(a, b)	add L_(b), L_(a) +#define	ADD_W(a, b)	add W_(b), W_(a) +#define	ADD_B(a, b)	add B_(b), B_(a) +#define	AND_L(a, b)	and L_(b), L_(a) +#define	AND_W(a, b)	and W_(b), W_(a) +#define	AND_B(a, b)	and B_(b), B_(a) +#define	ARPL(a,b)	arpl W_(b), a +#define	BOUND_L(a, b)	bound L_(b), L_(a) +#define	BOUND_W(a, b)	bound W_(b), W_(a) +#define	BSF_L(a, b)	bsf L_(b), L_(a) +#define	BSF_W(a, b)	bsf W_(b), W_(a) +#define	BSR_L(a, b)	bsr L_(b), L_(a) +#define	BSR_W(a, b)	bsr W_(b), W_(a) +#define	BT_L(a, b)	bt L_(b), L_(a) +#define	BT_W(a, b)	bt W_(b), W_(a) +#define	BTC_L(a, b)	btc L_(b), L_(a) +#define	BTC_W(a, b)	btc W_(b), W_(a) +#define	BTR_L(a, b)	btr L_(b), L_(a) +#define	BTR_W(a, b)	btr W_(b), W_(a) +#define	BTS_L(a, b)	bts L_(b), L_(a) +#define	BTS_W(a, b)	bts W_(b), W_(a) +#define	CALL(a)		call a +#define	CALLF(s,a)	call far s:a +#define	CBW		cbw		 +#define	CWDE		cwde		 +#define	CLC		clc		 +#define	CLD		cld		 +#define	CLI		cli		 +#define	CLTS		clts		 +#define	CMC		cmc		 +#define	CMP_L(a, b)	cmp L_(b), L_(a) +#define	CMP_W(a, b)	cmp W_(b), W_(a) +#define	CMP_B(a, b)	cmp B_(b), B_(a) +#define	CMPS_L		cmpsd +#define	CMPS_W		cmpsw +#define	CMPS_B		cmpsb +#define	CWD		cwd		 +#define	CDQ		cdq		 +#define	DAA		daa		 +#define	DAS		das		 +#define	DEC_L(a)	dec L_(a) +#define	DEC_W(a)	dec W_(a) +#define	DEC_B(a)	dec B_(a) +#define	DIV_L(a)	div L_(a) +#define	DIV_W(a)	div W_(a) +#define	DIV_B(a)	div B_(a) +#define	ENTER(a,b)	enter b, a +#define	HLT		hlt		 +#define	IDIV_L(a)	idiv L_(a) +#define	IDIV_W(a)	idiv W_(a) +#define	IDIV_B(a)	idiv B_(a) +#define	IMUL_L(a, b)	imul L_(b), L_(a) +#define	IMUL_W(a, b)	imul W_(b), W_(a) +#define	IMUL_B(a)	imul B_(a) +#define	IN_L		in EAX, DX +#define	IN_W		in AX, DX +#define	IN_B		in AL, DX +#define	IN1_L(a)	in1 L_(a) +#define	IN1_W(a)	in1 W_(a) +#define	IN1_B(a)	in1 B_(a) +#define	INC_L(a)	inc L_(a) +#define	INC_W(a)	inc W_(a) +#define	INC_B(a)	inc B_(a) +#define	INS_L		ins +#define	INS_W		ins +#define	INS_B		ins +#define	INT(a)		int B_(a) +#define	INT3		int3		 +#define	INTO		into		 +#define	IRET		iret		 +#define	IRETD		iretd		 +#define	JA(a)		ja NEAR a +#define	JAE(a)		jae NEAR a +#define	JB(a)		jb NEAR a +#define	JBE(a)		jbe NEAR a +#define	JC(a)		jc NEAR a +#define	JE(a)		je NEAR a +#define	JG(a)		jg NEAR a +#define	JGE(a)		jge NEAR a +#define	JL(a)		jl NEAR a +#define	JLE(a)		jle NEAR a +#define	JNA(a)		jna NEAR a +#define	JNAE(a)		jnae NEAR a +#define	JNB(a)		jnb NEAR a +#define	JNBE(a)		jnbe NEAR a +#define	JNC(a)		jnc NEAR a +#define	JNE(a)		jne NEAR a +#define	JNG(a)		jng NEAR a +#define	JNGE(a)		jnge NEAR a +#define	JNL(a)		jnl NEAR a +#define	JNLE(a)		jnle NEAR a +#define	JNO(a)		jno NEAR a +#define	JNP(a)		jnp NEAR a +#define	JNS(a)		jns NEAR a +#define	JNZ(a)		jnz NEAR a +#define	JO(a)		jo NEAR a +#define	JP(a)		jp NEAR a +#define	JPE(a)		jpe NEAR a +#define	JPO(a)		jpo NEAR a +#define	JS(a)		js NEAR a +#define	JZ(a)		jz NEAR a +#define	JMP(a)		jmp a +#define	JMPF(s,a)	jmpf +#define	LAHF		lahf		 +#define	LAR(a, b)	lar b, a +#define	LEA_L(a, b)	lea P_(b), P_(a) +#define	LEA_W(a, b)	lea P_(b), P_(a) +#define	LEAVE		leave		 +#define	LGDT(a)		lgdt a +#define	LIDT(a)		lidt a +#define	LDS(a, b)	lds b, a +#define	LES(a, b)	les b, a +#define	LFS(a, b)	lfs b, a +#define	LGS(a, b)	lgs b, a +#define	LSS(a, b)	lss b, a +#define	LLDT(a)		lldt a +#define	LMSW(a)		lmsw a +#define LOCK		lock		 +#define	LODS_L		lodsd +#define	LODS_W		lodsw +#define	LODS_B		lodsb +#define	LOOP(a)		loop a +#define	LOOPE(a)	loope a +#define	LOOPZ(a)	loopz a +#define	LOOPNE(a)	loopne a +#define	LOOPNZ(a)	loopnz a +#define	LSL(a, b)	lsl b, a +#define	LTR(a)		ltr a +#define	MOV_SR(a, b)	mov S_(b), S_(a) +#define	MOV_L(a, b)	mov L_(b), L_(a) +#define	MOV_W(a, b)	mov W_(b), W_(a) +#define	MOV_B(a, b)	mov B_(b), B_(a) +#define	MOVS_L		movsd +#define	MOVS_W		movsw +#define	MOVS_B		movsb +#define	MOVSX_BL(a, b)	movsx B_(b), B_(a) +#define	MOVSX_BW(a, b)	movsx B_(b), B_(a) +#define	MOVSX_WL(a, b)	movsx W_(b), W_(a) +#define	MOVZX_BL(a, b)	movzx B_(b), B_(a) +#define	MOVZX_BW(a, b)	movzx B_(b), B_(a) +#define	MOVZX_WL(a, b)	movzx W_(b), W_(a) +#define	MUL_L(a)	mul L_(a) +#define	MUL_W(a)	mul W_(a) +#define	MUL_B(a)	mul B_(a) +#define	NEG_L(a)	neg L_(a) +#define	NEG_W(a)	neg W_(a) +#define	NEG_B(a)	neg B_(a) +#define	NOP		nop		 +#define	NOT_L(a)	not L_(a) +#define	NOT_W(a)	not W_(a) +#define	NOT_B(a)	not B_(a) +#define	OR_L(a,b)	or L_(b), L_(a) +#define	OR_W(a,b)	or W_(b), W_(a) +#define	OR_B(a,b)	or B_(b), B_(a) +#define	OUT_L		out DX, EAX +#define	OUT_W		out DX, AX +#define	OUT_B		out DX, AL +#define	OUT1_L(a)	out1 L_(a) +#define	OUT1_W(a)	out1 W_(a) +#define	OUT1_B(a)	out1 B_(a) +#define	OUTS_L		outsd +#define	OUTS_W		outsw +#define	OUTS_B		outsb +#define	POP_SR(a)	pop S_(a) +#define	POP_L(a)	pop L_(a) +#define	POP_W(a)	pop W_(a) +#define	POPA_L		popad +#define	POPA_W		popa +#define	POPF_L		popfd +#define	POPF_W		popf +#define	PUSH_SR(a)	push S_(a) +#define	PUSH_L(a)	push L_(a) +#define	PUSH_W(a)	push W_(a) +#define	PUSH_B(a)	push B_(a) +#define	PUSHA_L		pushad +#define	PUSHA_W		pusha +#define	PUSHF_L		pushfd +#define	PUSHF_W		pushf +#define	RCL_L(a, b)	rcl L_(b), L_(a) +#define	RCL_W(a, b)	rcl W_(b), W_(a) +#define	RCL_B(a, b)	rcl B_(b), B_(a) +#define	RCR_L(a, b)	rcr L_(b), L_(a) +#define	RCR_W(a, b)	rcr W_(b), W_(a) +#define	RCR_B(a, b)	rcr B_(b), B_(a) +#define	ROL_L(a, b)	rol L_(b), L_(a) +#define	ROL_W(a, b)	rol W_(b), W_(a) +#define	ROL_B(a, b)	rol B_(b), B_(a) +#define	ROR_L(a, b)	ror L_(b), L_(a) +#define	ROR_W(a, b)	ror W_(b), W_(a) +#define	ROR_B(a, b)	ror B_(b), B_(a) +#define	REP		rep		 +#define	REPE		repe		 +#define	REPNE		repne		 +#define	REPNZ		REPNE +#define	REPZ		REPE +#define	RET		ret		 +#define	SAHF		sahf		 +#define	SAL_L(a, b)	sal L_(b), L_(a) +#define	SAL_W(a, b)	sal W_(b), W_(a) +#define	SAL_B(a, b)	sal B_(b), B_(a) +#define	SAR_L(a, b)	sar L_(b), L_(a) +#define	SAR_W(a, b)	sar W_(b), W_(a) +#define	SAR_B(a, b)	sar B_(b), B_(a) +#define	SBB_L(a, b)	sbb L_(b), L_(a) +#define	SBB_W(a, b)	sbb W_(b), W_(a) +#define	SBB_B(a, b)	sbb B_(b), B_(a) +#define	SCAS_L		scas +#define	SCAS_W		scas +#define	SCAS_B		scas +#define	SETA(a)		seta a +#define	SETAE(a)	setae a +#define	SETB(a)		setb a +#define	SETBE(a)	setbe a +#define	SETC(a)		setc a +#define	SETE(a)		sete a +#define	SETG(a)		setg a +#define	SETGE(a)	setge a +#define	SETL(a)		setl a +#define	SETLE(a)	setle a +#define	SETNA(a)	setna a +#define	SETNAE(a)	setnae a +#define	SETNB(a)	setnb a +#define	SETNBE(a)	setnbe a +#define	SETNC(a)	setnc a +#define	SETNE(a)	setne a +#define	SETNG(a)	setng a +#define	SETNGE(a)	setnge a +#define	SETNL(a)	setnl a +#define	SETNLE(a)	setnle a +#define	SETNO(a)	setno a +#define	SETNP(a)	setnp a +#define	SETNS(a)	setns a +#define	SETNZ(a)	setnz a +#define	SETO(a)		seto a +#define	SETP(a)		setp a +#define	SETPE(a)	setpe a +#define	SETPO(a)	setpo a +#define	SETS(a)		sets a +#define	SETZ(a)		setz a +#define	SGDT(a)		sgdt a +#define	SIDT(a)		sidt a +#define	SHL_L(a, b)	shl L_(b), L_(a) +#define	SHL_W(a, b)	shl W_(b), W_(a) +#define	SHL_B(a, b)	shl B_(b), B_(a) +#define	SHLD_L(a,b,c)	shld +#define	SHLD2_L(a,b)	shld L_(b), L_(a) +#define	SHLD_W(a,b,c)	shld +#define	SHLD2_W(a,b)	shld W_(b), W_(a) +#define	SHR_L(a, b)	shr L_(b), L_(a) +#define	SHR_W(a, b)	shr W_(b), W_(a) +#define	SHR_B(a, b)	shr B_(b), B_(a) +#define	SHRD_L(a,b,c)	shrd +#define	SHRD2_L(a,b)	shrd L_(b), L_(a) +#define	SHRD_W(a,b,c)	shrd +#define	SHRD2_W(a,b)	shrd W_(b), W_(a) +#define	SLDT(a)		sldt a +#define	SMSW(a)		smsw a +#define	STC		stc		 +#define	STD		std		 +#define	STI		sti		 +#define	STOS_L		stos +#define	STOS_W		stos +#define	STOS_B		stos +#define	STR(a)		str a +#define	SUB_L(a, b)	sub L_(b), L_(a) +#define	SUB_W(a, b)	sub W_(b), W_(a) +#define	SUB_B(a, b)	sub B_(b), B_(a) +#define	TEST_L(a, b)	test L_(b), L_(a) +#define	TEST_W(a, b)	test W_(b), W_(a) +#define	TEST_B(a, b)	test B_(b), B_(a) +#define	VERR(a)		verr a +#define	VERW(a)		verw a +#define	WAIT		wait		 +#define	XCHG_L(a, b)	xchg L_(b), L_(a) +#define	XCHG_W(a, b)	xchg W_(b), W_(a) +#define	XCHG_B(a, b)	xchg B_(b), B_(a) +#define	XLAT		xlat		 +#define	XOR_L(a, b)	xor L_(b), L_(a) +#define	XOR_W(a, b)	xor W_(b), W_(a) +#define	XOR_B(a, b)	xor B_(b), B_(a) +#define	F2XM1		f2xm1		 +#define	FABS		fabs		 +#define	FADD_D(a)	fadd D_(a) +#define	FADD_S(a)	fadd S_(a) +#define	FADD2(a, b)	fadd b, a +#define	FADDP(a, b)	faddp b, a +#define	FIADD_L(a)	fiadd L_(a) +#define	FIADD_W(a)	fiadd W_(a) +#define	FBLD(a)		fbld a +#define	FBSTP(a)	fbstp a +#define	FCHS		fchs		 +#define	FCLEX		fclex		 +#define	FNCLEX		fnclex		 +#define	FCOM(a)		fcom a +#define	FCOM_D(a)	fcom D_(a) +#define	FCOM_S(a)	fcom S_(a) +#define	FCOMP(a)	fcomp a +#define	FCOMP_D(a)	fcomp D_(a) +#define	FCOMP_S(a)	fcomp S_(a) +#define	FCOMPP		fcompp		 +#define	FCOS		fcos		 +#define	FDECSTP		fdecstp		 +#define	FDIV_D(a)	fdiv D_(a) +#define	FDIV_S(a)	fdiv S_(a) +#define	FDIV2(a, b)	fdiv b, a +#define	FDIVP(a, b)	fdivp b, a +#define	FIDIV_L(a)	fidiv L_(a) +#define	FIDIV_W(a)	fidiv W_(a) +#define	FDIVR_D(a)	fdivr D_(a) +#define	FDIVR_S(a)	fdivr S_(a) +#define	FDIVR2(a, b)	fdivr b, a +#define	FDIVRP(a, b)	fdivrp b, a +#define	FIDIVR_L(a)	fidivr L_(a) +#define	FIDIVR_W(a)	fidivr W_(a) +#define	FFREE(a)	ffree a +#define	FICOM_L(a)	ficom L_(a) +#define	FICOM_W(a)	ficom W_(a) +#define	FICOMP_L(a)	ficomp L_(a) +#define	FICOMP_W(a)	ficomp W_(a) +#define	FILD_Q(a)	fild D_(a) +#define	FILD_L(a)	fild L_(a) +#define	FILD_W(a)	fild W_(a) +#define	FINCSTP		fincstp		 +#define	FINIT		finit		 +#define	FNINIT		fninit		 +#define	FIST_L(a)	fist L_(a) +#define	FIST_W(a)	fist W_(a) +#define	FISTP_Q(a)	fistp D_(a) +#define	FISTP_L(a)	fistp L_(a) +#define	FISTP_W(a)	fistp W_(a) +#define	FLD_X(a)	fld X_(a) +#define	FLD_D(a)	fld D_(a) +#define	FLD_S(a)	fld S_(a) +#define	FLD1		fld1		 +#define	FLDL2T		fldl2t		 +#define	FLDL2E		fldl2e		 +#define	FLDPI		fldpi		 +#define	FLDLG2		fldlg2		 +#define	FLDLN2		fldln2		 +#define	FLDZ		fldz		 +#define	FLDCW(a)	fldcw a +#define	FLDENV(a)	fldenv a +#define	FMUL_S(a)	fmul S_(a) +#define	FMUL_D(a)	fmul D_(a) +#define	FMUL2(a, b)	fmul b, a +#define	FMULP(a, b)	fmulp b, a +#define	FIMUL_L(a)	fimul L_(a) +#define	FIMUL_W(a)	fimul W_(a) +#define	FNOP		fnop		 +#define	FPATAN		fpatan		 +#define	FPREM		fprem		 +#define	FPREM1		fprem1		 +#define	FPTAN		fptan		 +#define	FRNDINT		frndint		 +#define	FRSTOR(a)	frstor a +#define	FSAVE(a)	fsave a +#define	FNSAVE(a)	fnsave a +#define	FSCALE		fscale		 +#define	FSIN		fsin		 +#define	FSINCOS		fsincos		 +#define	FSQRT		fsqrt		 +#define	FST_D(a)	fst D_(a) +#define	FST_S(a)	fst S_(a) +#define	FSTP_X(a)	fstp X_(a) +#define	FSTP_D(a)	fstp D_(a) +#define	FSTP_S(a)	fstp S_(a) +#define	FSTP(a)		fstp a +#define	FSTCW(a)	fstcw a +#define	FNSTCW(a)	fnstcw a +#define	FSTENV(a)	fstenv a +#define	FNSTENV(a)	fnstenv a +#define	FSTSW(a)	fstsw a +#define	FNSTSW(a)	fnstsw a +#define	FSUB_S(a)	fsub S_(a) +#define	FSUB_D(a)	fsub D_(a) +#define	FSUB2(a, b)	fsub b, a +#define	FSUBP(a, b)	fsubp b, a +#define	FISUB_L(a)	fisub L_(a) +#define	FISUB_W(a)	fisub W_(a) +#define	FSUBR_S(a)	fsubr S_(a) +#define	FSUBR_D(a)	fsubr D_(a) +#define	FSUBR2(a, b)	fsubr b, a +#define	FSUBRP(a, b)	fsubrp b, a +#define	FISUBR_L(a)	fisubr L_(a) +#define	FISUBR_W(a)	fisubr W_(a) +#define	FTST		ftst		 +#define	FUCOM(a)	fucom a +#define	FUCOMP(a)	fucomp a +#define	FUCOMPP		fucompp		 +#define	FWAIT		fwait		 +#define	FXAM		fxam		 +#define	FXCH(a)		fxch a +#define	FXTRACT		fxtract		 +#define	FYL2X		fyl2x		 +#define	FYL2XP1		fyl2xp1		 + +/* New instructions */ +#define	CPUID		D_BYTE 15, 162 +#define	RDTSC		D_BYTE 15, 49 + +#endif /* NASM_ASSEMBLER, MASM_ASSEMBLER */ + +	/****************************************/ +	/*					*/ +	/*	Extensions to x86 insn set -	*/ +	/*	MMX, 3DNow!			*/ +	/*					*/ +	/****************************************/ + +#if defined(NASM_ASSEMBLER) || defined(MASM_ASSEMBLER) +#define P_ARG1(a) 	P_ ## a +#define P_ARG2(a, b) 	P_ ## b, P_ ## a +#define P_ARG3(a, b, c) 	P_ ## c, P_ ## b, P_ ## a +#else +#define P_ARG1(a) 	a +#define P_ARG2(a, b) 	a, b +#define P_ARG3(a, b) 	a, b, c +#endif + +/* MMX */ +#define MOVD(a, b) 	movd P_ARG2(a, b) +#define MOVQ(a, b) 	movq P_ARG2(a, b) + +#define PADDB(a, b) 	paddb P_ARG2(a, b) +#define PADDW(a, b) 	paddw P_ARG2(a, b) +#define PADDD(a, b) 	paddd P_ARG2(a, b) + +#define PADDSB(a, b) 	paddsb P_ARG2(a, b) +#define PADDSW(a, b) 	paddsw P_ARG2(a, b) + +#define PADDUSB(a, b) 	paddusb P_ARG2(a, b) +#define PADDUSW(a, b) 	paddusw P_ARG2(a, b) + +#define PSUBB(a, b) 	psubb P_ARG2(a, b) +#define PSUBW(a, b) 	psubw P_ARG2(a, b) +#define PSUBD(a, b) 	psubd P_ARG2(a, b) + +#define PSUBSB(a, b) 	psubsb P_ARG2(a, b) +#define PSUBSW(a, b) 	psubsw P_ARG2(a, b) + +#define PSUBUSB(a, b) 	psubusb P_ARG2(a, b) +#define PSUBUSW(a, b) 	psubusw P_ARG2(a, b) + +#define PCMPEQB(a, b) 	pcmpeqb P_ARG2(a, b) +#define PCMPEQW(a, b) 	pcmpeqw P_ARG2(a, b) +#define PCMPEQD(a, b) 	pcmpeqd P_ARG2(a, b) + +#define PCMPGTB(a, b) 	pcmpgtb P_ARG2(a, b) +#define PCMPGTW(a, b) 	pcmpgtw P_ARG2(a, b) +#define PCMPGTD(a, b) 	pcmpgtd P_ARG2(a, b) + +#define PMULHW(a, b) 	pmulhw P_ARG2(a, b) +#define PMULLW(a, b) 	pmullw P_ARG2(a, b) + +#define PMADDWD(a, b) 	pmaddwd P_ARG2(a, b) + +#define PAND(a, b) 	pand P_ARG2(a, b) + +#define PANDN(a, b) 	pandn P_ARG2(a, b) + +#define POR(a, b) 	por P_ARG2(a, b) + +#define PXOR(a, b) 	pxor P_ARG2(a, b) + +#define PSRAW(a, b) 	psraw P_ARG2(a, b) +#define PSRAD(a, b) 	psrad P_ARG2(a, b) + +#define PSRLW(a, b) 	psrlw P_ARG2(a, b) +#define PSRLD(a, b) 	psrld P_ARG2(a, b) +#define PSRLQ(a, b) 	psrlq P_ARG2(a, b) + +#define PSLLW(a, b) 	psllw P_ARG2(a, b) +#define PSLLD(a, b) 	pslld P_ARG2(a, b) +#define PSLLQ(a, b) 	psllq P_ARG2(a, b) + +#define PACKSSWB(a, b) 	packsswb P_ARG2(a, b) +#define PACKSSDW(a, b) 	packssdw P_ARG2(a, b) +#define PACKUSWB(a, b) 	packuswb P_ARG2(a, b) + +#define PUNPCKHBW(a, b) 	punpckhbw P_ARG2(a, b) +#define PUNPCKHWD(a, b) 	punpckhwd P_ARG2(a, b) +#define PUNPCKHDQ(a, b) 	punpckhdq P_ARG2(a, b) +#define PUNPCKLBW(a, b) 	punpcklbw P_ARG2(a, b) +#define PUNPCKLWD(a, b) 	punpcklwd P_ARG2(a, b) +#define PUNPCKLDQ(a, b) 	punpckldq P_ARG2(a, b) + +#define EMMS 	emms + +/* AMD 3DNow! */ +#define PAVGUSB(a, b) 	pavgusb P_ARG2(a, b) +#define PFADD(a, b) 	pfadd P_ARG2(a, b) +#define PFSUB(a, b) 	pfsub P_ARG2(a, b) +#define PFSUBR(a, b) 	pfsubr P_ARG2(a, b) +#define PFACC(a, b) 	pfacc P_ARG2(a, b) +#define PFCMPGE(a, b) 	pfcmpge P_ARG2(a, b) +#define PFCMPGT(a, b) 	pfcmpgt P_ARG2(a, b) +#define PFCMPEQ(a, b) 	pfcmpeq P_ARG2(a, b) +#define PFMIN(a, b) 	pfmin P_ARG2(a, b) +#define PFMAX(a, b) 	pfmax P_ARG2(a, b) +#define PI2FD(a, b) 	pi2fd P_ARG2(a, b) +#define PF2ID(a, b) 	pf2id P_ARG2(a, b) +#define PFRCP(a, b) 	pfrcp P_ARG2(a, b) +#define PFRSQRT(a, b) 	pfrsqrt P_ARG2(a, b) +#define PFMUL(a, b) 	pfmul P_ARG2(a, b) +#define PFRCPIT1(a, b) 	pfrcpit1 P_ARG2(a, b) +#define PFRSQIT1(a, b) 	pfrsqit1 P_ARG2(a, b) +#define PFRCPIT2(a, b) 	pfrcpit2 P_ARG2(a, b) +#define PMULHRW(a, b) 	pmulhrw P_ARG2(a, b) + +#define FEMMS	femms +#define PREFETCH(a) 	prefetch P_ARG1(a) + +/* Intel SSE */ +#define ADDPS(a, b)	addps P_ARG2(a, b) +#define ADDSS(a, b)	addss P_ARG2(a, b) +#define ANDNPS(a, b)	andnps P_ARG2(a, b) +#define ANDPS(a, b)	andps P_ARG2(a, b) +/* + NASM only knows the pseudo ops for these. +	#define CMPPS(a, b, c)	cmpps P_ARG3(a, b, c) +	#define CMPSS(a, b, c)	cmpss P_ARG3(a, b, c) +*/ +#define CMPEQPS(a, b)	cmpeqps P_ARG3(a, b) +#define CMPLTPS(a, b)	cmpltps P_ARG3(a, b) +#define CMPLEPS(a, b)	cmpleps P_ARG3(a, b) +#define CMPUNORDPS(a, b)	cmpunordps P_ARG3(a, b) +#define CMPNEQPS(a, b)	cmpneqps P_ARG3(a, b) +#define CMPNLTPS(a, b)	cmpnltps P_ARG3(a, b) +#define CMPNLEPS(a, b)	cmpnleps P_ARG3(a, b) +#define CMPORDPS(a, b)	cmpordps P_ARG3(a, b) +#define CMPEQSS(a, b)	cmpeqss P_ARG3(a, b) +#define CMPLTSS(a, b)	cmpltss P_ARG3(a, b) +#define CMPLESS(a, b)	cmpless P_ARG3(a, b) +#define CMPUNORDSS(a, b)	cmpunordss P_ARG3(a, b) +#define CMPNEQSS(a, b)	cmpneqss P_ARG3(a, b) +#define CMPNLTSS(a, b)	cmpnltss P_ARG3(a, b) +#define CMPNLESS(a, b)	cmpnless P_ARG3(a, b) +#define CMPORDSS(a, b)	cmpordss P_ARG3(a, b) +#define COMISS(a, b)	comiss P_ARG2(a, b) +#define CVTPI2PS(a, b)	cvtpi2ps P_ARG2(a, b) +#define CVTPS2PI(a, b)	cvtps2pi P_ARG2(a, b) +#define CVTSI2SS(a, b)	cvtsi2ss P_ARG2(a, b) +#define CVTSS2SI(a, b)	cvtss2si P_ARG2(a, b) +#define CVTTPS2PI(a, b)	cvttps2pi P_ARG2(a, b) +#define CVTTSS2SI(a, b)	cvttss2si P_ARG2(a, b) +#define DIVPS(a, b)	divps P_ARG2(a, b) +#define DIVSS(a, b)	divss P_ARG2(a, b) +#define FXRSTOR(a)	fxrstor P_ARG1(a) +#define FXSAVE(a)	fxsave P_ARG1(a) +#define LDMXCSR(a)	ldmxcsr P_ARG1(a) +#define MAXPS(a, b)	maxps P_ARG2(a, b) +#define MAXSS(a, b)	maxss P_ARG2(a, b) +#define MINPS(a, b)	minps P_ARG2(a, b) +#define MINSS(a, b)	minss P_ARG2(a, b) +#define MOVAPS(a, b)	movaps P_ARG2(a, b) +#define MOVHLPS(a, b)	movhlps P_ARG2(a, b) +#define MOVHPS(a, b)	movhps P_ARG2(a, b) +#define MOVLHPS(a, b)	movlhps P_ARG2(a, b) +#define MOVLPS(a, b)	movlps P_ARG2(a, b) +#define MOVMSKPS(a, b)	movmskps P_ARG2(a, b) +#define MOVSS(a, b)	movss P_ARG2(a, b) +#define MOVUPS(a, b)	movups P_ARG2(a, b) +#define MULPS(a, b)	mulps P_ARG2(a, b) +#define MULSS(a, b)	mulss P_ARG2(a, b) +#define ORPS(a, b)	orps P_ARG2(a, b) +#define RCPPS(a, b)	rcpps P_ARG2(a, b) +#define RCPSS(a, b)	rcpss P_ARG2(a, b) +#define RSQRTPS(a, b)	rsqrtps P_ARG2(a, b) +#define RSQRTSS(a, b)	rsqrtss P_ARG2(a, b) +#define SHUFPS(a, b, c)	shufps P_ARG3(a, b, c) +#define SQRTPS(a, b)	sqrtps P_ARG2(a, b) +#define SQRTSS(a, b)	sqrtss P_ARG2(a, b) +#define STMXCSR(a)	stmxcsr P_ARG1(a) +#define SUBPS(a, b)	subps P_ARG2(a, b) +#define UCOMISS(a, b)	ucomiss P_ARG2(a, b) +#define UNPCKHPS(a, b)	unpckhps P_ARG2(a, b) +#define UNPCKLPS(a, b)	unpcklps P_ARG2(a, b) +#define XORPS(a, b)	xorps P_ARG2(a, b) + + +#endif /* __ASSYNTAX_H__ */ diff --git a/src/mesa/x86/common_x86.c b/src/mesa/x86/common_x86.c new file mode 100644 index 0000000000..7d30be94cf --- /dev/null +++ b/src/mesa/x86/common_x86.c @@ -0,0 +1,77 @@ + +/* + * 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. + */ + + +/* + *  Check CPU capabilities & initialize optimized funtions for this particular + *   processor. + * + *  Written by Holger Waechtler <holger@akaflieg.extern.tu-berlin.de> + */ + +#include <stdlib.h> +#include "common_x86asm.h" + +int gl_x86_cpu_features = 0; + + +void gl_init_all_x86_asm (void) +{ +#ifdef USE_X86_ASM +   gl_x86_cpu_features = gl_identify_x86_cpu_features (); + +   if (gl_x86_cpu_features & GL_CPU_GenuineIntel) { +      printf ("GenuineIntel cpu detected.\n"); +   } +   gl_init_x86_asm_transforms (); + + +#ifdef USE_MMX_ASM +   if (gl_x86_cpu_features & GL_CPU_MMX) { +      char *s = getenv( "MESA_NO_MMX" ); +      if (s == NULL) {  +         printf ("MMX cpu detected.\n"); +      } else { +         gl_x86_cpu_features &= (!GL_CPU_MMX);  +      } +   } +#endif + + +#ifdef USE_3DNOW_ASM +   if (gl_x86_cpu_features & GL_CPU_3Dnow) { +      char *s = getenv( "MESA_NO_3DNOW" ); +      if (s == NULL) { +         printf ("3Dnow cpu detected.\n"); +         gl_init_3dnow_asm_transforms (); +      } else { +         gl_x86_cpu_features &= (!GL_CPU_3Dnow);  +      } +   } +#endif + +#endif +} + diff --git a/src/mesa/x86/mmx.h b/src/mesa/x86/mmx.h new file mode 100644 index 0000000000..c8c5eff302 --- /dev/null +++ b/src/mesa/x86/mmx.h @@ -0,0 +1,77 @@ + +/* + * 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 ASM_MMX_H +#define ASM_MMX_H + + +extern void +gl_mmx_blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[], +                           GLubyte rgba[][4], const GLubyte dest[][4] ); + + +void gl_mmx_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 (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 = gl_mmx_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; +   } +} + + +#endif diff --git a/src/mesa/x86/mmx_blend.S b/src/mesa/x86/mmx_blend.S new file mode 100644 index 0000000000..7bd9ec3d24 --- /dev/null +++ b/src/mesa/x86/mmx_blend.S @@ -0,0 +1,363 @@ +#include "assyntax.h" + + +#if !defined(NASM_ASSEMBLER) && !defined(MASM_ASSEMBLER) +#define LLBL(a) .L ## a +#else +#define LLBL(a) a +#endif + + +SEG_TEXT + + +ALIGNTEXT16 +GLOBL GLNAME(gl_mmx_blend_transparency) + +GLNAME( gl_mmx_blend_transparency ): +    PUSH_L    ( EBP ) +    MOV_L     ( ESP, EBP ) +    SUB_L     ( CONST(52), ESP ) +    PUSH_L    ( EBX ) +    MOV_L     ( CONST(16711680), REGOFF(-8, EBP) ) +    MOV_L     ( CONST(16711680), REGOFF(-4, EBP) ) +    MOV_L     ( CONST(0), REGOFF(-16, EBP) ) +    MOV_L     ( CONST(-1), REGOFF(-12, EBP) ) +    MOV_L     ( CONST(-1), REGOFF(-24, EBP) ) +    MOV_L     ( CONST(0), REGOFF(-20, EBP) ) +    MOV_L     ( REGOFF(24, EBP), EAX ) +    ADD_L     ( CONST(4), EAX ) +    MOV_L     ( EAX, EDX ) +    AND_L     ( REGOFF(20, EBP), EDX ) +    MOV_L     ( EDX, EAX ) +    AND_L     ( CONST(4), EAX ) +    CMP_L     ( CONST(8), EAX ) +    JNE       ( LLBL(GMBT_2) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    ADD_L     ( CONST(3), EAX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(EAX), DL ) +    MOV_L     ( EDX, REGOFF(-32, EBP) ) +    MOV_L     ( CONST(255), EAX ) +    MOV_L     ( EAX, EBX ) +    SUB_L     ( REGOFF(-32, EBP), EBX ) +    MOV_L     ( EBX, REGOFF(-36, EBP) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(EAX), DL ) +    MOV_L     ( EDX, EAX ) +    IMUL_L    ( REGOFF(-32, EBP), EAX ) +    MOV_L     ( REGOFF(24, EBP), EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EDX ) +    IMUL_L    ( REGOFF(-36, EBP), EDX ) +    ADD_L     ( EDX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-40, EBP) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    INC_L     ( EAX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(EAX), DL ) +    MOV_L     ( EDX, EAX ) +    IMUL_L    ( REGOFF(-32, EBP), EAX ) +    MOV_L     ( REGOFF(24, EBP), EDX ) +    INC_L     ( EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EDX ) +    IMUL_L    ( REGOFF(-36, EBP), EDX ) +    ADD_L     ( EDX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-44, EBP) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    ADD_L     ( CONST(2), EAX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(EAX), DL ) +    MOV_L     ( EDX, EAX ) +    IMUL_L    ( REGOFF(-32, EBP), EAX ) +    MOV_L     ( REGOFF(24, EBP), EDX ) +    ADD_L     ( CONST(2), EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EDX ) +    IMUL_L    ( REGOFF(-36, EBP), EDX ) +    ADD_L     ( EDX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-48, EBP) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    ADD_L     ( CONST(3), EAX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(EAX), DL ) +    MOV_L     ( EDX, EAX ) +    IMUL_L    ( REGOFF(-32, EBP), EAX ) +    MOV_L     ( REGOFF(24, EBP), EDX ) +    ADD_L     ( CONST(3), EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EDX ) +    IMUL_L    ( REGOFF(-36, EBP), EDX ) +    ADD_L     ( EDX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-52, EBP) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    MOV_B     ( REGOFF(-40, EBP), DL ) +    MOV_B     ( DL, REGIND(EAX) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    INC_L     ( EAX ) +    MOV_B     ( REGOFF(-44, EBP), DL ) +    MOV_B     ( DL, REGIND(EAX) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    ADD_L     ( CONST(2), EAX ) +    MOV_B     ( REGOFF(-48, EBP), DL ) +    MOV_B     ( DL, REGIND(EAX) ) +    MOV_L     ( REGOFF(20, EBP), EAX ) +    ADD_L     ( CONST(3), EAX ) +    MOV_B     ( REGOFF(-52, EBP), DL ) +    MOV_B     ( DL, REGIND(EAX) ) +    INC_L     ( REGOFF(16, EBP) ) +    ADD_L     ( CONST(4), REGOFF(20, EBP) ) +    ADD_L     ( CONST(4), REGOFF(24, EBP) ) +    DEC_L     ( REGOFF(12, EBP) ) +LLBL( GMBT_2 ): + +    CMP_L     ( CONST(0), REGOFF(12, EBP) ) +    JE        ( LLBL(GMBT_3) ) +    MOV_L     ( CONST(0), REGOFF(-28, EBP) ) +ALIGNTEXT4 +LLBL( GMBT_4 ): + +    MOV_L     ( REGOFF(12, EBP), EDX ) +    MOV_L     ( EDX, EAX ) +    SHR_L     ( CONST(1), EAX ) +    CMP_L     ( EAX, REGOFF(-28, EBP) ) +    JB        ( LLBL(GMBT_7) ) +    JMP       ( LLBL(GMBT_5) ) +ALIGNTEXT16 +LLBL( GMBT_7 ): + +    MOV_L     ( REGOFF(-28, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,2), EDX ) +    MOV_L     ( REGOFF(16, EBP), EAX ) +    CMP_B     ( CONST(0), REGBI(EAX,EDX) ) +    JE        ( LLBL(GMBT_6) ) +    MOV_L     ( REGOFF(-28, EBP), EAX ) +    MOV_L     ( EAX, EDX ) +    LEA_L     ( REGDIS(0,EDX,8), ECX ) +    MOV_L     ( ECX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    MOV_L     ( REGOFF(-28, EBP), EDX ) +    MOV_L     ( EDX, ECX ) +    LEA_L     ( REGDIS(0,ECX,8), EDX ) +    MOV_L     ( EDX, ECX ) +    ADD_L     ( REGOFF(24, EBP), ECX ) + +    MOVQ      ( REGIND(EAX), MM4 ) +    PXOR      ( MM5, MM5 ) +    MOVQ      ( MM4, MM1 ) +    MOVQ      ( REGIND(ECX), MM7 ) +    PUNPCKLBW ( MM5, MM1 ) +    MOVQ      ( MM7, MM6 ) +    MOVQ      ( MM1, MM0 ) +    PUNPCKLBW ( MM5, MM6 ) +    MOVQ      ( MM1, MM2 ) +    PSRLQ     ( CONST(48), MM0 ) +    PUNPCKHBW ( MM5, MM4 ) +    PACKSSDW  ( MM0, MM0 ) +    MOVQ      ( MM0, MM3 ) +    PUNPCKHBW ( MM5, MM7 ) +    PSLLQ     ( CONST(16), MM3 ) +    POR       ( REGOFF(-8, EBP), MM0 ) +    PUNPCKLWD ( MM6, MM1 ) +    PSUBW     ( MM3, MM0 ) +    PUNPCKHWD ( MM6, MM2 ) +    MOVQ      ( MM4, MM3 ) +    PSRLQ     ( CONST(48), MM3 ) +    PACKSSDW  ( MM3, MM3 ) +    MOVQ      ( MM3, MM6 ) +    POR       ( REGOFF(-8, EBP), MM3 ) +    PSLLQ     ( CONST(16), MM6 ) +    PSUBW     ( MM6, MM3 ) +    MOVQ      ( MM4, MM5 ) +    PUNPCKLWD ( MM7, MM4 ) +    PUNPCKHWD ( MM7, MM5 ) +    PMADDWD   ( MM0, MM1 ) +    PMADDWD   ( MM3, MM4 ) +    PMADDWD   ( MM0, MM2 ) +    PMADDWD   ( MM3, MM5 ) +    PSRLD     ( CONST(8), MM1 ) +    PSRLD     ( CONST(8), MM2 ) +    PSRLD     ( CONST(8), MM4 ) +    PACKSSDW  ( MM2, MM1 ) +    PSRLD     ( CONST(8), MM5 ) +    PACKUSWB  ( MM1, MM1 ) +    PACKSSDW  ( MM5, MM4 ) +    PAND      ( REGOFF(-24, EBP), MM1 ) +    PACKUSWB  ( MM4, MM4 ) +    PAND      ( REGOFF(-16, EBP), MM4 ) +    POR       ( MM1, MM4 ) +    MOVQ      ( MM4, REGIND(EAX) ) + + +LLBL( GMBT_8 ): + +LLBL( GMBT_6 ): + +    INC_L     ( REGOFF(-28, EBP) ) +    JMP       ( LLBL(GMBT_4) ) +ALIGNTEXT16 +LLBL( GMBT_5 ): + + +    EMMS + +LLBL( GMBT_3 ): + +    MOV_L     ( REGOFF(12, EBP), EAX ) +    AND_L     ( CONST(1), EAX ) +    TEST_L    ( EAX, EAX ) +    JE        ( LLBL(GMBT_9) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-1, EAX), EDX ) +    XOR_L     ( EAX, EAX ) +    MOV_B     ( REGIND(EDX), AL ) +    MOV_L     ( EAX, REGOFF(-52, EBP) ) +    MOV_L     ( CONST(255), EAX ) +    MOV_L     ( EAX, EBX ) +    SUB_L     ( REGOFF(-52, EBP), EBX ) +    MOV_L     ( EBX, REGOFF(-48, EBP) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-4, EAX), EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EAX ) +    IMUL_L    ( REGOFF(-52, EBP), EAX ) +    MOV_L     ( REGOFF(12, EBP), EDX ) +    LEA_L     ( REGDIS(0,EDX,4), ECX ) +    MOV_L     ( ECX, EDX ) +    ADD_L     ( REGOFF(24, EBP), EDX ) +    LEA_L     ( REGOFF(-4, EDX), ECX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(ECX), DL ) +    MOV_L     ( EDX, ECX ) +    IMUL_L    ( REGOFF(-48, EBP), ECX ) +    ADD_L     ( ECX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-44, EBP) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-3, EAX), EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EAX ) +    IMUL_L    ( REGOFF(-52, EBP), EAX ) +    MOV_L     ( REGOFF(12, EBP), EDX ) +    LEA_L     ( REGDIS(0,EDX,4), ECX ) +    MOV_L     ( ECX, EDX ) +    ADD_L     ( REGOFF(24, EBP), EDX ) +    LEA_L     ( REGOFF(-3, EDX), ECX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(ECX), DL ) +    MOV_L     ( EDX, ECX ) +    IMUL_L    ( REGOFF(-48, EBP), ECX ) +    ADD_L     ( ECX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-40, EBP) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-2, EAX), EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EAX ) +    IMUL_L    ( REGOFF(-52, EBP), EAX ) +    MOV_L     ( REGOFF(12, EBP), EDX ) +    LEA_L     ( REGDIS(0,EDX,4), ECX ) +    MOV_L     ( ECX, EDX ) +    ADD_L     ( REGOFF(24, EBP), EDX ) +    LEA_L     ( REGOFF(-2, EDX), ECX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(ECX), DL ) +    MOV_L     ( EDX, ECX ) +    IMUL_L    ( REGOFF(-48, EBP), ECX ) +    ADD_L     ( ECX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-36, EBP) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-1, EAX), EDX ) +    XOR_L     ( ECX, ECX ) +    MOV_B     ( REGIND(EDX), CL ) +    MOV_L     ( ECX, EAX ) +    IMUL_L    ( REGOFF(-52, EBP), EAX ) +    MOV_L     ( REGOFF(12, EBP), EDX ) +    LEA_L     ( REGDIS(0,EDX,4), ECX ) +    MOV_L     ( ECX, EDX ) +    ADD_L     ( REGOFF(24, EBP), EDX ) +    LEA_L     ( REGOFF(-1, EDX), ECX ) +    XOR_L     ( EDX, EDX ) +    MOV_B     ( REGIND(ECX), DL ) +    MOV_L     ( EDX, ECX ) +    IMUL_L    ( REGOFF(-48, EBP), ECX ) +    ADD_L     ( ECX, EAX ) +    MOV_L     ( EAX, EBX ) +    SAR_L     ( CONST(8), EBX ) +    MOV_L     ( EBX, REGOFF(-32, EBP) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-4, EAX), EDX ) +    MOV_B     ( REGOFF(-44, EBP), AL ) +    MOV_B     ( AL, REGIND(EDX) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-3, EAX), EDX ) +    MOV_B     ( REGOFF(-40, EBP), AL ) +    MOV_B     ( AL, REGIND(EDX) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-2, EAX), EDX ) +    MOV_B     ( REGOFF(-36, EBP), AL ) +    MOV_B     ( AL, REGIND(EDX) ) +    MOV_L     ( REGOFF(12, EBP), EAX ) +    LEA_L     ( REGDIS(0,EAX,4), EDX ) +    MOV_L     ( EDX, EAX ) +    ADD_L     ( REGOFF(20, EBP), EAX ) +    LEA_L     ( REGOFF(-1, EAX), EDX ) +    MOV_B     ( REGOFF(-32, EBP), AL ) +    MOV_B     ( AL, REGIND(EDX) ) +LLBL( GMBT_9 ): + +LLBL( GMBT_1 ): + +    MOV_L     ( REGOFF(-56, EBP), EBX ) +    MOV_L     ( EBP, ESP ) +    POP_L     ( EBP ) +    RET + + + + diff --git a/src/mesa/x86/x86.c b/src/mesa/x86/x86.c new file mode 100644 index 0000000000..fe3bb34c91 --- /dev/null +++ b/src/mesa/x86/x86.c @@ -0,0 +1,107 @@ +/* $Id: x86.c,v 1.1 1999/08/19 00:55:42 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. + */ + +/* + * Intel x86 assembly code by Josh Vanderhoof + */ + + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include "context.h" +#include "types.h" +#include "xform.h" +#include "x86.h" + + + +#define XFORM_ARGS 	GLvector4f *to_vec, 		\ +			const GLmatrix *mat, 		\ +			const GLvector4f *from_vec, 	\ +			const GLubyte *mask, 		\ +			const GLubyte flag + +#define DECLARE_XFORM_GROUP(pfx, vsize, masked) \ + extern void gl_##pfx##_transform_points##vsize##_general_##masked(XFORM_ARGS); 	\ + extern void gl_##pfx##_transform_points##vsize##_identity_##masked(XFORM_ARGS); 	\ + extern void gl_##pfx##_transform_points##vsize##_3d_no_rot_##masked(XFORM_ARGS); 	\ + extern void gl_##pfx##_transform_points##vsize##_perspective_##masked(XFORM_ARGS); 	\ + extern void gl_##pfx##_transform_points##vsize##_2d_##masked(XFORM_ARGS); 		\ + extern void gl_##pfx##_transform_points##vsize##_2d_no_rot_##masked(XFORM_ARGS); 	\ + extern void gl_##pfx##_transform_points##vsize##_3d_##masked(XFORM_ARGS); + +#define ASSIGN_XFORM_GROUP( pfx, cma, vsize, masked ) 		\ + gl_transform_tab[cma][vsize][MATRIX_GENERAL] 			\ +  = gl_##pfx##_transform_points##vsize##_general_##masked; 	\ + gl_transform_tab[cma][vsize][MATRIX_IDENTITY] 			\ +  = gl_##pfx##_transform_points##vsize##_identity_##masked; 	\ + gl_transform_tab[cma][vsize][MATRIX_3D_NO_ROT] 		\ +  = gl_##pfx##_transform_points##vsize##_3d_no_rot_##masked; 	\ + gl_transform_tab[cma][vsize][MATRIX_PERSPECTIVE] 		\ +  = gl_##pfx##_transform_points##vsize##_perspective_##masked; 	\ + gl_transform_tab[cma][vsize][MATRIX_2D] 			\ +  = gl_##pfx##_transform_points##vsize##_2d_##masked; 		\ + gl_transform_tab[cma][vsize][MATRIX_2D_NO_ROT] 		\ +  = gl_##pfx##_transform_points##vsize##_2d_no_rot_##masked; 	\ + gl_transform_tab[cma][vsize][MATRIX_3D] 			\ +  = gl_##pfx##_transform_points##vsize##_3d_##masked; + +void gl_init_x86_asm_transforms( void ) +{ +#ifdef USE_X86_ASM +   DECLARE_XFORM_GROUP( x86, 2, raw ) +   DECLARE_XFORM_GROUP( x86, 3, raw ) +   DECLARE_XFORM_GROUP( x86, 4, raw ) +   DECLARE_XFORM_GROUP( x86, 2, masked ) +   DECLARE_XFORM_GROUP( x86, 3, masked ) +   DECLARE_XFORM_GROUP( x86, 4, masked ) + +   extern GLvector4f *gl_x86_cliptest_points4( GLvector4f *clip_vec,  +                                               GLvector4f *proj_vec,  +                                               GLubyte clipMask[], +                                               GLubyte *orMask,  +                                               GLubyte *andMask ); + +    +   ASSIGN_XFORM_GROUP( x86, 0, 2, raw ) +   ASSIGN_XFORM_GROUP( x86, 0, 3, raw ) +   ASSIGN_XFORM_GROUP( x86, 0, 4, raw ) + +   ASSIGN_XFORM_GROUP( x86, CULL_MASK_ACTIVE, 2, masked ) +   ASSIGN_XFORM_GROUP( x86, CULL_MASK_ACTIVE, 3, masked ) +   ASSIGN_XFORM_GROUP( x86, CULL_MASK_ACTIVE, 4, masked ) + +   gl_clip_tab[4] = gl_x86_cliptest_points4; + +#ifdef DEBUG +   gl_test_all_transform_functions("x86"); +#endif + +#endif +} diff --git a/src/mesa/x86/x86.h b/src/mesa/x86/x86.h new file mode 100644 index 0000000000..c7aca91c9f --- /dev/null +++ b/src/mesa/x86/x86.h @@ -0,0 +1,37 @@ +/* $Id: x86.h,v 1.1 1999/08/19 00:55:42 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. + */ + +/* + * Intel x86 assembly code by Josh Vanderhoof + */ + + +#ifndef X86_H +#define X86_H + +extern void gl_init_x86_asm_transforms(void); + +#endif  | 
