summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorjtg <jtg>1999-08-19 00:55:39 +0000
committerjtg <jtg>1999-08-19 00:55:39 +0000
commitafb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1c (patch)
tree59d65b4da12fb5379224cf5f6b808fde91523c7f /src/mesa/drivers
parentf2544d4920ce168bec9cd94d774b7ea5103a3d74 (diff)
Initial revision
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/allegro/amesa.c395
-rw-r--r--src/mesa/drivers/allegro/direct.h189
-rw-r--r--src/mesa/drivers/allegro/generic.h233
-rw-r--r--src/mesa/drivers/beos/GLView.cpp1233
-rw-r--r--src/mesa/drivers/d3d/D3DCAPS.CPP251
-rw-r--r--src/mesa/drivers/d3d/D3DHAL.H69
-rw-r--r--src/mesa/drivers/d3d/D3DInit.cpp891
-rw-r--r--src/mesa/drivers/d3d/D3DMESA.H85
-rw-r--r--src/mesa/drivers/d3d/D3DRaster.cpp214
-rw-r--r--src/mesa/drivers/d3d/D3DShared.h154
-rw-r--r--src/mesa/drivers/d3d/D3DTEXT.CPP577
-rw-r--r--src/mesa/drivers/d3d/D3DTextureMgr.cpp948
-rw-r--r--src/mesa/drivers/d3d/D3DTextureMgr.h63
-rw-r--r--src/mesa/drivers/d3d/D3DUTILS.CPP639
-rw-r--r--src/mesa/drivers/d3d/D3Dvbrender.c2150
-rw-r--r--src/mesa/drivers/d3d/DDrawPROCS.c400
-rw-r--r--src/mesa/drivers/d3d/DEBUG.C144
-rw-r--r--src/mesa/drivers/d3d/DEBUG.H91
-rw-r--r--src/mesa/drivers/d3d/DbgEnv.bat25
-rw-r--r--src/mesa/drivers/d3d/MAKEFILE102
-rw-r--r--src/mesa/drivers/d3d/NULLProcs.h49
-rw-r--r--src/mesa/drivers/d3d/NullProcs.c130
-rw-r--r--src/mesa/drivers/d3d/OPENGL32.DEF443
-rw-r--r--src/mesa/drivers/d3d/WGL.C1262
-rw-r--r--src/mesa/drivers/d3d/d3dText.h53
-rw-r--r--src/mesa/drivers/dos/DEPEND.DOS119
-rw-r--r--src/mesa/drivers/dos/dosmesa.c1513
-rw-r--r--src/mesa/drivers/ggi/ggimesa.conf.in13
-rw-r--r--src/mesa/drivers/glide/fxapi.c1411
-rw-r--r--src/mesa/drivers/glide/fxdd.c632
-rw-r--r--src/mesa/drivers/glide/fxddspan.c817
-rw-r--r--src/mesa/drivers/glide/fxddtex.c1299
-rw-r--r--src/mesa/drivers/glide/fxdrv.h576
-rw-r--r--src/mesa/drivers/glide/fxglidew.c247
-rw-r--r--src/mesa/drivers/glide/fxglidew.h358
-rw-r--r--src/mesa/drivers/glide/fxopengl.def467
-rw-r--r--src/mesa/drivers/glide/fxsetup.c1552
-rw-r--r--src/mesa/drivers/glide/fxtexman.c579
-rw-r--r--src/mesa/drivers/glide/fxwgl.c806
-rw-r--r--src/mesa/drivers/osmesa/osmesa.c1594
-rw-r--r--src/mesa/drivers/svga/svgamesa.c540
-rw-r--r--src/mesa/drivers/windows/colors.h499
-rw-r--r--src/mesa/drivers/windows/mesa_extend.c211
-rw-r--r--src/mesa/drivers/windows/mesa_extend.h43
-rw-r--r--src/mesa/drivers/windows/stereo.h47
-rw-r--r--src/mesa/drivers/windows/wgl.c518
-rw-r--r--src/mesa/drivers/windows/wing32.def12
-rw-r--r--src/mesa/drivers/windows/wmesa.c3021
-rw-r--r--src/mesa/drivers/windows/wmesaBackup.c2879
-rw-r--r--src/mesa/drivers/windows/wmesaOld.c2737
-rw-r--r--src/mesa/drivers/windows/wmesa_stereo.c1872
-rw-r--r--src/mesa/drivers/windows/wmesadef.h154
-rw-r--r--src/mesa/drivers/x11/fakeglx.c1516
-rw-r--r--src/mesa/drivers/x11/glxapi.c405
-rw-r--r--src/mesa/drivers/x11/realglx.c239
-rw-r--r--src/mesa/drivers/x11/realglx.h111
-rw-r--r--src/mesa/drivers/x11/xfonts.c398
-rw-r--r--src/mesa/drivers/x11/xmesaP.h499
58 files changed, 38474 insertions, 0 deletions
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