From afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1c Mon Sep 17 00:00:00 2001 From: jtg Date: Thu, 19 Aug 1999 00:55:39 +0000 Subject: Initial revision --- src/mesa/drivers/allegro/amesa.c | 395 ++++ src/mesa/drivers/allegro/direct.h | 189 ++ src/mesa/drivers/allegro/generic.h | 233 +++ src/mesa/drivers/beos/GLView.cpp | 1233 +++++++++++++ src/mesa/drivers/d3d/D3DCAPS.CPP | 251 +++ src/mesa/drivers/d3d/D3DHAL.H | 69 + src/mesa/drivers/d3d/D3DInit.cpp | 891 +++++++++ src/mesa/drivers/d3d/D3DMESA.H | 85 + src/mesa/drivers/d3d/D3DRaster.cpp | 214 +++ src/mesa/drivers/d3d/D3DShared.h | 154 ++ src/mesa/drivers/d3d/D3DTEXT.CPP | 577 ++++++ src/mesa/drivers/d3d/D3DTextureMgr.cpp | 948 ++++++++++ src/mesa/drivers/d3d/D3DTextureMgr.h | 63 + src/mesa/drivers/d3d/D3DUTILS.CPP | 639 +++++++ src/mesa/drivers/d3d/D3Dvbrender.c | 2150 ++++++++++++++++++++++ src/mesa/drivers/d3d/DDrawPROCS.c | 400 ++++ src/mesa/drivers/d3d/DEBUG.C | 144 ++ src/mesa/drivers/d3d/DEBUG.H | 91 + src/mesa/drivers/d3d/DbgEnv.bat | 25 + src/mesa/drivers/d3d/MAKEFILE | 102 ++ src/mesa/drivers/d3d/NULLProcs.h | 49 + src/mesa/drivers/d3d/NullProcs.c | 130 ++ src/mesa/drivers/d3d/OPENGL32.DEF | 443 +++++ src/mesa/drivers/d3d/WGL.C | 1262 +++++++++++++ src/mesa/drivers/d3d/d3dText.h | 53 + src/mesa/drivers/dos/DEPEND.DOS | 119 ++ src/mesa/drivers/dos/dosmesa.c | 1513 ++++++++++++++++ src/mesa/drivers/ggi/ggimesa.conf.in | 13 + src/mesa/drivers/glide/fxapi.c | 1411 +++++++++++++++ src/mesa/drivers/glide/fxdd.c | 632 +++++++ src/mesa/drivers/glide/fxddspan.c | 817 +++++++++ src/mesa/drivers/glide/fxddtex.c | 1299 +++++++++++++ src/mesa/drivers/glide/fxdrv.h | 576 ++++++ src/mesa/drivers/glide/fxglidew.c | 247 +++ src/mesa/drivers/glide/fxglidew.h | 358 ++++ src/mesa/drivers/glide/fxopengl.def | 467 +++++ src/mesa/drivers/glide/fxsetup.c | 1552 ++++++++++++++++ src/mesa/drivers/glide/fxtexman.c | 579 ++++++ src/mesa/drivers/glide/fxwgl.c | 806 +++++++++ src/mesa/drivers/osmesa/osmesa.c | 1594 ++++++++++++++++ src/mesa/drivers/svga/svgamesa.c | 540 ++++++ src/mesa/drivers/windows/colors.h | 499 +++++ src/mesa/drivers/windows/mesa_extend.c | 211 +++ src/mesa/drivers/windows/mesa_extend.h | 43 + src/mesa/drivers/windows/stereo.h | 47 + src/mesa/drivers/windows/wgl.c | 518 ++++++ src/mesa/drivers/windows/wing32.def | 12 + src/mesa/drivers/windows/wmesa.c | 3021 +++++++++++++++++++++++++++++++ src/mesa/drivers/windows/wmesaBackup.c | 2879 +++++++++++++++++++++++++++++ src/mesa/drivers/windows/wmesaOld.c | 2737 ++++++++++++++++++++++++++++ src/mesa/drivers/windows/wmesa_stereo.c | 1872 +++++++++++++++++++ src/mesa/drivers/windows/wmesadef.h | 154 ++ src/mesa/drivers/x11/fakeglx.c | 1516 ++++++++++++++++ src/mesa/drivers/x11/glxapi.c | 405 +++++ src/mesa/drivers/x11/realglx.c | 239 +++ src/mesa/drivers/x11/realglx.h | 111 ++ src/mesa/drivers/x11/xfonts.c | 398 ++++ src/mesa/drivers/x11/xmesaP.h | 499 +++++ 58 files changed, 38474 insertions(+) create mode 100644 src/mesa/drivers/allegro/amesa.c create mode 100644 src/mesa/drivers/allegro/direct.h create mode 100644 src/mesa/drivers/allegro/generic.h create mode 100644 src/mesa/drivers/beos/GLView.cpp create mode 100644 src/mesa/drivers/d3d/D3DCAPS.CPP create mode 100644 src/mesa/drivers/d3d/D3DHAL.H create mode 100644 src/mesa/drivers/d3d/D3DInit.cpp create mode 100644 src/mesa/drivers/d3d/D3DMESA.H create mode 100644 src/mesa/drivers/d3d/D3DRaster.cpp create mode 100644 src/mesa/drivers/d3d/D3DShared.h create mode 100644 src/mesa/drivers/d3d/D3DTEXT.CPP create mode 100644 src/mesa/drivers/d3d/D3DTextureMgr.cpp create mode 100644 src/mesa/drivers/d3d/D3DTextureMgr.h create mode 100644 src/mesa/drivers/d3d/D3DUTILS.CPP create mode 100644 src/mesa/drivers/d3d/D3Dvbrender.c create mode 100644 src/mesa/drivers/d3d/DDrawPROCS.c create mode 100644 src/mesa/drivers/d3d/DEBUG.C create mode 100644 src/mesa/drivers/d3d/DEBUG.H create mode 100644 src/mesa/drivers/d3d/DbgEnv.bat create mode 100644 src/mesa/drivers/d3d/MAKEFILE create mode 100644 src/mesa/drivers/d3d/NULLProcs.h create mode 100644 src/mesa/drivers/d3d/NullProcs.c create mode 100644 src/mesa/drivers/d3d/OPENGL32.DEF create mode 100644 src/mesa/drivers/d3d/WGL.C create mode 100644 src/mesa/drivers/d3d/d3dText.h create mode 100644 src/mesa/drivers/dos/DEPEND.DOS create mode 100644 src/mesa/drivers/dos/dosmesa.c create mode 100644 src/mesa/drivers/ggi/ggimesa.conf.in create mode 100644 src/mesa/drivers/glide/fxapi.c create mode 100644 src/mesa/drivers/glide/fxdd.c create mode 100644 src/mesa/drivers/glide/fxddspan.c create mode 100644 src/mesa/drivers/glide/fxddtex.c create mode 100644 src/mesa/drivers/glide/fxdrv.h create mode 100644 src/mesa/drivers/glide/fxglidew.c create mode 100644 src/mesa/drivers/glide/fxglidew.h create mode 100644 src/mesa/drivers/glide/fxopengl.def create mode 100644 src/mesa/drivers/glide/fxsetup.c create mode 100644 src/mesa/drivers/glide/fxtexman.c create mode 100644 src/mesa/drivers/glide/fxwgl.c create mode 100644 src/mesa/drivers/osmesa/osmesa.c create mode 100644 src/mesa/drivers/svga/svgamesa.c create mode 100644 src/mesa/drivers/windows/colors.h create mode 100644 src/mesa/drivers/windows/mesa_extend.c create mode 100644 src/mesa/drivers/windows/mesa_extend.h create mode 100644 src/mesa/drivers/windows/stereo.h create mode 100644 src/mesa/drivers/windows/wgl.c create mode 100644 src/mesa/drivers/windows/wing32.def create mode 100644 src/mesa/drivers/windows/wmesa.c create mode 100644 src/mesa/drivers/windows/wmesaBackup.c create mode 100644 src/mesa/drivers/windows/wmesaOld.c create mode 100644 src/mesa/drivers/windows/wmesa_stereo.c create mode 100644 src/mesa/drivers/windows/wmesadef.h create mode 100644 src/mesa/drivers/x11/fakeglx.c create mode 100644 src/mesa/drivers/x11/glxapi.c create mode 100644 src/mesa/drivers/x11/realglx.c create mode 100644 src/mesa/drivers/x11/realglx.h create mode 100644 src/mesa/drivers/x11/xfonts.c create mode 100644 src/mesa/drivers/x11/xmesaP.h (limited to 'src/mesa/drivers') 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 +#include +#include +#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 +#include +#include +#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 +#include +#include +#include +#include +#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 +#include +#include +#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 +#include +/*===========================================================================*/ +/* 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 +#include +#include +#include +#include +#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, "" ); + 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 +#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 +#include +#include +#include +#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 +#include +#include +/*===========================================================================*/ +/* 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 +#include +#include +#include +#include + +#ifdef DJGPP +#include +#endif + +#ifdef MGL +#include +#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;iClipMask[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;iindex ); +#ifdef UNIVBE + SV_beginPixel(); +#endif + for (i=0;ired, DOSMesa->green, DOSMesa->blue ); + for (i=0; iindex ); +#ifdef UNIVBE + SV_beginPixel(); +#endif + for (i=0; iindex); +#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; ired, DOSMesa->green, DOSMesa->blue ); +#ifdef UNIVBE + SV_beginPixel(); +#endif + for (i=0; iDriver.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 + * CARD/ FB/ + * TM/ TMU/" + * where: CARD is the card used for the current context, + * FB is the number of MB for the framebuffer, + * TM is the number of MB for the texture memory, + * 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 + * - 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 + * - fixed a Voodoo Rush related problem in the fxwgl.c + * + * Daryll Strauss + * - 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;i0) { + 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;ycurrentFB); + +#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 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 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;icurrentFB, 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;icolor; + ++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;icolor; + } + + 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> 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;icurrentFB,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;icurrentFB,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;icurrentFB,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;iDriverCtx; + 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; iDepth.Mask) { + /* Update Z buffer */ + for (i=0;iDepth.Mask) { + /* Update Z buffer */ + for (i=0;i= *zptr) { + *zptr = z[i]; + passed++; + } else { + *m = 0; + } + } + } + } else { + /* Don't update Z buffer */ + for (i=0;i= *zptr) { + /* pass */ + passed++; + } else { + *m = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;i *zptr) { + *zptr = z[i]; + passed++; + } else { + *m = 0; + } + } + } + } else { + /* Don't update Z buffer */ + for (i=0;i *zptr) { + /* pass */ + passed++; + } else { + *m = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0;iDepth.Mask) { + /* Update Z buffer */ + for (i=0;iDepth.Mask) { + /* Update Z buffer */ + for (i=0;iDriverCtx; + 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; iDepth.Mask) { + /* Update Z buffer */ + for (i=0; iDepth.Mask) { + /* Update Z buffer */ + for (i=0; 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= zval) { + /* pass */ + } else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; 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 zval) { + /* pass */ + } else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + for (i=0; iDepth.Mask) { + /* Update Z buffer */ + for (i=0; iDepth.Mask) { + /* Update Z buffer */ + for (i=0; iDriver.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;itmi.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;iPaletteSize;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;iTexture.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> 3); + } + } else { + unsigned short r,g,b; + + for(y=0;y> 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++> 4); + } + } else { + unsigned short r,g,b,a; + + for(y=0;y> 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;yWidth; + 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;yData+(yoffset*image->Width+xoffset)*3); + dst=destimg+(yoffset*image->Width+xoffset); + + simgw=(image->Width-width)*3; + dimgw=image->Width-width; + for(y=0;y> 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> 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 +#include +#include +#include +#include + +#if defined(__linux__) +#include +#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 +#include + + +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 + +/* + * 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;iFog.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(startadrstartAddress) { + 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;itmi.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 +#include +#include + +#ifdef __cplusplus + } +#endif + +#include +#include +#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 +#include +#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;irowaddr[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;irowaddr[i] = origin + (i * (ctx->rowlength*3)); + } + } else { + /* 4-byte RGBA mode */ + GLuint *origin = (GLuint *) ctx->buffer; + for (i=0;irowaddr[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;irowaddr[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;irowaddr[i] = origin + ((ctx->height-i-1) * (ctx->rowlength*3)); + } + } else { + /* 4-byte RGBA mode */ + GLuint *origin = (GLuint *) ctx->buffer; + for (i=0;irowaddr[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;iclearpixel; + } + } + } + } + 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;irowlength * osmesa->height; + ptr4 = (GLuint *) osmesa->buffer; + for (i=0;iclearpixel; + } + } + else { + /* Clear part of RGBA buffer */ + GLint i, j; + for (i=0;iclearpixel; + } + } + } + } + } + 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;iDriverCtx; + GLuint *ptr4 = PIXELADDR4( x, y ); + const GLuint *rgba4 = (const GLuint *) rgba; + GLuint i; + if (mask) { + for (i=0;iDriverCtx; + 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;iDriverCtx; + GLuint *ptr4 = PIXELADDR4(x,y); + GLuint i; + for (i=0;ipixel; + } + } +} + + + +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;iDriverCtx; + GLuint i; + for (i=0;ipixel; + } + } +} + + +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;iDriverCtx; + 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;iDriverCtx; + GLubyte *ptr3 = PIXELADDR3( x, y); + GLuint i; + GLint rind = osmesa->rind; + GLint gind = osmesa->gind; + GLint bind = osmesa->bind; + if (mask) { + for (i=0;iDriverCtx; + GLubyte *ptr3 = PIXELADDR3( x, y); + GLuint i; + GLint rind = osmesa->rind; + GLint gind = osmesa->gind; + GLint bind = osmesa->bind; + if (mask) { + for (i=0;iDriverCtx; + + 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;iDriverCtx; + GLuint i; + GLint rind = osmesa->rind; + GLint gind = osmesa->gind; + GLint bind = osmesa->bind; + + for (i=0;iDriverCtx; + 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;iDriverCtx; + GLuint i; + GLint rind = osmesa->rind; + GLint gind = osmesa->gind; + GLint bind = osmesa->bind; + GLubyte *ptr3 = PIXELADDR3( x, y); + for (i=0;iDriverCtx; + GLuint i; + GLint rind = osmesa->rind; + GLint gind = osmesa->gind; + GLint bind = osmesa->bind; + for (i=0;iDriverCtx; + GLubyte *ptr1 = PIXELADDR1(x,y); + GLuint i; + if (mask) { + for (i=0;iDriverCtx; + GLubyte *ptr1 = PIXELADDR1(x,y); + GLuint i; + if (mask) { + for (i=0;iDriverCtx; + GLubyte *ptr1 = PIXELADDR1(x,y); + GLuint i; + for (i=0;ipixel; + } + } +} + + +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;iDriverCtx; + GLuint i; + for (i=0;ipixel; + } + } +} + + +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;iDriverCtx; + GLuint i; + for (i=0;iDriverCtx; + 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;iDriverCtx; +#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;iDriverCtx; + + 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 +#include +#include +#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;iindex ); + for (i=0;ired, SVGAMesa->green, SVGAMesa->blue ); + for (i=0; iindex ); + for (i=0; ired, SVGAMesa->green, SVGAMesa->blue ); + for (i=0; iDriver.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 +#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 +#include +#include +#include + +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 +#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 + +#include +#include + +#ifdef __cplusplus +} +#endif + +#include +#include +#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;inSize != 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 +#include +#include +#include +#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 +#endif + +#ifdef __CYGWIN32__ +#include "macros.h" +#include +#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 (iclearpixel); + 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; iScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; iScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; ipixel; + 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; iScreenMem+y*Current->ScanWidth+x; + y = FLIP(y); + if (mask) { + for (i=0; ihPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); + } + else { + for (i=0; ihPal,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; iScreenMem+y*Current->ScanWidth+x; + y = FLIP(y); + if (mask) { + for (i=0; ihPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP])); + } + else { + for (i=0; ihPal,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; ipixel), GetGValue(Current->pixel), GetBValue(Current->pixel)); + } + else { + for (i=0; ipixel); + } + 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; iScreenMem+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; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; ipixel), + 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; irgb_flag==GL_FALSE); + for (i=0; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; iDriver.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 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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; + 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;iDriverCtx; + 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;iColorPtr->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;xxColorPtr->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;xxColorPtr->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 +#include +#include +#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 +#endif + +#ifdef __CYGWIN32__ +#include "macros.h" +#include +#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 (iclearpixel); + 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; iScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; iScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; ipixel; + 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; iScreenMem+y*Current->ScanWidth+x; + y = FLIP(y); + if (mask) { + for (i=0; ihPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); + } + else { + for (i=0; ihPal,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; iScreenMem+y*Current->ScanWidth+x; + y = FLIP(y); + if (mask) { + for (i=0; ihPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP])); + } + else { + for (i=0; ihPal,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; ipixel), GetGValue(Current->pixel), GetBValue(Current->pixel)); + } + else { + for (i=0; ipixel); + } + 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; iScreenMem+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; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; ipixel), + 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; irgb_flag==GL_FALSE); + for (i=0; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; iDriver.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 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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; + 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;iDriverCtx; + 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;iColor[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;xxColor[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;xxColor[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 +#include +#include +#include +#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 +#endif + +#ifdef __CYGWIN32__ +#include "macros.h" +#include +#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(iclearpixel); + 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; iScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; ipixel; + 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; iScreenMem+y*Current->ScanWidth+x; + y=FLIP(y); + if (mask) { + for (i=0; ihPal,RGB(red[i],green[i],blue[i])); + } + else { + for (i=0; ihPal,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; ipixel), GetGValue(Current->pixel), GetBValue(Current->pixel)); + } + else { + for (i=0; ipixel); + } + + 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; iScreenMem+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; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; ipixel), + 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; irgb_flag==GL_FALSE); + for (i=0; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; iDriver.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 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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; +#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;iDriverCtx; +#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;iDriverCtx; +#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;xxDriverCtx; +#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;xxDriverCtx; + 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;iDriverCtx; + 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;iColor[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;xxColor[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;xxColor[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 +#include +#include +#include + +#include +#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 + +// 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; iclearpixel,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;icColorBits / 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;iPolygon.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; igl_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; iScreenMem+y*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; ipixel; + 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; iScreenMem+y*Current->ScanWidth+x; + if (mask) { + for (i=0; ihPal,RGB(red[i],green[i],blue[i])); + } + else { + for (i=0; ihPal,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; ipixel), GetGValue(Current->pixel), GetBValue(Current->pixel)); + } + else { + for (i=0; ipixel); + } + + 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; iScreenMem+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; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; ipixel), + 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; irgb_flag==GL_FALSE); + for (i=0; iScreenMem+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; irgb_flag==GL_TRUE); + for (i=0; iDriver.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 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; lineheight/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 +#include +#include "context.h" +#ifdef DDRAW + #include +#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 +#include +#include +#include +#include +#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;ioverlay_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; idisplay == 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;idisplay==dpy && VisualTable[i]->vishandle==vinfo) { + return VisualTable[i]; + } + } + /* try to match visual id */ + for (i=0;idisplay==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;ioverlay_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;ilayer!=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 +#include +#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 +#include +#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 +#include +#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 +#include +#include +#include +#include +#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 + +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 +#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 -- cgit v1.2.3